Settings
Manage security keys, authentication, and integrations.
Account
- Username
- Login method
- MFA status
- Enabled Not enabled — register a key below to activate MFA
Security Keys
Key registered! Give it a name so you can recognise it later.
-
Added · Last used
MCP Server
Connect any MCP-compatible AI client (Claude Desktop, Claude Code, Cursor…) to this dashboard.
The server is mounted at /mcp and uses a Personal Access Token for auth.
- Create a Personal Access Token in Settings → Security Keys → API Tokens (or
/tokens). - Copy the token — it starts with
vmcli_. - Add the following block to your MCP client config and replace the placeholder:
{
"mcpServers": {
"vm-dashboard": {
"url": "",
"headers": {
"Authorization": "Bearer vmcli_<your-pat-here>"
}
}
}
}
Enable MCP Server under Integrations first — the endpoint returns 404 while it is off.
Tools: dashboard_summary, list_jobs, get_job, list_inventory,
list_ec2_instances, list_azure_vms, list_gcp_instances,
list_oci_instances, list_amis, list_vms, list_containers,
list_databases, list_k8s_clusters, list_functions,
list_expiring, config_drift, list_agents, cost_summary,
secret_staleness.
All tools are read-only, and each returns only what the token's owner can see in the UI —
a token belonging to a non-admin sees that user's workgroups, not the estate.
Appearance
Name this instance and give it a colour. Applies to everyone, including the sign-in page and the documentation browser. Saved changes appear within a few seconds.
Shown in the menu, the browser tab and on the sign-in card. Leave blank for the default.
The smaller line under the name on the sign-in card only.
Replaces the mark in the navigation bar, the menu and the sign-in card. PNG, JPEG, WebP or SVG, up to 512 KB. A wide wordmark works better than a square icon. Saved as soon as you choose a file. The browser-tab icon is not changed.
· KB ·
Colours the navigation bar, the menu and the sign-in page. Each preset is checked for contrast, so the text stays readable; a custom palette is checked in the preview instead.
Paste the hex values from the customer's brand guide. All three are required.
Buttons, links and the selected menu row.
The navigation bar and the menu.
Badges, highlights and the logo strand.
Preview
Readable, but below the WCAG AA target of 4.5:1:
Link text is darkened automatically to stay legible on white.
Draws a labelled strip under the navigation bar, so two instances are never mistaken for each other. Blank hides it.
Defaults to the accent colour. The label switches between black and white automatically to stay legible.
Preview
Integrations
Enable and configure optional integrations. Changes take effect immediately.
Configure asset storage on /storage before enabling.
Reference
Documentation and API tooling shipped with this build — no internet access required for the docs.
Preview features
Early-access features with no extra configuration. Toggle on to reveal them in the nav — changes take effect immediately.
No preview features available.
Month-to-date cloud spend (AWS Cost Explorer + Azure Cost Management) shown on the
dashboard tile and the /costs page. Set a monthly budget to get an alert
when spend exceeds it — or is on pace to by month-end.
In your account currency. The dashboard's “Needs attention” panel flags
over (spend ≥ budget) and approaching (projected to
exceed by month-end). Needs ce:GetCostAndUsage (AWS) /
Cost Management reader (Azure).
Per-cloud budgets (optional)
Each cloud's MTD spend is flagged against its own budget, in addition to the overall budget above. 0 = no per-cloud alert.
GCP has no cost API — enable Cloud Billing export to BigQuery, then paste the export table here. Grant the dashboard service account BigQuery Data Viewer + Job User on that dataset. Blank → GCP cost stays unavailable. (Export data can lag ~24h; queries scan billed data, so results are cached for hours.)
Evaluate every deploy against OPA policies before the job starts. A blocked deploy returns 403 with the reason and is recorded in the tamper-evident audit log — nothing is created. See the guardrails guide.
Comma-separated. Only these actions are gated; everything else is unaffected. Leave blank and the gate is inert even while enabled.
Allow-list of regions/locations/zones. Blank = no region restriction. Edit directly or use the picker above.
Block-list of sizes/classes (EC2 type, Azure vm_size, GCE machine type, DB class/sku, node type).
Weekdays (UTC) on which deploys are frozen (mon…sun). Blank = no freeze.
Custom rules: drop a .rego into terraform/policy/admission/.
Requires the bundled OPA binary (in the image). With the gate on but OPA missing, gated deploys fail closed (403) rather than slipping through.
Give every new deployment an expiry, then permanently delete it when that time passes — the same destroy path the Destroy button uses. Terminated instances, deleted databases and destroyed clusters are not recoverable. Resources you registered rather than provisioned are never touched, and neither is anything that already existed before you enabled this: a resource only has a timer once something stamps one. See the auto-delete timer doc.
Hours. Applied to cloud VMs, databases and Kubernetes clusters the dashboard
provisions. 0 means new deploys get no timer and nothing is ever
deleted automatically — the safe way to enable this and watch it first.
The clock starts when the deploy is queued, so it includes provisioning time.
Hours, counted from when the resource was created — not from the last extension — so repeated extending can't outrun it. Admins are not capped.
Hours per click, clamped by the ceiling above.
Hours. A resource entering this window shows a warning on the dashboard, and — if is on — fires one resource.expiring message per endpoint, once each. Otherwise an operator has to open the dashboard to see it.
Min past expiry (floor 15).
Minutes (floor 5).
Cap 50.
Days, 0 = forever.
A sweep records a job every interval whether or not it found anything — 48 a day at the default. Completed ones are dropped past this age and are hidden on Job History unless you tick "Show routine sweeps"; a failed pass is always kept and always shown.
Comma-separated. Resources in these workgroups never get a timer and are never deleted. VMs, cloud databases and Kubernetes clusters carry a workgroup; cloud functions and desktop seats don't, so use "never expires" for those instead. A database or cluster left untagged has no workgroup to match here either. Blank = none.
Deletion runs on a schedule, not instantly, so a resource may sit briefly past its expiry. Two one-hour arming delays stand in the way and neither is configurable: the first sweep after you enable the feature only starts the clock, and turning Observe only off starts a second one — so there is always an hour, with the full list visible on Inventory, before anything is destroyed. Turning Observe only back on resets that second clock.
A change window is a recurring period during which changes may start. Define one here and every run form can book a job into it by name. See the change windows doc.
A change booked for a bare time rather than a named window gets this much leeway before it counts as missed. Named windows use their own length.
Windows
No change windows yet. Runs can still be booked for a specific time without one.
disabled
Long jobs — provisions, image builds, exports, deploys — run in a separate worker process, not in the web app. These limits say how many run at the same time, and are read fresh every couple of seconds, so a change here applies without restarting anything. See the job worker doc.
Image exports, promotes and copies, gateways, auto-delete sweeps. They start something in the cloud and then just wait — an export can poll for two hours. Cheap; raise this first. Max 12.
Cluster and database provisions, Packer builds. Each streams its output to the database line by line, so two is usually enough to saturate a small Postgres. Max 4.
VM deploys, tunnels, Kubernetes add-ons. Mostly cloud API calls plus a short terraform or helm. Max 4.
The overall ceiling, and the one that actually binds — the three limits above are allowed to add up to more than this, because they cap the mix while this caps the total. Lower this to shrink the worker's footprint. Max 16, but see the note below: it is also capped by how many database connections the worker has.
Seconds to let running jobs finish when the worker is asked to stop (a redeploy). Keep it under your platform's termination grace period — 30s by default on Azure Container Apps — or the process is killed before it finishes waiting. Jobs longer than this are failed promptly by the next worker instead of looking alive for ten minutes. 0 = don't wait.
0 derives it from the limits above, which is almost always
right. Set it only if the log shows jobs stuck at 0% — that means cloud
calls are queueing for a thread. Applied at worker start, so this one needs
a restart. Max 128.
Running more than one worker multiplies these limits — two workers with a total of 3 each run up to 6 jobs. Jobs are claimed atomically, so no job ever runs twice however many workers there are. Note that each worker needs its own database connections, which is why raising the limits inside one worker is usually cheaper than adding another.
Push dashboard events to Slack, Microsoft Teams, or any HTTP endpoint. Delivery is outbound only — nothing here opens an inbound webhook. See the notifications doc.
The worker has no idea what address you reach the dashboard on. Leave this blank and every message ships with no link — which looks like a bug but is this setting. No trailing path.
Comma-separated. Known: . An individual endpoint can narrow this further, but not widen it.
Below this, nothing is queued.
Seconds (floor 5).
Seconds (floor 300). Budget, stale-secret and drift checks.
Retries back off 30s → 2m → 10m → 30m and survive a worker restart. Past the queue ceiling, new messages are recorded as suppressed rather than queued — the brake that keeps a first enable against a large estate from becoming an incident.
Days. 0 = keep forever. Failed deliveries are never pruned — they're the evidence.
No endpoints yet. Nothing will be sent until you add one.
Only:
Teams: create a Power Automate Workflow from the "Post to a channel when a webhook request is received" template and paste its URL. The old outlook.office.com connector webhooks were permanently switched off in May 2026 and will not work. Messages post as the Flow bot; the name and icon can't be changed.
Slack: an Incoming Webhook URL from the Slack app that owns the channel.
Any endpoint that accepts JSON. The body is a stable, versioned envelope; set a secret below to have it signed with HMAC-SHA256.
Sent as X-Dashboard-Signature. An aws_sm:// / azure_kv:// / gcp_sm:// / bt_safe:// reference is resolved at send time.
Nothing recorded yet.
Delivery is at-least-once: a worker killed mid-send retries when the row is reclaimed, so a duplicate message is possible. A failing endpoint can never slow down or fail the job it is reporting on — sending happens in a separate process, after the fact.
BeyondTrust Password Safe / Secrets Safe — on-demand checkout of secrets and
managed-account credentials via the ps-cli
binary, plus onboarding of the VMs, cloud databases and Kubernetes ServiceAccount
tokens this dashboard builds as managed systems and accounts.
Shell Jump, Gateway and PRA Vault configuration lives on the panel.
API connection
Secret retrieval and managed-account credential checkout via the
ps-cli binary.
Required for the Password Safe Terraform provider (VM managed-system onboarding).
Authentication
Workload identity presents this dashboard's own identity token instead of a stored credential — set it up once on the panel, and add this product to its registration's Product Scopes in Pathfinder. Not yet verified live for this product.
Where calls go on workload identity auth; {site} is the site ID from
the platform identity panel. The default is a best guess at the
Pathfinder gateway path — if calls answer 404 or 421, this is the field to fix
(it may be the product's own host instead).
Covers the dashboard's own REST calls. ps-cli, the Secrets Safe backend, the Ansible runner and the passwordsafe Terraform provider still use the client credentials above — keep them set.
Resource registration (VMs)
Optionally onboard each built Linux VM into Password Safe as a managed system + its baked-in
adminuser account, via a per-deploy opt-in on the
cloud deploy forms. Each cloud defaults to its cloud-native plugin (no per-VPC Resource Broker):
AWS → AWS Systems Manager (over SSM), Azure →
Azure VM SSH Rotation (over Run Command), GCP → GCP VM SSH
Rotation (over GCE instance metadata). The functional account per cloud decides the
management method; each cloud can be switched to the traditional SSH flow below.
Manages Linux EC2 over AWS SSM SendCommand — no SSH
line-of-sight needed. The AWS functional account must be the AWS Systems Manager Custom Plugin
account (password {AccessKeyID}:{AccessKeySecret}), the
plugin must be admin-uploaded in BeyondInsight, and each instance must already be SSM-managed.
Traditional managed system keyed by hostname/IP; pushes the VM's own SSH key and needs SSH line-of-sight (Resource Broker / Gateway). GCP always uses this method (Azure has its own below).
Rotates the adminuser key over Azure VM
Run Command — no SSH line-of-sight needed. The Azure
functional account must be the Azure VM SSH Rotation Custom Plugin account (username = Azure
app/client ID, password = client secret), the plugin must be admin-uploaded in BeyondInsight, and the
service principal needs Virtual Machine Contributor on the resource group. Managed system
address = tenantId/subscriptionId/resourceGroup/vmName.
Traditional managed system keyed by hostname/IP; pushes the VM's own SSH key and needs SSH line-of-sight (Resource Broker / Gateway).
Rotates the adminuser key by writing it into the GCE
instance's ssh-keys metadata — no SSH line-of-sight
needed. The GCP functional account must be the GCP VM SSH Rotation Custom Plugin account
(username = service-account email, password = the service-account JSON key), the plugin must be
admin-uploaded in BeyondInsight, and the service account needs
roles/compute.instanceAdmin.v1. OS Login must
be disabled on the instance (metadata ssh-keys
is ignored when OS Login is on). Managed system address =
projectId/zone/instanceName.
Traditional managed system keyed by hostname/IP; pushes the VM's own SSH key and needs SSH line-of-sight (Resource Broker / Gateway).
Windows VMs (Azure + AWS)
The local administrator is onboarded as a password-managed account, seeded with the generated password. Needs a functional account on a Windows platform — not the SSH-rotation accounts above. Password Safe rotates over SMB/WinRM, so private VMs need a Resource Broker.
local for IAM-user mode; an AssumeRole ARN for EC2 cross-account mode.
The functional account + workgroup must already exist in Password Safe. The per-deploy opt-in
appears as “Onboard into Password Safe” on the AWS/Azure/GCP deploy forms. For AWS Systems Manager,
the managed system DNS name is {instance-id}:{region}
and the account name is {name};{suffix}.
A PRA Vault SSH account named <vm>-<account>
is associated to the VM's Jump Group and kept current by a Password Safe
SyncedAccounts link through the PRA Vault Private Key plugin — so the key
Password Safe rotates can be checked out and injected in PRA. Applies to the cloud-native
plugins only (AWS Systems Manager, Azure/GCP VM SSH Rotation). The functional account must be
on that plugin's platform; the OT and cloud-database PRA Vault accounts are a different
platform and are not used as a fallback.
A PRA Vault username/password account named <cell>-adminuser
is associated to the cell's Jump Group and kept current via a Password Safe
SyncedAccounts link through the PRA Vault Username Password plugin — so the
credential is check-out-able and injectable in PRA. Blank fields fall back to the cloud-database
PRA Vault settings on the tab.
Database Import
Tunes the Import from Password Safe button on the Databases page,
which lists the databases Password Safe already knows about and registers the ones you pick.
It only reads — nothing in Password Safe is created or changed.
All four are optional. Importing needs both the cloud_database:write
and secrets:use permissions.
Preselected in the import dialog. Password Safe does not record a cloud, so this is a starting point, not a lookup.
The dialog says so when it truncates — narrow with a workgroup rather than raising this.
Maps a Password Safe platform name to postgres, mysql, sqlserver or oracle. Invalid JSON is ignored.
Database Onboarding (AWS, Azure & GCP)
When on, provisioning an AWS, Azure or GCP database creates a dedicated managed DB user, onboards the DB as a
Password Safe managed system + managed account (via the {engine} SSM Custom Plugin
on AWS, the {engine} Azure Run Command Plugin on Azure, the
GCP Cloud SQL {engine} plugin on GCP; Azure and GCP each also need their onboarding method set below),
and onboards the PRA Vault credential (via the PRA Vault Username Password plugin)
so Password Safe propagates rotations into the tunnel-injected credential. OCI is not supported.
The custom plugins + the RSA key prep are one-time manual setup — see the database onboarding guide.
Cloud SQL for SQL Server has no IAM database authentication, so its functional account is a
real login with a real password. On create the
dashboard mints a dedicated login per database and keeps the instance admin credential out of
Password Safe. Set this rather than the SQL Server engine override, which also governs AWS and
Azure.
An engine override beats a cloud override, which beats the source
above. On Azure and AWS the functional account carries that database's admin
password, so reference there means creating the
account's database login on every server by hand — with a password Password Safe never hands back.
Prefer create on those two clouds; the cloud override
is how you do that without changing GCP.
The source is not really a preference — it follows whether the functional account has to carry a
per-database secret. On GCP, data-api
(PostgreSQL, MySQL) authenticates with a short-lived IAM token and its composite is
-:-:-, so one account you own serves every database.
SQL Server has no IAM database authentication, so it runs on
cloud-run with a real login for that database —
which one shared account cannot hold. Set sqlserver to
Create one per database and leave the others on the source above.
Sets Change Password Using Own Credentials on the managed
account, so the DB plugin rotates it in place instead of calling the via-functional-account action —
which needs a privileged DB login (CREATEROLE /
CREATE USER /
ALTER ANY LOGIN) that a provisioned server does not have.
Required with an operator-created functional account — that account is unprivileged on
the database, so only the self-rotate action can change a credential. Keep the functional account names in
SP: form and the Azure credential comes from the account
itself, so an off-Azure Resource Broker needs no extra setup. Their DB password segment must still be
valid: it is unused by a self-rotate change but Verify Functional Account logs in with it.
Config-Management runs against a provisioned database connect as the stored admin. Turn
this on and a database that has been onboarded here instead connects as its own Password Safe
managed account, checked out just-in-time — so a bulk run over several databases uses a different account
for each one rather than one admin for all of them. Registered databases already work this way.
Grant that account first. The managed user the dashboard creates
(psafe_<id>) holds
no privileges at all — it exists to be rotated, not to read anything — so until you
grant it what your playbooks need, every run fails on permissions. Leave this off if you are unsure.
The dashboard resolves the functional accounts you name below and never creates or deletes them — the same contract as the VM and Kubernetes onboarding. Each managed system inherits its account's platform, so the Platform fields become advisory, and the cloud credential stays in Password Safe instead of this config store. One account per engine per cloud, because a functional account belongs to a platform.
The dashboard creates a functional account per database from the credential material below, and deletes it on decommission. Switch to Reference an existing account to point at accounts you created yourself.
Oracle (native platform)
Oracle on RDS onboards on Password Safe's own Oracle platform, with no plugin. The Resource Broker serving this workgroup connects to the listener itself, so it must be able to reach the database on port 1521.
The functional account packs the AWS credentials for SSM SendCommand: setting both the Access Key ID and Secret selects IAM-user mode; leaving either blank selects EC2 instance-role mode (Password Safe node/broker on an EC2 with the SSM role). The account's username becomes EC2:<dbAdmin> / IAM:<dbAdmin> and its password the keyId:secret:dbAdminPassword triple the plugin parses.
Not used in this mode — the functional account you name above carries it.
Plugin RSA key material the dashboard drops onto the shared SSM jump host so the SSM plugin can decrypt the RSA-wrapped login password. Use a separate key pair from the Azure one below: these two private keys land on different hosts, so sharing one would mean a compromise of either host also decrypts the other cloud's payloads. Blank leaves the staging manual.
The PRA Vault plugin authenticates with the PRA Configuration API account on the panel. Unsaved edits here are discarded when the panel switches.
Leave the sqlcmd image blank: Microsoft publishes no sqlcmd container, so SQL Server
runs the jump host's own /opt/mssql-tools18/bin/sqlcmd
(installed by the jump-host prep, and the same binary the rotation plugin invokes). Only set it to use a
mirrored image instead, and only one carrying sqlcmd 18 at that path.
For Azure databases the DB is onboarded onto the {engine} Azure Run Command Plugin,
whose plugin reaches the private DB by running the DB client on the shared clouddb-jumpoint VM
via Azure VM Run Command. The functional account is the minted DB admin bundled with an Azure service principal; it rotates a dedicated
managed user. The three custom plugins + the RSA keypair (public cert on the Resource Broker, private key below) are one-time manual setup.
Azure databases skip Password Safe onboarding and fall back to the legacy admin-credential staging; the AWS SSM path above stays on. The checkbox above is shared by both clouds, so this is the only way to disable Azure alone.
Azure service principal for the functional account — leave blank to reuse the dashboard's Azure credentials. It needs Virtual Machine Contributor on the jump-VM resource group.
Not used in this mode — the functional account you name above carries it.
Plugin RSA private key + passphrase the dashboard drops onto the jump VM at /root/psplugin (matches the public cert on the Resource Broker).
For GCP databases the DB is onboarded onto the GCP Cloud SQL {engine} plugin.
PostgreSQL and MySQL use the Data API channel, which reaches a private-IP instance through
Google's own control plane — so unlike AWS and Azure there is no jump host, no broker certificate and no RSA key
pair, and under IAM database authentication the functional account has no database password at all.
SQL Server uses the Cloud Run channel, because Cloud SQL for SQL Server has no IAM database
authentication; that channel needs a small Cloud Run service you deploy yourself, and the dashboard only needs its audience below.
Every channel is now implemented plugin-side — the Data API covers verify, change managed account, change
functional account and discovery on PostgreSQL and MySQL, and no action reports “not implemented in this build” any
more. But none of them has been exercised against a live Cloud SQL instance, which is why this still ships off.
On MySQL, Account Discovery additionally needs GRANT SELECT ON mysql.user
for the rotator; the dashboard applies it during onboarding and reports the statement on the job if it cannot. Rotation and Verify
work without it.
GCP databases skip Password Safe onboarding and fall back to the legacy admin-credential staging; the AWS and Azure paths above are unaffected.
Automatic follows the plugin's own recommendation per engine. Cloud Run is also the only channel that can verify a managed account's password or let one rotate itself.
Operator-created functional accounts, one per engine. This is the recommended mode on GCP: unlike Azure the composite carries nothing per-database, so a single account covers every Cloud SQL instance on that platform.
An attached service account on a Compute Engine Resource Broker, or GOOGLE_APPLICATION_CREDENTIALS
on an on-premises one. No key material is stored in Password Safe or here.
The key travels in the functional account instead of on the broker — the only option for a Resource Broker with no GCP identity of its own, and the one Cloud SQL SQL Server can use.
The broker's identity needs roles/iam.serviceAccountTokenCreator on this account.
Used on the create path only — a reference-mode account already carries its own key.
Leave this blank and the dashboard mints a key for the Rotator Service Account below, per database, and deletes it when the database is
deregistered or decommissioned. Set it to override that: for an identity the dashboard holds no
roles/iam.serviceAccountKeyAdmin on, or a project under
constraints/iam.disableServiceAccountKeyCreation. Paste the file from
gcloud iam service-accounts keys create or its base64; either way it reaches Password Safe base64-encoded,
since raw JSON is read as the whole credential and would drop the database password. The composite runs to roughly 3.2 KB, which stores fine
— but leave that account's own password management off, because the plugin refuses a write-back over 1000 characters.
Operator-created, and used by the Data API channel only. The dashboard registers it as an IAM database user on
each instance it onboards and reads back the name the database actually stored. Keep the name short —
MySQL truncates an IAM database username at the @ and caps it at 32 characters.
Data API + SQL Server only, where it is address option
fasecret=. Cloud SQL for SQL Server has no IAM database authentication, so the Data
API cannot mint a token for the session — it needs the functional account's real password out of Secret Manager. Must be
a regional version; the global
projects/<p>/secrets/… form the plugin article prints is rejected.
Leave blank in create mode — the dashboard stages the credential it minted, per database. Required in
reference mode, because that account's password is one the dashboard has never seen.
Either way this is a second authority for a credential Password Safe exists to own, and nothing re-syncs the copy. Prefer the Cloud Run channel below, which mirrors nothing.
Cloud Run channel (SQL Server)
A small service inside the VPC holds the database drivers and opens the connection, so the credential can travel in the request body instead of being mirrored into Secret Manager. The dashboard deploys it — one per region, because it holds no per-database state and Direct VPC egress is region-locked. This is the only working path for Cloud SQL SQL Server: the control-plane channel has no IAM database authentication to use.
Not loaded — the Databases feature and Cloud Functions must both be on.
Each Resource Broker's identity, granted roles/run.invoker.
Named service accounts only — the Terraform module refuses
allUsers and allAuthenticatedUsers,
because this is an API that changes credentials. Blank deploys a service nothing can call.
Changing this does not reach a deployed service on its own — save, then
use Sync invokers above. No redeploy, so the URL and the audience are unchanged.
Public ingress means a credential-changing API on a globally resolvable endpoint, protected by IAM rather than by network
position. It is the default because an on-premises Resource Broker cannot reach an internal-only service.
Compensate with an org policy (constraints/iam.allowedPolicyMemberDomains); Private
Service Connect is the follow-on.
Warm instances is a correctness setting, not a latency one: Direct VPC egress can take over a minute to establish on a cold start, and a rotation that times out may already have applied the change. 1 bills continuously — a few dollars a month per region. Concurrency is well under Cloud Run's default of 80 because each request holds a database connection.
Only for a service you deployed, or one behind a custom domain or Private Service Connect. A dashboard-deployed service in the database's own region wins over this box — a Cloud Run service on Direct VPC egress is region-locked, and one global value would address a rotation at a service that cannot reach the instance. Sent verbatim as both the request target and the token audience, so a path, query or fragment is rejected. With neither this nor a deployed service, SQL Server onboarding stays off: there would be no address to build.
Kubernetes Token Rotation
Makes a cluster's PRA-injected ServiceAccount token a Password Safe managed account on the
Kubernetes Service Account Token plugin so it rotates on schedule,
and registers the PRA Vault copy as a second managed account on the
PRA Vault Token plugin. Registration then syncs the two in
Password Safe, so every rotation reaches PRA with nothing running on the dashboard's side.
Importing the two plugins, creating the functional accounts, and granting the API identity Requestor + an
auto-release access policy on the new managed accounts are one-time manual setup — see the
token rotation guide.
Neither account's access policy may enable "Change Password After
Release" — a credential change on either member of a synced pair re-rotates both, so a
release-triggered change on the PRA copy would rotate the real cluster token.
Functional accounts (name or id). Per cloud: an AWS access key, an Entra service principal (SP:<tenantId>:<clientId>), a GCP service-account key, or a bootstrap ServiceAccount credential for on-prem/OKE. The PRA Vault mirror's is a PRA Config-API OAuth client.
In-cluster rotator RBAC. The binding subject differs per cloud: AKS needs the service principal's object id (the plugin logs it on every run — not the client id), EKS the access-entry username + the IAM principal ARN behind the functional account's key. GKE derives the subject from the functional account's name when blank.
On AKS and EKS the binding alone does not authorise anything: an AKS cluster with Azure RBAC (every cluster built here) decides from an Azure role assignment, and EKS from an access entry. Both are created for you when the identity below is set, and both fail only at the first rotation when they are missing — on AKS with "User does not have access to the resource in Azure".
A rotation refused for want of a data-plane role grants it and retries for this long. Azure can take up to five minutes to apply a new assignment.
There is nothing to tune for PS → PRA delivery: registration syncs the PRA Vault account to the token account in Password Safe, and a managed account and its subscribers always share a credential, so rotations reach PRA as part of the change itself. In LongLived mode the old token is revoked at rotation, so use Bound mode on clusters whose tunnel must not break — Bound never revokes, and the old token stays valid until its TTL.
The managed account name is <namespace>/<serviceaccount>,
taken from the Kubernetes tunnel identity on the
panel. Unsaved edits here are discarded when the panel switches.
BeyondTrust Privileged Remote Access brokers access to everything the dashboard builds — Shell Jump, Web Jump, Remote RDP and Protocol Tunnel jump items, plus PRA Vault accounts. Provisioned via the BeyondTrust SRA Terraform provider (ARM64-native, no binary dependency).
The Jump Group and Gateway named below must already exist in PRA — the dashboard looks them up by name, it does not create them. Gateway hosts are deployed from the Containers page.
API connection
Shell Jump provisioning via the BeyondTrust SRA Terraform provider. Runs natively on ARM64 — no binary dependency.
Authentication
Workload identity presents this dashboard's own identity token instead of a stored credential — set it up once on the panel, and add this product to its registration's Product Scopes in Pathfinder. Not yet verified live for this product.
Where calls go on workload identity auth; {site} is the site ID from
the platform identity panel. The default is a best guess at the
Pathfinder gateway path — if calls answer 404 or 421, this is the field to fix
(it may be the product's own host instead).
Covers the dashboard's own REST calls (pickers, k8s tunnel jumps). The sra Terraform provider — Shell Jump, Web Jump, RDP and tunnel provisioning — still uses the client credentials above — keep them set.
Configuration API account
For the few calls the SRA Terraform provider cannot make — the PRA Vault accounts used by cloud-database onboarding. Optional: leave blank to reuse the credentials above.
Shell Jump provisioning
The Jump Group and Gateway must already exist in PRA — the dashboard looks them up by name and creates Shell Jumps inside them.
Size of the shared ECS Gateway host. A Web Jump renders headless Chromium on the Gateway and needs ≥2 GB — t3.small minimum, t3.medium preferred. Changing this never resizes a live host: terminate the Gateway host instance and the next deploy recreates it at the new size. Blank keeps the default (t3.small).
A PRA Network Tunnel leases the operator a real address on the target network, and the VPC only answers ARP for addresses registered as secondary private IPs on the gateway host's ENI — so the dashboard registers them, and clears the instance's SourceDestCheck. Blank derives the pool from the gateway subnet (last 8 usable addresses, from the top because AWS allocates from the bottom). Set an explicit pool as 10.99.5.200-10.99.5.207, a CIDR, or a single address; off disables it. This must match “Managed IP Addresses for Protocol Tunnel” on the Gateway in the Pathfinder console — the dashboard cannot read that, and a mismatch shows up only as the Gateway failing its ARP check. A per-region entry wins over this key.
Azure overrides — leave blank to reuse the AWS values above.
Applies to single deploys; a batch always shares one ACI group. ACI is Shell-Jump only — it cannot do protocol tunnels — and every group mounts the same /jpt share, so they contend over one Gateway identity. A deploy that supplies its own Gateway deploy key always gets ACI, since the shared host uses the configured key.
Where a Windows server build's administrator credential is vaulted for injection into its Shell Jump and RDP jump (Azure, AWS, GCP). Not used when Password Safe manages the account — PRA then injects it through its Password Safe integration.
A Windows build switches on OpenSSH Server at first boot and gets a Shell Jump on port 22 that opens in PowerShell. Server 2019 and 2022 download OpenSSH from Windows Update, so the VM needs outbound access. If OpenSSH does not come up, the build gets an RDP jump instead, with a warning on the job. Unchecked, every Windows build gets an RDP jump.
The default for the deploy form's Also enable RDP checkbox. Each deploy can still change it.
Size of the shared Gateway VM. A Web Jump renders headless Chromium on the Gateway and needs ≥2 GB — Standard_B1ms minimum, Standard_B2s preferred. Changing this never resizes a live Gateway: delete the Gateway VM and the next deploy recreates it at the new size. Blank keeps the default (Standard_B2s).
A PRA Network Tunnel leases the operator a real address on the target network, and Azure only honours addresses registered as secondary ipconfigs on the Gateway's NIC — so the dashboard registers them. Blank derives the pool from the gateway subnet (the last 8 usable addresses, taken from the top because Azure allocates from the bottom). Set an explicit pool as 10.99.5.200-10.99.5.207, a CIDR, or a single address. This must match “Managed IP Addresses for Protocol Tunnel” on the Gateway in the Pathfinder console — the dashboard cannot read that, and a mismatch shows up only as the Gateway failing its ARP check. A per-region entry wins over this key.
EC2 has no per-instance external-IP switch — the subnet's MapPublicIpOnLaunch decides — so a cell deployed into a public subnet comes up addressable from the internet and the air-gapped "plant network" the demo rests on is gone. Checked, the deploy refuses before launching anything. GCP and Azure cells pin the external IP off in the form and are unaffected.
Adds three firewall rules per cell, on its ot-sim network tag: no route out at all, and inbound only from the PRA Gateway's bt-jumpoint tag. They outrank the on-demand egress rule, so a cell stays air-gapped even with gcp_vm_nat_enabled on — without them, turning on egress for one ordinary VM quietly gives every plant cell a route to the internet. Removed with the cell; existing cells pick them up on Re-wire. On AWS the same zone is a security group that replaces the instance's, and on Azure an NSG whose outbound Deny is what actually closes the cell — Azure's default outbound access gives a VM with no public IP a route out otherwise. Those two apply only to a cell that also has a DMZ broker, so an existing cell's posture never changes underneath it.
The only way out of the plant. The cell's industrial-DMZ broker runs the Entitle agent, and this is the comma-separated set of addresses it may reach on 443 and 8080 — everything else, from both the broker and the cell, is denied. A firewall rule takes addresses, not names, so an address list from BeyondTrust is the supported answer, and it is the same firewall ticket a real plant raises. Left blank the deploy resolves agent.<region>.entitle.io itself and labels the result resolved, not published on the cell card; if that fails it refuses rather than widening to 0.0.0.0/0.
The escape hatch for a site that cannot pin BeyondTrust's addresses. Allows tcp 443 and 8080 to 0.0.0.0/0 from the broker only (the ot-dmz tag on GCP, the broker's security group on AWS, its NSG on Azure) — the PLC cell keeps its true air gap and the broker still gets no other port. It is a weaker claim than an address list, so the job summary and the cell card name which of the two drew the rule; the demo owns the difference out loud rather than implying a pinned path it does not have.
The broker has no public address, so the agent is installed over SSH by the in-cloud Ansible runner — and the broker admits :22 from the PRA Gateway and this range alone. Set it to the CIDR of the subnet the runner sources from: on GCP the direct VPC egress subnet (gcp_run_subnetwork) or the Serverless VPC connector (gcp_ansible_vpc_connector), on AWS the Fargate task's subnet (ansible_ecs_subnet_id), on Azure the ACI subnet (ansible_aci_subnet_id). Unset, the deploy refuses — an agent that cannot be installed also cannot be repaired on a Re-wire.
GCP overrides — leave blank to reuse the AWS values above.
Applies to single deploys; a batch always shares one Gateway. Paired costs an extra e2-micro per VM. A deploy that supplies its own Gateway deploy key is always paired, since the shared host uses the configured key.
Size of the shared Gateway host. A Web Jump renders headless Chromium on the Gateway and needs ≥2 GB — e2-small minimum, e2-medium preferred; below that the session is OOM-killed and the failure looks identical to a blocked firewall. Changing this never resizes a live Gateway: delete the Gateway VM and the next deploy recreates it at the new size. Blank keeps the default (e2-medium).
A PRA Network Tunnel leases the operator a real address on the target network. GCE only routes addresses declared as an alias IP range on the NIC, so the dashboard declares one and sets canIpForward. Blank derives it from the gateway subnetwork — for a /24, the highest aligned block of 8 clear of GCE's reserved addresses (x.x.x.240/29). Must be a CIDR, not a range, because an alias range is a prefix; off disables it. Both halves are create-only on GCE — an existing Gateway VM has to be recreated to carry network tunnels. Must match “Managed IP Addresses for Protocol Tunnel” in the Pathfinder console. A per-region entry wins over this key.
Kubernetes tunnel identity
The ServiceAccount PRA injects into a managed cluster for API-server tunnels, and the PRA Vault account group injected Kubernetes, database and Web Jump credentials land in. Password Safe can rotate this token on a schedule — see the panel's Kubernetes tab.
Site ID + Personal Access Token for the BeyondTrust Endpoint Privilege Management
for Linux API, on the Pathfinder gateway at
api.beyondtrust.io. Used to build and
download EPM-L client packages, sync them to asset storage, and mint activation tokens.
Find your Site ID by opening
app.beyondtrust.io/api/platform/currentSite
while signed in and copying the site_id
field. The PAT must be created while that site is the active one — PATs are bound to
the site, not the user.
Authentication
Workload identity presents this dashboard's own identity token instead of a stored credential — set it up once on the panel, and add this product to its registration's Product Scopes in Pathfinder. Not yet verified live for this product.
Containers are shown for every configured cloud provider (AWS ECS, Azure ACI, GCP Cloud Run) automatically. To also manage on-prem Docker hosts, either deploy a managed Portainer CE server from Containers → Portainer (which fills in the URL and token below for you), or connect one you already run.
Personal Access Token from Portainer (My account → Access tokens), or a vault
reference like bt_safe://Portainer_PAT,
aws_sm://…,
azure_kv://…,
gcp_sm://…. Stored encrypted.
A dashboard-deployed node serves a self-signed certificate, so deploying one turns this off automatically.
Managed Portainer server
Settings for a Portainer CE container the dashboard runs on a GCE Container-Optimized-OS VM. The node is ephemeral — a teardown wipes its users, environments and settings.
Comma-separated. Opens tcp 9443 (UI/API) and
8000 (Edge agent) to these sources only.
Empty is fail-closed unless "Allow open" below is on — the dashboard's own
egress IP is added automatically so a deploy can reach its node.
The dashboard's own public egress range. Auto-detected and saved on each deploy; set it by hand if you egress from a proxy pool (detection won't clobber a broader range that already contains the detected IP).
First-run password for the admin user.
Leave blank to auto-generate one (it is shown once on the Containers page).
Stored encrypted.
0.0.0.0/0) when no CIDRs are set
— GCP
0.0.0.0/0) when no CIDRs are set
— AWS
0.0.0.0/0) when no CIDRs are set
— AZURE
Users, environments and settings survive a teardown and come back on the next deploy. On GCP and AWS the disk is zonal, so it pins the node's zone — moving region needs a snapshot, not a redeploy. It keeps billing on every cloud until you tear the node down with Delete the data disk ticked.
Opt-in. Reach the node from the PRA representative console — brokered and recorded — without adding your IP to the CIDR list. The Gateway's egress IP is auto-allowed, and with a Vault account group the admin password is injected instead of shown. Can also be chosen per-deploy on the Containers page.
Effective firewall sources (closed — node unreachable)
Dashboard egress:
Hosting platform outbound pool:
Outbound pool:
Web-Jump Gateways:
Entitle adapter:
Merged allow-list:
none
Ports:
Remote Worker runs three kinds of job — config-management (Ansible), Kubernetes (kubectl/helm), and image-promote — either in-process or as a one-shot cloud task (AWS ECS Fargate, Azure ACI, GCP Cloud Run) with clean egress, chosen per the job's target cloud. All three share the per-cloud network settings below. Configure one storage backend for Ansible playbooks (S3 / Azure Blob / GCS).
Runner backends
Pick where each job runs by its target cloud: in-process on the dashboard host (Local), or as a one-shot task in that cloud — clean egress, for when a TLS-inspecting corporate proxy blocks direct access. Image-promote always runs in its target cloud, so it needs no selector here.
Ansible (config-mgmt) runner
Runs playbooks on your VMs over SSH, chosen by the run's target cloud.
A managed Portainer node's firewall is fail-closed and admits the dashboard's own egress — not a one-shot task's. If a Portainer play times out, either pick Local Docker here or add the runner's range to the node's allowed sources on the Portainer page.
Kubernetes (kubectl/helm) runner
Runs cluster-API ops (Entitle agent, ESO, mgmt-plane) chosen by the cluster's cloud.
Image-promote runner
A one-shot container (ECS / ACI / Cloud Run / Container Instances) that converts & stages a promoted disk image in the target cloud. It reads the hub artefact over a short-lived presigned URL, then writes to that cloud's staging bucket.
Blank → the public Docker Hub image; set a full registry path to use a private mirror (e.g. your ACR). Used for all four target clouds.
The task role is required and has no fallback — the Ansible runner's role can't write the S3 staging object. The rest falls back to the ECS Ansible-runner plumbing (cluster, subnet, SGs, execution role) and your S3 storage backend.
Must hold the source disk plus ~2 GiB for the offline image edit. Fargate's implicit default is 20 GiB.
The runner writes the staged VHD with the dashboard's own Azure service principal, so no extra IAM plumbing is needed — only the resource group and staging account matter, and both fall back to your Azure configuration.
The project comes from gcp_project_id. The runner needs roles/storage.objectAdmin on the staging bucket — either via the service account below or the dashboard's own SA.
Cloud Run's /tmp is memory-backed and the GCP path materialises the VHD, a full raw disk, and the tar.gz there, so the default is 4 CPU / 16Gi — multi-GB images OOM at 4Gi. Jobs take whole vCPU only (1, 2, 4, 6, 8), and memory is capped by the CPU count, so raise both together: 2 CPU tops out at 8Gi, 4 at 16Gi, 6 at 24Gi, 8 at 32Gi.
OCI's only remote-worker task is the image-promote runner. The staging bucket is required; the rest fall back to your OCI configuration.
Shared cloud infrastructure
Used by the Ansible runner, the Kubernetes runner, and the image-promote runner. Only the cloud(s) selected above are shown.
Carries kubernetes.core + community.postgresql/mysql/general. The winrm image lacks these, so k8s/DB runs always use this image.
AWS — ECS Fargate
Azure — Container Instances
Resource group + location come from the Azure configuration.
ACR credentials (only for a private registry image; blank for Docker Hub).
GCP — Cloud Run Jobs
Ansible runner
Config-management playbooks run on your VMs over SSH.
Default SSH login per cloud's stock image.
Kubernetes runner
Asset storage — configured — required
Active backend: . Enable the Remote Worker feature flag below to start running playbooks.
The Remote Worker feature flag can't be turned on until at least one storage backend is configured and selected as active. Configure storage on the dedicated /storage page, then return here to enable Remote Worker.
Entitle integration. As the dashboard builds Linux VMs and databases it registers each as an Entitle integration (SSH ephemeral accounts / PostgreSQL / MySQL / SQL Server) so users can request just-in-time access in Entitle. Requires an Entitle tenant.
Authentication
Workload identity presents this dashboard's own identity token instead of a stored credential — set it up once on the panel, and add this product to its registration's Product Scopes in Pathfinder. Not yet verified live for this product.
Where calls go on workload identity auth; {site} is the site ID from
the platform identity panel. The default is a best guess at the
Pathfinder gateway path — if calls answer 404 or 421, this is the field to fix
(it may be the product's own host instead).
Covers the dashboard's own REST reads and access requests. Resource registration (the entitleio/entitle Terraform provider) still uses the Terraform Provider API Key / API Token — keep one set.
Owner ID and Workflow ID are required to register VMs & databases in Entitle.
Virtual applications & persona bundles
Each approval tier routes through its own workflow — the ones
terraform/entitle_user_jit creates. A blank tier falls back to the Workflow ID above.
See virtual applications
and persona bundles.
Leave blank — each VM registers with its image's cloud-default login user automatically. Set this only to force a different sudo user for all SSH registrations.
The SSH private key is taken from the VM's own keypair (the key cloud-init injected), resolved per-cloud — not configured here.
Agent token: — auto-minted; attached to private (PRA-only) targets.
Atlas MongoDB connector
An Atlas programmatic API key with Organization Owner, which Entitle's Atlas MongoDB integration requires. It is separate from the provisioning service account under Databases. Add Entitle's egress IPs to this key's API access list in Atlas; the Databases panel's extra access CIDRs put them on each cluster's project.
One Entitle bundle per job function and cloud — or on-prem AD for the IT, OT and hypervisor
roles: the virtual-app role over the ent-<target>-<persona> group, the
target's own roles or delegated AD groups, and the matching dashboard-* groups. Preview reads Entitle and shows what each one resolves to; only bundles with
nothing missing are created. How bundles are built.
| Persona | Tier | |
|---|---|---|
|
—
|
Creates the selected bundles' ent-ad-* groups — and, if ticked,
their ent-<cloud>-* groups for an AD that syncs to your IdP — as empty global security
groups, through the directory's remote agent. It never adds members or deletes anything. A new group grants
nothing until you complete its Delegation steps and Entitle has synced it.
Routes cloud SDK writes (EC2 deploy / Azure VM / GCP compute) through Entitle-issued short-lived grants instead of baseline credentials. Per-cloud opt-in lets you promote one cloud at a time.
Each entry: "cloud:resource:verb" → {"bundle_id": "..."} or {"role_id": "..."}. Anything outside the matrix is denied (fail closed).
Surfaces a Request access link in the nav and deep-links from
the dashboard's 403 page to the matching Entitle resource so users can
self-serve missing permissions. Populate the resource map from the
resource_ids output of terraform/entitle_user_jit/.
Base URL of your Entitle portal's VM Dashboard bundle. The 403 page falls back to this when a missing permission has no specific resource id in the map below.
Paste the resource_ids output of
terraform/entitle_user_jit/ (Phase 2).
Keys are "scope:level"; e.g.
"aws:write".
access_token_expire_minutes
means a revoked Entitle grant takes effect on the user's next request rather than at the
token's natural expiry. The design recommends ≤30 minutes for
high-sensitivity tenants.
Connects to a Windows host running Hyper-V via WinRM (Windows Remote Management). Runs PowerShell Hyper-V cmdlets remotely — no agent required on the host. Works with Windows Server 2016–2025 and Windows 10/11 Pro / Enterprise with Hyper-V enabled.
WinRM must be enabled on the host:
Enable-PSRemoting -Force
See integration guide for full setup.
Connects to a vCenter Server or standalone ESXi host via the vSphere Web Services API.
Works with vCenter 6.7+ and ESXi 6.7+. Requires pyVmomi (installed by default).
Standalone ESXi returns ha-datacenter as the datacenter name.
vCenter exposes the full inventory — use the datacenter filter to scope the VM list.
Skytap hosts the multi-VM, multi-OS templates a customer POV runs on. The dashboard creates an environment from a template, then wires its VMs into that POV's PRA and Password Safe tenant.
Connection
Leave as the default unless your account is on another region's endpoint.
From your Skytap account page — not your account password.
Optional
Templates and environments are listed from this project, and new environments are created inside it. Blank lists everything the token can see — which is also the fix if the lists come back empty.
Reads one page of GET /v2/templates — the same read the POV page
makes — so it proves the token and what this account can
actually see, scoped to the Project ID above when one is set. An account that
authenticates but exposes no templates is reported as a failure, because there
would be nothing to build a POV from. Tests the saved values,
so save first.
Run POVs on a public cloud as well as Skytap. The dashboard builds the environment from a cloud template you author here, gives it its own network, suspends it on a schedule and reaps it when the evaluation ends.
Provider
One at a time. A POV instance holds one cloud's credentials, one cloud's quota to watch and one cloud's bill to explain. Switching this does not touch POVs you already built on the old provider — they stay visible, suspendable and destroyable.
/aws and its API stay unavailable on a POV instance,
because their deploys resolve the global BeyondTrust tenant rather than this
POV's. Everything here is built through
POV templates.
AWS credentials
The dashboard presents its own JWT-SVID
(spiffe://<trust domain>/dashboard, audience
sts.amazonaws.com) to AWS STS and assumes the role
below. AWS fetches the issuer's keys from
<issuer>/keys, so the issuer must be public.
terraform/dashboard_federation/aws creates the
OIDC provider and the role; terraform/pov_cloud_aws_policy
holds the permissions a POV needs.
The same setting as Settings → Remote Agents → the dashboard's own SPIFFE identity; the issuer and trust domain are set there too.
A stored access key still wins. While one is stored, every AWS call uses it and the role above is never assumed. Remove it once Test connection succeeds without it — or remove it now, save, and test.
Pages and API calls assume the role above, which needs only
pov-cloud-read. Build, power and teardown jobs take a
short-lived lease from Workload Credentials instead — its target role carries
pov-cloud-provision — so no write credential is live
between jobs. Workload Credentials authenticates the dashboard with the same SPIFFE
identity (wlc.jwt), so no PAT is stored either.
On the Workload Credentials panel:
- Authentication Workload identity, platform SPIRE, its Service Name and identity audience;
- the Workload Credentials audience ticked under Remote Agents → the dashboard's SPIFFE identity;
- Use dynamic credentials for AWS on, with the provisioning secret named (e.g. dashboard-provision).
As last saved.
Save this panel first — opening another discards unsaved changes here.
Where a POV builds when its template names no region. A fresh account's vCPU quota is often lower than a multi-VM template needs — worth checking before the first build.
scoped to EC2 in one region. It creates and
deletes VPCs, subnets, security groups and instances tagged
povManagedBy=vm-dashboard, and nothing else.
Azure credentials
The dashboard presents its own JWT-SVID
(spiffe://<trust domain>/dashboard, audience
api://AzureADTokenExchange) to Entra ID as a client
assertion for the app registration in Client ID
below, through a federated identity credential on that app. Entra fetches the
issuer's keys from <issuer>/keys, so the issuer
must be public. terraform/dashboard_federation/azure
adds the federated credential; terraform/pov_cloud_azure_role
holds the roles a POV needs.
A stored client secret still wins. While one is stored, every Azure call uses it and the federated credential is never presented. Remove it once Test connection succeeds without it — or remove it now, save, and test.
Pages and API calls run as the app in Client ID,
which needs only the POV cloud read role. Build,
power and teardown jobs use a short-lived password Workload Credentials mints onto
its own target app, which holds
POV cloud provision — so no write-capable secret
exists between jobs. Workload Credentials authenticates the dashboard with the
same SPIFFE identity (wlc.jwt), so no PAT is stored.
On the Workload Credentials panel:
- Authentication Workload identity, platform SPIRE, its Service Name and identity audience;
- the Workload Credentials audience ticked under Remote Agents → the dashboard's SPIFFE identity;
- Use dynamic credentials for Azure on, with the target app's dynamic secret named.
As last saved.
Save this panel first — opening another discards unsaved changes here.
Where a POV builds when its template names no region. A fresh subscription's vCPU quota is often lower than a multi-VM template needs.
Give this service principal
Contributor on its own subscription, or the
POV cloud provision role from terraform/pov_cloud_azure_role.
Give the app in Client ID the
POV cloud provision role from terraform/pov_cloud_azure_role
on a subscription kept for POVs.
Give the app in Client ID
POV cloud read, and the Workload Credentials target app
POV cloud provision, both from terraform/pov_cloud_azure_role.
Each POV becomes one resource group named povenv-<name>,
and destroying the POV deletes that group whole.
Azure requires an admin account on every VM it creates, so the dashboard generates one per POV and stores it encrypted. It is the platform login the Resource Broker install uses, and you can read it back from the POV page.
GCP credentials
Recorded on every POV built here, so a teardown weeks later aims at the project the environment actually went into.
The zone is resolved from the region, not assembled — us-east1 and
europe-west1 have no -a zone.
The dashboard presents its own JWT-SVID
(spiffe://<trust domain>/dashboard) to Google
STS through the workload identity provider below, then acts as the service
account. Google fetches the issuer's keys from
<issuer>/keys.
terraform/dashboard_federation/gcp creates the pool,
provider and impersonation binding; terraform/pov_cloud_gcp_role
holds the roles a POV needs.
The same settings as Remote Agents → the dashboard's own SPIFFE identity. With Entitle, this is the account assigned to the dashboard's Entitle user.
A stored service-account key still wins. While one is stored, every GCP call uses it and the SPIFFE identity is never presented. Remove it once Test connection succeeds without it.
The service account holds only POV cloud read.
Before the first write of a build, power change or teardown, the dashboard asks
Entitle for POV cloud provision on behalf of the
Entitle user below, waits for GCP to report the permissions, and lets Entitle's
duration end the grant. One grant serves later writes while it has a third of
its time left. Nothing is revoked early: Entitle's revoke needs a person's token.
A user in the IdP group Entitle syncs, assigned the service account above on the GCP integration. Requests are made on its behalf.
Must be a duration the target's workflow allows, and longer than your longest build.
Make the target's Entitle workflow auto-approve for the machine user's group, or every build waits on a person. Test connection checks the user and that the service account has no standing write role; it never files a request.
The service account needs Compute Admin
(or POV cloud provision from terraform/pov_cloud_gcp_role;
with Entitle, only POV cloud read standing) on its project, and the
Compute Engine API enabled. Each POV builds its
own VPC network, subnet and firewall rule named
povenv-<name>-*, plus its VMs.
OCI credentials
Recorded on every POV built here, so a teardown weeks later aims at the compartment the environment actually went into. A POV does not get a compartment of its own — see the docs for why the obvious analogy to an Azure resource group is the wrong one.
The user needs manage on instances,
VCNs, subnets, route tables, security lists and internet gateways in that
compartment. Most OCI shapes are Flex and need a size: a template's
instance type accepts SHAPE, SHAPE:ocpus or
SHAPE:ocpus:memory_gb.
Proves the credential and that the region is enabled for the account. Tests the saved values, so save first.
Connects to a Proxmox VE node or cluster via the REST API. Supports API token auth (recommended) or username/password.
Connection
API Token Auth (recommended)
Password Auth (fallback)
Connects to Prism Central (or Prism Element) via the Nutanix REST API v3. Supports start, graceful ACPI shutdown (requires Nutanix Guest Tools), force stop, reboot, reset, pause, and resume.
The API user needs the Prism Admin or Cluster Admin role. See integration guide for full setup.
Containerised agents run inside a private network and poll out to this dashboard for work, so on-premises Kubernetes clusters and databases can be discovered without opening any inbound firewall rule. Register and revoke them on the Agents page.
This publishes /api/agent for agents to reach —
the only API here that serves callers outside your own network.
Terminate TLS in front of the dashboard first. Signing gives the
agent protocol integrity and replay protection, not confidentiality; see
the remote agent docs and
docker-compose.agent.yml.
The origin agents reach you on. Leave blank only if nothing sits in front of the
dashboard — behind a reverse proxy the signing audience would otherwise be derived
from the request scheme, and an audience pinned as
http:// makes every agent fail authentication in a
way that looks exactly like a revoked agent. Also fixes the OAuth callback URIs.
The dashboard's own SPIRE server from docker-compose.spire.yml.
Migrate to SPIRE on the Agents page creates the agent's entries and
join token in it with docker exec, and its trust bundle
is re-read daily so attestation keeps verifying across key rotation. Ignored on a
managed container runtime, where the app reaches its SPIRE sidecar through
SPIRE_SERVER_SOCKET instead.
host or host:port that an
agent host dials for SPIRE (mTLS gRPC, TCP passthrough). Leave blank when tcp/8081 is
published on the same name as the agent gateway; set it when it is not — for example
an AWS Network Load Balancer's own DNS name.
Blank uses the pinned agent audience plus /spiffe, which
the agent gateway already publishes. Must equal SPIRE_JWT_ISSUER
exactly, and be reachable from the internet over HTTPS for AWS and Azure.
Audiences (one token file each)
The role the dashboard assumes with AssumeRoleWithWebIdentity.
Uses the Azure setup's client id and tenant id, as a federated credential on that app registration. Clear its client secret to switch.
Packer's azure-arm builder reads its credential once, so with no secret and no Workload Credentials lease each build gets its own signed assertion that lasts this long. Set it above your longest Azure image build (15–480).
Signing audience — pinned, read-only
Not pinned yet. The next enrolment code pins it permanently to .
New enrolment codes are refused until this is resolved, or until you confirm the prompt to issue against the pinned value anyway.
Clears the pin so the next enrolment code re-pins it from Public base URL. Every enrolled agent stops authenticating and has to be re-enrolled with a fresh code — each one signs against the audience it was handed at enrolment.
Connects to an XCP-ng or XenServer host or pool master via the XAPI XML-RPC API (Python stdlib — no external SDK required). Supports start, graceful shutdown/reboot (requires xe-guest-utilities), force stop, hard reboot, suspend, resume, pause, and unpause.
Connect using the pool master address. Root or equivalent admin access is required. See integration guide for full setup.
Per-cloud Managed-DB network placement. Normally populated by
setup-<cloud>.sh + the sandbox --push-only import;
set or override the values by hand here. Enable or disable the feature with its
toggle in the integrations list above.
AWS RDS
Azure Flexible Server
GCP Cloud SQL
MongoDB Atlas
Each MongoDB cluster gets its own Atlas project in this organization, created by an Atlas service account with Organization Project Creator. The cluster runs in the same cloud and region as the PRA gateway, and its public endpoint is locked to the gateway's egress IP.
Added to every cluster's access list beside the gateway's /32 — e.g. Entitle's egress IPs, which its Atlas connector needs to reach clusters.
Defaults for provisioning AWS EKS (and OCI OKE) clusters. Normally
populated by setup-aws.sh + the sandbox --push-only import; set
or override the values by hand here. Registering an existing cluster from its kubeconfig
needs none of this. Enable or disable the feature with its toggle in the integrations list
above.
AWS EKS — cluster networking
EKS requires two subnets in distinct AZs. The provision form can override these per-cluster.
AWS EKS — defaults (optional)
The EKS build creates + peers its own VPC. Must not overlap the sandbox VPC (10.99.0.0/16); the provision form can override it per-cluster.
OCI OKE — defaults (optional, experimental)
The OKE build creates its own VCN (api / nodes / lb subnets carved from this block). Must not overlap the sandbox VCN (10.98.0.0/16); the provision form can override it per-cluster.
IdP group → cluster RBAC (real-identity JIT)
Default group the k8s IdP group cluster action binds — members get the role below, and Entitle's directory integration JIT-grants membership so a user signs in as themselves (no impersonation). Each cluster's action can override the group. Which IdP is chosen under Cluster federation IdP below; AKS always uses the Entra group.
Usually the group's name for Okta and PingOne. On EKS the binding names it <provider>:<group> (e.g. okta:k8s-admins), so an IdP group can never be a built-in system: group.
e.g. cluster-admin, admin, view, or a custom ClusterRole — the action lets you pick per-bind.
Subject Entitle's Kubernetes integration binds for a JIT grant (<prefix>:<email>) — and what a user passes to kubectl --as= with the Impersonation access action.
Cluster federation IdP (EKS, GKE)
The identity provider the IdP federation action makes a managed cluster trust, so people sign in to it as themselves and their groups match the binding above. EKS associates this IdP's app as the cluster's OIDC identity provider; GKE reaches it through the workforce pool below. AKS only ever trusts Entra ID (its managed AAD), whatever is chosen here. On-prem clusters use Dex, which can federate any of these. See the federation guide.
Changing it does not touch clusters already federated: each keeps the IdP it was federated with until you disable federation on it.
Exactly as the IdP's discovery document advertises it, https only: EKS compares the string with each token's iss, and fetches the discovery document and keys from the internet.
A public client (no secret) that kubectl oidc-login signs in with; it is also the token audience EKS requires. Emit a groups claim on its ID token.
Device code needs the app's device-authorization grant turned on. Browser needs http://localhost:8000 and http://localhost:18000 registered as redirect URIs.
Entra OIDC federation (EKS)
Shared Entra app registration the IdP federation action associates as an EKS cluster's OIDC identity provider, so a user's Entra token authenticates and its group Object IDs match the binding above. AKS is natively Entra-integrated (no federation needed); GKE uses Workforce Identity Federation (separate). See the Entra federation guide.
The shared Entra app registration's Application (client) ID — the OIDC audience. Required to federate EKS.
Blank derives from the tenant id. The Entra app needs the groups claim on the ID token + public-client flows for kubectl oidc-login.
Dex (on-prem clusters)
People reach on-prem (k3s) clusters only through Dex: the API-tunnel download for such a cluster is a kubectl oidc-login kubeconfig against this issuer, never the cluster's stored admin kubeconfig. Stand Dex up with examples/playbooks/dex/dex-helm.yml, run k3s/k3s-dex-auth.yml on each cluster, then turn on Trusts Dex on its row. Managed clusters are unaffected.
Exactly as Dex's discovery document advertises it — the API server compares the string.
The public client dex-helm.yml registers, and the audience k3s-dex-auth.yml requires.
Only for a lab Dex with its own CA (the one dex-helm.yml prints). It is embedded in the downloaded kubeconfig so oidc-login trusts it.
GKE Workforce Identity Federation (GKE)
GKE can't use an OIDC identity provider (GKE Identity Service is off for new orgs), so the IdP federation action wires the cluster to a Workforce Identity pool + Connect Gateway. The RBAC subject becomes principalSet://…/workforcePools/<pool>/group/<group> — the same group as above. Create the pool + an OIDC provider for your IdP (Entra, Okta, PingOne…) once at the org level (gcloud iam workforce-pools); see the federation guide.
The pool's OIDC provider needs the attribute mapping google.groups=assertion.groups so the IdP's groups reach the token.
Rancher management node (GCE COS)
The central Rancher server runs as a single privileged container on a public Container-Optimized-OS GCE VM (deployed from the Containers page). Every k8s cluster is imported into it — the cattle-cluster-agent dials out to the node, so private clusters on any cloud / on-prem work as long as they have egress. The node is ephemeral: a stop/recreate changes its IP and wipes state. See the integration guide for full setup.
Used once to bootstrap the Rancher admin on first boot; the API token is minted from it and stored encrypted.
GCE firewall source ranges for the node's public IP (tcp 80/443). Dashboard-provisioned clusters' egress IPs — and, when the Web Jump is enabled, the dashboard-managed Gateway's egress IP — are added automatically. Use this only for extra operator/human IPs and pre-existing (operator-owned) Gateways. If nothing is set here and nothing is auto-discovered, the firewall stays closed unless you tick "Allow open".
The dashboard reaches the node over its public IP to bootstrap it, so its own egress must be allowed. Auto-detected + saved on deploy. Corp proxies (Cloudflare WARP) egress from a pool of IPs — set the pool's CIDR (e.g. 104.28.182.0/24) and it is kept as long as the detected IP falls inside it. Bare IP → /32.
Set this when a TLS-inspecting proxy (Cloudflare Gateway, Zscaler) sits between you and the node: it verifies the origin certificate and kills the handshake on a self-signed one, so the UI is unreachable from a browser no matter what the firewall allows — and -k / "ignore certificate" cannot help, because the rejection happens upstream of you. Rancher's built-in ACME client then serves a real, auto-renewing certificate. Unlike the runner transport, this fixes your browser too.
Two conditions: an A record for this name must already point at the node's external IP (checked at deploy — the job fails fast naming the record if not), and port 80 is opened to 0.0.0.0/0 for the HTTP-01 challenge, permanently, since renewal re-validates. That is a separate rule — 443 stays source-restricted. The node is then reached by name, not by IP. Let's Encrypt allows 5 certificates per name per week and the node does not persist ACME state, so avoid repeated redeploys.
Pick runner when this network TLS-inspects and blocks the node's self-signed cert (deploy fails with "HTTPS handshake terminated in transit"). Reuses the k8s runner's GCP region + VPC connector; calls target the node's internal IP.
The Cloud Run VPC connector's /28 — auto-added to the node firewall so the runner's internal traffic is admitted.
Effective firewall allow-list
No sources yet — provision a cluster, enable the Web Jump, or add a CIDR above.
Plus tcp 80 from 0.0.0.0/0 — the Let's Encrypt HTTP-01 challenge for . The sources above still govern 443.
Rancher needs ≥4 GB RAM.
Rancher needs ≥4 GB RAM — t3.small (2 GB) OOMs.
Rancher needs ≥4 GB RAM — Standard_B1s (1 GB) OOMs.
How long the deploy waits for Rancher to serve after boot. Raise it for a cold image pull / slow disk.
Opt-in. Reach the node from the PRA representative console — brokered and recorded — without adding your IP to the CIDR list. The Gateway's egress IP is auto-allowed, and with a Vault account group the admin password is injected instead of shown. Jump Group, Gateway and Vault account group can also be chosen per-deploy on the Containers page — these are the defaults it starts from.
Which dashboard-managed Gateway brokers the UI. Azure's host has no public IP — add that one to the CIDRs by hand.
Defaults for desktop pools on all three clouds. Each pool can still override them at create time. Enable/disable the feature with the Preview toggle. See Virtual Desktops.
AWS and GCP pools are Linux-only. EC2 returns Windows credentials
as password data encrypted to the launch key pair and GCE delivers them through
windows-keys metadata; neither is wired, so those backends refuse a
Windows pool rather than ship a seat nobody can sign into. Their Linux seats are
brokered as PRA Shell Jumps with no credential injection — the rep
supplies the SSH key. Only Azure Windows seats get a vaulted, injected password.
Azure — desktop pool networking
Must be a non-delegated subnet whose NSG allows outbound 443 —
the RS jump client registers with the appliance at first boot. The sandbox creates
desktops-subnet for exactly this. Do not use aci-subnet:
ACI-delegated subnets can't host VM NICs.
Azure — defaults (optional)
Win 11 / Trusted Launch needs a Gen2 size (e.g. Standard_D2s_v3) — not a B-series.
Numeric PRA Vault account-group id — the per-seat Windows admin credential is stored there and injected at RDP launch. Windows seats are Azure-only. Blank → the account lands in PRA's Default group.
AWS — desktop pool defaults (optional)
Blank falls back to this region's desktops_subnet_id, then to
aws_default_subnet_id. Safe to leave blank: unlike Azure's
aci-subnet, no AWS subnet is delegated away from hosting a VM NIC,
so inheriting the ordinary VM subnet cannot produce a pool that fails to deploy.
Offered in the pool form even if it isn't in the curated list.
GCP — desktop pool defaults (optional)
Full self-link, matching what the pool form's picker returns. Blank falls back to
this region's desktops_subnetwork, then gcp_subnetwork.
A subnetwork is regional — one from another region fails at launch.
Per-region config sets
Run several regions in one account? Each region's resource group, subnets, DNS zone, gallery, and default VM size now live in the panel (alongside AWS and GCP), which now carries each cloud's desktops subnet and default size too. Blank fields fall back to the flat keys above, so single-region setups are unchanged.
Password Safe as a certificate registrar and broker — the managed account holds the PKCS#12 passphrase, Secrets Safe holds the bundle it opens. Nothing here is a secret: both of the plugin's credentials ride one Password Safe functional account, which is the protected field built for them, and this panel only names it. Enable/disable the feature with the Preview toggle. Feature guide.
Password Safe objects
Resolved live through GET /Platforms, so a renamed platform just
needs its new name here.
The plugin ships as two .psplugin packages over a
shared core, with different plugin ids, so both install side by side and
neither overwrites the other. Certificate issues an end-entity
certificate on any of its nine backends; Subordinate CA issues
an issuing authority on the four that can sign one. The split is what lets the
team that may request a leaf not automatically be the team that may request an
issuer. Leave it blank unless you renamed the platform in BeyondInsight.
One account, two credentials — the certificate authority's,
and the BeyondInsight identity that writes the bundle to Secrets Safe. On
the OAuth path the name and password are the CA credential
whole and the BeyondInsight client id and secret ride the account's
own API key and secret fields. On the packed one both are split on the
last colon: username
<ca-account>:<bi-run-as-user>, password
<ca-secret>:<bi-api-key> — splitting from the right is
what lets a CA password contain colons there.
The dashboard mints one per CA from the build's own enrollment credential
and deletes it on teardown. That credential is returned once, by
the apply — this is the only moment it can be captured — and the REST API
used here accepts a 1.7 KB private key where ps-cli caps
a functional account password at 1,000 characters.
You maintain the account by hand. Right for a CA this dashboard did not build — an ADCS enterprise CA has no enrollment identity to mint from.
On the Certificate platform.
A functional account is platform-bound and a managed system inherits its platform, so the account above cannot carry a Subordinate CA managed system — it would onboard green and then fail every credential action. Blank reuses it anyway, which is right if you run only one of the two platforms and wrong if you run both.
The plugin reads both and prefers OAuth. What it cannot tell you from here is whether your Password Safe console offers an API key credential type on a plugin-supplied platform — open the functional account form on the Certificate platform and look. If it does not, pin Packed API registration key; the plugin works either way. Automatic keeps an install that already has an API key set on that path, so nothing changes underneath a CA that works.
An API registration permitting the client credentials grant, with write access to the Secrets Safe folder below. The account carries it in its API key and secret fields, so nothing is packed and the plugin presents a short-lived bearer token instead of a static key. Blank falls back to the dashboard's own registration — same tenant, but that one administers the whole of it, and this one is handed to a plugin on a Resource Broker.
Both or neither — half a pair is refused rather than quietly falling back to a different registration than the one named above.
The packed path's second half of the password, with the run-as user below as the second half of the username. Needed only where the console will not take an API key credential type on a plugin platform.
The username's second half. Same tenant and almost always the same identity as the Password Safe run-as account, so leaving it blank is what stops the two drifting apart.
Where the bundle goes
The origin only — the plugin appends its own API path, so a full API URL
here yields a doubled path and a 404 on the first credential change. On a
Password Safe Cloud tenant this is the only possible source: the
appsettings.json inside the .psplugin cannot be edited.
<safe>/<folder>/…. The first segment must be an
existing safe; the folder tree beneath it is created for you. The
plugin itself creates nothing and fails when the folder is absent — scattering
bundles into an unexpected folder with unexpected permissions is worse than a
clear error.
Secrets Safe requires an owner for created secrets. This is a group id — not the numeric user id the Secrets page uses.
Keep {account} in it. A template resolving to the same title for two
accounts would have them overwrite each other, and a consumer finds its own bundle
by this name with no out-of-band configuration.
Certificate defaults
Applied to a new managed system unless the form overrides them. Blank means the option is not emitted at all, which is what keeps the address inside Password Safe's 255-character column — a fully spelled-out ADCS profile is 269 characters before anyone types a real CA name.
Named explicitly on purpose: under Auto a DNS SAN drags
serverAuth into the set.
A share of the certificate's own lifetime, capped at 90. One absolute threshold cannot serve both regimes — 21 days would fire permanently on a 24-hour certificate.
Tokens {AccountName}, {DomainName},
{SamAccountName}, {Upn}. Values are hex-escaped, so an
account name containing a comma cannot inject an extra RDN.
A different quantity from a leaf's lifetime, which is why it has its own field.
Rotation does not revoke — a relying party walks the chain to
the root and neither knows nor cares which subordinate was current when a leaf
was minted — so this, not the rotation interval, is the exposure window
if the signing key leaks. Issue it just longer than the interval Password Safe
rotates it on, sizing the overlap to the longest expected session:
8d against a 7-day schedule. A one-year subordinate rotated weekly
leaves ~52 concurrently valid authorities and makes the control illusory.
GCP CAS lab
DevOps is about $20/month per pool plus ~$0.30 per certificate and keeps no certificate records. A pool bills whether or not it ever issues anything, which is why every CA built here carries an auto-delete timer.
A SPIRE trust domain on a VM this dashboard already deployed, so
the Password Safe SPIFFE SVID plugin has something to govern.
Nothing here is a secret: the administrative credential is minted
on the VM and written straight into Secrets Safe under
no_log — it never passes through the dashboard, the run form or
your shell history. Enable/disable the feature with the Preview toggle.
Feature guide.
Reachability
Who may reach tcp/8081, the SPIRE server API. Blank makes
no cloud ACL change at all — not “open to the
world”: 8081 mints identities, so an unstated source set can only mean
“nobody new”. A lab whose Resource Broker is already in-subnet needs
nothing here.
Pin every address you actually egress from. Corporate egress commonly rotates between two, and a rule holding one of them fails on about half the connections — which presents as an intermittent credential fault, not a network one.
Server
Caps every SVID the server issues, the administrative credential included. A 720h mint against 168h yields ~7 days and SPIRE says so rather than failing. Raise it for a lab that has to outlive a week.
What the mint asks for. CA TTL above decides what it gets.
Where the credential lands
Must already exist, with create rights — the playbook creates no safe.
Four titles land under <root>/<lab>: the PKCS#12, its
passphrase, and — public, so the page can read them back as values
instead of parsing a log — the trust bundle and the granted expiry.
A run fetches assets by filename from storage, never from the repo, so
the spire-*.yml playbooks (and, per mode,
install-docker.yml or k3s-server-init.yml) have to be
uploaded on the Storage page first — Config Management only runs
them. The build form tells you which are missing.
Kubernetes mode
Blank uses the pins, never “latest”. Chart 0.30.2 ships SPIRE 1.15.3, the version the VM and Docker modes install — move the chart and the SPIRE version together, because the value keys the playbook sets are exactly what a chart release renames.
At least 1.34: structured authentication is GA there, and the playbook refuses anything older.
From get.helm.sh/helm-v<ver>-linux-<arch>.tar.gz.sha256sum.
Helm publishes checksums only there, so none is shipped.
Merged over the playbook's values, so it can undo them — including the upstream hardening the lab turns on.
Supply chain
Defaults for building directories and for joining Windows servers to them. Enable or disable the feature with the Preview toggle. Guide.
Users or groups per page when browsing an Entra ID, Okta or PingOne directory.
How often the Directory health page re-checks each directory. On-prem directories are probed through their agent at most hourly. 0 turns scheduled checks off.
How often an on-prem AD domain is checked for replication, FSMO roles, clock skew, DC services, SYSVOL and LDAPS certificates. Each check is a Config Management run that checks out the directory's Password Safe account. 0 turns scheduled checks off; Check now still runs one.
Attached to GCE Windows servers that join a
domain; it needs roles/managedidentities.domainJoin.
Directory administrator in Password Safe
The dashboard builds a deterministic zip from
web_dashboard/functions/, uploads it to an object store
in the same cloud as the function, and Terraform references it by
content hash. Configure the store for each cloud you want to deploy to — a cloud
without one is offered but blocked in the deploy form. Enable or disable the
feature with its toggle in the integrations list above.
Integration guide.
Package stores
Every GCP deploy runs Cloud Build and pushes an image to Artifact Registry
(60–120 s). terraform destroy removes the function but leaves
those images behind.
Uses the dashboard's existing storage account (storage_azure_account);
the key is resolved over ARM at deploy time, never stored.
B1 is the cheapest SKU that supports both VNet
integration and run-from-package. Y1 (Consumption) is cheaper but
cannot do VNet integration — pairing it with a subnet fails at plan time.
VPC / VNet attachment (optional)
Only needed for functions that must reach private resources. Leave blank to deploy public-only functions.
Comma-separated. A VPC-attached Lambda has no internet access unless these subnets route through NAT.
Typically one already allowed into the database's security group.
Must be delegated to Microsoft.Web/serverFarms — a
different subnet from the database one (delegated to the DB
service). The module also sets WEBSITE_DNS_SERVER, without which
privatelink.* zones never resolve even when routing is correct.
Direct VPC egress — no connector, so nothing is billed while idle and the attachment is created and destroyed with the function. It is region-locked: give a bare subnet name (not a regional self-link) so it resolves in whatever region the function lands in. Reaching an internal IP in another region silently drops traffic.
Leave blank and the function runs as the broad default compute SA — and gets no per-secret accessor binding, so it cannot read its own bearer secret.
Only needed to reach another region from a region-pinned
function — the one thing direct egress cannot do. Ignored when the network and
subnetwork above are set. An existing connector runs a minimum of two
e2-micro instances (~$26/mo) whether or not the function is invoked.
One identity for every BeyondTrust product this dashboard calls. Instead of a stored token or client secret, the dashboard presents its own short-lived identity token — from the cloud it runs on, or its own SPIFFE identity — and Pathfinder trusts it because you registered a Workload Identity under Administration → Workload Identities. Register it once and tick a Product Scope for each product you switch to workload identity: Workload Credentials (Secrets), PRA, Password Safe, EPM for Linux, Entitle. Each product then opts in with its own Authentication setting. Guide.
Terraform, ps-cli and the Ansible runner cannot present a workload
identity — the sra, passwordsafe and entitle providers take client credentials or
an API key only. Those features keep using the stored credentials on each
product's panel.
Fills {site} in each product's workload API URL. Open
https://app.beyondtrust.io/api/platform/currentSite while signed in
and copy site_id. The registration must be on this same site, or
every call answers 401 Access denied for this site.
Which platform vouches for this container. Azure and GCP each answer on their
own metadata endpoint; AWS and Other read a token the platform
has written to a file.
On AWS this works on EKS only. ECS and
plain EC2 hand out SigV4 credentials and an instance identity document — neither
is an OIDC token — so a dashboard on ECS stays on a stored token above.
In Pathfinder, Azure registers as Azure Entra ID; GCP and AWS
register as a Custom IDP with a claim condition on
sub.
SPIFFE identity needs no cloud at all, so it also works on
ECS and on-prem: the dashboard's own SPIRE server mints the token, and
Pathfinder trusts it as a Custom IDP whose issuer is the
dashboard's public /spiffe URL.
How to register it.
The Service Name from the Workload Identity registration,
sent as the X-BT-Service-Name header. It tells Pathfinder which
registration to evaluate this container's token against.
Where the platform mounts this container's identity token. Leave blank for the
defaults — AWS_WEB_IDENTITY_TOKEN_FILE or
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE on AWS, the Kubernetes
ServiceAccount token path otherwise. The file is not a secret you
manage: the platform writes it, rotates it in place, and this app only
reads it.
What the managed identity requests a token for; it becomes the
token's aud. Use an app registration in your own tenant with
accessTokenAcceptedVersion: 2 — that is what makes the issuer
…/v2.0, which is the issuer the Azure Entra ID registration type
expects.
Any string, as long as it matches the audience your Custom IDP registration in
Pathfinder expects. The metadata server signs a token with this as its
aud; the issuer is https://accounts.google.com.
Any string, as long as it matches the aud condition of your Custom
IDP registration in Pathfinder. The dashboard mints wlc.jwt for it
once Give the dashboard its own SPIFFE identity and its
Workload Credentials audience are ticked under
Settings → Integrations → Remote Agents.
Leave blank to use the container's system-assigned identity. A user-assigned identity is usually the better choice here: the app and the worker are separate container apps, and sharing one identity means one registration in Pathfinder instead of two — and the worker is where credentials are actually minted. Azure only — GCP attaches a service account to the revision and AWS projects a token for the pod, so neither has an equivalent.
Fetches a token and shows its iss, aud,
sub and exp — the values your registration's issuer and
claim conditions must match. Free, and it calls no BeyondTrust
endpoint, so a pass proves this container has an identity, not that Pathfinder
accepts it; each product's own test does that. Tests the saved
values — save first.
Requires a US-region Pathfinder site with the feature enabled.
Mint short-lived AWS and Azure credentials on demand instead of storing static keys. This is additive: each cloud is opted in separately, and any cloud left off keeps using the credentials it uses today. GCP is absent because Workload Credentials mints AWS and Azure only — a mixed install is normal. Enable/disable the feature with its toggle under Integrations → BeyondTrust. Integration guide.
Connection
Your site (tenant) GUID — the tenant_id claim in the access token
your browser holds after signing in to Pathfinder.
Workload identity is available when the platform hands this container its own identity token. The token is presented to Pathfinder, which trusts it because you registered a Workload Identity there — so this install holds no BeyondTrust credential at all. Registering the trust is a one-time action in the Pathfinder GUI under Administration → Workload Identities; there is no API for it. See Cloud hosting.
Created under Manage Profile → Personal Access Tokens. Stored encrypted; the box is always empty — leave it blank to keep the stored token, type to replace it, or clear it to remove it. A PAT is scoped to a single site. This is the one long-lived credential this mode still needs — it replaces the per-cloud static keys rather than eliminating secrets entirely. The workload-identity mode above removes it.
Workload identity uses the BeyondTrust platform identity — the platform, service name and audience are set once there and shared with PRA, Password Safe, EPM-L and Entitle. . Its registration's Product Scopes must include Secrets.
The version is sent as the mandatory bt-secrets-api-version header.
A wrong value fails in a way that looks like an authentication error, so change it
only when BeyondTrust says to.
Authenticates with GET /session — it proves the site ID, the API
version and whatever this panel authenticates with (the stored token, or this
container's identity) together without issuing a credential, so it is free
and safe to repeat. Tests the saved values, so save first. Unlike
Active credential source below, this asks BeyondTrust rather than replaying the last
stored result.
Static secrets (free, unmetered)
Where the Secrets page writes when Workload Credentials is the selected backend. Static secrets are not metered — only dynamic credential issuances are.
Dynamic credentials (billed per issuance)
Each cloud below is opted in separately, and each stays off until you have created the matching dynamic secret in Workload Credentials. Turning one on reroutes that cloud's credentials on the next refresh; the other clouds are untouched. Prefer a TTL of an hour or more on the dynamic secret — issuances are metered, and AWS credentials cannot be revoked early anyway, so a short TTL buys nothing.
Set this to split the credential by lifecycle. Everything outside a job uses this
lease; the provisioning lease is minted only while a job runs and is never
pre-warmed, so iam:PassRole and iam:CreateRole
are absent from the stored credential between jobs — which is the point
of the split.
Not literally read-only, despite the setting name. The dashboard writes on the request path too — editing a secret, uploading to storage, re-tagging a VM, starting a container task. Its session policy needs those, and only needs to exclude IAM. A strictly read-only policy here breaks the Secrets and Storage pages.
It can point at the same role as the provisioning secret with a narrower session policy. Leave blank to use one lease for everything, which is the default and changes nothing.
With the SPIFFE identity, pages and API calls assume the role in
aws_federation_role_arn (Remote Agents → the dashboard's own SPIFFE
identity), and the provisioning lease is minted only when a job needs it. No
everyday dynamic secret is needed. If federation is not usable, AWS calls outside
jobs fail rather than fall back to the lease.
With the SPIFFE identity, pages and API calls use the app in
azure_client_id through its federated credential, and the
Workload Credentials password, which carries role-assignment rights, is
minted only when a job needs it. If federation is not usable, Azure calls
outside jobs fail rather than fall back to the lease.
Granted cluster admin on AKS clusters a job builds, so the Kubernetes pages can still reach them.
Regenerate once less than this share of a lease's lifetime remains. Lower means fewer issuances but a smaller safety window; the value is clamped to 1–99 because 0 would pin a dead lease and 100 would bill an issuance on every check.
Terraform and Packer read their credential once, at start, so they are given a lease only while at least this share of its lifetime remains; otherwise a fresh one is issued. Keeps a short provisioning lease from expiring mid-apply. Clamped to 1–95.
Active credential source
What each cloud is actually using right now. Worth checking after changing anything above — a broken lease and a cloud still on its static key look the same from the outside otherwise.
|
everyday
expires
minted when a job runs
no lease yet
static key in the encrypted config
no credential configured
|
readonly is the lease every page and API call uses.
provision carries write privilege and is minted only while a
job is running, so no lease between jobs is normal — that is the point of
the split.
Point this at any OpenID Connect provider — the authorize, token and JWKS endpoints are read from the issuer's discovery document, so there is nothing else to fill in. SSO goes live as soon as an issuer and client id are saved; clear the issuer to turn it off. Sign-in with Microsoft is configured separately under Azure and is unaffected. See integration guide for full setup.
Register this redirect URI with your provider
Base URL only — /.well-known/openid-configuration is appended automatically.
Optional — PKCE is always sent, so a public client works. Leave the dots untouched to keep the stored value.
Shown on the login page as “Sign in with …”.
openid is always included.
Claim carrying the user's groups, matched against the mappings on
Groups to assign workgroups.
Usually groups; some Okta setups use roles.
Save first — the probe reads the stored issuer.
Discovery succeeded
Issuer:
Authorize:
Token:
The provider does not advertise a
claim. Group→workgroup mapping may
not work until it is configured to emit one — some providers emit claims they do not
advertise, so this is worth checking rather than assuming broken.
Workload tokens
Accept access tokens this IdP issues to workloads (client credentials, managed identities) and map them to service accounts under Users → OAuth clients → External identities. Off until an audience is set. Works without SSO: no client id is needed here.
What the token's aud must be, so a token minted for another API at the
same IdP is refused. Space-separate to accept several (Entra: api://<app-id>
and the bare app id).
Optional. Other iss values signed by the same keys — Entra v1 tokens carry
https://sts.windows.net/<tenant>/ (with the slash) unless the app's
accessTokenAcceptedVersion is 2.
Signing keys fetched ()
Accepted issuers:
Audience:
The provider reports its issuer as ,
which is not in the accepted list. Tokens carrying it will be refused — add it above
if that is what your tokens say.
Run several regions in one account? Each region carries its own resource ids (subnets, security groups, SSH secrets, networks). Blank fields fall back to the flat config keys, and the default region always resolves to those — so single-region setups are unchanged. The sandbox auto-populates these when you run its setup script in more than one region.
No region sets configured — every region resolves to the flat defaults.