open-vault/vault/external_tests/api/sudo_paths_test.go

126 lines
3.5 KiB
Go
Raw Normal View History

Global flag that outputs minimum policy HCL required for an operation (#14899) * WIP: output policy * Outputs example policy HCL for given request * Simplify conditional * Add PATCH capability * Use OpenAPI spec and regex patterns to determine if path is sudo * Add test for isSudoPath * Add changelog * Fix broken CLI tests * Add output-policy to client cloning code * Smaller fixes from PR comments * Clone client instead of saving and restoring custom values * Fix test * Address comments * Don't unset output-policy flag on KV requests otherwise the preflight request will fail and not populate LastOutputPolicyError * Print errors saved in buffer from preflight KV requests * Unescape characters in request URL * Rename methods and properties to improve readability * Put KV-specificness at front of KV-specific error * Simplify logic by doing more direct returns of strings and errors * Use precompiled regexes and move OpenAPI call to tests * Remove commented out code * Remove legacy MFA paths * Remove unnecessary use of client * Move sudo paths map to plugin helper * Remove unused error return * Add explanatory comment * Remove need to pass in address * Make {name} regex less greedy * Use method and path instead of info from retryablerequest * Add test for IsSudoPaths, use more idiomatic naming * Use precompiled regexes and move OpenAPI call to tests (#15170) * Use precompiled regexes and move OpenAPI call to tests * Remove commented out code * Remove legacy MFA paths * Remove unnecessary use of client * Move sudo paths map to plugin helper * Remove unused error return * Add explanatory comment * Remove need to pass in address * Make {name} regex less greedy * Use method and path instead of info from retryablerequest * Add test for IsSudoPaths, use more idiomatic naming * Make stderr writing more obvious, fix nil pointer deref
2022-04-27 23:35:18 +00:00
package api
import (
"fmt"
"testing"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/audit"
auditFile "github.com/hashicorp/vault/builtin/audit/file"
credUserpass "github.com/hashicorp/vault/builtin/credential/userpass"
"github.com/hashicorp/vault/builtin/logical/database"
"github.com/hashicorp/vault/builtin/logical/pki"
"github.com/hashicorp/vault/builtin/logical/transit"
"github.com/hashicorp/vault/helper/builtinplugins"
"github.com/hashicorp/vault/sdk/helper/jsonutil"
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/vault"
)
const sudoKey = "x-vault-sudo"
// Tests that the static list of sudo paths in the api package matches what's in the current OpenAPI spec.
func TestSudoPaths(t *testing.T) {
t.Parallel()
coreConfig := &vault.CoreConfig{
DisableMlock: true,
DisableCache: true,
EnableRaw: true,
Logger: log.NewNullLogger(),
CredentialBackends: map[string]logical.Factory{
"userpass": credUserpass.Factory,
},
AuditBackends: map[string]audit.Factory{
"file": auditFile.Factory,
},
LogicalBackends: map[string]logical.Factory{
"database": database.Factory,
"generic-leased": vault.LeasedPassthroughBackendFactory,
"pki": pki.Factory,
"transit": transit.Factory,
},
BuiltinRegistry: builtinplugins.Registry,
}
client, _, closer := testVaultServerCoreConfig(t, coreConfig)
defer closer()
for credBackendName := range coreConfig.CredentialBackends {
err := client.Sys().EnableAuthWithOptions(credBackendName, &api.EnableAuthOptions{
Type: credBackendName,
})
if err != nil {
t.Fatalf("error enabling auth backend for test: %v", err)
}
}
for logicalBackendName := range coreConfig.LogicalBackends {
err := client.Sys().Mount(logicalBackendName, &api.MountInput{
Type: logicalBackendName,
})
if err != nil {
t.Fatalf("error enabling logical backend for test: %v", err)
}
}
sudoPathsFromSpec, err := getSudoPathsFromSpec(client)
if err != nil {
t.Fatalf("error getting list of paths that require sudo from OpenAPI endpoint: %v", err)
}
sudoPathsInCode := api.SudoPaths()
// check for missing paths
Global flag that outputs minimum policy HCL required for an operation (#14899) * WIP: output policy * Outputs example policy HCL for given request * Simplify conditional * Add PATCH capability * Use OpenAPI spec and regex patterns to determine if path is sudo * Add test for isSudoPath * Add changelog * Fix broken CLI tests * Add output-policy to client cloning code * Smaller fixes from PR comments * Clone client instead of saving and restoring custom values * Fix test * Address comments * Don't unset output-policy flag on KV requests otherwise the preflight request will fail and not populate LastOutputPolicyError * Print errors saved in buffer from preflight KV requests * Unescape characters in request URL * Rename methods and properties to improve readability * Put KV-specificness at front of KV-specific error * Simplify logic by doing more direct returns of strings and errors * Use precompiled regexes and move OpenAPI call to tests * Remove commented out code * Remove legacy MFA paths * Remove unnecessary use of client * Move sudo paths map to plugin helper * Remove unused error return * Add explanatory comment * Remove need to pass in address * Make {name} regex less greedy * Use method and path instead of info from retryablerequest * Add test for IsSudoPaths, use more idiomatic naming * Use precompiled regexes and move OpenAPI call to tests (#15170) * Use precompiled regexes and move OpenAPI call to tests * Remove commented out code * Remove legacy MFA paths * Remove unnecessary use of client * Move sudo paths map to plugin helper * Remove unused error return * Add explanatory comment * Remove need to pass in address * Make {name} regex less greedy * Use method and path instead of info from retryablerequest * Add test for IsSudoPaths, use more idiomatic naming * Make stderr writing more obvious, fix nil pointer deref
2022-04-27 23:35:18 +00:00
for path := range sudoPathsFromSpec {
if _, ok := sudoPathsInCode[path]; !ok {
t.Fatalf(
"A path in the OpenAPI spec is missing from the static list of "+
"sudo paths in the api module (%s). Please reconcile the two "+
"accordingly.", path)
}
}
}
func getSudoPathsFromSpec(client *api.Client) (map[string]struct{}, error) {
r := client.NewRequest("GET", "/v1/sys/internal/specs/openapi")
resp, err := client.RawRequest(r)
if err != nil {
return nil, fmt.Errorf("unable to retrieve sudo endpoints: %v", err)
}
if resp != nil {
defer resp.Body.Close()
}
oasInfo := make(map[string]interface{})
if err := jsonutil.DecodeJSONFromReader(resp.Body, &oasInfo); err != nil {
return nil, fmt.Errorf("unable to decode JSON from OpenAPI response: %v", err)
}
paths, ok := oasInfo["paths"]
if !ok {
return nil, fmt.Errorf("OpenAPI response did not include paths")
}
pathsMap, ok := paths.(map[string]interface{})
if !ok {
return nil, fmt.Errorf("OpenAPI response did not return valid paths")
}
sudoPaths := make(map[string]struct{})
for pathName, pathInfo := range pathsMap {
pathInfoMap, ok := pathInfo.(map[string]interface{})
if !ok {
continue
}
if sudo, ok := pathInfoMap[sudoKey]; ok {
if sudo == true {
sudoPaths[pathName] = struct{}{}
}
}
}
return sudoPaths, nil
}