mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-07 23:27:01 +02:00
* Fix sudo paths missing from OpenAPI and docs Various sudo (a.k.a. root-protected) paths are implemented in non-standard ways, and as a result: * are not declared as x-vault-sudo in the OpenAPI spec * and as a result of that, are not included in the hardcoded patterns powering the Vault CLI `-output-policy` flag * and in some cases are missing from the table of all sudo paths in the docs too Fix these problems by: * Adding `seal` and `step-down` to the list of root paths for the system backend. They don't need to be there for enforcement, as those two special endpoints bypass the standard request handling code, but they do need to be there for the OpenAPI generator to be able to know they require sudo. The way in which those two endpoints do things differently can be observed in the code search results for `RootPrivsRequired`: https://github.com/search?q=repo%3Ahashicorp%2Fvault%20RootPrivsRequired&type=code * Fix the implementation of `auth/token/revoke-orphan` to implement endpoint sudo requirements in the standard way. Currently, it has an **incorrect** path declared in the special paths metadata, and then compensates with custom code throwing an error within the request handler function itself. * changelog * As discussed in PR, delete test which is just testing equality of a constant * Restore sudo check as requested, and add comment * Update vault/token_store.go Co-authored-by: Anton Averchenkov <84287187+averche@users.noreply.github.com> --------- Co-authored-by: Anton Averchenkov <84287187+averche@users.noreply.github.com>
88 lines
5.2 KiB
Go
88 lines
5.2 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
package api
|
|
|
|
import (
|
|
"regexp"
|
|
)
|
|
|
|
// sudoPaths is a map containing the paths that require a token's policy
|
|
// to have the "sudo" capability. The keys are the paths as strings, in
|
|
// the same format as they are returned by the OpenAPI spec. The values
|
|
// are the regular expressions that can be used to test whether a given
|
|
// path matches that path or not (useful specifically for the paths that
|
|
// contain templated fields.)
|
|
var sudoPaths = map[string]*regexp.Regexp{
|
|
"/auth/token/accessors": regexp.MustCompile(`^/auth/token/accessors/?$`),
|
|
"/auth/token/revoke-orphan": regexp.MustCompile(`^/auth/token/revoke-orphan$`),
|
|
"/pki/root": regexp.MustCompile(`^/pki/root$`),
|
|
"/pki/root/sign-self-issued": regexp.MustCompile(`^/pki/root/sign-self-issued$`),
|
|
"/sys/audit": regexp.MustCompile(`^/sys/audit$`),
|
|
"/sys/audit/{path}": regexp.MustCompile(`^/sys/audit/.+$`),
|
|
"/sys/auth/{path}": regexp.MustCompile(`^/sys/auth/.+$`),
|
|
"/sys/auth/{path}/tune": regexp.MustCompile(`^/sys/auth/.+/tune$`),
|
|
"/sys/config/auditing/request-headers": regexp.MustCompile(`^/sys/config/auditing/request-headers$`),
|
|
"/sys/config/auditing/request-headers/{header}": regexp.MustCompile(`^/sys/config/auditing/request-headers/.+$`),
|
|
"/sys/config/cors": regexp.MustCompile(`^/sys/config/cors$`),
|
|
"/sys/config/ui/headers": regexp.MustCompile(`^/sys/config/ui/headers/?$`),
|
|
"/sys/config/ui/headers/{header}": regexp.MustCompile(`^/sys/config/ui/headers/.+$`),
|
|
"/sys/internal/inspect/router/{tag}": regexp.MustCompile(`^/sys/internal/inspect/router/.+$`),
|
|
"/sys/leases": regexp.MustCompile(`^/sys/leases$`),
|
|
// This entry is a bit wrong... sys/leases/lookup does NOT require sudo. But sys/leases/lookup/ with a trailing
|
|
// slash DOES require sudo. But the part of the Vault CLI that uses this logic doesn't pass operation-appropriate
|
|
// trailing slashes, it always strips them off, so we end up giving the wrong answer for one of these.
|
|
"/sys/leases/lookup": regexp.MustCompile(`^/sys/leases/lookup/?$`),
|
|
"/sys/leases/lookup/{prefix}": regexp.MustCompile(`^/sys/leases/lookup/.+$`),
|
|
"/sys/leases/revoke-force/{prefix}": regexp.MustCompile(`^/sys/leases/revoke-force/.+$`),
|
|
"/sys/leases/revoke-prefix/{prefix}": regexp.MustCompile(`^/sys/leases/revoke-prefix/.+$`),
|
|
"/sys/plugins/catalog/{name}": regexp.MustCompile(`^/sys/plugins/catalog/[^/]+$`),
|
|
"/sys/plugins/catalog/{type}": regexp.MustCompile(`^/sys/plugins/catalog/[\w-]+$`),
|
|
"/sys/plugins/catalog/{type}/{name}": regexp.MustCompile(`^/sys/plugins/catalog/[\w-]+/[^/]+$`),
|
|
"/sys/raw": regexp.MustCompile(`^/sys/raw$`),
|
|
"/sys/raw/{path}": regexp.MustCompile(`^/sys/raw/.+$`),
|
|
"/sys/remount": regexp.MustCompile(`^/sys/remount$`),
|
|
"/sys/revoke-force/{prefix}": regexp.MustCompile(`^/sys/revoke-force/.+$`),
|
|
"/sys/revoke-prefix/{prefix}": regexp.MustCompile(`^/sys/revoke-prefix/.+$`),
|
|
"/sys/rotate": regexp.MustCompile(`^/sys/rotate$`),
|
|
"/sys/seal": regexp.MustCompile(`^/sys/seal$`),
|
|
"/sys/step-down": regexp.MustCompile(`^/sys/step-down$`),
|
|
|
|
// enterprise-only paths
|
|
"/sys/replication/dr/primary/secondary-token": regexp.MustCompile(`^/sys/replication/dr/primary/secondary-token$`),
|
|
"/sys/replication/performance/primary/secondary-token": regexp.MustCompile(`^/sys/replication/performance/primary/secondary-token$`),
|
|
"/sys/replication/primary/secondary-token": regexp.MustCompile(`^/sys/replication/primary/secondary-token$`),
|
|
"/sys/replication/reindex": regexp.MustCompile(`^/sys/replication/reindex$`),
|
|
"/sys/storage/raft/snapshot-auto/config": regexp.MustCompile(`^/sys/storage/raft/snapshot-auto/config/?$`),
|
|
"/sys/storage/raft/snapshot-auto/config/{name}": regexp.MustCompile(`^/sys/storage/raft/snapshot-auto/config/[^/]+$`),
|
|
}
|
|
|
|
func SudoPaths() map[string]*regexp.Regexp {
|
|
return sudoPaths
|
|
}
|
|
|
|
// Determine whether the given path requires the sudo capability.
|
|
// Note that this uses hardcoded static path information, so will return incorrect results for paths in namespaces,
|
|
// or for secret engines mounted at non-default paths.
|
|
// Expects to receive a path with an initial slash, but no trailing slashes, as the Vault CLI (the only known and
|
|
// expected user of this function) sanitizes its paths that way.
|
|
func IsSudoPath(path string) bool {
|
|
// Return early if the path is any of the non-templated sudo paths.
|
|
if _, ok := sudoPaths[path]; ok {
|
|
return true
|
|
}
|
|
|
|
// Some sudo paths have templated fields in them.
|
|
// (e.g. /sys/revoke-prefix/{prefix})
|
|
// The values in the sudoPaths map are actually regular expressions,
|
|
// so we can check if our path matches against them.
|
|
for _, sudoPathRegexp := range sudoPaths {
|
|
match := sudoPathRegexp.MatchString(path)
|
|
if match {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|