Backstage Vault plugin for secrets visibility: what it shows and how it connects
Platform teams often want component owners to find where a service's secrets live without anyone seeing the secret values. The Backstage Vault plugin addresses this by listing secrets paths for a catalog entity from HashiCorp Vault or OpenBao, driven by the vault.io/secrets-path annotation on the entity. It is a community plugin that reads the Vault API, and its purpose is to show paths, not values. Treat it as a visibility aid for owners, reviewers and auditors. It does not create, rotate, store or protect secrets, and it does not replace the policies and access model you already run in Vault or OpenBao.
Before you rely on the output, confirm exactly what the plugin version you choose returns: whether it lists only paths or also metadata, whether it descends into nested paths, and how it reports a path the token cannot read. Secret values should never appear on the entity page, so verify that in a test instance using a non-production secret before any rollout. The annotation is only as accurate as the catalog. An entity with a wrong or stale path will show a wrong or empty list, so path review belongs in the same change process that maintains ownership and other entity metadata.
The plugin needs a token to call the API, and that token should carry a read-only policy limited to the paths you choose to expose. Confirm the exact capabilities the plugin calls in its own documentation, because listing and reading differ in the KV engine APIs, and grant only those. Keep the token in backend configuration, never in frontend config, and plan how it will be rotated. If you run OpenBao, note that its OpenBao migration guide states testing against Vault 1.14.1 Community Edition only, so confirm the plugin's compatibility with your server version and edition before you commit to it.
What you need before installing the Vault plugin
The plugin depends on four things working before you install it: a supported Backstage and Node.js pairing, a secrets cluster you can reach, a trust path for its TLS certificate, and a catalog and sign-in setup that tie each component to a path. Work through the cards in order, since a gap in one usually shows up as an empty or failing panel in another.
Backstage release line and Node.js
Pick the Backstage release line your portal runs on, then confirm the Node.js version that line supports. The versioning policy supports two adjacent even-numbered Node.js releases, and as of Backstage 1.46.0 those are Node.js 22 and 24. Before you install, check that the plugin version you choose lists your exact Backstage release as compatible in its repository, because plugin packages often lag behind the core framework.
A running Vault or OpenBao cluster
Decide which secrets manager you run and the exact version you will point the plugin at. Vault Community Edition, Vault Enterprise and OpenBao each expose the same HTTP API the plugin reads, but OpenBao's migration guide was tested only against Vault 1.14.1 Community Edition, so confirm behavior on your own version before relying on it. Ask the plugin's maintainers which secrets engines and API versions they test against.
Network path from the Backstage backend
The plugin calls the secrets API from the Backstage backend, not from the browser, so the backend host needs a route to the Vault or OpenBao address and port. Check this from the same container or pod that runs the backend, since egress rules and network policies often differ from a laptop. Also confirm which Vault or OpenBao nodes accept traffic when the cluster runs in high availability, because a standby may redirect requests to the active node.
TLS trust for the secrets endpoint
The backend must trust the certificate chain that presents the secrets endpoint. Add your internal certificate authority to the backend's trust store rather than turning off certificate verification, which would expose the token in transit. Confirm the certificate's subject names match the address in your configuration, and test the connection from the backend host with the same CA bundle the plugin will use.
Components annotated in the catalog
The plugin shows nothing for a component unless its catalog descriptor carries the vault.io/secrets-path annotation with the path to read. Decide which entities belong to the pilot, and agree on a path convention, such as one path per component or per environment, before you write annotations across the catalog. Entities without the annotation show an empty panel, so treat a missing annotation as a gap in the catalog data, not as a plugin fault.
Sign-in that resolves to one identity
The plugin's access checks depend on the signed-in user resolving to the same identity that the catalog and secrets policy know about. Configure a sign-in resolver so every provider maps to one catalog user, and avoid guest access in production. If a user can reach a component page without a resolvable identity, the plugin cannot apply the expected per-user checks, so verify sign-in against a catalog user before testing secrets visibility.
How to configure the Vault plugin step by step
This sequence gives the Backstage backend a read-only credential for Vault or OpenBao, then shows secret paths on the entity pages of components that carry the vault.io/secrets-path annotation. Each step closes with a check you can run before moving to the next one.
Create a read-only policy for the backend
A platform engineer writes a Vault policy that allows listing and reading metadata under the mounts and paths that teams will annotate, and nothing that returns secret values. Confirm the exact capabilities the plugin needs in its documentation before you finalize the policy, since listing paths may require a different set than reading values. Check: read the policy back with the Vault CLI and confirm it covers only the intended mounts. A dedicated policy keeps the portal from inheriting broader access.
Issue a scoped token or AppRole for the backend
An administrator creates a token or AppRole bound to the read-only policy, with a time-to-live and renewal settings that your security team approves. OpenBao's auth documentation recommends AppRole for servers, so a server-hosted Backstage backend is usually the better fit for AppRole, but confirm the method your Vault or OpenBao version supports for this plugin. Check: run a token lookup with the new credential to confirm the attached policy and TTL, then list a permitted path and confirm a read of a secret value is denied.
Store the Vault address and credential as backend secrets
An engineer adds the Vault address to the backend section of app-config and references the credential through an environment variable or your existing secret store, never as a literal value in committed files. Keep these settings out of any frontend configuration, because the browser receives that code. Check: start the backend in a test environment, confirm it reads the address and credential from the environment, and confirm the resolved token does not appear in startup logs or the configuration view.
Install and register the backend plugin package
A Backstage engineer adds the Vault backend plugin package named in the plugin's own documentation to the backend, registers it in the backend entry point, and rebuilds the app. Confirm the current package name, its maintainer, and whether it works with both Vault and OpenBao endpoints before you install it, and check it against the vetting checklist for third-party plugins. Check: the backend starts without plugin load errors, and the logs show a successful connection to the Vault address with the scoped credential.
Annotate a pilot component with the secrets path
A component owner picks one pilot service and adds the vault.io/secrets-path annotation to its catalog-info.yaml, using a path that the read-only policy permits. Keep the pilot small so problems stay easy to trace. Check: the descriptor passes catalog validation when you commit it, and after the next catalog refresh the annotation appears under the entity's metadata with the path spelled exactly as it is in Vault.
Confirm the entity tab lists the expected paths
After the catalog loads the pilot entity, the platform team opens its Vault tab and compares the listed paths with the output of a Vault list command run using an administrator account. The tab should show paths and metadata only, with no secret values. Check: every path in the Vault listing appears in the tab, and nothing outside the annotated path does. If the tab is missing, check the annotation spelling, the plugin registration and the backend logs first.
How the plugin maps catalog entities to Vault paths
The mapping starts with the vault.io/secrets-path annotation on a component's catalog entity, which holds the path the team registered for that component in HashiCorp Vault or OpenBao. When someone opens the entity page, the frontend asks the plugin's backend for the secrets under that path. The backend reads the annotation from the entity, calls the Vault API with a token configured on the server, and returns only the names it receives to the browser. The Vault call happens in the backend so the token and the Vault address never reach the browser. Anyone who can view the entity sees the listing, so confirm with your plugin version that the response contains secret names and never secret values, and keep the plugin's role to listing.
The annotation value is a path, so it should follow a naming convention agreed with the Vault administrators before any team annotates its entities. A common approach is to mirror the hierarchy Vault already uses, with segments for the secrets engine mount, team, service and environment. For example, and only as an illustration, kv/payments/checkout/prod shows that layout. Ask the administrators which KV engine version and mount each team uses, because listing behavior and path layout differ between versions, and a mismatch returns empty results that look like a broken plugin. Renaming a path later means editing every annotation and any scripts that reference it, so settle the scheme early, document it in your catalog guidelines, and make the owning team responsible for keeping each annotation current.
The plugin can only show what its token is allowed to list. Vault checks the token's policy on every request, so the display directly reflects that policy. A broad token exposes secret names across teams to anyone who views an entity, while a narrow token returns empty or partial listings for paths the team expects to see. Work with the Vault administrators to create a dedicated token for the plugin with list capability limited to the prefixes that appear in annotations, then test it against one entity from each team before rollout. Confirm how the plugin reports a denied path, since an empty card and an error message mean different things to the team looking at them. Plan a review each time a new team adopts the annotation, because each new prefix needs a corresponding policy change.
What the plugin shows and what it does not show
The plugin lists secret paths that the annotated component is associated with, so an owner can see where its secrets live without opening the Vault interface. The listing reflects what the token is allowed to read. A path that the token can see appears; a path it cannot see does not, and the plugin does not explain the gap. Confirm the exact fields each listing returns, such as path names, metadata or timestamps, in the plugin README before promising them internally.
- Path names: the logical paths mapped to the component through the
vault.io/secrets-pathannotation. - Listing metadata: any fields the plugin returns from Vault's list and metadata responses, which depend on the plugin version.
- Permission-filtered results: only paths the configured token can list or read.
- Entity linkage: the association between the catalog entity and the path set, controlled by the annotation value in the descriptor.
- Read-only display: the tab reports paths and does not offer create, update or delete actions.
Before approving the tab for application owners, run it against a test component and compare the output with a Vault listing made with the same token.
Some information stays out of the tab by design of the Vault API and the plugin's read path. Secret values are not part of the listing, and the plugin should not be expected to display them, cache them or pass them to the browser. The policy documents attached to a token are also not a general feed for the portal. Treat any gap between what you expect and what appears as a question for the plugin maintainers, not an assumption to fill in.
- Secret values: the plugin lists paths and does not fetch or render the value stored at them.
- Policy contents: policy text beyond what the Vault API returns to the token is not exposed in the tab.
- Other namespaces: secrets in a Vault namespace the token cannot read are not listed, even if the component uses them.
- Other tokens' scope: the tab cannot show what a different identity could read.
- Access history: audit log entries and who read a path are not part of the listing.
Ask the security team to confirm that these exclusions match their threat model, and record the confirmation with the plugin's version.
What the plugin can show depends on how Vault is deployed and licensed. Namespaces are a feature that Vault Enterprise documents as requiring a license on the cluster, and OpenBao documents namespaces as a concept in its own right. A token scoped to one namespace will see that namespace only, so a multi-namespace layout needs either a token per namespace or a documented approach from the plugin. Confirm which combination your organization runs before writing the annotation convention.
- Vault Enterprise namespaces: listing across namespaces depends on the license and on the token's policy in each namespace.
- Community Edition layout: a single namespace setup is the simpler case to validate first.
- OpenBao namespaces: check the namespace behavior in the OpenBao documentation and the plugin's support for it.
- Path naming: a consistent path convention per component makes the annotation predictable across teams.
- Version pairing: confirm which Vault or OpenBao versions the plugin release has been tested against.
Write down the edition, namespace layout and plugin version together so a later upgrade of any one of them triggers a retest.
How annotations, paths and token scope map to Backstage and Vault
This table maps each Backstage attribute to its Vault counterpart, from the vault.io/secrets-path annotation to the token policy behind the entity tab. Read each row as a decision your platform and security teams must settle before rollout, because a mismatch in any one of them shows teams the wrong paths or nothing at all.
| Element | Backstage side | Vault or OpenBao side | What to agree before rollout |
|---|---|---|---|
| Path reference | vault.io/secrets-path annotation on the catalog entity | Full secret path under a KV mount, such as a team-scoped prefix | Confirm the annotation holds the exact path the token can list, with no guessed or abbreviated values |
| Owning team | Catalog entity owner and system relation | Team-level path prefix or policy grouping secrets by owner | Each path prefix should map to one owning team so that the entity tab shows the right owner's paths |
| Namespace or mount | Plugin configuration key naming the Vault address and scope | Enterprise namespace or the KV secrets engine mount point | Record which namespace or mount the plugin targets, and whether your OpenBao or Vault edition supports the namespace model you use |
| Read capability | Entity tab listing secret paths | List and read capabilities on the metadata path of the token policy | Grant list on paths the portal shows, and avoid read on secret values if the tab only needs path names |
| Token identity | Backend plugin credential, not the user's browser session | Token or auth method bound to a service identity with a narrow policy | Assign a dedicated service identity so audit logs show portal lookups, and confirm rotation ownership |
| Entity scope | Entities without the annotation | Paths not covered by the token policy | Decide whether unannotated entities show nothing or a configuration hint, and confirm that the token cannot widen to unrelated paths |
| Visibility limits | What the tab displays: path names and metadata only | Secret values and dynamic credentials stay in Vault or OpenBao | Confirm with the plugin's documentation whether any value or version data is shown, and tell auditors which fields the tab exposes |
Token policy and hardening for the Vault plugin
The plugin reads secret paths through a backend credential, so that credential is the main risk in this design. The cards below cover how to scope it, keep it out of the browser and repositories, and record how it is used.
Read-only, path-scoped policy
Give the backend a policy that allows only list and read on the mounts the portal needs, and nothing else. Use metadata-level listing where the plugin only needs paths, so the token cannot fetch secret values. Confirm the exact capabilities the plugin requests in your version before writing the policy, and test the policy against a non-production mount first.
Dedicated AppRole for the backend
Create a separate AppRole for the Backstage backend rather than reusing a human or CI credential. The OpenBao auth methods guidance recommends AppRole for servers, so pair it with a narrow policy and a single purpose. Keep the role ID and secret ID in your deployment secret store, not in app-config.yaml.
Short TTLs and renewal
Set a short token TTL and let the backend renew it, so a leaked token expires quickly. Limit the maximum lifetime so renewal cannot run indefinitely, and plan for re-authentication when the secret ID is rotated. Confirm the TTL values with your Vault or OpenBao administrator and test renewal after a restart.
Keep the credential out of the frontend and git
Backstage frontend code is bundled and shipped to every signed-in browser, so the token must only exist in backend configuration. Check that no VAULT_ value appears in a frontend config key, a template, or a committed file. Scan the repository and container image as part of your release checks.
Audit logging on the Vault side
Enable an audit device in Vault or OpenBao so every list call from the backend is recorded with its token accessor and path. Send audit logs to a store your security team monitors, and alert on requests outside the expected mounts. The Backstage side does not replace this record.
Review namespaces and license needs
Decide which namespaces the portal may see before granting access, and keep the list short. Namespaces are a Vault Enterprise feature that needs a license applied to the cluster, so confirm your edition first. OpenBao documents namespaces separately, so check your fork's behavior against its namespace guide.
Vault, Vault Enterprise or OpenBao: which edition to connect
Decide which secrets server the portal will read from before you write any annotation or token policy, because the licence, the support model and the API surface all follow from that choice. HashiCorp announced on August 10, 2023 that future Vault releases would move from MPL-2.0 to the Business Source License 1.1, and the Vault LICENSE file names IBM as licensor for Vault 1.15.0 or later. The licence bars competitive hosted or embedded offerings and converts each version to MPL-2.0 four years after publication. IBM completed its acquisition of HashiCorp on February 27, 2025. If your organization must run only OSI-approved open-source components, that licence history is the first thing your legal and procurement teams will ask about.
OpenBao is the MPL-2.0 option, a community fork of Vault managed under the Linux Foundation's OpenSSF. It is a Sandbox project, so ask your team to review its governance and maintenance commitments against your own support expectations. Its migration guide was tested only against Vault 1.14.1 community edition, not Vault Enterprise, so treat any move between the two as a project that needs its own test plan. HashiCorp does not publish Vault Enterprise prices. Its pricing pages direct self-managed Enterprise buyers to sales, so the licence cost is a quote item and should be requested alongside the support terms.
Whichever server you choose, the plugin's API calls must be confirmed against that exact server and version, because Vault and OpenBao are separate projects that have diverged. Check the current Vault releases on the hashicorp/vault releases page and the current OpenBao releases on its GitHub releases page, and read the release notes for any change to the KV or auth endpoints the plugin calls. Pin the versions you test and record the result in your change log, so a later upgrade does not silently break the secrets listing.
Why the Vault tab stays empty or returns errors
This table lists the failures teams hit most often when the Vault secrets view shows nothing or an error, with the likely cause and the fix for each. Check the rows in order: the annotation and entity first, then the token and its policy, then network trust, namespace, token lifetime, and finally whether the backend plugin is running.
| Symptom or failure | Likely cause | Fix |
|---|---|---|
| Tab is empty for one component | The vault.io/secrets-path annotation is missing from the component's catalog descriptor, or the entity was not refreshed after the change | Add the annotation to catalog-info.yaml with the exact path, commit it, and wait for the catalog to re-ingest the entity |
| Error says the path was not found | The annotation value has a typo, a wrong mount name, a missing leading or trailing slash convention, or points to a path that does not exist in Vault | Compare the annotation to the path shown in the Vault UI or CLI and correct the value, then reload the entity page |
| Error says permission denied on list | The token lacks list capability on the metadata path for that secret path, so the plugin can see the path name but not enumerate keys | Add list capability on the relevant metadata path to the policy attached to the token, and confirm it with a test call using the same token |
| Tab is empty for every component | The token used by the backend plugin has no read or list rights anywhere in the mount, or the plugin is pointed at the wrong Vault address | Verify the Vault address in the plugin configuration and attach a read-only policy scoped to the component mounts |
| TLS or certificate trust error | Vault uses a certificate issued by a private CA that the Backstage backend container does not trust | Mount the CA bundle into the backend runtime and point the Node.js trust settings at it, then restart the backend |
| Works for a day, then fails with an authentication error | The token has expired or reached its maximum lifetime, and no renewal or re-authentication is configured | Use a token with a renewal policy or a machine login method such as AppRole, and confirm the backend renews it before expiry |
| Namespace not found or empty results on Enterprise | The plugin queries the root namespace while the secrets sit in a child namespace, or the token is scoped to another namespace | Set the namespace in the plugin configuration to match where the mount lives and confirm the token belongs to that namespace |
| Frontend shows nothing and no request reaches Vault | The backend plugin is not installed or not mounted in the backend index, so the frontend card has no API to call | Add the backend package to the backend, restart it, and check the backend logs for the plugin loading without errors |
Questions teams ask before connecting Backstage to Vault
How much does it cost to connect Backstage to Vault?
The Backstage software has no license fee, since it is released under the Apache License 2.0, so your spend sits in services, hosting and the Vault edition you run. Vault Community Edition is available as binaries or source, while Vault Enterprise is licensed commercially and HashiCorp's pricing page directs self-managed Enterprise buyers to sales without publishing prices. The main cost lines are your staff time, the implementation scope, infrastructure for Backstage and Vault, and any Enterprise license. One-time work covers design, the annotation pass and the first policy set. Recurring work covers token and policy reviews, and testing the plugin through each Backstage and Vault upgrade. Ask any quote to itemize these lines separately, and ask which costs recur each year.
What drives the effort of a Vault secrets visibility rollout?
Effort rises with four factors: how many catalog components already carry the vault.io/secrets-path annotation, how many Vault namespaces or path prefixes the portal must read, how much token policy design the security team requires, and how many Backstage upgrades the plugin must survive. Missing annotations mean catalog owners must review entities one by one, which is often the largest single task. Each additional namespace adds policy scoping and testing. Namespaces are an Enterprise feature in Vault, so confirm your edition before planning. Ask any quote to state the assumed number of components, namespaces and environments, so you can compare scope changes later.
How long does it take to connect Backstage to Vault?
No reliable duration can be set from the platform facts alone, so the answer depends on your environment. The main variables are the size of your software catalog, how many components need annotations confirmed by their owners, and how long your access review takes to approve a token policy. A small pilot group can validate the approach before the full catalog is covered, and that pilot usually shapes the rest of the timeline. Ask for a schedule in the written scope with named milestones: policy approval, pilot sign-off, annotation completion and production cutover. Fixed-scope engagements agree these in writing before work starts.
What must our team provide before a Vault plugin engagement starts?
Your team needs to supply four things. First, Vault admin access or an admin who can create the read-only policy and token for the portal. Second, named catalog owners who will confirm which secrets paths belong to each component. Third, a pilot group of teams willing to test the entity pages and report gaps. Fourth, Backstage administrator access to the configuration and sign-in setup, including the sign-in resolvers that map identities to catalog users. Confirm that the Vault instance, namespaces and environments are documented, since the scope depends on that inventory. Missing access usually delays the start more than the technical work does.
Can our own team set up the Backstage Vault plugin without a partner?
Yes, a team that already operates Backstage and Vault can set up the plugin without an outside partner. The work includes configuring the plugin, adding the vault.io/secrets-path annotation to entities, creating a read-only Vault policy and testing that the entity pages show only what the policy allows. The harder parts are the policy review with your security team and keeping the setup working across Backstage upgrades, which follow a monthly main release line and a weekly next release line. If your team lacks Vault or Backstage operations depth, DeployOpen works on fixed-scope implementations and offers retainers for ongoing upgrades and testing, with the scope agreed in writing first.
Does the Backstage Vault plugin reveal secret values?
The plugin is built to list secrets paths for a component, so the expected answer is that it shows where secrets live, not the secret values themselves. Confirm this in the plugin's own documentation for the version you install, because the exact fields it returns are set by that plugin, not by Backstage itself. Then verify it in your environment: use a non-production token, open a sample entity, and check the browser network responses and the backend logs for any value. Keep the token on the backend, never in the frontend. A visibility plugin still shows internal path names, which can reveal system structure, so review which teams can see which entities.
Which Vault token policy should the Backstage plugin use?
Use a dedicated token with the least access that still lists the paths the portal needs. In practice this means a policy that grants list and read metadata capabilities on the relevant path prefixes, scoped per team or environment, and no root, admin or write permissions. A typical starting point looks like this (illustrative only):
- A token attached to one policy, not a shared administrator token
- Path prefixes limited to the teams in the pilot group
- Separate tokens for staging and production
Confirm the exact capabilities the plugin requires against its documentation before writing the policy. Set a rotation schedule, and record who approved the policy, since auditors often test that access to secret metadata is reviewed.
Should we use Vault or OpenBao behind the Backstage plugin?
The choice depends on licensing, support needs and your existing estate, and it should be made before the policy design starts. Vault moved to the Business Source License 1.1 for releases from 1.15.0 onward, a change HashiCorp announced on August 10, 2023, and the license bars competitive hosted or embedded offerings. OpenBao is a community fork under MPL-2.0 that the Linux Foundation's OpenSSF stewards, and its migration guide was tested only against Vault 1.14.1 Community Edition, not Enterprise. If you already run Vault Enterprise, confirm that the plugin and your features work on it. If you are starting fresh, have legal review the license terms and confirm the plugin supports your chosen server.
How DeployOpen scopes and supports the Vault plugin integration
DeployOpen plans and builds the secrets visibility integration inside your own infrastructure, from the Backstage side of the plugin to the Vault or OpenBao token policy behind it. Each engagement starts with a written scope that names the instances, annotated components and access rules involved.
How we scope
- Inventory which Vault or OpenBao clusters, namespaces and KV mounts the portal should list secrets paths from.
- Agree which components get the vault.io/secrets-path annotation and who owns each entity.
- Record the token policy, network route and Backstage configuration changes in the written scope before work starts.
- Confirm with your own team which edition and version of Vault or OpenBao you run before scoping begins.
How we build
- Create a least-privilege token policy that allows listing paths only, and confirm it cannot read secret values.
- Configure the plugin backend against a non-production instance first, then promote the same settings to production.
- Test that annotated entities show paths they own and that unannotated or unauthorized entities show nothing.
- Verify the frontend never receives a Vault token, and that token rotation does not break entity pages.
How we hand over
- Deliver a configuration record covering annotations, token policy, mount paths and Backstage configuration keys.
- Document what the plugin shows and does not show, so catalog users know it is not a secret viewer.
- Walk your platform and security engineers through the token rotation and policy change procedure.
How we support
- Offer ongoing support, plugin upgrades and continuous testing as a retainer after handover.
- Review the token policy when Vault or OpenBao versions change, and retest the plugin against the new release.
- Ask any support provider to confirm response scope, upgrade handling and access to your environment in the written agreement.

