VAULT-24437 Address OpenAPI endpoint ignoring redact_version listener parameter (#26607)

* VAULT-24437 Address OpenAPI endpoint ignoring redact_version listener parameter

* VAULT-24437 changelog

* VAULT-24437 changelog mistake
This commit is contained in:
Violet Hynes 2024-04-24 12:16:55 -04:00 committed by GitHub
parent 5369aa88b0
commit b896dc1610
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 134 additions and 3 deletions

3
changelog/26607.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
core: Fix `redact_version` listener parameter being ignored for some OpenAPI related endpoints.
```

View File

@ -4,8 +4,16 @@
package http
import (
"net/http"
"strings"
"testing"
"github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/vault/helper/testhelpers/corehelpers"
"github.com/hashicorp/vault/internalshared/configutil"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/vault"
"github.com/hashicorp/vault/version"
"github.com/stretchr/testify/require"
)
@ -157,3 +165,109 @@ func TestOptions_WithRedactVersion(t *testing.T) {
})
}
}
// TestRedactVersionListener tests that the version will be redacted
// from e.g. sys/health and the OpenAPI response if `redact_version`
// is set on the listener.
func TestRedactVersionListener(t *testing.T) {
conf := &vault.CoreConfig{
EnableUI: false,
EnableRaw: true,
BuiltinRegistry: corehelpers.NewMockBuiltinRegistry(),
}
core, _, token := vault.TestCoreUnsealedWithConfig(t, conf)
// Setup listener without redaction
ln, addr := TestListener(t)
props := &vault.HandlerProperties{
Core: core,
ListenerConfig: &configutil.Listener{
RedactVersion: false,
},
}
TestServerWithListenerAndProperties(t, ln, addr, core, props)
defer ln.Close()
TestServerAuth(t, addr, token)
testRedactVersionEndpoints(t, addr, token, version.Version)
// Setup listener with redaction
ln, addr = TestListener(t)
props.ListenerConfig.RedactVersion = true
TestServerWithListenerAndProperties(t, ln, addr, core, props)
defer ln.Close()
TestServerAuth(t, addr, token)
testRedactVersionEndpoints(t, addr, token, "")
}
// testRedactVersionEndpoints tests the endpoints containing versions
// contain the expected version
func testRedactVersionEndpoints(t *testing.T, addr, token, expectedVersion string) {
client := cleanhttp.DefaultClient()
req, err := http.NewRequest("GET", addr+"/v1/auth/token?help=1", nil)
require.NoError(t, err)
req.Header.Set(consts.AuthHeaderName, token)
resp, err := client.Do(req)
require.NoError(t, err)
testResponseStatus(t, resp, 200)
var actual map[string]interface{}
testResponseBody(t, resp, &actual)
require.NotNil(t, actual["openapi"])
openAPI, ok := actual["openapi"].(map[string]interface{})
require.True(t, ok)
require.NotNil(t, openAPI["info"])
info, ok := openAPI["info"].(map[string]interface{})
require.True(t, ok)
require.NotNil(t, info["version"])
version, ok := info["version"].(string)
require.True(t, ok)
require.Equal(t, expectedVersion, version)
req, err = http.NewRequest("GET", addr+"/v1/sys/internal/specs/openapi", nil)
require.NoError(t, err)
req.Header.Set(consts.AuthHeaderName, "")
resp, err = client.Do(req)
require.NoError(t, err)
testResponseStatus(t, resp, 200)
testResponseBody(t, resp, &actual)
require.NotNil(t, actual["info"])
info, ok = openAPI["info"].(map[string]interface{})
require.True(t, ok)
require.NotNil(t, info["version"])
version, ok = info["version"].(string)
require.True(t, ok)
require.Equal(t, expectedVersion, version)
req, err = http.NewRequest("GET", addr+"/v1/sys/health", nil)
require.NoError(t, err)
req.Header.Set(consts.AuthHeaderName, "")
resp, err = client.Do(req)
require.NoError(t, err)
testResponseStatus(t, resp, 200)
testResponseBody(t, resp, &actual)
require.NotNil(t, actual["version"])
version, ok = actual["version"].(string)
require.True(t, ok)
// sys/health is special and uses a different format to the OpenAPI
// version.GetVersion().VersionNumber() instead of version.Version
// We use substring to make sure the check works anyway.
// In practice, version.GetVersion().VersionNumber() will give something like 1.17.0-beta1
// and version.Version gives something like 1.17.0
require.Truef(t, strings.HasPrefix(version, expectedVersion), "version was not as expected, version=%s, expectedVersion=%s",
version, expectedVersion)
}

View File

@ -220,7 +220,7 @@ func (b *Backend) HandleRequest(ctx context.Context, req *logical.Request) (*log
// If the path is empty and it is a help operation, handle that.
if req.Path == "" && req.Operation == logical.HelpOperation {
return b.handleRootHelp(req)
return b.handleRootHelp(ctx, req)
}
// Find the matching route
@ -548,7 +548,7 @@ func (b *Backend) route(path string) (*Path, map[string]string) {
return nil, nil
}
func (b *Backend) handleRootHelp(req *logical.Request) (*logical.Response, error) {
func (b *Backend) handleRootHelp(ctx context.Context, req *logical.Request) (*logical.Response, error) {
// Build a mapping of the paths and get the paths alphabetized to
// make the output prettier.
pathsMap := make(map[string]*Path)
@ -596,6 +596,10 @@ func (b *Backend) handleRootHelp(req *logical.Request) (*logical.Response, error
vaultVersion = env.VaultVersion
}
redactVersion, _, _, _ := logical.CtxRedactionSettingsValue(ctx)
if redactVersion {
vaultVersion = ""
}
doc := NewOASDocument(vaultVersion)
if err := documentPaths(b, requestResponsePrefix, doc); err != nil {
b.Logger().Warn("error generating OpenAPI", "error", err)

View File

@ -384,6 +384,10 @@ func (p *Path) helpCallback(b *Backend) OperationFunc {
vaultVersion = env.VaultVersion
}
}
redactVersion, _, _, _ := logical.CtxRedactionSettingsValue(ctx)
if redactVersion {
vaultVersion = ""
}
doc := NewOASDocument(vaultVersion)
if err := documentPath(p, b, requestResponsePrefix, doc); err != nil {
b.Logger().Warn("error generating OpenAPI", "error", err)

View File

@ -5259,8 +5259,14 @@ func (b *SystemBackend) pathInternalOpenAPI(ctx context.Context, req *logical.Re
context := d.Get("context").(string)
vaultVersion := version.Version
redactVersion, _, _, _ := logical.CtxRedactionSettingsValue(ctx)
if redactVersion {
vaultVersion = ""
}
// Set up target document
doc := framework.NewOASDocument(version.Version)
doc := framework.NewOASDocument(vaultVersion)
// Generic mount paths will primarily be used for code generation purposes.
// This will result in parameterized mount paths being returned instead of