The information contained in this article has been verified as up-to-date on the date of the original publication of the article. HashiCorp endeavors to keep this information up-to-date and correct, but it makes no representations or warranties of any kind, express or implied, about the ongoing completeness, accuracy, reliability, or suitability of the information provided.
All information contained in this article is for general information purposes only. Any reliance you place on such information as it applies to your use of your HashiCorp product is therefore strictly at your own risk.
Introduction
In HashiCorp Vault, there are differences between how the Command Line Interface (CLI) and the User Interface (UI) determine which secret engines to display to a user. While the CLI often relies on explicit sys/mounts permissions, the UI uses the sys/internal/ui/mounts endpoint. This endpoint dynamically populates the engines displayed based on the access provided in a user's assigned policies.
Scenario
A user applies a policy using a root-level wildcard (the + symbol), such as:
path "+/library" {
capabilities = ["list"]
}The Issue: The user might intend to only grant access to secret engines that contain a specific path (e.g., ldap-1/library. However, wildcard characters can grant implicit access to all paths at a particular level.
The sys/internal/ui/mounts endpoint is designed to return any mounts (secret engines or auth methods) for which a user has permissions. This implicit access at the root level means every secret engine would be shown. When using a wildcard path at the root level in a policy, consider the security implications of listing all mounts.
The UI interprets a root-level wildcard as the user having implicit access to any mount. To prevent users from seeing additional secret engines and maintain the principle of least privilege, use one of the following strategies:
1. Explicit Path Mapping (Most Secure)
Define each mount explicitly in the policy. This prevents the UI from guessing and only shows the specified engines.
path "ldap-1/library" {
capabilities = ["list"]
}
path "ldap-2/library" {
capabilities = ["list"]
}Note: This can be automated using Terraform locals and loops to manage large policy files. If done without Terraform, it can increase the size of your Vault policies by a fair amount, depending on the number of secret engines enabled in your Vault server.
2. Hierarchical Pathing of Secret Engines (Best Practice for Scaling)
Organize secret engines under a parent prefix. By moving engines to a nested path, you can use wildcards that do not sit at the root level.
Action: Create secret engines using nested paths
vault secrets enable -path=ldaps/1 ldap
vault secrets enable -path=ldaps/2 ldapPolicy: Create policies using the parent prefix with a wildcard instead of the root level
path "ldaps/+/library" {
capabilities = ["list"]
}Result: The UI will only show the
ldaps/path, keeping the root directory clean.
Additional Information
UI vs. CLI: Normally, to display secrets in the UI
sys/mountsis used in policies; however, the UI actually doesn't use this endpoint. The UI endpoint issys/internal/ui/mountsand cannot be explicitly managed in policies; it is a helper endpoint that reflects the user's existing permissions.Using Previously Created Secret Engine(s): It's possible to utilize hierarchical pathing of secret engines in previously created secret engines. This will instead require one to move their secret engine to a new path:
vault secrets move ldap-1 ldaps/1. However, there will potentially be downtime, and there is always a risk that something could happen during the migration of secrets. Therefore, it's important to always take a Raft snapshot first and allocate brief downtime while the data is being re-indexed.-
Wildcard Policies and Resources:
-
UI Endpoints and Further Resources: