diff --git a/changelog/14229.txt b/changelog/14229.txt new file mode 100644 index 000000000..5fa7a2d23 --- /dev/null +++ b/changelog/14229.txt @@ -0,0 +1,4 @@ +```release-note:change +core: Vault version has been moved out of sdk and into main vault module. +Plugins using sdk/useragent.String must instead use sdk/useragent.PluginString. +``` diff --git a/command/agent.go b/command/agent.go index f9ebf1c7c..0edd96eb9 100644 --- a/command/agent.go +++ b/command/agent.go @@ -45,12 +45,12 @@ import ( "github.com/hashicorp/vault/command/agent/winsvc" "github.com/hashicorp/vault/helper/logging" "github.com/hashicorp/vault/helper/metricsutil" + "github.com/hashicorp/vault/helper/useragent" "github.com/hashicorp/vault/internalshared/configutil" "github.com/hashicorp/vault/internalshared/listenerutil" "github.com/hashicorp/vault/sdk/helper/consts" - "github.com/hashicorp/vault/sdk/helper/useragent" "github.com/hashicorp/vault/sdk/logical" - "github.com/hashicorp/vault/sdk/version" + "github.com/hashicorp/vault/version" "github.com/kr/pretty" "github.com/mitchellh/cli" "github.com/oklog/run" diff --git a/command/agent/auth/azure/azure.go b/command/agent/auth/azure/azure.go index 528e82ffe..5554e72c2 100644 --- a/command/agent/auth/azure/azure.go +++ b/command/agent/auth/azure/azure.go @@ -11,8 +11,8 @@ import ( hclog "github.com/hashicorp/go-hclog" "github.com/hashicorp/vault/api" "github.com/hashicorp/vault/command/agent/auth" + "github.com/hashicorp/vault/helper/useragent" "github.com/hashicorp/vault/sdk/helper/jsonutil" - "github.com/hashicorp/vault/sdk/helper/useragent" ) const ( diff --git a/command/commands.go b/command/commands.go index 256c22ae8..35465ef81 100644 --- a/command/commands.go +++ b/command/commands.go @@ -9,7 +9,7 @@ import ( "github.com/hashicorp/vault/builtin/plugin" "github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/physical" - "github.com/hashicorp/vault/sdk/version" + "github.com/hashicorp/vault/version" "github.com/mitchellh/cli" /* diff --git a/command/debug.go b/command/debug.go index 71e1a97c8..1ea276901 100644 --- a/command/debug.go +++ b/command/debug.go @@ -21,7 +21,7 @@ import ( "github.com/hashicorp/vault/helper/osutil" "github.com/hashicorp/vault/sdk/helper/jsonutil" "github.com/hashicorp/vault/sdk/helper/logging" - "github.com/hashicorp/vault/sdk/version" + "github.com/hashicorp/vault/version" "github.com/mholt/archiver/v3" "github.com/mitchellh/cli" "github.com/oklog/run" diff --git a/command/operator_diagnose.go b/command/operator_diagnose.go index df5af11d9..0bfe512d8 100644 --- a/command/operator_diagnose.go +++ b/command/operator_diagnose.go @@ -28,12 +28,12 @@ import ( physconsul "github.com/hashicorp/vault/physical/consul" "github.com/hashicorp/vault/physical/raft" "github.com/hashicorp/vault/sdk/physical" - "github.com/hashicorp/vault/sdk/version" sr "github.com/hashicorp/vault/serviceregistration" srconsul "github.com/hashicorp/vault/serviceregistration/consul" "github.com/hashicorp/vault/vault" "github.com/hashicorp/vault/vault/diagnose" "github.com/hashicorp/vault/vault/hcp_link" + "github.com/hashicorp/vault/version" "github.com/mitchellh/cli" "github.com/posener/complete" ) diff --git a/command/server.go b/command/server.go index 7f6a34b43..9f070a6c0 100644 --- a/command/server.go +++ b/command/server.go @@ -39,20 +39,20 @@ import ( loghelper "github.com/hashicorp/vault/helper/logging" "github.com/hashicorp/vault/helper/metricsutil" "github.com/hashicorp/vault/helper/namespace" + "github.com/hashicorp/vault/helper/useragent" vaulthttp "github.com/hashicorp/vault/http" "github.com/hashicorp/vault/internalshared/configutil" "github.com/hashicorp/vault/internalshared/listenerutil" "github.com/hashicorp/vault/sdk/helper/consts" "github.com/hashicorp/vault/sdk/helper/jsonutil" "github.com/hashicorp/vault/sdk/helper/strutil" - "github.com/hashicorp/vault/sdk/helper/useragent" "github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/physical" - "github.com/hashicorp/vault/sdk/version" sr "github.com/hashicorp/vault/serviceregistration" "github.com/hashicorp/vault/vault" "github.com/hashicorp/vault/vault/hcp_link" vaultseal "github.com/hashicorp/vault/vault/seal" + "github.com/hashicorp/vault/version" "github.com/mitchellh/cli" "github.com/mitchellh/go-testing-interface" "github.com/pkg/errors" diff --git a/command/version.go b/command/version.go index ad366601b..5e5503ba8 100644 --- a/command/version.go +++ b/command/version.go @@ -3,7 +3,7 @@ package command import ( "strings" - "github.com/hashicorp/vault/sdk/version" + "github.com/hashicorp/vault/version" "github.com/mitchellh/cli" "github.com/posener/complete" ) diff --git a/command/version_history_test.go b/command/version_history_test.go index ba02626a4..69bd56788 100644 --- a/command/version_history_test.go +++ b/command/version_history_test.go @@ -6,7 +6,7 @@ import ( "strings" "testing" - "github.com/hashicorp/vault/sdk/version" + "github.com/hashicorp/vault/version" "github.com/mitchellh/cli" ) diff --git a/command/version_test.go b/command/version_test.go index b952cef01..0f59e9ffc 100644 --- a/command/version_test.go +++ b/command/version_test.go @@ -4,7 +4,7 @@ import ( "strings" "testing" - "github.com/hashicorp/vault/sdk/version" + "github.com/hashicorp/vault/version" "github.com/mitchellh/cli" ) diff --git a/helper/useragent/useragent.go b/helper/useragent/useragent.go new file mode 100644 index 000000000..b2fa40a30 --- /dev/null +++ b/helper/useragent/useragent.go @@ -0,0 +1,31 @@ +package useragent + +import ( + "fmt" + "runtime" + + "github.com/hashicorp/vault/version" +) + +var ( + // projectURL is the project URL. + projectURL = "https://www.vaultproject.io/" + + // rt is the runtime - variable for tests. + rt = runtime.Version() + + // versionFunc is the func that returns the current version. This is a + // function to take into account the different build processes and distinguish + // between enterprise and oss builds. + versionFunc = func() string { + return version.GetVersion().VersionNumber() + } +) + +// String returns the consistent user-agent string for Vault. +// +// e.g. Vault/0.10.4 (+https://www.vaultproject.io/; go1.10.1) +func String() string { + return fmt.Sprintf("Vault/%s (+%s; %s)", + versionFunc(), projectURL, rt) +} diff --git a/helper/useragent/useragent_test.go b/helper/useragent/useragent_test.go new file mode 100644 index 000000000..cb0cf3294 --- /dev/null +++ b/helper/useragent/useragent_test.go @@ -0,0 +1,18 @@ +package useragent + +import ( + "testing" +) + +func TestUserAgent(t *testing.T) { + projectURL = "https://vault-test.com" + rt = "go5.0" + versionFunc = func() string { return "1.2.3" } + + act := String() + + exp := "Vault/1.2.3 (+https://vault-test.com; go5.0)" + if exp != act { + t.Errorf("expected %q to be %q", act, exp) + } +} diff --git a/helper/versions/version.go b/helper/versions/version.go index 6bbd18698..b64dd3d26 100644 --- a/helper/versions/version.go +++ b/helper/versions/version.go @@ -8,7 +8,7 @@ import ( semver "github.com/hashicorp/go-version" "github.com/hashicorp/vault/sdk/helper/consts" - "github.com/hashicorp/vault/sdk/version" + "github.com/hashicorp/vault/version" ) const ( diff --git a/http/sys_health.go b/http/sys_health.go index fcaf4e159..a1f2bb8bd 100644 --- a/http/sys_health.go +++ b/http/sys_health.go @@ -10,8 +10,8 @@ import ( "github.com/hashicorp/go-secure-stdlib/parseutil" "github.com/hashicorp/vault/sdk/helper/consts" - "github.com/hashicorp/vault/sdk/version" "github.com/hashicorp/vault/vault" + "github.com/hashicorp/vault/version" ) func handleSysHealth(core *vault.Core) http.Handler { diff --git a/http/sys_seal_test.go b/http/sys_seal_test.go index c2e39ed16..26796d02c 100644 --- a/http/sys_seal_test.go +++ b/http/sys_seal_test.go @@ -14,9 +14,9 @@ import ( "github.com/go-test/deep" "github.com/hashicorp/vault/helper/namespace" "github.com/hashicorp/vault/sdk/logical" - "github.com/hashicorp/vault/sdk/version" "github.com/hashicorp/vault/vault" "github.com/hashicorp/vault/vault/seal" + "github.com/hashicorp/vault/version" ) func TestSysSealStatus(t *testing.T) { diff --git a/physical/gcs/gcs.go b/physical/gcs/gcs.go index f38ffa53d..b5d1f6b9f 100644 --- a/physical/gcs/gcs.go +++ b/physical/gcs/gcs.go @@ -12,13 +12,12 @@ import ( "strings" "time" + "cloud.google.com/go/storage" metrics "github.com/armon/go-metrics" log "github.com/hashicorp/go-hclog" multierror "github.com/hashicorp/go-multierror" - "github.com/hashicorp/vault/sdk/helper/useragent" + "github.com/hashicorp/vault/helper/useragent" "github.com/hashicorp/vault/sdk/physical" - - "cloud.google.com/go/storage" "google.golang.org/api/iterator" "google.golang.org/api/option" ) diff --git a/physical/raft/raft.go b/physical/raft/raft.go index 78f01834e..eaf341555 100644 --- a/physical/raft/raft.go +++ b/physical/raft/raft.go @@ -31,9 +31,9 @@ import ( "github.com/hashicorp/vault/sdk/helper/jsonutil" "github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/physical" - "github.com/hashicorp/vault/sdk/version" "github.com/hashicorp/vault/vault/cluster" "github.com/hashicorp/vault/vault/seal" + "github.com/hashicorp/vault/version" bolt "go.etcd.io/bbolt" ) diff --git a/physical/spanner/spanner.go b/physical/spanner/spanner.go index 09634da53..723b78819 100644 --- a/physical/spanner/spanner.go +++ b/physical/spanner/spanner.go @@ -9,17 +9,16 @@ import ( "strings" "time" + "cloud.google.com/go/spanner" metrics "github.com/armon/go-metrics" log "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-secure-stdlib/strutil" - "github.com/hashicorp/vault/sdk/helper/useragent" + "github.com/hashicorp/vault/helper/useragent" "github.com/hashicorp/vault/sdk/physical" + "github.com/pkg/errors" "google.golang.org/api/iterator" "google.golang.org/api/option" "google.golang.org/grpc/codes" - - "cloud.google.com/go/spanner" - "github.com/pkg/errors" ) // Verify Backend satisfies the correct interfaces diff --git a/scripts/build.sh b/scripts/build.sh index c041e0574..5ee2ecc74 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -40,7 +40,7 @@ mkdir -p bin/ echo "==> Building..." ${GO_CMD} build \ -gcflags "${GCFLAGS}" \ - -ldflags "${LD_FLAGS} -X github.com/hashicorp/vault/sdk/version.GitCommit='${GIT_COMMIT}${GIT_DIRTY}' -X github.com/hashicorp/vault/sdk/version.BuildDate=${BUILD_DATE}" \ + -ldflags "${LD_FLAGS} -X github.com/hashicorp/vault/version.GitCommit='${GIT_COMMIT}${GIT_DIRTY}' -X github.com/hashicorp/vault/version.BuildDate=${BUILD_DATE}" \ -o "bin/vault" \ -tags "${BUILD_TAGS}" \ . diff --git a/scripts/crt-builder.sh b/scripts/crt-builder.sh index f69797efc..3747b8131 100755 --- a/scripts/crt-builder.sh +++ b/scripts/crt-builder.sh @@ -39,7 +39,7 @@ function version_base() { return fi - : "${VERSION_FILE:=$(repo_root)/sdk/version/version_base.go}" + : "${VERSION_FILE:=$(repo_root)/version/version_base.go}" awk '$1 == "Version" && $2 == "=" { gsub(/"/, "", $3); print $3 }' < "$VERSION_FILE" } @@ -52,7 +52,7 @@ function version_pre() { return fi - : "${VERSION_FILE:=$(repo_root)/sdk/version/version_base.go}" + : "${VERSION_FILE:=$(repo_root)/version/version_base.go}" awk '$1 == "VersionPrerelease" && $2 == "=" { gsub(/"/, "", $3); print $3 }' < "$VERSION_FILE" } @@ -65,7 +65,7 @@ function version_metadata() { return fi - : "${VERSION_FILE:=$(repo_root)/sdk/version/version_base.go}" + : "${VERSION_FILE:=$(repo_root)/version/version_base.go}" awk '$1 == "VersionMetadata" && $2 == "=" { gsub(/"/, "", $3); print $3 }' < "$VERSION_FILE" } @@ -144,16 +144,16 @@ function build() { ldflags="-s -w " fi - ldflags="${ldflags}-X github.com/hashicorp/vault/sdk/version.Version=$version -X github.com/hashicorp/vault/sdk/version.GitCommit=$revision -X github.com/hashicorp/vault/sdk/version.BuildDate=$build_date" + ldflags="${ldflags}-X github.com/hashicorp/vault/version.Version=$version -X github.com/hashicorp/vault/version.GitCommit=$revision -X github.com/hashicorp/vault/version.BuildDate=$build_date" if [ -n "$prerelease" ]; then msg="${msg}, prerelease ${prerelease}" - ldflags="${ldflags} -X github.com/hashicorp/vault/sdk/version.VersionPrerelease=$prerelease" + ldflags="${ldflags} -X github.com/hashicorp/vault/version.VersionPrerelease=$prerelease" fi if [ -n "$metadata" ]; then msg="${msg}, metadata ${VAULT_METADATA}" - ldflags="${ldflags} -X github.com/hashicorp/vault/sdk/version.VersionMetadata=$metadata" + ldflags="${ldflags} -X github.com/hashicorp/vault/version.VersionMetadata=$metadata" fi # Build vault diff --git a/scripts/windows/build.bat b/scripts/windows/build.bat index 1452911e5..79e27605a 100644 --- a/scripts/windows/build.bat +++ b/scripts/windows/build.bat @@ -63,7 +63,7 @@ del /f "%_GO_ENV_TMP_FILE%" 2>nul REM Build! echo ==^> Building... go build^ - -ldflags "-X github.com/hashicorp/vault/sdk/version.GitCommit=%_GIT_COMMIT%%_GIT_DIRTY% -X github.com/hashicorp/vault/sdk/version.BuildDate=%_BUILD_DATE%"^ + -ldflags "-X github.com/hashicorp/vault/version.GitCommit=%_GIT_COMMIT%%_GIT_DIRTY% -X github.com/hashicorp/vault/version.BuildDate=%_BUILD_DATE%"^ -o "bin/vault.exe"^ . diff --git a/sdk/database/dbplugin/v5/plugin_client_test.go b/sdk/database/dbplugin/v5/plugin_client_test.go index f41ecf8ef..903cec65d 100644 --- a/sdk/database/dbplugin/v5/plugin_client_test.go +++ b/sdk/database/dbplugin/v5/plugin_client_test.go @@ -135,6 +135,10 @@ type mockRunnerUtil struct { mock.Mock } +func (m *mockRunnerUtil) VaultVersion(ctx context.Context) (string, error) { + return "dummyversion", nil +} + func (m *mockRunnerUtil) NewPluginClient(ctx context.Context, config pluginutil.PluginClientConfig) (pluginutil.PluginClient, error) { args := m.Called(ctx, config) return args.Get(0).(pluginutil.PluginClient), args.Error(1) diff --git a/sdk/database/dbplugin/v5/plugin_factory.go b/sdk/database/dbplugin/v5/plugin_factory.go index f68cc5621..649f0f3fc 100644 --- a/sdk/database/dbplugin/v5/plugin_factory.go +++ b/sdk/database/dbplugin/v5/plugin_factory.go @@ -55,6 +55,7 @@ func PluginFactoryVersion(ctx context.Context, pluginName string, pluginVersion Logger: namedLogger, IsMetadataMode: false, AutoMTLS: true, + Wrapper: sys, } // create a DatabasePluginClient instance db, err = NewPluginClient(ctx, sys, config) diff --git a/sdk/framework/backend.go b/sdk/framework/backend.go index 73d8f14e6..33c965e26 100644 --- a/sdk/framework/backend.go +++ b/sdk/framework/backend.go @@ -547,7 +547,16 @@ func (b *Backend) handleRootHelp(req *logical.Request) (*logical.Response, error genericMountPaths, _ := req.Get("genericMountPaths").(bool) // Build OpenAPI response for the entire backend - doc := NewOASDocument() + vaultVersion := "unknown" + if b.System() != nil { + env, err := b.System().PluginEnv(context.Background()) + if err != nil { + return nil, err + } + vaultVersion = env.VaultVersion + } + + doc := NewOASDocument(vaultVersion) if err := documentPaths(b, requestResponsePrefix, genericMountPaths, doc); err != nil { b.Logger().Warn("error generating OpenAPI", "error", err) } diff --git a/sdk/framework/openapi.go b/sdk/framework/openapi.go index 59515e335..8ea820631 100644 --- a/sdk/framework/openapi.go +++ b/sdk/framework/openapi.go @@ -11,7 +11,6 @@ import ( log "github.com/hashicorp/go-hclog" "github.com/hashicorp/vault/sdk/helper/wrapping" "github.com/hashicorp/vault/sdk/logical" - "github.com/hashicorp/vault/sdk/version" "github.com/mitchellh/mapstructure" "golang.org/x/text/cases" "golang.org/x/text/language" @@ -21,13 +20,13 @@ import ( const OASVersion = "3.0.2" // NewOASDocument returns an empty OpenAPI document. -func NewOASDocument() *OASDocument { +func NewOASDocument(version string) *OASDocument { return &OASDocument{ Version: OASVersion, Info: OASInfo{ Title: "HashiCorp Vault API", Description: "HTTP API that gives you full access to Vault. All API routes are prefixed with `/v1/`.", - Version: version.GetVersion().Version, + Version: version, License: OASLicense{ Name: "Mozilla Public License 2.0", URL: "https://www.mozilla.org/en-US/MPL/2.0", diff --git a/sdk/framework/openapi_test.go b/sdk/framework/openapi_test.go index a21e139c1..47b445271 100644 --- a/sdk/framework/openapi_test.go +++ b/sdk/framework/openapi_test.go @@ -15,7 +15,6 @@ import ( "github.com/hashicorp/vault/sdk/helper/jsonutil" "github.com/hashicorp/vault/sdk/helper/wrapping" "github.com/hashicorp/vault/sdk/logical" - "github.com/hashicorp/vault/sdk/version" ) func TestOpenAPI_Regex(t *testing.T) { @@ -263,7 +262,7 @@ func TestOpenAPI_SpecialPaths(t *testing.T) { {"foo/bar", []string{"a", "b", "foo/*"}, true, []string{"foo/baz/*"}, false}, } for i, test := range tests { - doc := NewOASDocument() + doc := NewOASDocument("version") path := Path{ Pattern: test.pattern, } @@ -528,7 +527,7 @@ func TestOpenAPI_OperationID(t *testing.T) { } for _, context := range []string{"", "bar"} { - doc := NewOASDocument() + doc := NewOASDocument("version") err := documentPath(path1, nil, "kv", false, logical.TypeLogical, doc) if err != nil { t.Fatal(err) @@ -592,7 +591,7 @@ func TestOpenAPI_CustomDecoder(t *testing.T) { }, } - docOrig := NewOASDocument() + docOrig := NewOASDocument("version") err := documentPath(p, nil, "kv", false, logical.TypeLogical, docOrig) if err != nil { t.Fatal(err) @@ -655,7 +654,7 @@ func TestOpenAPI_CleanResponse(t *testing.T) { func testPath(t *testing.T, path *Path, sp *logical.Paths, expectedJSON string) { t.Helper() - doc := NewOASDocument() + doc := NewOASDocument("dummyversion") if err := documentPath(path, sp, "kv", false, logical.TypeLogical, doc); err != nil { t.Fatal(err) } @@ -701,7 +700,7 @@ func expected(name string) string { panic(err) } - content := strings.Replace(string(data), "", version.GetVersion().Version, 1) + content := strings.Replace(string(data), "", "dummyversion", 1) return content } diff --git a/sdk/framework/path.go b/sdk/framework/path.go index 16dec52e1..c3cf385cd 100644 --- a/sdk/framework/path.go +++ b/sdk/framework/path.go @@ -317,7 +317,19 @@ func (p *Path) helpCallback(b *Backend) OperationFunc { } // Build OpenAPI response for this path - doc := NewOASDocument() + vaultVersion := "unknown" + if b.System() != nil { + // b.System() should always be non-nil, except tests might create a + // Backend without one. + env, err := b.System().PluginEnv(context.Background()) + if err != nil { + return nil, err + } + if env != nil { + vaultVersion = env.VaultVersion + } + } + doc := NewOASDocument(vaultVersion) if err := documentPath(p, b.SpecialPaths(), requestResponsePrefix, false, b.BackendType, doc); err != nil { b.Logger().Warn("error generating OpenAPI", "error", err) } diff --git a/sdk/helper/pluginutil/run_config.go b/sdk/helper/pluginutil/run_config.go index 3eb8fb2b2..f344ca979 100644 --- a/sdk/helper/pluginutil/run_config.go +++ b/sdk/helper/pluginutil/run_config.go @@ -10,7 +10,6 @@ import ( log "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-plugin" "github.com/hashicorp/vault/sdk/helper/consts" - "github.com/hashicorp/vault/sdk/version" ) type PluginClientConfig struct { @@ -46,7 +45,11 @@ func (rc runConfig) makeConfig(ctx context.Context) (*plugin.ClientConfig, error if rc.MLock || (rc.Wrapper != nil && rc.Wrapper.MlockEnabled()) { cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginMlockEnabled, "true")) } - cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version)) + version, err := rc.Wrapper.VaultVersion(ctx) + if err != nil { + return nil, err + } + cmd.Env = append(cmd.Env, fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version)) if rc.IsMetadataMode { rc.Logger = rc.Logger.With("metadata", "true") diff --git a/sdk/helper/pluginutil/run_config_test.go b/sdk/helper/pluginutil/run_config_test.go index 3c2fef219..b817ef955 100644 --- a/sdk/helper/pluginutil/run_config_test.go +++ b/sdk/helper/pluginutil/run_config_test.go @@ -7,8 +7,6 @@ import ( "testing" "time" - "github.com/hashicorp/vault/sdk/version" - "github.com/hashicorp/go-hclog" "github.com/hashicorp/go-plugin" "github.com/hashicorp/vault/sdk/helper/wrapping" @@ -76,7 +74,7 @@ func TestMakeConfig(t *testing.T) { []string{"foo", "bar"}, []string{ "initial=true", - fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version), + fmt.Sprintf("%s=%s", PluginVaultVersionEnv, "dummyversion"), fmt.Sprintf("%s=%t", PluginMetadataModeEnv, true), fmt.Sprintf("%s=%t", PluginAutoMTLSEnv, false), }, @@ -142,7 +140,7 @@ func TestMakeConfig(t *testing.T) { []string{ "initial=true", fmt.Sprintf("%s=%t", PluginMlockEnabled, true), - fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version), + fmt.Sprintf("%s=%s", PluginVaultVersionEnv, "dummyversion"), fmt.Sprintf("%s=%t", PluginMetadataModeEnv, false), fmt.Sprintf("%s=%t", PluginAutoMTLSEnv, false), fmt.Sprintf("%s=%s", PluginUnwrapTokenEnv, "testtoken"), @@ -205,7 +203,7 @@ func TestMakeConfig(t *testing.T) { []string{"foo", "bar"}, []string{ "initial=true", - fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version), + fmt.Sprintf("%s=%s", PluginVaultVersionEnv, "dummyversion"), fmt.Sprintf("%s=%t", PluginMetadataModeEnv, true), fmt.Sprintf("%s=%t", PluginAutoMTLSEnv, true), }, @@ -267,7 +265,7 @@ func TestMakeConfig(t *testing.T) { []string{"foo", "bar"}, []string{ "initial=true", - fmt.Sprintf("%s=%s", PluginVaultVersionEnv, version.GetVersion().Version), + fmt.Sprintf("%s=%s", PluginVaultVersionEnv, "dummyversion"), fmt.Sprintf("%s=%t", PluginMetadataModeEnv, false), fmt.Sprintf("%s=%t", PluginAutoMTLSEnv, true), }, @@ -339,6 +337,10 @@ type mockRunnerUtil struct { mock.Mock } +func (m *mockRunnerUtil) VaultVersion(ctx context.Context) (string, error) { + return "dummyversion", nil +} + func (m *mockRunnerUtil) NewPluginClient(ctx context.Context, config PluginClientConfig) (PluginClient, error) { args := m.Called(ctx, config) return args.Get(0).(PluginClient), args.Error(1) diff --git a/sdk/helper/pluginutil/runner.go b/sdk/helper/pluginutil/runner.go index 631c4f3a2..886efe21f 100644 --- a/sdk/helper/pluginutil/runner.go +++ b/sdk/helper/pluginutil/runner.go @@ -27,6 +27,7 @@ type RunnerUtil interface { NewPluginClient(ctx context.Context, config PluginClientConfig) (PluginClient, error) ResponseWrapData(ctx context.Context, data map[string]interface{}, ttl time.Duration, jwt bool) (*wrapping.ResponseWrapInfo, error) MlockEnabled() bool + VaultVersion(ctx context.Context) (string, error) } // LookRunnerUtil defines the functions for both Looker and Wrapper diff --git a/sdk/helper/useragent/useragent.go b/sdk/helper/useragent/useragent.go index e7e23ac2b..33b2a23b8 100644 --- a/sdk/helper/useragent/useragent.go +++ b/sdk/helper/useragent/useragent.go @@ -31,6 +31,15 @@ var ( // Given comments will be appended to the semicolon-delimited comment section. // // e.g. Vault/0.10.4 (+https://www.vaultproject.io/; go1.10.1; comment-0; comment-1) +// +// Deprecated: use PluginString instead. +// At one point the user-agent string returned contained the Vault +// version hardcoded into the vault/sdk/version/ package. This works for builtin +// plugins that are compiled into the `vault` binary, in that it correctly described +// the version of that Vault binary. It does not work for external plugins: for them, +// the version will be based on the version stored in the sdk based on the +// contents of the external plugin's go.mod. Now that we're no longer updating +// the version in vault/sdk/version/, it is even less meaningful than ever. func String(comments ...string) string { c := append([]string{"+" + projectURL, rt}, comments...) return fmt.Sprintf("Vault/%s (%s)", versionFunc(), strings.Join(c, "; ")) diff --git a/sdk/logical/system_view.go b/sdk/logical/system_view.go index 4e5627b1c..fc7f30a7f 100644 --- a/sdk/logical/system_view.go +++ b/sdk/logical/system_view.go @@ -83,6 +83,9 @@ type SystemView interface { // PluginEnv returns Vault environment information used by plugins PluginEnv(context.Context) (*PluginEnvironment, error) + // VaultVersion returns the version string for the currently running Vault. + VaultVersion(context.Context) (string, error) + // GeneratePasswordFromPolicy generates a password from the policy referenced. // If the policy does not exist, this will return an error. GeneratePasswordFromPolicy(ctx context.Context, policyName string) (password string, err error) @@ -113,9 +116,9 @@ type StaticSystemView struct { EntityVal *Entity GroupsVal []*Group Features license.Features - VaultVersion string PluginEnvironment *PluginEnvironment PasswordPolicies map[string]PasswordGenerator + VersionString string } type noopAuditor struct{} @@ -204,6 +207,10 @@ func (d StaticSystemView) PluginEnv(_ context.Context) (*PluginEnvironment, erro return d.PluginEnvironment, nil } +func (d StaticSystemView) VaultVersion(_ context.Context) (string, error) { + return d.VersionString, nil +} + func (d StaticSystemView) GeneratePasswordFromPolicy(ctx context.Context, policyName string) (password string, err error) { select { case <-ctx.Done(): diff --git a/sdk/logical/testing.go b/sdk/logical/testing.go index 765f09826..8cb41e2e7 100644 --- a/sdk/logical/testing.go +++ b/sdk/logical/testing.go @@ -73,6 +73,7 @@ func TestSystemView() *StaticSystemView { return &StaticSystemView{ DefaultLeaseTTLVal: defaultLeaseTTLVal, MaxLeaseTTLVal: maxLeaseTTLVal, + VersionString: "testVersionString", } } diff --git a/sdk/plugin/grpc_system.go b/sdk/plugin/grpc_system.go index 5ab680a5d..f6cbe6001 100644 --- a/sdk/plugin/grpc_system.go +++ b/sdk/plugin/grpc_system.go @@ -26,6 +26,8 @@ func newGRPCSystemView(conn *grpc.ClientConn) *gRPCSystemViewClient { } } +var _ logical.SystemView = &gRPCSystemViewClient{} + type gRPCSystemViewClient struct { client pb.SystemViewClient } @@ -177,6 +179,15 @@ func (s *gRPCSystemViewClient) PluginEnv(ctx context.Context) (*logical.PluginEn return reply.PluginEnvironment, nil } +func (s *gRPCSystemViewClient) VaultVersion(ctx context.Context) (string, error) { + reply, err := s.client.PluginEnv(ctx, &pb.Empty{}) + if err != nil { + return "", err + } + + return reply.PluginEnvironment.VaultVersion, nil +} + func (s *gRPCSystemViewClient) GeneratePasswordFromPolicy(ctx context.Context, policyName string) (password string, err error) { req := &pb.GeneratePasswordFromPolicyRequest{ PolicyName: policyName, diff --git a/vault/core.go b/vault/core.go index b3808096c..0d24ef84e 100644 --- a/vault/core.go +++ b/vault/core.go @@ -49,12 +49,12 @@ import ( "github.com/hashicorp/vault/sdk/helper/logging" "github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/physical" - "github.com/hashicorp/vault/sdk/version" sr "github.com/hashicorp/vault/serviceregistration" "github.com/hashicorp/vault/shamir" "github.com/hashicorp/vault/vault/cluster" "github.com/hashicorp/vault/vault/quotas" vaultseal "github.com/hashicorp/vault/vault/seal" + "github.com/hashicorp/vault/version" "github.com/patrickmn/go-cache" uberAtomic "go.uber.org/atomic" "google.golang.org/grpc" diff --git a/vault/core_test.go b/vault/core_test.go index 1dc93c031..3789c6853 100644 --- a/vault/core_test.go +++ b/vault/core_test.go @@ -20,7 +20,7 @@ import ( "github.com/hashicorp/vault/sdk/logical" "github.com/hashicorp/vault/sdk/physical" "github.com/hashicorp/vault/sdk/physical/inmem" - "github.com/hashicorp/vault/sdk/version" + "github.com/hashicorp/vault/version" ) // invalidKey is used to test Unseal diff --git a/vault/dynamic_system_view.go b/vault/dynamic_system_view.go index f87089e7b..de55f4ed0 100644 --- a/vault/dynamic_system_view.go +++ b/vault/dynamic_system_view.go @@ -13,7 +13,7 @@ import ( "github.com/hashicorp/vault/sdk/helper/pluginutil" "github.com/hashicorp/vault/sdk/helper/wrapping" "github.com/hashicorp/vault/sdk/logical" - "github.com/hashicorp/vault/sdk/version" + "github.com/hashicorp/vault/version" ) type ctxKeyForwardedRequestMountAccessor struct{} @@ -381,6 +381,10 @@ func (d dynamicSystemView) PluginEnv(_ context.Context) (*logical.PluginEnvironm }, nil } +func (d dynamicSystemView) VaultVersion(_ context.Context) (string, error) { + return version.GetVersion().Version, nil +} + func (d dynamicSystemView) GeneratePasswordFromPolicy(ctx context.Context, policyName string) (password string, err error) { if policyName == "" { return "", fmt.Errorf("missing password policy name") diff --git a/vault/external_tests/raft/raft_autopilot_test.go b/vault/external_tests/raft/raft_autopilot_test.go index cc8822130..731393ca9 100644 --- a/vault/external_tests/raft/raft_autopilot_test.go +++ b/vault/external_tests/raft/raft_autopilot_test.go @@ -16,8 +16,8 @@ import ( "github.com/hashicorp/vault/helper/testhelpers" "github.com/hashicorp/vault/helper/testhelpers/teststorage" "github.com/hashicorp/vault/physical/raft" - "github.com/hashicorp/vault/sdk/version" "github.com/hashicorp/vault/vault" + "github.com/hashicorp/vault/version" "github.com/kr/pretty" testingintf "github.com/mitchellh/go-testing-interface" "github.com/stretchr/testify/require" diff --git a/vault/logical_system.go b/vault/logical_system.go index 994d4989c..961c30a9e 100644 --- a/vault/logical_system.go +++ b/vault/logical_system.go @@ -41,7 +41,7 @@ import ( "github.com/hashicorp/vault/sdk/helper/pluginutil" "github.com/hashicorp/vault/sdk/helper/wrapping" "github.com/hashicorp/vault/sdk/logical" - "github.com/hashicorp/vault/sdk/version" + "github.com/hashicorp/vault/version" "github.com/mitchellh/mapstructure" "golang.org/x/crypto/sha3" ) @@ -4438,7 +4438,7 @@ func (b *SystemBackend) pathInternalOpenAPI(ctx context.Context, req *logical.Re // Set up target document and convert to map[string]interface{} which is what will // be received from plugin backends. - doc := framework.NewOASDocument() + doc := framework.NewOASDocument(version.Version) genericMountPaths, _ := d.Get("generic_mount_paths").(bool) diff --git a/vault/logical_system_integ_test.go b/vault/logical_system_integ_test.go index c04ccbf6b..db3598778 100644 --- a/vault/logical_system_integ_test.go +++ b/vault/logical_system_integ_test.go @@ -12,8 +12,8 @@ import ( "github.com/hashicorp/vault/sdk/helper/logging" "github.com/hashicorp/vault/sdk/physical" "github.com/hashicorp/vault/sdk/physical/inmem" - "github.com/hashicorp/vault/sdk/version" "github.com/hashicorp/vault/vault" + "github.com/hashicorp/vault/version" ) func TestSystemBackend_InternalUIResultantACL(t *testing.T) { diff --git a/vault/logical_system_test.go b/vault/logical_system_test.go index 182e0f4c2..e0e4dd50f 100644 --- a/vault/logical_system_test.go +++ b/vault/logical_system_test.go @@ -33,7 +33,7 @@ import ( "github.com/hashicorp/vault/sdk/helper/pluginutil" "github.com/hashicorp/vault/sdk/helper/salt" "github.com/hashicorp/vault/sdk/logical" - "github.com/hashicorp/vault/sdk/version" + "github.com/hashicorp/vault/version" "github.com/mitchellh/mapstructure" ) diff --git a/vault/plugin_catalog.go b/vault/plugin_catalog.go index dd92f591d..19e19ea75 100644 --- a/vault/plugin_catalog.go +++ b/vault/plugin_catalog.go @@ -24,6 +24,7 @@ import ( "github.com/hashicorp/vault/sdk/helper/pluginutil" "github.com/hashicorp/vault/sdk/logical" backendplugin "github.com/hashicorp/vault/sdk/plugin" + "github.com/hashicorp/vault/version" "google.golang.org/grpc" "google.golang.org/grpc/metadata" ) @@ -55,7 +56,8 @@ type PluginCatalog struct { externalPlugins map[externalPluginsKey]*externalPlugin mlockPlugins bool - lock sync.RWMutex + lock sync.RWMutex + wrapper pluginutil.RunnerUtil } // Only plugins running with identical PluginRunner config can be multiplexed, @@ -168,6 +170,7 @@ func (c *Core) setupPluginCatalog(ctx context.Context) error { directory: c.pluginDirectory, logger: c.logger, mlockPlugins: c.enableMlock, + wrapper: logical.StaticSystemView{VersionString: version.GetVersion().Version}, } // Run upgrade if untyped plugins exist @@ -461,6 +464,7 @@ func (c *PluginCatalog) getBackendPluginType(ctx context.Context, pluginRunner * Logger: log.NewNullLogger(), IsMetadataMode: false, AutoMTLS: true, + Wrapper: c.wrapper, } var client logical.Backend @@ -500,7 +504,7 @@ func (c *PluginCatalog) getBackendPluginType(ctx context.Context, pluginRunner * config.AutoMTLS = false config.IsMetadataMode = true // attempt to run as a v4 backend plugin - client, err = backendplugin.NewPluginClient(ctx, nil, pluginRunner, log.NewNullLogger(), true) + client, err = backendplugin.NewPluginClient(ctx, c.wrapper, pluginRunner, log.NewNullLogger(), true) if err != nil { merr = multierror.Append(merr, fmt.Errorf("failed to dispense v4 backend plugin: %w", err)) c.logger.Debug("failed to dispense v4 backend plugin", "name", pluginRunner.Name, "error", merr) @@ -550,6 +554,7 @@ func (c *PluginCatalog) getBackendRunningVersion(ctx context.Context, pluginRunn Logger: log.NewNullLogger(), IsMetadataMode: false, AutoMTLS: true, + Wrapper: c.wrapper, } var client logical.Backend @@ -590,7 +595,7 @@ func (c *PluginCatalog) getBackendRunningVersion(ctx context.Context, pluginRunn config.AutoMTLS = false config.IsMetadataMode = true // attempt to run as a v4 backend plugin - client, err = backendplugin.NewPluginClient(ctx, nil, pluginRunner, log.NewNullLogger(), true) + client, err = backendplugin.NewPluginClient(ctx, c.wrapper, pluginRunner, log.NewNullLogger(), true) if err != nil { merr = multierror.Append(merr, fmt.Errorf("failed to dispense v4 backend plugin: %w", err)) c.logger.Debug("failed to dispense v4 backend plugin", "name", pluginRunner.Name, "error", merr) @@ -621,6 +626,7 @@ func (c *PluginCatalog) getDatabaseRunningVersion(ctx context.Context, pluginRun Logger: log.Default(), IsMetadataMode: true, AutoMTLS: true, + Wrapper: c.wrapper, } // Attempt to run as database V5+ multiplexed plugin @@ -651,7 +657,7 @@ func (c *PluginCatalog) getDatabaseRunningVersion(ctx context.Context, pluginRun merr = multierror.Append(merr, fmt.Errorf("failed to load plugin as database v5: %w", err)) c.logger.Debug("attempting to load database plugin as v4", "name", pluginRunner.Name) - v4Client, err := v4.NewPluginClient(ctx, nil, pluginRunner, log.NewNullLogger(), true) + v4Client, err := v4.NewPluginClient(ctx, c.wrapper, pluginRunner, log.NewNullLogger(), true) if err == nil { // Close the client and cleanup the plugin process defer func() { @@ -683,6 +689,7 @@ func (c *PluginCatalog) isDatabasePlugin(ctx context.Context, pluginRunner *plug Logger: log.NewNullLogger(), IsMetadataMode: true, AutoMTLS: true, + Wrapper: c.wrapper, } // Attempt to run as database V5+ multiplexed plugin @@ -704,7 +711,7 @@ func (c *PluginCatalog) isDatabasePlugin(ctx context.Context, pluginRunner *plug merr = multierror.Append(merr, fmt.Errorf("failed to load plugin as database v5: %w", err)) c.logger.Debug("attempting to load database plugin as v4", "name", pluginRunner.Name) - v4Client, err := v4.NewPluginClient(ctx, nil, pluginRunner, log.NewNullLogger(), true) + v4Client, err := v4.NewPluginClient(ctx, c.wrapper, pluginRunner, log.NewNullLogger(), true) if err == nil { // Close the client and cleanup the plugin process err = v4Client.Close() diff --git a/vault/testing.go b/vault/testing.go index 8d46fb0e5..caede6a41 100644 --- a/vault/testing.go +++ b/vault/testing.go @@ -607,9 +607,9 @@ func TestRunTestPlugin(t testing.T, c *Core, pluginType consts.PluginType, plugi } func TestPluginClientConfig(c *Core, pluginType consts.PluginType, pluginName string) pluginutil.PluginClientConfig { + dsv := TestDynamicSystemView(c, nil) switch pluginType { case consts.PluginTypeCredential, consts.PluginTypeSecrets: - dsv := TestDynamicSystemView(c, nil) return pluginutil.PluginClientConfig{ Name: pluginName, PluginType: pluginType, @@ -629,6 +629,7 @@ func TestPluginClientConfig(c *Core, pluginType consts.PluginType, pluginName st Logger: log.NewNullLogger(), AutoMTLS: true, IsMetadataMode: false, + Wrapper: dsv, } } return pluginutil.PluginClientConfig{} diff --git a/vault/version_store_test.go b/vault/version_store_test.go index 823301c2b..f4b3ad13b 100644 --- a/vault/version_store_test.go +++ b/vault/version_store_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - "github.com/hashicorp/vault/sdk/version" + "github.com/hashicorp/vault/version" ) // TestVersionStore_StoreMultipleVaultVersions writes multiple versions of 1.9.0 and verifies that only diff --git a/version/cgo.go b/version/cgo.go new file mode 100644 index 000000000..5bc93e5bf --- /dev/null +++ b/version/cgo.go @@ -0,0 +1,7 @@ +//go:build cgo + +package version + +func init() { + CgoEnabled = true +} diff --git a/version/version.go b/version/version.go new file mode 100644 index 000000000..42f0c1a11 --- /dev/null +++ b/version/version.go @@ -0,0 +1,79 @@ +package version + +import ( + "bytes" + "fmt" +) + +type VersionInfo struct { + Revision string `json:"revision,omitempty"` + Version string `json:"version,omitempty"` + VersionPrerelease string `json:"version_prerelease,omitempty"` + VersionMetadata string `json:"version_metadata,omitempty"` + BuildDate string `json:"build_date,omitempty"` +} + +func GetVersion() *VersionInfo { + ver := Version + rel := VersionPrerelease + md := VersionMetadata + if GitDescribe != "" { + ver = GitDescribe + } + if GitDescribe == "" && rel == "" && VersionPrerelease != "" { + rel = "dev" + } + + return &VersionInfo{ + Revision: GitCommit, + Version: ver, + VersionPrerelease: rel, + VersionMetadata: md, + BuildDate: BuildDate, + } +} + +func (c *VersionInfo) VersionNumber() string { + if Version == "unknown" && VersionPrerelease == "unknown" { + return "(version unknown)" + } + + version := c.Version + + if c.VersionPrerelease != "" { + version = fmt.Sprintf("%s-%s", version, c.VersionPrerelease) + } + + if c.VersionMetadata != "" { + version = fmt.Sprintf("%s+%s", version, c.VersionMetadata) + } + + return version +} + +func (c *VersionInfo) FullVersionNumber(rev bool) string { + var versionString bytes.Buffer + + if Version == "unknown" && VersionPrerelease == "unknown" { + return "Vault (version unknown)" + } + + fmt.Fprintf(&versionString, "Vault v%s", c.Version) + if c.VersionPrerelease != "" { + fmt.Fprintf(&versionString, "-%s", c.VersionPrerelease) + } + + if c.VersionMetadata != "" { + fmt.Fprintf(&versionString, "+%s", c.VersionMetadata) + } + + if rev && c.Revision != "" { + fmt.Fprintf(&versionString, " (%s)", c.Revision) + } + + if c.BuildDate != "" { + fmt.Fprintf(&versionString, ", built %s", c.BuildDate) + } + + return versionString.String() +} diff --git a/version/version_base.go b/version/version_base.go new file mode 100644 index 000000000..e45626e2c --- /dev/null +++ b/version/version_base.go @@ -0,0 +1,17 @@ +package version + +var ( + // The git commit that was compiled. This will be filled in by the compiler. + GitCommit string + GitDescribe string + + // The compilation date. This will be filled in by the compiler. + BuildDate string + + // Whether cgo is enabled or not; set at build time + CgoEnabled bool + + Version = "1.13.0" + VersionPrerelease = "dev1" + VersionMetadata = "" +)