DBPW - Copy newdbplugin package to dbplugin/v5 (#10151)

This is part 1 of 4 for renaming the `newdbplugin` package. This copies the existing package to the new location but keeps the current one in place so we can migrate the existing references over more easily.
This commit is contained in:
Michael Golowka
2020-10-15 13:20:12 -06:00
committed by GitHub
parent 4ed4550d93
commit a69ee0f65a
73 changed files with 5539 additions and 894 deletions

View File

@@ -200,7 +200,7 @@ proto:
protoc helper/identity/mfa/types.proto --go_out=plugins=grpc,paths=source_relative:.
protoc helper/identity/types.proto --go_out=plugins=grpc,paths=source_relative:.
protoc sdk/database/dbplugin/*.proto --go_out=plugins=grpc,paths=source_relative:.
protoc sdk/database/newdbplugin/proto/*.proto --go_out=plugins=grpc,paths=source_relative:.
protoc sdk/database/dbplugin/v5/proto/*.proto --go_out=plugins=grpc,paths=source_relative:.
protoc sdk/plugin/pb/*.proto --go_out=plugins=grpc,paths=source_relative:.
sed -i -e 's/Id/ID/' vault/request_forwarding_service.pb.go
sed -i -e 's/Idp/IDP/' -e 's/Url/URL/' -e 's/Id/ID/' -e 's/IDentity/Identity/' -e 's/EntityId/EntityID/' -e 's/Api/API/' -e 's/Qr/QR/' -e 's/Totp/TOTP/' -e 's/Mfa/MFA/' -e 's/Pingid/PingID/' -e 's/protobuf:"/sentinel:"" protobuf:"/' -e 's/namespaceId/namespaceID/' -e 's/Ttl/TTL/' -e 's/BoundCidrs/BoundCIDRs/' helper/identity/types.pb.go helper/identity/mfa/types.pb.go helper/storagepacker/types.pb.go sdk/plugin/pb/backend.pb.go sdk/logical/identity.pb.go vault/activity/activity_log.pb.go

View File

@@ -11,9 +11,9 @@ import (
"github.com/hashicorp/errwrap"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/sdk/database/dbplugin"
v4 "github.com/hashicorp/vault/sdk/database/dbplugin"
v5 "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/locksutil"
"github.com/hashicorp/vault/sdk/helper/strutil"
@@ -193,7 +193,7 @@ func (b *databaseBackend) roleAtPath(ctx context.Context, s logical.Storage, rol
switch {
case upgradeCh.Statements != nil:
var stmts dbplugin.Statements
var stmts v4.Statements
if upgradeCh.Statements.CreationStatements != "" {
stmts.Creation = []string{upgradeCh.Statements.CreationStatements}
}
@@ -265,7 +265,7 @@ func (b *databaseBackend) GetConnectionWithConfig(ctx context.Context, name stri
return nil, fmt.Errorf("unable to create database instance: %w", err)
}
initReq := newdbplugin.InitializeRequest{
initReq := v5.InitializeRequest{
Config: config.ConnectionDetails,
VerifyConnection: true,
}
@@ -316,7 +316,7 @@ func (b *databaseBackend) clearConnection(name string) error {
func (b *databaseBackend) CloseIfShutdown(db *dbPluginInstance, err error) {
// Plugin has shutdown, close it so next call can reconnect.
switch err {
case rpc.ErrShutdown, dbplugin.ErrPluginShutdown:
case rpc.ErrShutdown, v4.ErrPluginShutdown:
// Put this in a goroutine so that requests can run with the read or write lock
// and simply defer the unlock. Since we are attaching the instance and matching
// the id in the connection map, we can safely do this.

View File

@@ -4,35 +4,35 @@ import (
"context"
"time"
"github.com/hashicorp/vault/sdk/database/dbplugin"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
v4 "github.com/hashicorp/vault/sdk/database/dbplugin"
v5 "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/stretchr/testify/mock"
)
var _ newdbplugin.Database = &mockNewDatabase{}
var _ v5.Database = &mockNewDatabase{}
type mockNewDatabase struct {
mock.Mock
}
func (m *mockNewDatabase) Initialize(ctx context.Context, req newdbplugin.InitializeRequest) (newdbplugin.InitializeResponse, error) {
func (m *mockNewDatabase) Initialize(ctx context.Context, req v5.InitializeRequest) (v5.InitializeResponse, error) {
args := m.Called(ctx, req)
return args.Get(0).(newdbplugin.InitializeResponse), args.Error(1)
return args.Get(0).(v5.InitializeResponse), args.Error(1)
}
func (m *mockNewDatabase) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (newdbplugin.NewUserResponse, error) {
func (m *mockNewDatabase) NewUser(ctx context.Context, req v5.NewUserRequest) (v5.NewUserResponse, error) {
args := m.Called(ctx, req)
return args.Get(0).(newdbplugin.NewUserResponse), args.Error(1)
return args.Get(0).(v5.NewUserResponse), args.Error(1)
}
func (m *mockNewDatabase) UpdateUser(ctx context.Context, req newdbplugin.UpdateUserRequest) (newdbplugin.UpdateUserResponse, error) {
func (m *mockNewDatabase) UpdateUser(ctx context.Context, req v5.UpdateUserRequest) (v5.UpdateUserResponse, error) {
args := m.Called(ctx, req)
return args.Get(0).(newdbplugin.UpdateUserResponse), args.Error(1)
return args.Get(0).(v5.UpdateUserResponse), args.Error(1)
}
func (m *mockNewDatabase) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserRequest) (newdbplugin.DeleteUserResponse, error) {
func (m *mockNewDatabase) DeleteUser(ctx context.Context, req v5.DeleteUserRequest) (v5.DeleteUserResponse, error) {
args := m.Called(ctx, req)
return args.Get(0).(newdbplugin.DeleteUserResponse), args.Error(1)
return args.Get(0).(v5.DeleteUserResponse), args.Error(1)
}
func (m *mockNewDatabase) Type() (string, error) {
@@ -45,23 +45,23 @@ func (m *mockNewDatabase) Close() error {
return args.Error(0)
}
var _ dbplugin.Database = &mockLegacyDatabase{}
var _ v4.Database = &mockLegacyDatabase{}
type mockLegacyDatabase struct {
mock.Mock
}
func (m *mockLegacyDatabase) CreateUser(ctx context.Context, statements dbplugin.Statements, usernameConfig dbplugin.UsernameConfig, expiration time.Time) (username string, password string, err error) {
func (m *mockLegacyDatabase) CreateUser(ctx context.Context, statements v4.Statements, usernameConfig v4.UsernameConfig, expiration time.Time) (username string, password string, err error) {
args := m.Called(ctx, statements, usernameConfig, expiration)
return args.String(0), args.String(1), args.Error(2)
}
func (m *mockLegacyDatabase) RenewUser(ctx context.Context, statements dbplugin.Statements, username string, expiration time.Time) error {
func (m *mockLegacyDatabase) RenewUser(ctx context.Context, statements v4.Statements, username string, expiration time.Time) error {
args := m.Called(ctx, statements, username, expiration)
return args.Error(0)
}
func (m *mockLegacyDatabase) RevokeUser(ctx context.Context, statements dbplugin.Statements, username string) error {
func (m *mockLegacyDatabase) RevokeUser(ctx context.Context, statements v4.Statements, username string) error {
args := m.Called(ctx, statements, username)
return args.Error(0)
}
@@ -76,7 +76,7 @@ func (m *mockLegacyDatabase) GenerateCredentials(ctx context.Context) (string, e
return args.String(0), args.Error(1)
}
func (m *mockLegacyDatabase) SetCredentials(ctx context.Context, statements dbplugin.Statements, staticConfig dbplugin.StaticUserConfig) (username string, password string, err error) {
func (m *mockLegacyDatabase) SetCredentials(ctx context.Context, statements v4.Statements, staticConfig v4.StaticUserConfig) (username string, password string, err error) {
args := m.Called(ctx, statements, staticConfig)
return args.String(0), args.String(1), args.Error(2)
}

View File

@@ -7,7 +7,7 @@ import (
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/sdk/database/dbplugin"
v4 "github.com/hashicorp/vault/sdk/database/dbplugin"
)
const mockV4Type = "mockv4"
@@ -17,7 +17,7 @@ type MockDatabaseV4 struct {
config map[string]interface{}
}
var _ dbplugin.Database = &MockDatabaseV4{}
var _ v4.Database = &MockDatabaseV4{}
// New returns a new in-memory instance
func NewV4() (interface{}, error) {
@@ -31,7 +31,7 @@ func RunV4(apiTLSConfig *api.TLSConfig) error {
return err
}
dbplugin.Serve(dbType.(dbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
v4.Serve(dbType.(v4.Database), api.VaultPluginTLSProvider(apiTLSConfig))
return nil
}
@@ -49,7 +49,7 @@ func (m MockDatabaseV4) Initialize(ctx context.Context, config map[string]interf
return err
}
func (m MockDatabaseV4) CreateUser(ctx context.Context, statements dbplugin.Statements, usernameConfig dbplugin.UsernameConfig, expiration time.Time) (username string, password string, err error) {
func (m MockDatabaseV4) CreateUser(ctx context.Context, statements v4.Statements, usernameConfig v4.UsernameConfig, expiration time.Time) (username string, password string, err error) {
log.Default().Info("CreateUser called",
"statements", statements,
"usernameConfig", usernameConfig,
@@ -64,7 +64,7 @@ func (m MockDatabaseV4) CreateUser(ctx context.Context, statements dbplugin.Stat
return user, pass, nil
}
func (m MockDatabaseV4) RenewUser(ctx context.Context, statements dbplugin.Statements, username string, expiration time.Time) error {
func (m MockDatabaseV4) RenewUser(ctx context.Context, statements v4.Statements, username string, expiration time.Time) error {
log.Default().Info("RenewUser called",
"statements", statements,
"username", username,
@@ -73,7 +73,7 @@ func (m MockDatabaseV4) RenewUser(ctx context.Context, statements dbplugin.State
return nil
}
func (m MockDatabaseV4) RevokeUser(ctx context.Context, statements dbplugin.Statements, username string) error {
func (m MockDatabaseV4) RevokeUser(ctx context.Context, statements v4.Statements, username string) error {
log.Default().Info("RevokeUser called",
"statements", statements,
"username", username)
@@ -94,7 +94,7 @@ func (m MockDatabaseV4) RotateRootCredentials(ctx context.Context, statements []
return m.config, nil
}
func (m MockDatabaseV4) SetCredentials(ctx context.Context, statements dbplugin.Statements, staticConfig dbplugin.StaticUserConfig) (username string, password string, err error) {
func (m MockDatabaseV4) SetCredentials(ctx context.Context, statements v4.Statements, staticConfig v4.StaticUserConfig) (username string, password string, err error) {
log.Default().Info("SetCredentials called",
"statements", statements,
"staticConfig", staticConfig)

View File

@@ -7,7 +7,7 @@ import (
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
v5 "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
)
const mockV5Type = "mockv5"
@@ -17,7 +17,7 @@ type MockDatabaseV5 struct {
config map[string]interface{}
}
var _ newdbplugin.Database = &MockDatabaseV5{}
var _ v5.Database = &MockDatabaseV5{}
// New returns a new in-memory instance
func New() (interface{}, error) {
@@ -32,46 +32,46 @@ func RunV5(apiTLSConfig *api.TLSConfig) error {
return err
}
newdbplugin.Serve(dbType.(newdbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
v5.Serve(dbType.(v5.Database), api.VaultPluginTLSProvider(apiTLSConfig))
return nil
}
func (m MockDatabaseV5) Initialize(ctx context.Context, req newdbplugin.InitializeRequest) (newdbplugin.InitializeResponse, error) {
func (m MockDatabaseV5) Initialize(ctx context.Context, req v5.InitializeRequest) (v5.InitializeResponse, error) {
log.Default().Info("Initialize called",
"req", req)
config := req.Config
config["from-plugin"] = "this value is from the plugin itself"
resp := newdbplugin.InitializeResponse{
resp := v5.InitializeResponse{
Config: req.Config,
}
return resp, nil
}
func (m MockDatabaseV5) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (newdbplugin.NewUserResponse, error) {
func (m MockDatabaseV5) NewUser(ctx context.Context, req v5.NewUserRequest) (v5.NewUserResponse, error) {
log.Default().Info("NewUser called",
"req", req)
now := time.Now()
user := fmt.Sprintf("mockv5_user_%s", now.Format(time.RFC3339))
resp := newdbplugin.NewUserResponse{
resp := v5.NewUserResponse{
Username: user,
}
return resp, nil
}
func (m MockDatabaseV5) UpdateUser(ctx context.Context, req newdbplugin.UpdateUserRequest) (newdbplugin.UpdateUserResponse, error) {
func (m MockDatabaseV5) UpdateUser(ctx context.Context, req v5.UpdateUserRequest) (v5.UpdateUserResponse, error) {
log.Default().Info("UpdateUser called",
"req", req)
return newdbplugin.UpdateUserResponse{}, nil
return v5.UpdateUserResponse{}, nil
}
func (m MockDatabaseV5) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserRequest) (newdbplugin.DeleteUserResponse, error) {
func (m MockDatabaseV5) DeleteUser(ctx context.Context, req v5.DeleteUserRequest) (v5.DeleteUserResponse, error) {
log.Default().Info("DeleteUser called",
"req", req)
return newdbplugin.DeleteUserResponse{}, nil
return v5.DeleteUserResponse{}, nil
}
func (m MockDatabaseV5) Type() (string, error) {

View File

@@ -10,7 +10,7 @@ import (
"github.com/fatih/structs"
"github.com/hashicorp/errwrap"
uuid "github.com/hashicorp/go-uuid"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
v5 "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
@@ -318,7 +318,7 @@ func (b *databaseBackend) connectionWriteHandler() framework.OperationFunc {
return logical.ErrorResponse("error creating database object: %s", err), nil
}
initReq := newdbplugin.InitializeRequest{
initReq := v5.InitializeRequest{
Config: config.ConnectionDetails,
VerifyConnection: verifyConnection,
}

View File

@@ -5,7 +5,7 @@ import (
"fmt"
"time"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
v5 "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/strutil"
"github.com/hashicorp/vault/sdk/logical"
@@ -95,15 +95,15 @@ func (b *databaseBackend) pathCredsCreateRead() framework.OperationFunc {
return nil, fmt.Errorf("unable to generate password: %w", err)
}
newUserReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
newUserReq := v5.NewUserRequest{
UsernameConfig: v5.UsernameMetadata{
DisplayName: req.DisplayName,
RoleName: name,
},
Statements: newdbplugin.Statements{
Statements: v5.Statements{
Commands: role.Statements.Creation,
},
RollbackStatements: newdbplugin.Statements{
RollbackStatements: v5.Statements{
Commands: role.Statements.Rollback,
},
Password: password,

View File

@@ -6,7 +6,7 @@ import (
"strings"
"time"
"github.com/hashicorp/vault/sdk/database/dbplugin"
v4 "github.com/hashicorp/vault/sdk/database/dbplugin"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/locksutil"
"github.com/hashicorp/vault/sdk/helper/strutil"
@@ -523,7 +523,7 @@ func (b *databaseBackend) pathStaticRoleCreateUpdate(ctx context.Context, req *l
type roleEntry struct {
DBName string `json:"db_name"`
Statements dbplugin.Statements `json:"statements"`
Statements v4.Statements `json:"statements"`
DefaultTTL time.Duration `json:"default_ttl"`
MaxTTL time.Duration `json:"max_ttl"`
StaticAccount *staticAccount `json:"static_account" mapstructure:"static_account"`

View File

@@ -5,7 +5,7 @@ import (
"fmt"
"time"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
v5 "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/sdk/queue"
@@ -111,11 +111,11 @@ func (b *databaseBackend) pathRotateRootCredentialsUpdate() framework.OperationF
return nil, err
}
updateReq := newdbplugin.UpdateUserRequest{
updateReq := v5.UpdateUserRequest{
Username: username,
Password: &newdbplugin.ChangePassword{
Password: &v5.ChangePassword{
NewPassword: newPassword,
Statements: newdbplugin.Statements{
Statements: v5.Statements{
Commands: config.RootCredentialsRotateStatements,
},
},

View File

@@ -4,7 +4,7 @@ import (
"context"
"errors"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
v5 "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/logical"
"github.com/mitchellh/mapstructure"
"google.golang.org/grpc/codes"
@@ -91,11 +91,11 @@ func (b *databaseBackend) rollbackDatabaseCredentials(ctx context.Context, confi
}
}()
updateReq := newdbplugin.UpdateUserRequest{
updateReq := v5.UpdateUserRequest{
Username: entry.UserName,
Password: &newdbplugin.ChangePassword{
Password: &v5.ChangePassword{
NewPassword: entry.OldPassword,
Statements: newdbplugin.Statements{
Statements: v5.Statements{
Commands: config.RootCredentialsRotateStatements,
},
},

View File

@@ -8,7 +8,7 @@ import (
"github.com/hashicorp/vault/helper/namespace"
postgreshelper "github.com/hashicorp/vault/helper/testhelpers/postgresql"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
v5 "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
@@ -102,9 +102,9 @@ func TestBackend_RotateRootCredentials_WAL_rollback(t *testing.T) {
// Alter the database password so it no longer matches what is in storage
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
updateReq := newdbplugin.UpdateUserRequest{
updateReq := v5.UpdateUserRequest{
Username: databaseUser,
Password: &newdbplugin.ChangePassword{
Password: &v5.ChangePassword{
NewPassword: "newSecret",
},
}
@@ -348,9 +348,9 @@ func TestBackend_RotateRootCredentials_WAL_no_rollback_2(t *testing.T) {
// Alter the database password
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
updateReq := newdbplugin.UpdateUserRequest{
updateReq := v5.UpdateUserRequest{
Username: databaseUser,
Password: &newdbplugin.ChangePassword{
Password: &v5.ChangePassword{
NewPassword: "newSecret",
},
}

View File

@@ -9,8 +9,8 @@ import (
"github.com/hashicorp/errwrap"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/sdk/database/dbplugin"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
v4 "github.com/hashicorp/vault/sdk/database/dbplugin"
v5 "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/locksutil"
@@ -340,7 +340,7 @@ func (b *databaseBackend) setStaticAccount(ctx context.Context, s logical.Storag
}
output.Password = newPassword
config := dbplugin.StaticUserConfig{
config := v4.StaticUserConfig{
Username: input.Role.StaticAccount.Username,
Password: newPassword,
}
@@ -358,11 +358,11 @@ func (b *databaseBackend) setStaticAccount(ctx context.Context, s logical.Storag
}
}
updateReq := newdbplugin.UpdateUserRequest{
updateReq := v5.UpdateUserRequest{
Username: input.Role.StaticAccount.Username,
Password: &newdbplugin.ChangePassword{
Password: &v5.ChangePassword{
NewPassword: newPassword,
Statements: newdbplugin.Statements{
Statements: v5.Statements{
Commands: input.Role.Statements.Rotation,
},
},

View File

@@ -2,14 +2,13 @@ package database
import (
"context"
"database/sql"
"log"
"os"
"strings"
"testing"
"time"
"database/sql"
"github.com/Sectorbob/mlab-ns2/gae/ns/digest"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/helper/testhelpers/mongodb"

View File

@@ -5,8 +5,8 @@ import (
"fmt"
"time"
"github.com/hashicorp/vault/sdk/database/dbplugin"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
v4 "github.com/hashicorp/vault/sdk/database/dbplugin"
v5 "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/framework"
"github.com/hashicorp/vault/sdk/logical"
)
@@ -65,11 +65,11 @@ func (b *databaseBackend) secretCredsRenew() framework.OperationFunc {
// to ensure the database credential does not expire before the lease
expireTime = expireTime.Add(5 * time.Second)
updateReq := newdbplugin.UpdateUserRequest{
updateReq := v5.UpdateUserRequest{
Username: username,
Expiration: &newdbplugin.ChangeExpiration{
Expiration: &v5.ChangeExpiration{
NewExpiration: expireTime,
Statements: newdbplugin.Statements{
Statements: v5.Statements{
Commands: role.Statements.Renewal,
},
},
@@ -104,7 +104,7 @@ func (b *databaseBackend) secretCredsRevoke() framework.OperationFunc {
}
var dbName string
var statements dbplugin.Statements
var statements v4.Statements
role, err := b.Role(ctx, req.Storage, roleNameRaw.(string))
if err != nil {
@@ -148,9 +148,9 @@ func (b *databaseBackend) secretCredsRevoke() framework.OperationFunc {
dbi.RLock()
defer dbi.RUnlock()
deleteReq := newdbplugin.DeleteUserRequest{
deleteReq := v5.DeleteUserRequest{
Username: username,
Statements: newdbplugin.Statements{
Statements: v5.Statements{
Commands: statements.Revocation,
},
}

View File

@@ -8,22 +8,22 @@ import (
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/helper/random"
"github.com/hashicorp/vault/sdk/database/dbplugin"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
v4 "github.com/hashicorp/vault/sdk/database/dbplugin"
v5 "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type databaseVersionWrapper struct {
v4 dbplugin.Database
v5 newdbplugin.Database
v4 v4.Database
v5 v5.Database
}
// newDatabaseWrapper figures out which version of the database the pluginName is referring to and returns a wrapper object
// that can be used to make operations on the underlying database plugin.
func newDatabaseWrapper(ctx context.Context, pluginName string, sys pluginutil.LookRunnerUtil, logger log.Logger) (dbw databaseVersionWrapper, err error) {
newDB, err := newdbplugin.PluginFactory(ctx, pluginName, sys, logger)
newDB, err := v5.PluginFactory(ctx, pluginName, sys, logger)
if err == nil {
dbw = databaseVersionWrapper{
v5: newDB,
@@ -34,7 +34,7 @@ func newDatabaseWrapper(ctx context.Context, pluginName string, sys pluginutil.L
merr := &multierror.Error{}
merr = multierror.Append(merr, err)
legacyDB, err := dbplugin.PluginFactory(ctx, pluginName, sys, logger)
legacyDB, err := v4.PluginFactory(ctx, pluginName, sys, logger)
if err == nil {
dbw = databaseVersionWrapper{
v4: legacyDB,
@@ -48,9 +48,9 @@ func newDatabaseWrapper(ctx context.Context, pluginName string, sys pluginutil.L
// Initialize the underlying database. This is analogous to a constructor on the database plugin object.
// Errors if the wrapper does not contain an underlying database.
func (d databaseVersionWrapper) Initialize(ctx context.Context, req newdbplugin.InitializeRequest) (newdbplugin.InitializeResponse, error) {
func (d databaseVersionWrapper) Initialize(ctx context.Context, req v5.InitializeRequest) (v5.InitializeResponse, error) {
if !d.isV5() && !d.isV4() {
return newdbplugin.InitializeResponse{}, fmt.Errorf("no underlying database specified")
return v5.InitializeResponse{}, fmt.Errorf("no underlying database specified")
}
// v5 Database
@@ -61,9 +61,9 @@ func (d databaseVersionWrapper) Initialize(ctx context.Context, req newdbplugin.
// v4 Database
saveConfig, err := d.v4.Init(ctx, req.Config, req.VerifyConnection)
if err != nil {
return newdbplugin.InitializeResponse{}, err
return v5.InitializeResponse{}, err
}
resp := newdbplugin.InitializeResponse{
resp := v5.InitializeResponse{
Config: saveConfig,
}
return resp, nil
@@ -74,9 +74,9 @@ func (d databaseVersionWrapper) Initialize(ctx context.Context, req newdbplugin.
// does not have a way of returning the password so this function signature needs to be different.
// The password returned here should be considered the source of truth, not the provided password.
// Errors if the wrapper does not contain an underlying database.
func (d databaseVersionWrapper) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (resp newdbplugin.NewUserResponse, password string, err error) {
func (d databaseVersionWrapper) NewUser(ctx context.Context, req v5.NewUserRequest) (resp v5.NewUserResponse, password string, err error) {
if !d.isV5() && !d.isV4() {
return newdbplugin.NewUserResponse{}, "", fmt.Errorf("no underlying database specified")
return v5.NewUserResponse{}, "", fmt.Errorf("no underlying database specified")
}
// v5 Database
@@ -86,11 +86,11 @@ func (d databaseVersionWrapper) NewUser(ctx context.Context, req newdbplugin.New
}
// v4 Database
stmts := dbplugin.Statements{
stmts := v4.Statements{
Creation: req.Statements.Commands,
Rollback: req.RollbackStatements.Commands,
}
usernameConfig := dbplugin.UsernameConfig{
usernameConfig := v4.UsernameConfig{
DisplayName: req.UsernameConfig.DisplayName,
RoleName: req.UsernameConfig.RoleName,
}
@@ -99,7 +99,7 @@ func (d databaseVersionWrapper) NewUser(ctx context.Context, req newdbplugin.New
return resp, "", err
}
resp = newdbplugin.NewUserResponse{
resp = v5.NewUserResponse{
Username: username,
}
return resp, password, nil
@@ -108,7 +108,7 @@ func (d databaseVersionWrapper) NewUser(ctx context.Context, req newdbplugin.New
// UpdateUser in the underlying database. This is used to update any information currently supported
// in the UpdateUserRequest such as password credentials or user TTL.
// Errors if the wrapper does not contain an underlying database.
func (d databaseVersionWrapper) UpdateUser(ctx context.Context, req newdbplugin.UpdateUserRequest, isRootUser bool) (saveConfig map[string]interface{}, err error) {
func (d databaseVersionWrapper) UpdateUser(ctx context.Context, req v5.UpdateUserRequest, isRootUser bool) (saveConfig map[string]interface{}, err error) {
if !d.isV5() && !d.isV4() {
return nil, fmt.Errorf("no underlying database specified")
}
@@ -136,7 +136,7 @@ func (d databaseVersionWrapper) UpdateUser(ctx context.Context, req newdbplugin.
// Change expiration date
if req.Expiration != nil {
stmts := dbplugin.Statements{
stmts := v4.Statements{
Renewal: req.Expiration.Statements.Commands,
}
err := d.v4.RenewUser(ctx, stmts, req.Username, req.Expiration.NewExpiration)
@@ -148,7 +148,7 @@ func (d databaseVersionWrapper) UpdateUser(ctx context.Context, req newdbplugin.
// changePasswordLegacy attempts to use SetCredentials to change the password for the user with the password provided
// in ChangePassword. If that user is the root user and SetCredentials is unimplemented, it will fall back to using
// RotateRootCredentials. If not the root user, this will not use RotateRootCredentials.
func (d databaseVersionWrapper) changePasswordLegacy(ctx context.Context, username string, passwordChange *newdbplugin.ChangePassword, isRootUser bool) (saveConfig map[string]interface{}, err error) {
func (d databaseVersionWrapper) changePasswordLegacy(ctx context.Context, username string, passwordChange *v5.ChangePassword, isRootUser bool) (saveConfig map[string]interface{}, err error) {
err = d.changeUserPasswordLegacy(ctx, username, passwordChange)
// If changing the root user's password but SetCredentials is unimplemented, fall back to RotateRootCredentials
@@ -165,11 +165,11 @@ func (d databaseVersionWrapper) changePasswordLegacy(ctx context.Context, userna
return nil, nil
}
func (d databaseVersionWrapper) changeUserPasswordLegacy(ctx context.Context, username string, passwordChange *newdbplugin.ChangePassword) (err error) {
stmts := dbplugin.Statements{
func (d databaseVersionWrapper) changeUserPasswordLegacy(ctx context.Context, username string, passwordChange *v5.ChangePassword) (err error) {
stmts := v4.Statements{
Rotation: passwordChange.Statements.Commands,
}
staticConfig := dbplugin.StaticUserConfig{
staticConfig := v4.StaticUserConfig{
Username: username,
Password: passwordChange.NewPassword,
}
@@ -177,14 +177,14 @@ func (d databaseVersionWrapper) changeUserPasswordLegacy(ctx context.Context, us
return err
}
func (d databaseVersionWrapper) changeRootUserPasswordLegacy(ctx context.Context, passwordChange *newdbplugin.ChangePassword) (saveConfig map[string]interface{}, err error) {
func (d databaseVersionWrapper) changeRootUserPasswordLegacy(ctx context.Context, passwordChange *v5.ChangePassword) (saveConfig map[string]interface{}, err error) {
return d.v4.RotateRootCredentials(ctx, passwordChange.Statements.Commands)
}
// DeleteUser in the underlying database. Errors if the wrapper does not contain an underlying database.
func (d databaseVersionWrapper) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserRequest) (newdbplugin.DeleteUserResponse, error) {
func (d databaseVersionWrapper) DeleteUser(ctx context.Context, req v5.DeleteUserRequest) (v5.DeleteUserResponse, error) {
if !d.isV5() && !d.isV4() {
return newdbplugin.DeleteUserResponse{}, fmt.Errorf("no underlying database specified")
return v5.DeleteUserResponse{}, fmt.Errorf("no underlying database specified")
}
// v5 Database
@@ -193,11 +193,11 @@ func (d databaseVersionWrapper) DeleteUser(ctx context.Context, req newdbplugin.
}
// v4 Database
stmts := dbplugin.Statements{
stmts := v4.Statements{
Revocation: req.Statements.Commands,
}
err := d.v4.RevokeUser(ctx, stmts, req.Username)
return newdbplugin.DeleteUserResponse{}, err
return v5.DeleteUserResponse{}, err
}
// Type of the underlying database. Errors if the wrapper does not contain an underlying database.

View File

@@ -8,7 +8,7 @@ import (
"testing"
"time"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
v5 "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/logical"
"github.com/stretchr/testify/mock"
"google.golang.org/grpc/codes"
@@ -18,13 +18,13 @@ import (
func TestInitDatabase_missingDB(t *testing.T) {
dbw := databaseVersionWrapper{}
req := newdbplugin.InitializeRequest{}
req := v5.InitializeRequest{}
resp, err := dbw.Initialize(context.Background(), req)
if err == nil {
t.Fatalf("err expected, got nil")
}
expectedResp := newdbplugin.InitializeResponse{}
expectedResp := v5.InitializeResponse{}
if !reflect.DeepEqual(resp, expectedResp) {
t.Fatalf("Actual resp: %#v\nExpected resp: %#v", resp, expectedResp)
}
@@ -32,31 +32,31 @@ func TestInitDatabase_missingDB(t *testing.T) {
func TestInitDatabase_newDB(t *testing.T) {
type testCase struct {
req newdbplugin.InitializeRequest
req v5.InitializeRequest
newInitResp newdbplugin.InitializeResponse
newInitResp v5.InitializeResponse
newInitErr error
newInitCalls int
expectedResp newdbplugin.InitializeResponse
expectedResp v5.InitializeResponse
expectErr bool
}
tests := map[string]testCase{
"success": {
req: newdbplugin.InitializeRequest{
req: v5.InitializeRequest{
Config: map[string]interface{}{
"foo": "bar",
},
VerifyConnection: true,
},
newInitResp: newdbplugin.InitializeResponse{
newInitResp: v5.InitializeResponse{
Config: map[string]interface{}{
"foo": "bar",
},
},
newInitCalls: 1,
expectedResp: newdbplugin.InitializeResponse{
expectedResp: v5.InitializeResponse{
Config: map[string]interface{}{
"foo": "bar",
},
@@ -64,16 +64,16 @@ func TestInitDatabase_newDB(t *testing.T) {
expectErr: false,
},
"error": {
req: newdbplugin.InitializeRequest{
req: v5.InitializeRequest{
Config: map[string]interface{}{
"foo": "bar",
},
VerifyConnection: true,
},
newInitResp: newdbplugin.InitializeResponse{},
newInitResp: v5.InitializeResponse{},
newInitErr: fmt.Errorf("test error"),
newInitCalls: 1,
expectedResp: newdbplugin.InitializeResponse{},
expectedResp: v5.InitializeResponse{},
expectErr: true,
},
}
@@ -106,19 +106,19 @@ func TestInitDatabase_newDB(t *testing.T) {
func TestInitDatabase_legacyDB(t *testing.T) {
type testCase struct {
req newdbplugin.InitializeRequest
req v5.InitializeRequest
initConfig map[string]interface{}
initErr error
initCalls int
expectedResp newdbplugin.InitializeResponse
expectedResp v5.InitializeResponse
expectErr bool
}
tests := map[string]testCase{
"success": {
req: newdbplugin.InitializeRequest{
req: v5.InitializeRequest{
Config: map[string]interface{}{
"foo": "bar",
},
@@ -128,7 +128,7 @@ func TestInitDatabase_legacyDB(t *testing.T) {
"foo": "bar",
},
initCalls: 1,
expectedResp: newdbplugin.InitializeResponse{
expectedResp: v5.InitializeResponse{
Config: map[string]interface{}{
"foo": "bar",
},
@@ -136,7 +136,7 @@ func TestInitDatabase_legacyDB(t *testing.T) {
expectErr: false,
},
"error": {
req: newdbplugin.InitializeRequest{
req: v5.InitializeRequest{
Config: map[string]interface{}{
"foo": "bar",
},
@@ -144,7 +144,7 @@ func TestInitDatabase_legacyDB(t *testing.T) {
},
initErr: fmt.Errorf("test error"),
initCalls: 1,
expectedResp: newdbplugin.InitializeResponse{},
expectedResp: v5.InitializeResponse{},
expectErr: true,
},
}
@@ -348,13 +348,13 @@ func TestGeneratePassword_no_policy(t *testing.T) {
func TestNewUser_missingDB(t *testing.T) {
dbw := databaseVersionWrapper{}
req := newdbplugin.NewUserRequest{}
req := v5.NewUserRequest{}
resp, pass, err := dbw.NewUser(context.Background(), req)
if err == nil {
t.Fatalf("err expected, got nil")
}
expectedResp := newdbplugin.NewUserResponse{}
expectedResp := v5.NewUserResponse{}
if !reflect.DeepEqual(resp, expectedResp) {
t.Fatalf("Actual resp: %#v\nExpected resp: %#v", resp, expectedResp)
}
@@ -366,41 +366,41 @@ func TestNewUser_missingDB(t *testing.T) {
func TestNewUser_newDB(t *testing.T) {
type testCase struct {
req newdbplugin.NewUserRequest
req v5.NewUserRequest
newUserResp newdbplugin.NewUserResponse
newUserResp v5.NewUserResponse
newUserErr error
newUserCalls int
expectedResp newdbplugin.NewUserResponse
expectedResp v5.NewUserResponse
expectErr bool
}
tests := map[string]testCase{
"success": {
req: newdbplugin.NewUserRequest{
req: v5.NewUserRequest{
Password: "new_password",
},
newUserResp: newdbplugin.NewUserResponse{
newUserResp: v5.NewUserResponse{
Username: "newuser",
},
newUserCalls: 1,
expectedResp: newdbplugin.NewUserResponse{
expectedResp: v5.NewUserResponse{
Username: "newuser",
},
expectErr: false,
},
"error": {
req: newdbplugin.NewUserRequest{
req: v5.NewUserRequest{
Password: "new_password",
},
newUserErr: fmt.Errorf("test error"),
newUserCalls: 1,
expectedResp: newdbplugin.NewUserResponse{},
expectedResp: v5.NewUserResponse{},
expectErr: true,
},
}
@@ -437,21 +437,21 @@ func TestNewUser_newDB(t *testing.T) {
func TestNewUser_legacyDB(t *testing.T) {
type testCase struct {
req newdbplugin.NewUserRequest
req v5.NewUserRequest
createUserUsername string
createUserPassword string
createUserErr error
createUserCalls int
expectedResp newdbplugin.NewUserResponse
expectedResp v5.NewUserResponse
expectedPassword string
expectErr bool
}
tests := map[string]testCase{
"success": {
req: newdbplugin.NewUserRequest{
req: v5.NewUserRequest{
Password: "new_password",
},
@@ -459,21 +459,21 @@ func TestNewUser_legacyDB(t *testing.T) {
createUserPassword: "securepassword",
createUserCalls: 1,
expectedResp: newdbplugin.NewUserResponse{
expectedResp: v5.NewUserResponse{
Username: "newuser",
},
expectedPassword: "securepassword",
expectErr: false,
},
"error": {
req: newdbplugin.NewUserRequest{
req: v5.NewUserRequest{
Password: "new_password",
},
createUserErr: fmt.Errorf("test error"),
createUserCalls: 1,
expectedResp: newdbplugin.NewUserResponse{},
expectedResp: v5.NewUserResponse{},
expectErr: true,
},
}
@@ -511,7 +511,7 @@ func TestNewUser_legacyDB(t *testing.T) {
func TestUpdateUser_missingDB(t *testing.T) {
dbw := databaseVersionWrapper{}
req := newdbplugin.UpdateUserRequest{}
req := v5.UpdateUserRequest{}
resp, err := dbw.UpdateUser(context.Background(), req, false)
if err == nil {
t.Fatalf("err expected, got nil")
@@ -525,25 +525,25 @@ func TestUpdateUser_missingDB(t *testing.T) {
func TestUpdateUser_newDB(t *testing.T) {
type testCase struct {
req newdbplugin.UpdateUserRequest
req v5.UpdateUserRequest
updateUserErr error
updateUserCalls int
expectedResp newdbplugin.UpdateUserResponse
expectedResp v5.UpdateUserResponse
expectErr bool
}
tests := map[string]testCase{
"success": {
req: newdbplugin.UpdateUserRequest{
req: v5.UpdateUserRequest{
Username: "existing_user",
},
updateUserCalls: 1,
expectErr: false,
},
"error": {
req: newdbplugin.UpdateUserRequest{
req: v5.UpdateUserRequest{
Username: "existing_user",
},
updateUserErr: fmt.Errorf("test error"),
@@ -556,7 +556,7 @@ func TestUpdateUser_newDB(t *testing.T) {
t.Run(name, func(t *testing.T) {
newDB := new(mockNewDatabase)
newDB.On("UpdateUser", mock.Anything, mock.Anything).
Return(newdbplugin.UpdateUserResponse{}, test.updateUserErr)
Return(v5.UpdateUserResponse{}, test.updateUserErr)
defer newDB.AssertNumberOfCalls(t, "UpdateUser", test.updateUserCalls)
dbw := databaseVersionWrapper{
@@ -576,7 +576,7 @@ func TestUpdateUser_newDB(t *testing.T) {
func TestUpdateUser_legacyDB(t *testing.T) {
type testCase struct {
req newdbplugin.UpdateUserRequest
req v5.UpdateUserRequest
isRootUser bool
setCredentialsErr error
@@ -595,7 +595,7 @@ func TestUpdateUser_legacyDB(t *testing.T) {
tests := map[string]testCase{
"missing changes": {
req: newdbplugin.UpdateUserRequest{
req: v5.UpdateUserRequest{
Username: "existing_user",
},
isRootUser: false,
@@ -607,10 +607,10 @@ func TestUpdateUser_legacyDB(t *testing.T) {
expectErr: true,
},
"both password and expiration changes": {
req: newdbplugin.UpdateUserRequest{
req: v5.UpdateUserRequest{
Username: "existing_user",
Password: &newdbplugin.ChangePassword{},
Expiration: &newdbplugin.ChangeExpiration{},
Password: &v5.ChangePassword{},
Expiration: &v5.ChangeExpiration{},
},
isRootUser: false,
@@ -621,9 +621,9 @@ func TestUpdateUser_legacyDB(t *testing.T) {
expectErr: true,
},
"change password - SetCredentials": {
req: newdbplugin.UpdateUserRequest{
req: v5.UpdateUserRequest{
Username: "existing_user",
Password: &newdbplugin.ChangePassword{
Password: &v5.ChangePassword{
NewPassword: "newpassowrd",
},
},
@@ -638,9 +638,9 @@ func TestUpdateUser_legacyDB(t *testing.T) {
expectErr: false,
},
"change password - SetCredentials failed": {
req: newdbplugin.UpdateUserRequest{
req: v5.UpdateUserRequest{
Username: "existing_user",
Password: &newdbplugin.ChangePassword{
Password: &v5.ChangePassword{
NewPassword: "newpassowrd",
},
},
@@ -655,9 +655,9 @@ func TestUpdateUser_legacyDB(t *testing.T) {
expectErr: true,
},
"change password - SetCredentials unimplemented but not a root user": {
req: newdbplugin.UpdateUserRequest{
req: v5.UpdateUserRequest{
Username: "existing_user",
Password: &newdbplugin.ChangePassword{
Password: &v5.ChangePassword{
NewPassword: "newpassowrd",
},
},
@@ -673,9 +673,9 @@ func TestUpdateUser_legacyDB(t *testing.T) {
expectErr: true,
},
"change password - RotateRootCredentials": {
req: newdbplugin.UpdateUserRequest{
req: v5.UpdateUserRequest{
Username: "existing_user",
Password: &newdbplugin.ChangePassword{
Password: &v5.ChangePassword{
NewPassword: "newpassowrd",
},
},
@@ -697,9 +697,9 @@ func TestUpdateUser_legacyDB(t *testing.T) {
expectErr: false,
},
"change password - RotateRootCredentials failed": {
req: newdbplugin.UpdateUserRequest{
req: v5.UpdateUserRequest{
Username: "existing_user",
Password: &newdbplugin.ChangePassword{
Password: &v5.ChangePassword{
NewPassword: "newpassowrd",
},
},
@@ -717,9 +717,9 @@ func TestUpdateUser_legacyDB(t *testing.T) {
},
"change expiration": {
req: newdbplugin.UpdateUserRequest{
req: v5.UpdateUserRequest{
Username: "existing_user",
Expiration: &newdbplugin.ChangeExpiration{
Expiration: &v5.ChangeExpiration{
NewExpiration: time.Now(),
},
},
@@ -735,9 +735,9 @@ func TestUpdateUser_legacyDB(t *testing.T) {
expectErr: false,
},
"change expiration failed": {
req: newdbplugin.UpdateUserRequest{
req: v5.UpdateUserRequest{
Username: "existing_user",
Expiration: &newdbplugin.ChangeExpiration{
Expiration: &v5.ChangeExpiration{
NewExpiration: time.Now(),
},
},
@@ -791,7 +791,7 @@ func TestUpdateUser_legacyDB(t *testing.T) {
func TestDeleteUser_missingDB(t *testing.T) {
dbw := databaseVersionWrapper{}
req := newdbplugin.DeleteUserRequest{}
req := v5.DeleteUserRequest{}
_, err := dbw.DeleteUser(context.Background(), req)
if err == nil {
t.Fatalf("err expected, got nil")
@@ -800,7 +800,7 @@ func TestDeleteUser_missingDB(t *testing.T) {
func TestDeleteUser_newDB(t *testing.T) {
type testCase struct {
req newdbplugin.DeleteUserRequest
req v5.DeleteUserRequest
deleteUserErr error
deleteUserCalls int
@@ -810,7 +810,7 @@ func TestDeleteUser_newDB(t *testing.T) {
tests := map[string]testCase{
"success": {
req: newdbplugin.DeleteUserRequest{
req: v5.DeleteUserRequest{
Username: "existing_user",
},
@@ -820,7 +820,7 @@ func TestDeleteUser_newDB(t *testing.T) {
expectErr: false,
},
"error": {
req: newdbplugin.DeleteUserRequest{
req: v5.DeleteUserRequest{
Username: "existing_user",
},
@@ -835,7 +835,7 @@ func TestDeleteUser_newDB(t *testing.T) {
t.Run(name, func(t *testing.T) {
newDB := new(mockNewDatabase)
newDB.On("DeleteUser", mock.Anything, mock.Anything).
Return(newdbplugin.DeleteUserResponse{}, test.deleteUserErr)
Return(v5.DeleteUserResponse{}, test.deleteUserErr)
defer newDB.AssertNumberOfCalls(t, "DeleteUser", test.deleteUserCalls)
dbw := databaseVersionWrapper{
@@ -855,7 +855,7 @@ func TestDeleteUser_newDB(t *testing.T) {
func TestDeleteUser_legacyDB(t *testing.T) {
type testCase struct {
req newdbplugin.DeleteUserRequest
req v5.DeleteUserRequest
revokeUserErr error
revokeUserCalls int
@@ -865,7 +865,7 @@ func TestDeleteUser_legacyDB(t *testing.T) {
tests := map[string]testCase{
"success": {
req: newdbplugin.DeleteUserRequest{
req: v5.DeleteUserRequest{
Username: "existing_user",
},
@@ -875,7 +875,7 @@ func TestDeleteUser_legacyDB(t *testing.T) {
expectErr: false,
},
"error": {
req: newdbplugin.DeleteUserRequest{
req: v5.DeleteUserRequest{
Username: "existing_user",
},

View File

@@ -92,7 +92,7 @@ func TestPlugin_lifecycle(t *testing.T) {
Storage: config.StorageView,
Data: test.configData,
}
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
resp, err := b.HandleRequest(ctx, req)
@@ -113,7 +113,7 @@ func TestPlugin_lifecycle(t *testing.T) {
Path: fmt.Sprintf("rotate-root/%s", test.dbName),
Storage: config.StorageView,
}
ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
resp, err = b.HandleRequest(ctx, req)
@@ -136,7 +136,7 @@ func TestPlugin_lifecycle(t *testing.T) {
"max_ttl": "1m",
},
}
ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
resp, err = b.HandleRequest(ctx, req)
@@ -156,7 +156,7 @@ func TestPlugin_lifecycle(t *testing.T) {
Path: fmt.Sprintf("creds/%s", dynamicRoleName),
Storage: config.StorageView,
}
ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
resp, err = b.HandleRequest(ctx, req)
@@ -182,7 +182,7 @@ func TestPlugin_lifecycle(t *testing.T) {
"rotation_period": "5",
},
}
ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
resp, err = b.HandleRequest(ctx, req)
@@ -202,7 +202,7 @@ func TestPlugin_lifecycle(t *testing.T) {
Path: fmt.Sprintf("static-creds/%s", staticRoleName),
Storage: config.StorageView,
}
ctx, cancel = context.WithTimeout(context.Background(), 2*time.Second)
ctx, cancel = context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
resp, err = b.HandleRequest(ctx, req)

View File

@@ -8,9 +8,9 @@ import (
"github.com/gocql/gocql"
multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/api"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/database/helper/credsutil"
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
"github.com/hashicorp/vault/sdk/helper/strutil"
)
@@ -21,7 +21,7 @@ const (
cassandraTypeName = "cassandra"
)
var _ newdbplugin.Database = &Cassandra{}
var _ dbplugin.Database = &Cassandra{}
// Cassandra is an implementation of Database interface
type Cassandra struct {
@@ -31,7 +31,7 @@ type Cassandra struct {
// New returns a new Cassandra instance
func New() (interface{}, error) {
db := new()
dbType := newdbplugin.NewDatabaseErrorSanitizerMiddleware(db, db.secretValues)
dbType := dbplugin.NewDatabaseErrorSanitizerMiddleware(db, db.secretValues)
return dbType, nil
}
@@ -52,7 +52,7 @@ func Run(apiTLSConfig *api.TLSConfig) error {
return err
}
newdbplugin.Serve(dbType.(newdbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
dbplugin.Serve(dbType.(dbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
return nil
}
@@ -73,13 +73,13 @@ func (c *Cassandra) getConnection(ctx context.Context) (*gocql.Session, error) {
// NewUser generates the username/password on the underlying Cassandra secret backend as instructed by
// the statements provided.
func (c *Cassandra) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (newdbplugin.NewUserResponse, error) {
func (c *Cassandra) NewUser(ctx context.Context, req dbplugin.NewUserRequest) (dbplugin.NewUserResponse, error) {
c.Lock()
defer c.Unlock()
session, err := c.getConnection(ctx)
if err != nil {
return newdbplugin.NewUserResponse{}, err
return dbplugin.NewUserResponse{}, err
}
creationCQL := req.Statements.Commands
@@ -100,7 +100,7 @@ func (c *Cassandra) NewUser(ctx context.Context, req newdbplugin.NewUserRequest)
credsutil.ToLower(),
)
if err != nil {
return newdbplugin.NewUserResponse{}, err
return dbplugin.NewUserResponse{}, err
}
username = strings.ReplaceAll(username, "-", "_")
@@ -124,12 +124,12 @@ func (c *Cassandra) NewUser(ctx context.Context, req newdbplugin.NewUserRequest)
if rollbackErr != nil {
err = multierror.Append(err, rollbackErr)
}
return newdbplugin.NewUserResponse{}, err
return dbplugin.NewUserResponse{}, err
}
}
}
resp := newdbplugin.NewUserResponse{
resp := dbplugin.NewUserResponse{
Username: username,
}
return resp, nil
@@ -158,20 +158,20 @@ func rollbackUser(ctx context.Context, session *gocql.Session, username string,
return nil
}
func (c *Cassandra) UpdateUser(ctx context.Context, req newdbplugin.UpdateUserRequest) (newdbplugin.UpdateUserResponse, error) {
func (c *Cassandra) UpdateUser(ctx context.Context, req dbplugin.UpdateUserRequest) (dbplugin.UpdateUserResponse, error) {
if req.Password == nil && req.Expiration == nil {
return newdbplugin.UpdateUserResponse{}, fmt.Errorf("no changes requested")
return dbplugin.UpdateUserResponse{}, fmt.Errorf("no changes requested")
}
if req.Password != nil {
err := c.changeUserPassword(ctx, req.Username, req.Password)
return newdbplugin.UpdateUserResponse{}, err
return dbplugin.UpdateUserResponse{}, err
}
// Expiration is no-op
return newdbplugin.UpdateUserResponse{}, nil
return dbplugin.UpdateUserResponse{}, nil
}
func (c *Cassandra) changeUserPassword(ctx context.Context, username string, changePass *newdbplugin.ChangePassword) error {
func (c *Cassandra) changeUserPassword(ctx context.Context, username string, changePass *dbplugin.ChangePassword) error {
session, err := c.getConnection(ctx)
if err != nil {
return err
@@ -206,13 +206,13 @@ func (c *Cassandra) changeUserPassword(ctx context.Context, username string, cha
}
// DeleteUser attempts to drop the specified user.
func (c *Cassandra) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserRequest) (newdbplugin.DeleteUserResponse, error) {
func (c *Cassandra) DeleteUser(ctx context.Context, req dbplugin.DeleteUserRequest) (dbplugin.DeleteUserResponse, error) {
c.Lock()
defer c.Unlock()
session, err := c.getConnection(ctx)
if err != nil {
return newdbplugin.DeleteUserResponse{}, err
return dbplugin.DeleteUserResponse{}, err
}
revocationCQL := req.Statements.Commands
@@ -240,5 +240,5 @@ func (c *Cassandra) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserRe
}
}
return newdbplugin.DeleteUserResponse{}, result.ErrorOrNil()
return dbplugin.DeleteUserResponse{}, result.ErrorOrNil()
}

View File

@@ -7,12 +7,11 @@ import (
"testing"
"time"
dbtesting "github.com/hashicorp/vault/sdk/database/newdbplugin/testing"
backoff "github.com/cenkalti/backoff/v3"
"github.com/gocql/gocql"
"github.com/hashicorp/vault/helper/testhelpers/cassandra"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
dbtesting "github.com/hashicorp/vault/sdk/database/dbplugin/v5/testing"
)
func getCassandra(t *testing.T, protocolVersion interface{}) (*Cassandra, func()) {
@@ -20,7 +19,7 @@ func getCassandra(t *testing.T, protocolVersion interface{}) (*Cassandra, func()
pieces := strings.Split(connURL, ":")
db := new()
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: map[string]interface{}{
"hosts": connURL,
"port": pieces[1],
@@ -70,12 +69,12 @@ func TestCassandra_CreateUser(t *testing.T) {
defer cleanup()
password := "myreallysecurepassword"
createReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
createReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{createUserStatements},
},
Password: password,
@@ -98,12 +97,12 @@ func TestMyCassandra_UpdateUserPassword(t *testing.T) {
defer cleanup()
password := "myreallysecurepassword"
createReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
createReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{createUserStatements},
},
Password: password,
@@ -115,11 +114,11 @@ func TestMyCassandra_UpdateUserPassword(t *testing.T) {
assertCreds(t, db.Hosts, db.Port, createResp.Username, password, 5*time.Second)
newPassword := "somenewpassword"
updateReq := newdbplugin.UpdateUserRequest{
updateReq := dbplugin.UpdateUserRequest{
Username: createResp.Username,
Password: &newdbplugin.ChangePassword{
Password: &dbplugin.ChangePassword{
NewPassword: newPassword,
Statements: newdbplugin.Statements{},
Statements: dbplugin.Statements{},
},
Expiration: nil,
}
@@ -134,12 +133,12 @@ func TestCassandra_DeleteUser(t *testing.T) {
defer cleanup()
password := "myreallysecurepassword"
createReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
createReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{createUserStatements},
},
Password: password,
@@ -150,7 +149,7 @@ func TestCassandra_DeleteUser(t *testing.T) {
assertCreds(t, db.Hosts, db.Port, createResp.Username, password, 5*time.Second)
deleteReq := newdbplugin.DeleteUserRequest{
deleteReq := dbplugin.DeleteUserRequest{
Username: createResp.Username,
}

View File

@@ -8,16 +8,15 @@ import (
"sync"
"time"
"github.com/mitchellh/mapstructure"
"github.com/gocql/gocql"
"github.com/hashicorp/errwrap"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/database/helper/connutil"
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/helper/parseutil"
"github.com/hashicorp/vault/sdk/helper/tlsutil"
"github.com/mitchellh/mapstructure"
)
// cassandraConnectionProducer implements ConnectionProducer and provides an
@@ -52,7 +51,7 @@ type cassandraConnectionProducer struct {
sync.Mutex
}
func (c *cassandraConnectionProducer) Initialize(ctx context.Context, req newdbplugin.InitializeRequest) (newdbplugin.InitializeResponse, error) {
func (c *cassandraConnectionProducer) Initialize(ctx context.Context, req dbplugin.InitializeRequest) (dbplugin.InitializeResponse, error) {
c.Lock()
defer c.Unlock()
@@ -60,7 +59,7 @@ func (c *cassandraConnectionProducer) Initialize(ctx context.Context, req newdbp
err := mapstructure.WeakDecode(req.Config, c)
if err != nil {
return newdbplugin.InitializeResponse{}, err
return dbplugin.InitializeResponse{}, err
}
if c.ConnectTimeoutRaw == nil {
@@ -68,7 +67,7 @@ func (c *cassandraConnectionProducer) Initialize(ctx context.Context, req newdbp
}
c.connectTimeout, err = parseutil.ParseDurationSecond(c.ConnectTimeoutRaw)
if err != nil {
return newdbplugin.InitializeResponse{}, errwrap.Wrapf("invalid connect_timeout: {{err}}", err)
return dbplugin.InitializeResponse{}, errwrap.Wrapf("invalid connect_timeout: {{err}}", err)
}
if c.SocketKeepAliveRaw == nil {
@@ -76,16 +75,16 @@ func (c *cassandraConnectionProducer) Initialize(ctx context.Context, req newdbp
}
c.socketKeepAlive, err = parseutil.ParseDurationSecond(c.SocketKeepAliveRaw)
if err != nil {
return newdbplugin.InitializeResponse{}, errwrap.Wrapf("invalid socket_keep_alive: {{err}}", err)
return dbplugin.InitializeResponse{}, errwrap.Wrapf("invalid socket_keep_alive: {{err}}", err)
}
switch {
case len(c.Hosts) == 0:
return newdbplugin.InitializeResponse{}, fmt.Errorf("hosts cannot be empty")
return dbplugin.InitializeResponse{}, fmt.Errorf("hosts cannot be empty")
case len(c.Username) == 0:
return newdbplugin.InitializeResponse{}, fmt.Errorf("username cannot be empty")
return dbplugin.InitializeResponse{}, fmt.Errorf("username cannot be empty")
case len(c.Password) == 0:
return newdbplugin.InitializeResponse{}, fmt.Errorf("password cannot be empty")
return dbplugin.InitializeResponse{}, fmt.Errorf("password cannot be empty")
}
var certBundle *certutil.CertBundle
@@ -94,11 +93,11 @@ func (c *cassandraConnectionProducer) Initialize(ctx context.Context, req newdbp
case len(c.PemJSON) != 0:
parsedCertBundle, err = certutil.ParsePKIJSON([]byte(c.PemJSON))
if err != nil {
return newdbplugin.InitializeResponse{}, errwrap.Wrapf("could not parse given JSON; it must be in the format of the output of the PKI backend certificate issuing command: {{err}}", err)
return dbplugin.InitializeResponse{}, errwrap.Wrapf("could not parse given JSON; it must be in the format of the output of the PKI backend certificate issuing command: {{err}}", err)
}
certBundle, err = parsedCertBundle.ToCertBundle()
if err != nil {
return newdbplugin.InitializeResponse{}, errwrap.Wrapf("Error marshaling PEM information: {{err}}", err)
return dbplugin.InitializeResponse{}, errwrap.Wrapf("Error marshaling PEM information: {{err}}", err)
}
c.certificate = certBundle.Certificate
c.privateKey = certBundle.PrivateKey
@@ -108,11 +107,11 @@ func (c *cassandraConnectionProducer) Initialize(ctx context.Context, req newdbp
case len(c.PemBundle) != 0:
parsedCertBundle, err = certutil.ParsePEMBundle(c.PemBundle)
if err != nil {
return newdbplugin.InitializeResponse{}, errwrap.Wrapf("Error parsing the given PEM information: {{err}}", err)
return dbplugin.InitializeResponse{}, errwrap.Wrapf("Error parsing the given PEM information: {{err}}", err)
}
certBundle, err = parsedCertBundle.ToCertBundle()
if err != nil {
return newdbplugin.InitializeResponse{}, errwrap.Wrapf("Error marshaling PEM information: {{err}}", err)
return dbplugin.InitializeResponse{}, errwrap.Wrapf("Error marshaling PEM information: {{err}}", err)
}
c.certificate = certBundle.Certificate
c.privateKey = certBundle.PrivateKey
@@ -126,11 +125,11 @@ func (c *cassandraConnectionProducer) Initialize(ctx context.Context, req newdbp
if req.VerifyConnection {
if _, err := c.Connection(ctx); err != nil {
return newdbplugin.InitializeResponse{}, errwrap.Wrapf("error verifying connection: {{err}}", err)
return dbplugin.InitializeResponse{}, errwrap.Wrapf("error verifying connection: {{err}}", err)
}
}
resp := newdbplugin.InitializeResponse{
resp := dbplugin.InitializeResponse{
Config: req.Config,
}

View File

@@ -8,8 +8,8 @@ import (
"time"
"github.com/hashicorp/errwrap"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/database/helper/connutil"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
"github.com/hashicorp/vault/sdk/helper/certutil"
"github.com/hashicorp/vault/sdk/helper/parseutil"
"github.com/hashicorp/vault/sdk/helper/tlsutil"
@@ -43,7 +43,7 @@ type influxdbConnectionProducer struct {
sync.Mutex
}
func (i *influxdbConnectionProducer) Initialize(ctx context.Context, req newdbplugin.InitializeRequest) (newdbplugin.InitializeResponse, error) {
func (i *influxdbConnectionProducer) Initialize(ctx context.Context, req dbplugin.InitializeRequest) (dbplugin.InitializeResponse, error) {
i.Lock()
defer i.Unlock()
@@ -51,7 +51,7 @@ func (i *influxdbConnectionProducer) Initialize(ctx context.Context, req newdbpl
err := mapstructure.WeakDecode(req.Config, i)
if err != nil {
return newdbplugin.InitializeResponse{}, err
return dbplugin.InitializeResponse{}, err
}
if i.ConnectTimeoutRaw == nil {
@@ -62,16 +62,16 @@ func (i *influxdbConnectionProducer) Initialize(ctx context.Context, req newdbpl
}
i.connectTimeout, err = parseutil.ParseDurationSecond(i.ConnectTimeoutRaw)
if err != nil {
return newdbplugin.InitializeResponse{}, errwrap.Wrapf("invalid connect_timeout: {{err}}", err)
return dbplugin.InitializeResponse{}, errwrap.Wrapf("invalid connect_timeout: {{err}}", err)
}
switch {
case len(i.Host) == 0:
return newdbplugin.InitializeResponse{}, fmt.Errorf("host cannot be empty")
return dbplugin.InitializeResponse{}, fmt.Errorf("host cannot be empty")
case len(i.Username) == 0:
return newdbplugin.InitializeResponse{}, fmt.Errorf("username cannot be empty")
return dbplugin.InitializeResponse{}, fmt.Errorf("username cannot be empty")
case len(i.Password) == 0:
return newdbplugin.InitializeResponse{}, fmt.Errorf("password cannot be empty")
return dbplugin.InitializeResponse{}, fmt.Errorf("password cannot be empty")
}
var certBundle *certutil.CertBundle
@@ -80,11 +80,11 @@ func (i *influxdbConnectionProducer) Initialize(ctx context.Context, req newdbpl
case len(i.PemJSON) != 0:
parsedCertBundle, err = certutil.ParsePKIJSON([]byte(i.PemJSON))
if err != nil {
return newdbplugin.InitializeResponse{}, errwrap.Wrapf("could not parse given JSON; it must be in the format of the output of the PKI backend certificate issuing command: {{err}}", err)
return dbplugin.InitializeResponse{}, errwrap.Wrapf("could not parse given JSON; it must be in the format of the output of the PKI backend certificate issuing command: {{err}}", err)
}
certBundle, err = parsedCertBundle.ToCertBundle()
if err != nil {
return newdbplugin.InitializeResponse{}, errwrap.Wrapf("Error marshaling PEM information: {{err}}", err)
return dbplugin.InitializeResponse{}, errwrap.Wrapf("Error marshaling PEM information: {{err}}", err)
}
i.certificate = certBundle.Certificate
i.privateKey = certBundle.PrivateKey
@@ -94,11 +94,11 @@ func (i *influxdbConnectionProducer) Initialize(ctx context.Context, req newdbpl
case len(i.PemBundle) != 0:
parsedCertBundle, err = certutil.ParsePEMBundle(i.PemBundle)
if err != nil {
return newdbplugin.InitializeResponse{}, errwrap.Wrapf("Error parsing the given PEM information: {{err}}", err)
return dbplugin.InitializeResponse{}, errwrap.Wrapf("Error parsing the given PEM information: {{err}}", err)
}
certBundle, err = parsedCertBundle.ToCertBundle()
if err != nil {
return newdbplugin.InitializeResponse{}, errwrap.Wrapf("Error marshaling PEM information: {{err}}", err)
return dbplugin.InitializeResponse{}, errwrap.Wrapf("Error marshaling PEM information: {{err}}", err)
}
i.certificate = certBundle.Certificate
i.privateKey = certBundle.PrivateKey
@@ -112,11 +112,11 @@ func (i *influxdbConnectionProducer) Initialize(ctx context.Context, req newdbpl
if req.VerifyConnection {
if _, err := i.Connection(ctx); err != nil {
return newdbplugin.InitializeResponse{}, errwrap.Wrapf("error verifying connection: {{err}}", err)
return dbplugin.InitializeResponse{}, errwrap.Wrapf("error verifying connection: {{err}}", err)
}
}
resp := newdbplugin.InitializeResponse{
resp := dbplugin.InitializeResponse{
Config: req.Config,
}

View File

@@ -5,12 +5,11 @@ import (
"fmt"
"strings"
"github.com/hashicorp/vault/sdk/database/helper/credsutil"
multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/api"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/database/helper/credsutil"
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
"github.com/hashicorp/vault/sdk/helper/strutil"
influx "github.com/influxdata/influxdb/client/v2"
)
@@ -22,7 +21,7 @@ const (
influxdbTypeName = "influxdb"
)
var _ newdbplugin.Database = &Influxdb{}
var _ dbplugin.Database = &Influxdb{}
// Influxdb is an implementation of Database interface
type Influxdb struct {
@@ -32,7 +31,7 @@ type Influxdb struct {
// New returns a new Cassandra instance
func New() (interface{}, error) {
db := new()
dbType := newdbplugin.NewDatabaseErrorSanitizerMiddleware(db, db.secretValues)
dbType := dbplugin.NewDatabaseErrorSanitizerMiddleware(db, db.secretValues)
return dbType, nil
}
@@ -53,7 +52,7 @@ func Run(apiTLSConfig *api.TLSConfig) error {
return err
}
newdbplugin.Serve(dbType.(newdbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
dbplugin.Serve(dbType.(dbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
return nil
}
@@ -74,13 +73,13 @@ func (i *Influxdb) getConnection(ctx context.Context) (influx.Client, error) {
// NewUser generates the username/password on the underlying Influxdb secret backend as instructed by
// the statements provided.
func (i *Influxdb) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (resp newdbplugin.NewUserResponse, err error) {
func (i *Influxdb) NewUser(ctx context.Context, req dbplugin.NewUserRequest) (resp dbplugin.NewUserResponse, err error) {
i.Lock()
defer i.Unlock()
cli, err := i.getConnection(ctx)
if err != nil {
return newdbplugin.NewUserResponse{}, fmt.Errorf("unable to get connection: %w", err)
return dbplugin.NewUserResponse{}, fmt.Errorf("unable to get connection: %w", err)
}
creationIFQL := req.Statements.Commands
@@ -101,7 +100,7 @@ func (i *Influxdb) NewUser(ctx context.Context, req newdbplugin.NewUserRequest)
credsutil.ToLower(),
)
if err != nil {
return newdbplugin.NewUserResponse{}, fmt.Errorf("failed to generate username: %w", err)
return dbplugin.NewUserResponse{}, fmt.Errorf("failed to generate username: %w", err)
}
username = strings.Replace(username, "-", "_", -1)
@@ -122,11 +121,11 @@ func (i *Influxdb) NewUser(ctx context.Context, req newdbplugin.NewUserRequest)
if response != nil && response.Error() != nil {
attemptRollback(cli, username, rollbackIFQL)
}
return newdbplugin.NewUserResponse{}, fmt.Errorf("failed to run query in InfluxDB: %w", err)
return dbplugin.NewUserResponse{}, fmt.Errorf("failed to run query in InfluxDB: %w", err)
}
}
}
resp = newdbplugin.NewUserResponse{
resp = dbplugin.NewUserResponse{
Username: username,
}
return resp, nil
@@ -157,13 +156,13 @@ func attemptRollback(cli influx.Client, username string, rollbackStatements []st
return nil
}
func (i *Influxdb) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserRequest) (newdbplugin.DeleteUserResponse, error) {
func (i *Influxdb) DeleteUser(ctx context.Context, req dbplugin.DeleteUserRequest) (dbplugin.DeleteUserResponse, error) {
i.Lock()
defer i.Unlock()
cli, err := i.getConnection(ctx)
if err != nil {
return newdbplugin.DeleteUserResponse{}, fmt.Errorf("unable to get connection: %w", err)
return dbplugin.DeleteUserResponse{}, fmt.Errorf("unable to get connection: %w", err)
}
revocationIFQL := req.Statements.Commands
@@ -190,14 +189,14 @@ func (i *Influxdb) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserReq
}
}
if result.ErrorOrNil() != nil {
return newdbplugin.DeleteUserResponse{}, fmt.Errorf("failed to delete user cleanly: %w", result.ErrorOrNil())
return dbplugin.DeleteUserResponse{}, fmt.Errorf("failed to delete user cleanly: %w", result.ErrorOrNil())
}
return newdbplugin.DeleteUserResponse{}, nil
return dbplugin.DeleteUserResponse{}, nil
}
func (i *Influxdb) UpdateUser(ctx context.Context, req newdbplugin.UpdateUserRequest) (newdbplugin.UpdateUserResponse, error) {
func (i *Influxdb) UpdateUser(ctx context.Context, req dbplugin.UpdateUserRequest) (dbplugin.UpdateUserResponse, error) {
if req.Password == nil && req.Expiration == nil {
return newdbplugin.UpdateUserResponse{}, fmt.Errorf("no changes requested")
return dbplugin.UpdateUserResponse{}, fmt.Errorf("no changes requested")
}
i.Lock()
@@ -206,14 +205,14 @@ func (i *Influxdb) UpdateUser(ctx context.Context, req newdbplugin.UpdateUserReq
if req.Password != nil {
err := i.changeUserPassword(ctx, req.Username, req.Password)
if err != nil {
return newdbplugin.UpdateUserResponse{}, fmt.Errorf("failed to change %q password: %w", req.Username, err)
return dbplugin.UpdateUserResponse{}, fmt.Errorf("failed to change %q password: %w", req.Username, err)
}
}
// Expiration is a no-op
return newdbplugin.UpdateUserResponse{}, nil
return dbplugin.UpdateUserResponse{}, nil
}
func (i *Influxdb) changeUserPassword(ctx context.Context, username string, changePassword *newdbplugin.ChangePassword) error {
func (i *Influxdb) changeUserPassword(ctx context.Context, username string, changePassword *dbplugin.ChangePassword) error {
cli, err := i.getConnection(ctx)
if err != nil {
return fmt.Errorf("unable to get connection: %w", err)

View File

@@ -11,12 +11,10 @@ import (
"testing"
"time"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
dbtesting "github.com/hashicorp/vault/sdk/database/newdbplugin/testing"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/vault/helper/testhelpers/docker"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
dbtesting "github.com/hashicorp/vault/sdk/database/dbplugin/v5/testing"
influx "github.com/influxdata/influxdb/client/v2"
)
@@ -101,78 +99,78 @@ func TestInfluxdb_Initialize(t *testing.T) {
defer cleanup()
type testCase struct {
req newdbplugin.InitializeRequest
expectedResponse newdbplugin.InitializeResponse
req dbplugin.InitializeRequest
expectedResponse dbplugin.InitializeResponse
expectErr bool
expectInitialized bool
}
tests := map[string]testCase{
"port is an int": {
req: newdbplugin.InitializeRequest{
req: dbplugin.InitializeRequest{
Config: makeConfig(config.connectionParams()),
VerifyConnection: true,
},
expectedResponse: newdbplugin.InitializeResponse{
expectedResponse: dbplugin.InitializeResponse{
Config: config.connectionParams(),
},
expectErr: false,
expectInitialized: true,
},
"port is a string": {
req: newdbplugin.InitializeRequest{
req: dbplugin.InitializeRequest{
Config: makeConfig(config.connectionParams(), "port", strconv.Itoa(config.connectionParams()["port"].(int))),
VerifyConnection: true,
},
expectedResponse: newdbplugin.InitializeResponse{
expectedResponse: dbplugin.InitializeResponse{
Config: makeConfig(config.connectionParams(), "port", strconv.Itoa(config.connectionParams()["port"].(int))),
},
expectErr: false,
expectInitialized: true,
},
"missing config": {
req: newdbplugin.InitializeRequest{
req: dbplugin.InitializeRequest{
Config: nil,
VerifyConnection: true,
},
expectedResponse: newdbplugin.InitializeResponse{},
expectedResponse: dbplugin.InitializeResponse{},
expectErr: true,
expectInitialized: false,
},
"missing host": {
req: newdbplugin.InitializeRequest{
req: dbplugin.InitializeRequest{
Config: makeConfig(config.connectionParams(), "host", ""),
VerifyConnection: true,
},
expectedResponse: newdbplugin.InitializeResponse{},
expectedResponse: dbplugin.InitializeResponse{},
expectErr: true,
expectInitialized: false,
},
"missing username": {
req: newdbplugin.InitializeRequest{
req: dbplugin.InitializeRequest{
Config: makeConfig(config.connectionParams(), "username", ""),
VerifyConnection: true,
},
expectedResponse: newdbplugin.InitializeResponse{},
expectedResponse: dbplugin.InitializeResponse{},
expectErr: true,
expectInitialized: false,
},
"missing password": {
req: newdbplugin.InitializeRequest{
req: dbplugin.InitializeRequest{
Config: makeConfig(config.connectionParams(), "password", ""),
VerifyConnection: true,
},
expectedResponse: newdbplugin.InitializeResponse{},
expectedResponse: dbplugin.InitializeResponse{},
expectErr: true,
expectInitialized: false,
},
"failed to validate connection": {
req: newdbplugin.InitializeRequest{
req: dbplugin.InitializeRequest{
// Host exists, but isn't a running instance
Config: makeConfig(config.connectionParams(), "host", "foobar://bad_connection"),
VerifyConnection: true,
},
expectedResponse: newdbplugin.InitializeResponse{},
expectedResponse: dbplugin.InitializeResponse{},
expectErr: true,
expectInitialized: true,
},
@@ -227,19 +225,19 @@ func TestInfluxdb_CreateUser(t *testing.T) {
defer cleanup()
db := new()
req := newdbplugin.InitializeRequest{
req := dbplugin.InitializeRequest{
Config: config.connectionParams(),
VerifyConnection: true,
}
dbtesting.AssertInitialize(t, db, req)
password := "nuozxby98523u89bdfnkjl"
newUserReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
newUserReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{createUserStatements},
},
Password: password,
@@ -261,19 +259,19 @@ func TestUpdateUser_expiration(t *testing.T) {
defer cleanup()
db := new()
req := newdbplugin.InitializeRequest{
req := dbplugin.InitializeRequest{
Config: config.connectionParams(),
VerifyConnection: true,
}
dbtesting.AssertInitialize(t, db, req)
password := "nuozxby98523u89bdfnkjl"
newUserReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
newUserReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{createUserStatements},
},
Password: password,
@@ -283,9 +281,9 @@ func TestUpdateUser_expiration(t *testing.T) {
assertCredsExist(t, config.URL().String(), newUserResp.Username, password)
renewReq := newdbplugin.UpdateUserRequest{
renewReq := dbplugin.UpdateUserRequest{
Username: newUserResp.Username,
Expiration: &newdbplugin.ChangeExpiration{
Expiration: &dbplugin.ChangeExpiration{
NewExpiration: time.Now().Add(5 * time.Minute),
},
}
@@ -300,19 +298,19 @@ func TestUpdateUser_password(t *testing.T) {
defer cleanup()
db := new()
req := newdbplugin.InitializeRequest{
req := dbplugin.InitializeRequest{
Config: config.connectionParams(),
VerifyConnection: true,
}
dbtesting.AssertInitialize(t, db, req)
initialPassword := "nuozxby98523u89bdfnkjl"
newUserReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
newUserReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{createUserStatements},
},
Password: initialPassword,
@@ -323,9 +321,9 @@ func TestUpdateUser_password(t *testing.T) {
assertCredsExist(t, config.URL().String(), newUserResp.Username, initialPassword)
newPassword := "y89qgmbzadiygry8uazodijnb"
newPasswordReq := newdbplugin.UpdateUserRequest{
newPasswordReq := dbplugin.UpdateUserRequest{
Username: newUserResp.Username,
Password: &newdbplugin.ChangePassword{
Password: &dbplugin.ChangePassword{
NewPassword: newPassword,
},
}
@@ -346,14 +344,14 @@ func TestInfluxdb_RevokeDeletedUser(t *testing.T) {
defer cleanup()
db := new()
req := newdbplugin.InitializeRequest{
req := dbplugin.InitializeRequest{
Config: config.connectionParams(),
VerifyConnection: true,
}
dbtesting.AssertInitialize(t, db, req)
// attempt to revoke a user that does not exist
delReq := newdbplugin.DeleteUserRequest{
delReq := dbplugin.DeleteUserRequest{
Username: "someuser",
}
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
@@ -369,19 +367,19 @@ func TestInfluxdb_RevokeUser(t *testing.T) {
defer cleanup()
db := new()
req := newdbplugin.InitializeRequest{
req := dbplugin.InitializeRequest{
Config: config.connectionParams(),
VerifyConnection: true,
}
dbtesting.AssertInitialize(t, db, req)
initialPassword := "nuozxby98523u89bdfnkjl"
newUserReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
newUserReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{createUserStatements},
},
Password: initialPassword,
@@ -391,7 +389,7 @@ func TestInfluxdb_RevokeUser(t *testing.T) {
assertCredsExist(t, config.URL().String(), newUserResp.Username, initialPassword)
delReq := newdbplugin.DeleteUserRequest{
delReq := dbplugin.DeleteUserRequest{
Username: newUserResp.Username,
}
dbtesting.AssertDeleteUser(t, db, delReq)

View File

@@ -10,10 +10,9 @@ import (
"sync"
"time"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/vault/sdk/database/helper/connutil"
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
"github.com/hashicorp/errwrap"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"

View File

@@ -15,7 +15,7 @@ import (
"github.com/hashicorp/vault/helper/testhelpers/certhelpers"
"github.com/hashicorp/vault/helper/testhelpers/mongodb"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/ory/dockertest"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
@@ -79,7 +79,7 @@ net:
// Test
mongo := new()
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: map[string]interface{}{
"connection_url": retURL,
"allowed_roles": "*",

View File

@@ -8,9 +8,9 @@ import (
"strings"
"github.com/hashicorp/vault/api"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/database/helper/credsutil"
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
"github.com/mitchellh/mapstructure"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
@@ -26,12 +26,12 @@ type MongoDB struct {
*mongoDBConnectionProducer
}
var _ newdbplugin.Database = &MongoDB{}
var _ dbplugin.Database = &MongoDB{}
// New returns a new MongoDB instance
func New() (interface{}, error) {
db := new()
dbType := newdbplugin.NewDatabaseErrorSanitizerMiddleware(db, db.secretValues)
dbType := dbplugin.NewDatabaseErrorSanitizerMiddleware(db, db.secretValues)
return dbType, nil
}
@@ -52,7 +52,7 @@ func Run(apiTLSConfig *api.TLSConfig) error {
return err
}
newdbplugin.Serve(dbType.(newdbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
dbplugin.Serve(dbType.(dbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
return nil
}
@@ -71,7 +71,7 @@ func (m *MongoDB) getConnection(ctx context.Context) (*mongo.Client, error) {
return client.(*mongo.Client), nil
}
func (m *MongoDB) Initialize(ctx context.Context, req newdbplugin.InitializeRequest) (newdbplugin.InitializeResponse, error) {
func (m *MongoDB) Initialize(ctx context.Context, req dbplugin.InitializeRequest) (dbplugin.InitializeResponse, error) {
m.Lock()
defer m.Unlock()
@@ -79,21 +79,21 @@ func (m *MongoDB) Initialize(ctx context.Context, req newdbplugin.InitializeRequ
err := mapstructure.WeakDecode(req.Config, m.mongoDBConnectionProducer)
if err != nil {
return newdbplugin.InitializeResponse{}, err
return dbplugin.InitializeResponse{}, err
}
if len(m.ConnectionURL) == 0 {
return newdbplugin.InitializeResponse{}, fmt.Errorf("connection_url cannot be empty-mongo fail")
return dbplugin.InitializeResponse{}, fmt.Errorf("connection_url cannot be empty-mongo fail")
}
writeOpts, err := m.getWriteConcern()
if err != nil {
return newdbplugin.InitializeResponse{}, err
return dbplugin.InitializeResponse{}, err
}
authOpts, err := m.getTLSAuth()
if err != nil {
return newdbplugin.InitializeResponse{}, err
return dbplugin.InitializeResponse{}, err
}
m.clientOptions = options.MergeClientOptions(writeOpts, authOpts)
@@ -105,28 +105,28 @@ func (m *MongoDB) Initialize(ctx context.Context, req newdbplugin.InitializeRequ
if req.VerifyConnection {
_, err := m.Connection(ctx)
if err != nil {
return newdbplugin.InitializeResponse{}, fmt.Errorf("failed to verify connection: %w", err)
return dbplugin.InitializeResponse{}, fmt.Errorf("failed to verify connection: %w", err)
}
err = m.client.Ping(ctx, readpref.Primary())
if err != nil {
return newdbplugin.InitializeResponse{}, fmt.Errorf("failed to verify connection: %w", err)
return dbplugin.InitializeResponse{}, fmt.Errorf("failed to verify connection: %w", err)
}
}
resp := newdbplugin.InitializeResponse{
resp := dbplugin.InitializeResponse{
Config: req.Config,
}
return resp, nil
}
func (m *MongoDB) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (newdbplugin.NewUserResponse, error) {
func (m *MongoDB) NewUser(ctx context.Context, req dbplugin.NewUserRequest) (dbplugin.NewUserResponse, error) {
// Grab the lock
m.Lock()
defer m.Unlock()
if len(req.Statements.Commands) == 0 {
return newdbplugin.NewUserResponse{}, dbutil.ErrEmptyCreationStatement
return dbplugin.NewUserResponse{}, dbutil.ErrEmptyCreationStatement
}
username, err := credsutil.GenerateUsername(
@@ -136,14 +136,14 @@ func (m *MongoDB) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (
credsutil.Separator("-"),
)
if err != nil {
return newdbplugin.NewUserResponse{}, err
return dbplugin.NewUserResponse{}, err
}
// Unmarshal statements.CreationStatements into mongodbRoles
var mongoCS mongoDBStatement
err = json.Unmarshal([]byte(req.Statements.Commands[0]), &mongoCS)
if err != nil {
return newdbplugin.NewUserResponse{}, err
return dbplugin.NewUserResponse{}, err
}
// Default to "admin" if no db provided
@@ -152,7 +152,7 @@ func (m *MongoDB) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (
}
if len(mongoCS.Roles) == 0 {
return newdbplugin.NewUserResponse{}, fmt.Errorf("roles array is required in creation statement")
return dbplugin.NewUserResponse{}, fmt.Errorf("roles array is required in creation statement")
}
createUserCmd := createUserCommand{
@@ -162,21 +162,21 @@ func (m *MongoDB) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (
}
if err := m.runCommandWithRetry(ctx, mongoCS.DB, createUserCmd); err != nil {
return newdbplugin.NewUserResponse{}, err
return dbplugin.NewUserResponse{}, err
}
resp := newdbplugin.NewUserResponse{
resp := dbplugin.NewUserResponse{
Username: username,
}
return resp, nil
}
func (m *MongoDB) UpdateUser(ctx context.Context, req newdbplugin.UpdateUserRequest) (newdbplugin.UpdateUserResponse, error) {
func (m *MongoDB) UpdateUser(ctx context.Context, req dbplugin.UpdateUserRequest) (dbplugin.UpdateUserResponse, error) {
if req.Password != nil {
err := m.changeUserPassword(ctx, req.Username, req.Password.NewPassword)
return newdbplugin.UpdateUserResponse{}, err
return dbplugin.UpdateUserResponse{}, err
}
return newdbplugin.UpdateUserResponse{}, nil
return dbplugin.UpdateUserResponse{}, nil
}
func (m *MongoDB) changeUserPassword(ctx context.Context, username, password string) error {
@@ -208,7 +208,7 @@ func (m *MongoDB) changeUserPassword(ctx context.Context, username, password str
return nil
}
func (m *MongoDB) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserRequest) (newdbplugin.DeleteUserResponse, error) {
func (m *MongoDB) DeleteUser(ctx context.Context, req dbplugin.DeleteUserRequest) (dbplugin.DeleteUserResponse, error) {
m.Lock()
defer m.Unlock()
@@ -220,14 +220,14 @@ func (m *MongoDB) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserRequ
case 1:
revocationStatement = req.Statements.Commands[0]
default:
return newdbplugin.DeleteUserResponse{}, fmt.Errorf("expected 0 or 1 revocation statements, got %d", len(req.Statements.Commands))
return dbplugin.DeleteUserResponse{}, fmt.Errorf("expected 0 or 1 revocation statements, got %d", len(req.Statements.Commands))
}
// Unmarshal revocation statements into mongodbRoles
var mongoCS mongoDBStatement
err := json.Unmarshal([]byte(revocationStatement), &mongoCS)
if err != nil {
return newdbplugin.DeleteUserResponse{}, err
return dbplugin.DeleteUserResponse{}, err
}
db := mongoCS.DB
@@ -242,7 +242,7 @@ func (m *MongoDB) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserRequ
}
err = m.runCommandWithRetry(ctx, db, dropUserCmd)
return newdbplugin.DeleteUserResponse{}, err
return dbplugin.DeleteUserResponse{}, err
}
// runCommandWithRetry runs a command and retries once more if there's a failure

View File

@@ -12,8 +12,8 @@ import (
"github.com/hashicorp/vault/helper/testhelpers/certhelpers"
"github.com/hashicorp/vault/helper/testhelpers/mongodb"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
dbtesting "github.com/hashicorp/vault/sdk/database/newdbplugin/testing"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
dbtesting "github.com/hashicorp/vault/sdk/database/dbplugin/v5/testing"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"go.mongodb.org/mongo-driver/mongo/readpref"
@@ -35,7 +35,7 @@ func TestMongoDB_Initialize(t *testing.T) {
// Make a copy since the original map could be modified by the Initialize call
expectedConfig := copyConfig(config)
req := newdbplugin.InitializeRequest{
req := dbplugin.InitializeRequest{
Config: config,
VerifyConnection: true,
}
@@ -58,7 +58,7 @@ func TestMongoDB_CreateUser(t *testing.T) {
db := new()
defer dbtesting.AssertClose(t, db)
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: map[string]interface{}{
"connection_url": connURL,
},
@@ -67,12 +67,12 @@ func TestMongoDB_CreateUser(t *testing.T) {
dbtesting.AssertInitialize(t, db, initReq)
password := "myreallysecurepassword"
createReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
createReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{mongoAdminRole},
},
Password: password,
@@ -87,7 +87,7 @@ func TestMongoDB_CreateUser_writeConcern(t *testing.T) {
cleanup, connURL := mongodb.PrepareTestContainer(t, "latest")
defer cleanup()
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: map[string]interface{}{
"connection_url": connURL,
"write_concern": `{ "wmode": "majority", "wtimeout": 5000 }`,
@@ -101,12 +101,12 @@ func TestMongoDB_CreateUser_writeConcern(t *testing.T) {
dbtesting.AssertInitialize(t, db, initReq)
password := "myreallysecurepassword"
createReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
createReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{mongoAdminRole},
},
Password: password,
@@ -124,7 +124,7 @@ func TestMongoDB_DeleteUser(t *testing.T) {
db := new()
defer dbtesting.AssertClose(t, db)
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: map[string]interface{}{
"connection_url": connURL,
},
@@ -133,12 +133,12 @@ func TestMongoDB_DeleteUser(t *testing.T) {
dbtesting.AssertInitialize(t, db, initReq)
password := "myreallysecurepassword"
createReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
createReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{mongoAdminRole},
},
Password: password,
@@ -148,7 +148,7 @@ func TestMongoDB_DeleteUser(t *testing.T) {
assertCredsExist(t, createResp.Username, password, connURL)
// Test default revocation statement
delReq := newdbplugin.DeleteUserRequest{
delReq := dbplugin.DeleteUserRequest{
Username: createResp.Username,
}
@@ -167,7 +167,7 @@ func TestMongoDB_UpdateUser_Password(t *testing.T) {
db := new()
defer dbtesting.AssertClose(t, db)
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: map[string]interface{}{
"connection_url": connURL,
},
@@ -182,9 +182,9 @@ func TestMongoDB_UpdateUser_Password(t *testing.T) {
newPassword := "myreallysecurecredentials"
updateReq := newdbplugin.UpdateUserRequest{
updateReq := dbplugin.UpdateUserRequest{
Username: dbUser,
Password: &newdbplugin.ChangePassword{
Password: &dbplugin.ChangePassword{
NewPassword: newPassword,
},
}

View File

@@ -11,17 +11,17 @@ import (
"github.com/hashicorp/errwrap"
multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/api"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/database/helper/connutil"
"github.com/hashicorp/vault/sdk/database/helper/credsutil"
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
"github.com/hashicorp/vault/sdk/helper/dbtxn"
"github.com/hashicorp/vault/sdk/helper/strutil"
)
const msSQLTypeName = "mssql"
var _ newdbplugin.Database = &MSSQL{}
var _ dbplugin.Database = &MSSQL{}
// MSSQL is an implementation of Database interface
type MSSQL struct {
@@ -31,7 +31,7 @@ type MSSQL struct {
func New() (interface{}, error) {
db := new()
// Wrap the plugin with middleware to sanitize errors
dbType := newdbplugin.NewDatabaseErrorSanitizerMiddleware(db, db.secretValues)
dbType := dbplugin.NewDatabaseErrorSanitizerMiddleware(db, db.secretValues)
return dbType, nil
}
@@ -52,7 +52,7 @@ func Run(apiTLSConfig *api.TLSConfig) error {
return err
}
newdbplugin.Serve(dbType.(newdbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
dbplugin.Serve(dbType.(dbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
return nil
}
@@ -77,12 +77,12 @@ func (m *MSSQL) getConnection(ctx context.Context) (*sql.DB, error) {
return db.(*sql.DB), nil
}
func (m *MSSQL) Initialize(ctx context.Context, req newdbplugin.InitializeRequest) (newdbplugin.InitializeResponse, error) {
func (m *MSSQL) Initialize(ctx context.Context, req dbplugin.InitializeRequest) (dbplugin.InitializeResponse, error) {
newConf, err := m.SQLConnectionProducer.Init(ctx, req.Config, req.VerifyConnection)
if err != nil {
return newdbplugin.InitializeResponse{}, err
return dbplugin.InitializeResponse{}, err
}
resp := newdbplugin.InitializeResponse{
resp := dbplugin.InitializeResponse{
Config: newConf,
}
return resp, nil
@@ -90,17 +90,17 @@ func (m *MSSQL) Initialize(ctx context.Context, req newdbplugin.InitializeReques
// NewUser generates the username/password on the underlying MSSQL secret backend as instructed by
// the statements provided.
func (m *MSSQL) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (newdbplugin.NewUserResponse, error) {
func (m *MSSQL) NewUser(ctx context.Context, req dbplugin.NewUserRequest) (dbplugin.NewUserResponse, error) {
m.Lock()
defer m.Unlock()
db, err := m.getConnection(ctx)
if err != nil {
return newdbplugin.NewUserResponse{}, fmt.Errorf("unable to get connection: %w", err)
return dbplugin.NewUserResponse{}, fmt.Errorf("unable to get connection: %w", err)
}
if len(req.Statements.Commands) == 0 {
return newdbplugin.NewUserResponse{}, dbutil.ErrEmptyCreationStatement
return dbplugin.NewUserResponse{}, dbutil.ErrEmptyCreationStatement
}
username, err := credsutil.GenerateUsername(
@@ -110,14 +110,14 @@ func (m *MSSQL) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (ne
credsutil.Separator("-"),
)
if err != nil {
return newdbplugin.NewUserResponse{}, err
return dbplugin.NewUserResponse{}, err
}
expirationStr := req.Expiration.Format("2006-01-02 15:04:05-0700")
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return newdbplugin.NewUserResponse{}, err
return dbplugin.NewUserResponse{}, err
}
defer tx.Rollback()
@@ -135,16 +135,16 @@ func (m *MSSQL) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (ne
}
if err := dbtxn.ExecuteTxQuery(ctx, tx, m, query); err != nil {
return newdbplugin.NewUserResponse{}, err
return dbplugin.NewUserResponse{}, err
}
}
}
if err := tx.Commit(); err != nil {
return newdbplugin.NewUserResponse{}, err
return dbplugin.NewUserResponse{}, err
}
resp := newdbplugin.NewUserResponse{
resp := dbplugin.NewUserResponse{
Username: username,
}
@@ -154,15 +154,15 @@ func (m *MSSQL) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (ne
// DeleteUser attempts to drop the specified user. It will first attempt to disable login,
// then kill pending connections from that user, and finally drop the user and login from the
// database instance.
func (m *MSSQL) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserRequest) (newdbplugin.DeleteUserResponse, error) {
func (m *MSSQL) DeleteUser(ctx context.Context, req dbplugin.DeleteUserRequest) (dbplugin.DeleteUserResponse, error) {
if len(req.Statements.Commands) == 0 {
err := m.revokeUserDefault(ctx, req.Username)
return newdbplugin.DeleteUserResponse{}, err
return dbplugin.DeleteUserResponse{}, err
}
db, err := m.getConnection(ctx)
if err != nil {
return newdbplugin.DeleteUserResponse{}, fmt.Errorf("unable to get connection: %w", err)
return dbplugin.DeleteUserResponse{}, fmt.Errorf("unable to get connection: %w", err)
}
merr := &multierror.Error{}
@@ -184,7 +184,7 @@ func (m *MSSQL) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserReques
}
}
return newdbplugin.DeleteUserResponse{}, merr.ErrorOrNil()
return dbplugin.DeleteUserResponse{}, merr.ErrorOrNil()
}
func (m *MSSQL) revokeUserDefault(ctx context.Context, username string) error {
@@ -290,19 +290,19 @@ func (m *MSSQL) revokeUserDefault(ctx context.Context, username string) error {
return nil
}
func (m *MSSQL) UpdateUser(ctx context.Context, req newdbplugin.UpdateUserRequest) (newdbplugin.UpdateUserResponse, error) {
func (m *MSSQL) UpdateUser(ctx context.Context, req dbplugin.UpdateUserRequest) (dbplugin.UpdateUserResponse, error) {
if req.Password == nil && req.Expiration == nil {
return newdbplugin.UpdateUserResponse{}, fmt.Errorf("no changes requested")
return dbplugin.UpdateUserResponse{}, fmt.Errorf("no changes requested")
}
if req.Password != nil {
err := m.updateUserPass(ctx, req.Username, req.Password)
return newdbplugin.UpdateUserResponse{}, err
return dbplugin.UpdateUserResponse{}, err
}
// Expiration is a no-op
return newdbplugin.UpdateUserResponse{}, nil
return dbplugin.UpdateUserResponse{}, nil
}
func (m *MSSQL) updateUserPass(ctx context.Context, username string, changePass *newdbplugin.ChangePassword) error {
func (m *MSSQL) updateUserPass(ctx context.Context, username string, changePass *dbplugin.ChangePassword) error {
stmts := changePass.Statements.Commands
if len(stmts) == 0 {
stmts = []string{alterLoginSQL}

View File

@@ -10,11 +10,10 @@ import (
"testing"
"time"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
dbtesting "github.com/hashicorp/vault/sdk/database/newdbplugin/testing"
"github.com/hashicorp/vault/sdk/helper/dbtxn"
mssqlhelper "github.com/hashicorp/vault/helper/testhelpers/mssql"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
dbtesting "github.com/hashicorp/vault/sdk/database/dbplugin/v5/testing"
"github.com/hashicorp/vault/sdk/helper/dbtxn"
)
func TestInitialize(t *testing.T) {
@@ -22,12 +21,12 @@ func TestInitialize(t *testing.T) {
defer cleanup()
type testCase struct {
req newdbplugin.InitializeRequest
req dbplugin.InitializeRequest
}
tests := map[string]testCase{
"happy path": {
req: newdbplugin.InitializeRequest{
req: dbplugin.InitializeRequest{
Config: map[string]interface{}{
"connection_url": connURL,
},
@@ -35,7 +34,7 @@ func TestInitialize(t *testing.T) {
},
},
"max_open_connections set": {
newdbplugin.InitializeRequest{
dbplugin.InitializeRequest{
Config: map[string]interface{}{
"connection_url": connURL,
"max_open_connections": "5",
@@ -63,7 +62,7 @@ func TestNewUser(t *testing.T) {
defer cleanup()
type testCase struct {
req newdbplugin.NewUserRequest
req dbplugin.NewUserRequest
usernameRegex string
expectErr bool
assertUser func(t testing.TB, connURL, username, password string)
@@ -71,12 +70,12 @@ func TestNewUser(t *testing.T) {
tests := map[string]testCase{
"no creation statements": {
req: newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
req: dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{},
Statements: dbplugin.Statements{},
Password: "AG4qagho-dsvZ",
Expiration: time.Now().Add(1 * time.Second),
},
@@ -85,12 +84,12 @@ func TestNewUser(t *testing.T) {
assertUser: assertCredsDoNotExist,
},
"with creation statements": {
req: newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
req: dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{testMSSQLRole},
},
Password: "AG4qagho-dsvZ",
@@ -109,7 +108,7 @@ func TestNewUser(t *testing.T) {
t.Fatalf("failed to compile username regex %q: %s", test.usernameRegex, err)
}
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: map[string]interface{}{
"connection_url": connURL,
},
@@ -133,7 +132,7 @@ func TestNewUser(t *testing.T) {
}
// Protect against future fields that aren't specified
expectedResp := newdbplugin.NewUserResponse{
expectedResp := dbplugin.NewUserResponse{
Username: createResp.Username,
}
if !reflect.DeepEqual(createResp, expectedResp) {
@@ -147,7 +146,7 @@ func TestNewUser(t *testing.T) {
func TestUpdateUser_password(t *testing.T) {
type testCase struct {
req newdbplugin.UpdateUserRequest
req dbplugin.UpdateUserRequest
expectErr bool
expectedPassword string
}
@@ -157,33 +156,33 @@ func TestUpdateUser_password(t *testing.T) {
tests := map[string]testCase{
"missing password": {
req: newdbplugin.UpdateUserRequest{
req: dbplugin.UpdateUserRequest{
Username: dbUser,
Password: &newdbplugin.ChangePassword{
Password: &dbplugin.ChangePassword{
NewPassword: "",
Statements: newdbplugin.Statements{},
Statements: dbplugin.Statements{},
},
},
expectErr: true,
expectedPassword: initPassword,
},
"empty rotation statements": {
req: newdbplugin.UpdateUserRequest{
req: dbplugin.UpdateUserRequest{
Username: dbUser,
Password: &newdbplugin.ChangePassword{
Password: &dbplugin.ChangePassword{
NewPassword: "N90gkKLy8$angf",
Statements: newdbplugin.Statements{},
Statements: dbplugin.Statements{},
},
},
expectErr: false,
expectedPassword: "N90gkKLy8$angf",
},
"username rotation": {
req: newdbplugin.UpdateUserRequest{
req: dbplugin.UpdateUserRequest{
Username: dbUser,
Password: &newdbplugin.ChangePassword{
Password: &dbplugin.ChangePassword{
NewPassword: "N90gkKLy8$angf",
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{
"ALTER LOGIN [{{username}}] WITH PASSWORD = '{{password}}'",
},
@@ -194,11 +193,11 @@ func TestUpdateUser_password(t *testing.T) {
expectedPassword: "N90gkKLy8$angf",
},
"bad statements": {
req: newdbplugin.UpdateUserRequest{
req: dbplugin.UpdateUserRequest{
Username: dbUser,
Password: &newdbplugin.ChangePassword{
Password: &dbplugin.ChangePassword{
NewPassword: "N90gkKLy8$angf",
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{
"ahosh98asjdffs",
},
@@ -215,7 +214,7 @@ func TestUpdateUser_password(t *testing.T) {
cleanup, connURL := mssqlhelper.PrepareMSSQLTestContainer(t)
defer cleanup()
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: map[string]interface{}{
"connection_url": connURL,
},
@@ -241,7 +240,7 @@ func TestUpdateUser_password(t *testing.T) {
}
// Protect against future fields that aren't specified
expectedResp := newdbplugin.UpdateUserResponse{}
expectedResp := dbplugin.UpdateUserResponse{}
if !reflect.DeepEqual(updateResp, expectedResp) {
t.Fatalf("Fields missing from expected response: Actual: %#v", updateResp)
}
@@ -258,7 +257,7 @@ func TestDeleteUser(t *testing.T) {
dbUser := "vaultuser"
initPassword := "p4$sw0rd"
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: map[string]interface{}{
"connection_url": connURL,
},
@@ -273,7 +272,7 @@ func TestDeleteUser(t *testing.T) {
assertCredsExist(t, connURL, dbUser, initPassword)
deleteReq := newdbplugin.DeleteUserRequest{
deleteReq := dbplugin.DeleteUserRequest{
Username: dbUser,
}
@@ -285,7 +284,7 @@ func TestDeleteUser(t *testing.T) {
}
// Protect against future fields that aren't specified
expectedResp := newdbplugin.DeleteUserResponse{}
expectedResp := dbplugin.DeleteUserResponse{}
if !reflect.DeepEqual(deleteResp, expectedResp) {
t.Fatalf("Fields missing from expected response: Actual: %#v", deleteResp)
}

View File

@@ -7,14 +7,13 @@ import (
"fmt"
"strings"
stdmysql "github.com/go-sql-driver/mysql"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/vault/api"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/database/helper/credsutil"
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
"github.com/hashicorp/vault/sdk/helper/strutil"
stdmysql "github.com/go-sql-driver/mysql"
)
const (
@@ -37,7 +36,7 @@ var (
LegacyUsernameLen int = 16
)
var _ newdbplugin.Database = (*MySQL)(nil)
var _ dbplugin.Database = (*MySQL)(nil)
type MySQL struct {
*mySQLConnectionProducer
@@ -49,7 +48,7 @@ func New(legacy bool) func() (interface{}, error) {
return func() (interface{}, error) {
db := new(legacy)
// Wrap the plugin with middleware to sanitize errors
dbType := newdbplugin.NewDatabaseErrorSanitizerMiddleware(db, db.SecretValues)
dbType := dbplugin.NewDatabaseErrorSanitizerMiddleware(db, db.SecretValues)
return dbType, nil
}
@@ -82,7 +81,7 @@ func runCommon(legacy bool, apiTLSConfig *api.TLSConfig) error {
return err
}
newdbplugin.Serve(dbType.(newdbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
dbplugin.Serve(dbType.(dbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
return nil
}
@@ -100,25 +99,25 @@ func (m *MySQL) getConnection(ctx context.Context) (*sql.DB, error) {
return db.(*sql.DB), nil
}
func (m *MySQL) Initialize(ctx context.Context, req newdbplugin.InitializeRequest) (newdbplugin.InitializeResponse, error) {
func (m *MySQL) Initialize(ctx context.Context, req dbplugin.InitializeRequest) (dbplugin.InitializeResponse, error) {
err := m.mySQLConnectionProducer.Initialize(ctx, req.Config, req.VerifyConnection)
if err != nil {
return newdbplugin.InitializeResponse{}, err
return dbplugin.InitializeResponse{}, err
}
resp := newdbplugin.InitializeResponse{
resp := dbplugin.InitializeResponse{
Config: req.Config,
}
return resp, nil
}
func (m *MySQL) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (newdbplugin.NewUserResponse, error) {
func (m *MySQL) NewUser(ctx context.Context, req dbplugin.NewUserRequest) (dbplugin.NewUserResponse, error) {
if len(req.Statements.Commands) == 0 {
return newdbplugin.NewUserResponse{}, dbutil.ErrEmptyCreationStatement
return dbplugin.NewUserResponse{}, dbutil.ErrEmptyCreationStatement
}
username, err := m.generateUsername(req)
if err != nil {
return newdbplugin.NewUserResponse{}, err
return dbplugin.NewUserResponse{}, err
}
password := req.Password
@@ -133,16 +132,16 @@ func (m *MySQL) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (ne
}
if err := m.executePreparedStatementsWithMap(ctx, req.Statements.Commands, queryMap); err != nil {
return newdbplugin.NewUserResponse{}, err
return dbplugin.NewUserResponse{}, err
}
resp := newdbplugin.NewUserResponse{
resp := dbplugin.NewUserResponse{
Username: username,
}
return resp, nil
}
func (m *MySQL) generateUsername(req newdbplugin.NewUserRequest) (string, error) {
func (m *MySQL) generateUsername(req dbplugin.NewUserRequest) (string, error) {
var dispNameLen, roleNameLen, maxLen int
if m.legacy {
@@ -167,7 +166,7 @@ func (m *MySQL) generateUsername(req newdbplugin.NewUserRequest) (string, error)
return username, nil
}
func (m *MySQL) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserRequest) (newdbplugin.DeleteUserResponse, error) {
func (m *MySQL) DeleteUser(ctx context.Context, req dbplugin.DeleteUserRequest) (dbplugin.DeleteUserResponse, error) {
// Grab the read lock
m.Lock()
defer m.Unlock()
@@ -175,7 +174,7 @@ func (m *MySQL) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserReques
// Get the connection
db, err := m.getConnection(ctx)
if err != nil {
return newdbplugin.DeleteUserResponse{}, err
return dbplugin.DeleteUserResponse{}, err
}
revocationStmts := req.Statements.Commands
@@ -187,7 +186,7 @@ func (m *MySQL) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserReques
// Start a transaction
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return newdbplugin.DeleteUserResponse{}, err
return dbplugin.DeleteUserResponse{}, err
}
defer tx.Rollback()
@@ -205,31 +204,31 @@ func (m *MySQL) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserReques
query = strings.Replace(query, "{{username}}", req.Username, -1)
_, err = tx.ExecContext(ctx, query)
if err != nil {
return newdbplugin.DeleteUserResponse{}, err
return dbplugin.DeleteUserResponse{}, err
}
}
}
// Commit the transaction
err = tx.Commit()
return newdbplugin.DeleteUserResponse{}, err
return dbplugin.DeleteUserResponse{}, err
}
func (m *MySQL) UpdateUser(ctx context.Context, req newdbplugin.UpdateUserRequest) (newdbplugin.UpdateUserResponse, error) {
func (m *MySQL) UpdateUser(ctx context.Context, req dbplugin.UpdateUserRequest) (dbplugin.UpdateUserResponse, error) {
if req.Password == nil && req.Expiration == nil {
return newdbplugin.UpdateUserResponse{}, fmt.Errorf("no change requested")
return dbplugin.UpdateUserResponse{}, fmt.Errorf("no change requested")
}
if req.Password != nil {
err := m.changeUserPassword(ctx, req.Username, req.Password.NewPassword, req.Password.Statements.Commands)
if err != nil {
return newdbplugin.UpdateUserResponse{}, fmt.Errorf("failed to change password: %w", err)
return dbplugin.UpdateUserResponse{}, fmt.Errorf("failed to change password: %w", err)
}
}
// Expiration change/update is currently a no-op
return newdbplugin.UpdateUserResponse{}, nil
return dbplugin.UpdateUserResponse{}, nil
}
func (m *MySQL) changeUserPassword(ctx context.Context, username, password string, rotateStatements []string) error {

View File

@@ -9,14 +9,13 @@ import (
stdmysql "github.com/go-sql-driver/mysql"
mysqlhelper "github.com/hashicorp/vault/helper/testhelpers/mysql"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/database/helper/credsutil"
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
"github.com/hashicorp/vault/sdk/helper/strutil"
)
var _ newdbplugin.Database = (*MySQL)(nil)
var _ dbplugin.Database = (*MySQL)(nil)
func TestMySQL_Initialize(t *testing.T) {
cleanup, connURL := mysqlhelper.PrepareTestContainer(t, false, "secret")
@@ -26,7 +25,7 @@ func TestMySQL_Initialize(t *testing.T) {
"connection_url": connURL,
}
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: connectionDetails,
VerifyConnection: true,
}
@@ -52,7 +51,7 @@ func TestMySQL_Initialize(t *testing.T) {
"max_open_connections": "5",
}
initReq = newdbplugin.InitializeRequest{
initReq = dbplugin.InitializeRequest{
Config: connectionDetails,
VerifyConnection: true,
}
@@ -73,12 +72,12 @@ func TestMySQL_CreateUser(t *testing.T) {
t.Fatalf("unable to generate password: %s", err)
}
createReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
createReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{},
},
Password: password,
@@ -103,7 +102,7 @@ func TestMySQL_CreateUser(t *testing.T) {
"connection_url": connURL,
}
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: connectionDetails,
VerifyConnection: true,
}
@@ -126,7 +125,7 @@ func TestMySQL_CreateUser(t *testing.T) {
"connection_url": connURL,
}
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: connectionDetails,
VerifyConnection: true,
}
@@ -188,12 +187,12 @@ func testCreateUser(t *testing.T, db *MySQL, connURL string) {
t.Fatalf("unable to generate password: %s", err)
}
createReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
createReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: test.createStmts,
},
Password: password,
@@ -256,7 +255,7 @@ func TestMySQL_RotateRootCredentials(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: connectionDetails,
VerifyConnection: true,
}
@@ -271,11 +270,11 @@ func TestMySQL_RotateRootCredentials(t *testing.T) {
t.Fatal("Database should be initialized")
}
updateReq := newdbplugin.UpdateUserRequest{
updateReq := dbplugin.UpdateUserRequest{
Username: "root",
Password: &newdbplugin.ChangePassword{
Password: &dbplugin.ChangePassword{
NewPassword: "different_sercret",
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: test.statements,
},
},
@@ -331,7 +330,7 @@ func TestMySQL_DeleteUser(t *testing.T) {
"connection_url": connURL,
}
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: connectionDetails,
VerifyConnection: true,
}
@@ -349,12 +348,12 @@ func TestMySQL_DeleteUser(t *testing.T) {
t.Fatalf("unable to generate password: %s", err)
}
createReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
createReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{`
CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}';
GRANT SELECT ON *.* TO '{{name}}'@'%';`,
@@ -377,9 +376,9 @@ func TestMySQL_DeleteUser(t *testing.T) {
t.Fatalf("Could not connect with new credentials: %s", err)
}
deleteReq := newdbplugin.DeleteUserRequest{
deleteReq := dbplugin.DeleteUserRequest{
Username: userResp.Username,
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: test.revokeStmts,
},
}
@@ -436,7 +435,7 @@ func TestMySQL_UpdateUser(t *testing.T) {
"connection_url": connURL,
}
initReq := newdbplugin.InitializeRequest{
initReq := dbplugin.InitializeRequest{
Config: connectionDetails,
VerifyConnection: true,
}
@@ -456,11 +455,11 @@ func TestMySQL_UpdateUser(t *testing.T) {
t.Fatalf("unable to generate password: %s", err)
}
updateReq := newdbplugin.UpdateUserRequest{
updateReq := dbplugin.UpdateUserRequest{
Username: dbUser,
Password: &newdbplugin.ChangePassword{
Password: &dbplugin.ChangePassword{
NewPassword: newPassword,
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: test.rotateStmts,
},
},

View File

@@ -10,10 +10,10 @@ import (
"github.com/hashicorp/errwrap"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/api"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/database/helper/connutil"
"github.com/hashicorp/vault/sdk/database/helper/credsutil"
"github.com/hashicorp/vault/sdk/database/helper/dbutil"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
"github.com/hashicorp/vault/sdk/helper/dbtxn"
"github.com/hashicorp/vault/sdk/helper/strutil"
"github.com/lib/pq"
@@ -32,7 +32,7 @@ ALTER ROLE "{{username}}" WITH PASSWORD '{{password}}';
)
var (
_ newdbplugin.Database = &PostgreSQL{}
_ dbplugin.Database = &PostgreSQL{}
// postgresEndStatement is basically the word "END" but
// surrounded by a word boundary to differentiate it from
@@ -52,7 +52,7 @@ var (
func New() (interface{}, error) {
db := new()
// Wrap the plugin with middleware to sanitize errors
dbType := newdbplugin.NewDatabaseErrorSanitizerMiddleware(db, db.secretValues)
dbType := dbplugin.NewDatabaseErrorSanitizerMiddleware(db, db.secretValues)
return dbType, nil
}
@@ -74,7 +74,7 @@ func Run(apiTLSConfig *api.TLSConfig) error {
return err
}
newdbplugin.Serve(dbType.(newdbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
dbplugin.Serve(dbType.(dbplugin.Database), api.VaultPluginTLSProvider(apiTLSConfig))
return nil
}
@@ -83,12 +83,12 @@ type PostgreSQL struct {
*connutil.SQLConnectionProducer
}
func (p *PostgreSQL) Initialize(ctx context.Context, req newdbplugin.InitializeRequest) (newdbplugin.InitializeResponse, error) {
func (p *PostgreSQL) Initialize(ctx context.Context, req dbplugin.InitializeRequest) (dbplugin.InitializeResponse, error) {
newConf, err := p.SQLConnectionProducer.Init(ctx, req.Config, req.VerifyConnection)
if err != nil {
return newdbplugin.InitializeResponse{}, err
return dbplugin.InitializeResponse{}, err
}
resp := newdbplugin.InitializeResponse{
resp := dbplugin.InitializeResponse{
Config: newConf,
}
return resp, nil
@@ -107,12 +107,12 @@ func (p *PostgreSQL) getConnection(ctx context.Context) (*sql.DB, error) {
return db.(*sql.DB), nil
}
func (p *PostgreSQL) UpdateUser(ctx context.Context, req newdbplugin.UpdateUserRequest) (newdbplugin.UpdateUserResponse, error) {
func (p *PostgreSQL) UpdateUser(ctx context.Context, req dbplugin.UpdateUserRequest) (dbplugin.UpdateUserResponse, error) {
if req.Username == "" {
return newdbplugin.UpdateUserResponse{}, fmt.Errorf("missing username")
return dbplugin.UpdateUserResponse{}, fmt.Errorf("missing username")
}
if req.Password == nil && req.Expiration == nil {
return newdbplugin.UpdateUserResponse{}, fmt.Errorf("no changes requested")
return dbplugin.UpdateUserResponse{}, fmt.Errorf("no changes requested")
}
merr := &multierror.Error{}
@@ -124,10 +124,10 @@ func (p *PostgreSQL) UpdateUser(ctx context.Context, req newdbplugin.UpdateUserR
err := p.changeUserExpiration(ctx, req.Username, req.Expiration)
merr = multierror.Append(merr, err)
}
return newdbplugin.UpdateUserResponse{}, merr.ErrorOrNil()
return dbplugin.UpdateUserResponse{}, merr.ErrorOrNil()
}
func (p *PostgreSQL) changeUserPassword(ctx context.Context, username string, changePass *newdbplugin.ChangePassword) error {
func (p *PostgreSQL) changeUserPassword(ctx context.Context, username string, changePass *dbplugin.ChangePassword) error {
stmts := changePass.Statements.Commands
if len(stmts) == 0 {
stmts = []string{defaultChangePasswordStatement}
@@ -184,7 +184,7 @@ func (p *PostgreSQL) changeUserPassword(ctx context.Context, username string, ch
return nil
}
func (p *PostgreSQL) changeUserExpiration(ctx context.Context, username string, changeExp *newdbplugin.ChangeExpiration) error {
func (p *PostgreSQL) changeUserExpiration(ctx context.Context, username string, changeExp *dbplugin.ChangeExpiration) error {
p.Lock()
defer p.Unlock()
@@ -229,9 +229,9 @@ func (p *PostgreSQL) changeUserExpiration(ctx context.Context, username string,
return tx.Commit()
}
func (p *PostgreSQL) NewUser(ctx context.Context, req newdbplugin.NewUserRequest) (newdbplugin.NewUserResponse, error) {
func (p *PostgreSQL) NewUser(ctx context.Context, req dbplugin.NewUserRequest) (dbplugin.NewUserResponse, error) {
if len(req.Statements.Commands) == 0 {
return newdbplugin.NewUserResponse{}, dbutil.ErrEmptyCreationStatement
return dbplugin.NewUserResponse{}, dbutil.ErrEmptyCreationStatement
}
p.Lock()
@@ -244,19 +244,19 @@ func (p *PostgreSQL) NewUser(ctx context.Context, req newdbplugin.NewUserRequest
credsutil.MaxLength(63),
)
if err != nil {
return newdbplugin.NewUserResponse{}, err
return dbplugin.NewUserResponse{}, err
}
expirationStr := req.Expiration.Format(expirationFormat)
db, err := p.getConnection(ctx)
if err != nil {
return newdbplugin.NewUserResponse{}, fmt.Errorf("unable to get connection: %w", err)
return dbplugin.NewUserResponse{}, fmt.Errorf("unable to get connection: %w", err)
}
tx, err := db.BeginTx(ctx, nil)
if err != nil {
return newdbplugin.NewUserResponse{}, fmt.Errorf("unable to start transaction: %w", err)
return dbplugin.NewUserResponse{}, fmt.Errorf("unable to start transaction: %w", err)
}
defer tx.Rollback()
@@ -271,7 +271,7 @@ func (p *PostgreSQL) NewUser(ctx context.Context, req newdbplugin.NewUserRequest
"expiration": expirationStr,
}
if err := dbtxn.ExecuteTxQuery(ctx, tx, m, stmt); err != nil {
return newdbplugin.NewUserResponse{}, fmt.Errorf("failed to execute query: %w", err)
return dbplugin.NewUserResponse{}, fmt.Errorf("failed to execute query: %w", err)
}
continue
}
@@ -289,30 +289,30 @@ func (p *PostgreSQL) NewUser(ctx context.Context, req newdbplugin.NewUserRequest
"expiration": expirationStr,
}
if err := dbtxn.ExecuteTxQuery(ctx, tx, m, query); err != nil {
return newdbplugin.NewUserResponse{}, fmt.Errorf("failed to execute query: %w", err)
return dbplugin.NewUserResponse{}, fmt.Errorf("failed to execute query: %w", err)
}
}
}
if err := tx.Commit(); err != nil {
return newdbplugin.NewUserResponse{}, err
return dbplugin.NewUserResponse{}, err
}
resp := newdbplugin.NewUserResponse{
resp := dbplugin.NewUserResponse{
Username: username,
}
return resp, nil
}
func (p *PostgreSQL) DeleteUser(ctx context.Context, req newdbplugin.DeleteUserRequest) (newdbplugin.DeleteUserResponse, error) {
func (p *PostgreSQL) DeleteUser(ctx context.Context, req dbplugin.DeleteUserRequest) (dbplugin.DeleteUserResponse, error) {
p.Lock()
defer p.Unlock()
if len(req.Statements.Commands) == 0 {
return newdbplugin.DeleteUserResponse{}, p.defaultDeleteUser(ctx, req.Username)
return dbplugin.DeleteUserResponse{}, p.defaultDeleteUser(ctx, req.Username)
}
return newdbplugin.DeleteUserResponse{}, p.customDeleteUser(ctx, req.Username, req.Statements.Commands)
return dbplugin.DeleteUserResponse{}, p.customDeleteUser(ctx, req.Username, req.Statements.Commands)
}
func (p *PostgreSQL) customDeleteUser(ctx context.Context, username string, revocationStmts []string) error {

View File

@@ -9,8 +9,8 @@ import (
"time"
"github.com/hashicorp/vault/helper/testhelpers/postgresql"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
dbtesting "github.com/hashicorp/vault/sdk/database/newdbplugin/testing"
dbplugin "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
dbtesting "github.com/hashicorp/vault/sdk/database/dbplugin/v5/testing"
)
func getPostgreSQL(t *testing.T, options map[string]interface{}) (*PostgreSQL, func()) {
@@ -23,7 +23,7 @@ func getPostgreSQL(t *testing.T, options map[string]interface{}) (*PostgreSQL, f
connectionDetails[k] = v
}
req := newdbplugin.InitializeRequest{
req := dbplugin.InitializeRequest{
Config: connectionDetails,
VerifyConnection: true,
}
@@ -61,15 +61,15 @@ func TestPostgreSQL_InitializeWithStringVals(t *testing.T) {
func TestPostgreSQL_NewUser(t *testing.T) {
type testCase struct {
req newdbplugin.NewUserRequest
req dbplugin.NewUserRequest
expectErr bool
credsAssertion credsAssertion
}
tests := map[string]testCase{
"no creation statements": {
req: newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
req: dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
@@ -81,12 +81,12 @@ func TestPostgreSQL_NewUser(t *testing.T) {
credsAssertion: assertCredsDoNotExist,
},
"admin name": {
req: newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
req: dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{`
CREATE ROLE "{{name}}" WITH
LOGIN
@@ -102,12 +102,12 @@ func TestPostgreSQL_NewUser(t *testing.T) {
credsAssertion: assertCredsExist,
},
"admin username": {
req: newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
req: dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{`
CREATE ROLE "{{username}}" WITH
LOGIN
@@ -123,12 +123,12 @@ func TestPostgreSQL_NewUser(t *testing.T) {
credsAssertion: assertCredsExist,
},
"read only name": {
req: newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
req: dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{`
CREATE ROLE "{{name}}" WITH
LOGIN
@@ -145,12 +145,12 @@ func TestPostgreSQL_NewUser(t *testing.T) {
credsAssertion: assertCredsExist,
},
"read only username": {
req: newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
req: dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{`
CREATE ROLE "{{username}}" WITH
LOGIN
@@ -168,12 +168,12 @@ func TestPostgreSQL_NewUser(t *testing.T) {
},
// https://github.com/hashicorp/vault/issues/6098
"reproduce GH-6098": {
req: newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
req: dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{
// NOTE: "rolname" in the following line is not a typo.
"DO $$ BEGIN IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname='my_role') THEN CREATE ROLE my_role; END IF; END $$",
@@ -186,12 +186,12 @@ func TestPostgreSQL_NewUser(t *testing.T) {
credsAssertion: assertCredsDoNotExist,
},
"reproduce issue with template": {
req: newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
req: dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{
`DO $$ BEGIN IF NOT EXISTS (SELECT FROM pg_catalog.pg_roles WHERE rolname='my_role') THEN CREATE ROLE "{{username}}"; END IF; END $$`,
},
@@ -203,12 +203,12 @@ func TestPostgreSQL_NewUser(t *testing.T) {
credsAssertion: assertCredsDoNotExist,
},
"large block statements": {
req: newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
req: dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: newUserLargeBlockStatements,
},
Password: "somesecurepassword",
@@ -284,12 +284,12 @@ func TestUpdateUser_Password(t *testing.T) {
for name, test := range tests {
t.Run(name, func(t *testing.T) {
initialPass := "myreallysecurepassword"
createReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
createReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{createAdminUser},
},
Password: initialPass,
@@ -300,11 +300,11 @@ func TestUpdateUser_Password(t *testing.T) {
assertCredsExist(t, db.ConnectionURL, createResp.Username, initialPass)
newPass := "somenewpassword"
updateReq := newdbplugin.UpdateUserRequest{
updateReq := dbplugin.UpdateUserRequest{
Username: createResp.Username,
Password: &newdbplugin.ChangePassword{
Password: &dbplugin.ChangePassword{
NewPassword: newPass,
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: test.statements,
},
},
@@ -326,11 +326,11 @@ func TestUpdateUser_Password(t *testing.T) {
t.Run("user does not exist", func(t *testing.T) {
newPass := "somenewpassword"
updateReq := newdbplugin.UpdateUserRequest{
updateReq := dbplugin.UpdateUserRequest{
Username: "missing-user",
Password: &newdbplugin.ChangePassword{
Password: &dbplugin.ChangePassword{
NewPassword: newPass,
Statements: newdbplugin.Statements{},
Statements: dbplugin.Statements{},
},
}
@@ -394,12 +394,12 @@ func TestUpdateUser_Expiration(t *testing.T) {
t.Run(name, func(t *testing.T) {
password := "myreallysecurepassword"
initialExpiration := test.initialExpiration.Truncate(time.Second)
createReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
createReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{createAdminUser},
},
Password: password,
@@ -418,11 +418,11 @@ func TestUpdateUser_Expiration(t *testing.T) {
}
newExpiration := test.newExpiration.Truncate(time.Second)
updateReq := newdbplugin.UpdateUserRequest{
updateReq := dbplugin.UpdateUserRequest{
Username: createResp.Username,
Expiration: &newdbplugin.ChangeExpiration{
Expiration: &dbplugin.ChangeExpiration{
NewExpiration: newExpiration,
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: test.statements,
},
},
@@ -538,12 +538,12 @@ func TestDeleteUser(t *testing.T) {
for name, test := range tests {
t.Run(name, func(t *testing.T) {
password := "myreallysecurepassword"
createReq := newdbplugin.NewUserRequest{
UsernameConfig: newdbplugin.UsernameMetadata{
createReq := dbplugin.NewUserRequest{
UsernameConfig: dbplugin.UsernameMetadata{
DisplayName: "test",
RoleName: "test",
},
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: []string{createAdminUser},
},
Password: password,
@@ -553,9 +553,9 @@ func TestDeleteUser(t *testing.T) {
assertCredsExist(t, db.ConnectionURL, createResp.Username, password)
deleteReq := newdbplugin.DeleteUserRequest{
deleteReq := dbplugin.DeleteUserRequest{
Username: createResp.Username,
Statements: newdbplugin.Statements{
Statements: dbplugin.Statements{
Commands: test.revokeStmts,
},
}

View File

@@ -0,0 +1,506 @@
package dbplugin
import (
"fmt"
"reflect"
"strings"
"testing"
"time"
"unicode"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/timestamppb"
)
func TestConversionsHaveAllFields(t *testing.T) {
t.Run("initReqToProto", func(t *testing.T) {
req := InitializeRequest{
Config: map[string]interface{}{
"foo": map[string]interface{}{
"bar": "baz",
},
},
VerifyConnection: true,
}
protoReq, err := initReqToProto(req)
if err != nil {
t.Fatalf("Failed to convert request to proto request: %s", err)
}
values := getAllGetterValues(protoReq)
if len(values) == 0 {
// Probably a test failure - the protos used in these tests should have Get functions on them
t.Fatalf("No values found from Get functions!")
}
for _, gtr := range values {
err := assertAllFieldsSet(fmt.Sprintf("InitializeRequest.%s", gtr.name), gtr.value)
if err != nil {
t.Fatalf("%s", err)
}
}
})
t.Run("newUserReqToProto", func(t *testing.T) {
req := NewUserRequest{
UsernameConfig: UsernameMetadata{
DisplayName: "dispName",
RoleName: "roleName",
},
Statements: Statements{
Commands: []string{
"statement",
},
},
RollbackStatements: Statements{
Commands: []string{
"rollback_statement",
},
},
Password: "password",
Expiration: time.Now(),
}
protoReq, err := newUserReqToProto(req)
if err != nil {
t.Fatalf("Failed to convert request to proto request: %s", err)
}
values := getAllGetterValues(protoReq)
if len(values) == 0 {
// Probably a test failure - the protos used in these tests should have Get functions on them
t.Fatalf("No values found from Get functions!")
}
for _, gtr := range values {
err := assertAllFieldsSet(fmt.Sprintf("NewUserRequest.%s", gtr.name), gtr.value)
if err != nil {
t.Fatalf("%s", err)
}
}
})
t.Run("updateUserReqToProto", func(t *testing.T) {
req := UpdateUserRequest{
Username: "username",
Password: &ChangePassword{
NewPassword: "newpassword",
Statements: Statements{
Commands: []string{
"statement",
},
},
},
Expiration: &ChangeExpiration{
NewExpiration: time.Now(),
Statements: Statements{
Commands: []string{
"statement",
},
},
},
}
protoReq, err := updateUserReqToProto(req)
if err != nil {
t.Fatalf("Failed to convert request to proto request: %s", err)
}
values := getAllGetterValues(protoReq)
if len(values) == 0 {
// Probably a test failure - the protos used in these tests should have Get functions on them
t.Fatalf("No values found from Get functions!")
}
for _, gtr := range values {
err := assertAllFieldsSet(fmt.Sprintf("UpdateUserRequest.%s", gtr.name), gtr.value)
if err != nil {
t.Fatalf("%s", err)
}
}
})
t.Run("deleteUserReqToProto", func(t *testing.T) {
req := DeleteUserRequest{
Username: "username",
Statements: Statements{
Commands: []string{
"statement",
},
},
}
protoReq, err := deleteUserReqToProto(req)
if err != nil {
t.Fatalf("Failed to convert request to proto request: %s", err)
}
values := getAllGetterValues(protoReq)
if len(values) == 0 {
// Probably a test failure - the protos used in these tests should have Get functions on them
t.Fatalf("No values found from Get functions!")
}
for _, gtr := range values {
err := assertAllFieldsSet(fmt.Sprintf("DeleteUserRequest.%s", gtr.name), gtr.value)
if err != nil {
t.Fatalf("%s", err)
}
}
})
t.Run("getUpdateUserRequest", func(t *testing.T) {
req := &proto.UpdateUserRequest{
Username: "username",
Password: &proto.ChangePassword{
NewPassword: "newpass",
Statements: &proto.Statements{
Commands: []string{
"statement",
},
},
},
Expiration: &proto.ChangeExpiration{
NewExpiration: timestamppb.Now(),
Statements: &proto.Statements{
Commands: []string{
"statement",
},
},
},
}
protoReq, err := getUpdateUserRequest(req)
if err != nil {
t.Fatalf("Failed to convert request to proto request: %s", err)
}
err = assertAllFieldsSet("proto.UpdateUserRequest", protoReq)
if err != nil {
t.Fatalf("%s", err)
}
})
}
type getter struct {
name string
value interface{}
}
func getAllGetterValues(value interface{}) (values []getter) {
typ := reflect.TypeOf(value)
val := reflect.ValueOf(value)
for i := 0; i < typ.NumMethod(); i++ {
method := typ.Method(i)
if !strings.HasPrefix(method.Name, "Get") {
continue
}
valMethod := val.Method(i)
resp := valMethod.Call(nil)
getVal := resp[0].Interface()
gtr := getter{
name: strings.TrimPrefix(method.Name, "Get"),
value: getVal,
}
values = append(values, gtr)
}
return values
}
// Ensures the assertion works properly
func TestAssertAllFieldsSet(t *testing.T) {
type testCase struct {
value interface{}
expectErr bool
}
tests := map[string]testCase{
"zero int": {
value: 0,
expectErr: true,
},
"non-zero int": {
value: 1,
expectErr: false,
},
"zero float64": {
value: 0.0,
expectErr: true,
},
"non-zero float64": {
value: 1.0,
expectErr: false,
},
"empty string": {
value: "",
expectErr: true,
},
"true boolean": {
value: true,
expectErr: false,
},
"false boolean": { // False is an exception to the "is zero" rule
value: false,
expectErr: false,
},
"blank struct": {
value: struct{}{},
expectErr: true,
},
"non-blank but empty struct": {
value: struct {
str string
}{
str: "",
},
expectErr: true,
},
"non-empty string": {
value: "foo",
expectErr: false,
},
"non-empty struct": {
value: struct {
str string
}{
str: "foo",
},
expectErr: false,
},
"empty nested struct": {
value: struct {
Str string
Substruct struct {
Substr string
}
}{
Str: "foo",
Substruct: struct {
Substr string
}{}, // Empty sub-field
},
expectErr: true,
},
"filled nested struct": {
value: struct {
str string
substruct struct {
substr string
}
}{
str: "foo",
substruct: struct {
substr string
}{
substr: "sub-foo",
},
},
expectErr: false,
},
"nil map": {
value: map[string]string(nil),
expectErr: true,
},
"empty map": {
value: map[string]string{},
expectErr: true,
},
"filled map": {
value: map[string]string{
"foo": "bar",
"int": "42",
},
expectErr: false,
},
"map with empty string value": {
value: map[string]string{
"foo": "",
},
expectErr: true,
},
"nested map with empty string value": {
value: map[string]interface{}{
"bar": "baz",
"foo": map[string]interface{}{
"subfoo": "",
},
},
expectErr: true,
},
"nil slice": {
value: []string(nil),
expectErr: true,
},
"empty slice": {
value: []string{},
expectErr: true,
},
"filled slice": {
value: []string{
"foo",
},
expectErr: false,
},
"slice with empty string value": {
value: []string{
"",
},
expectErr: true,
},
"empty structpb": {
value: newStructPb(t, map[string]interface{}{}),
expectErr: true,
},
"filled structpb": {
value: newStructPb(t, map[string]interface{}{
"foo": "bar",
"int": 42,
}),
expectErr: false,
},
"pointer to zero int": {
value: intPtr(0),
expectErr: true,
},
"pointer to non-zero int": {
value: intPtr(1),
expectErr: false,
},
"pointer to zero float64": {
value: float64Ptr(0.0),
expectErr: true,
},
"pointer to non-zero float64": {
value: float64Ptr(1.0),
expectErr: false,
},
"pointer to nil string": {
value: new(string),
expectErr: true,
},
"pointer to non-nil string": {
value: strPtr("foo"),
expectErr: false,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
err := assertAllFieldsSet("", test.value)
if test.expectErr && err == nil {
t.Fatalf("err expected, got nil")
}
if !test.expectErr && err != nil {
t.Fatalf("no error expected, got: %s", err)
}
})
}
}
func assertAllFieldsSet(name string, val interface{}) error {
if val == nil {
return fmt.Errorf("value is nil")
}
rVal := reflect.ValueOf(val)
return assertAllFieldsSetValue(name, rVal)
}
func assertAllFieldsSetValue(name string, rVal reflect.Value) error {
// All booleans are allowed - we don't have a way of differentiating between
// and intentional false and a missing false
if rVal.Kind() == reflect.Bool {
return nil
}
// Primitives fall through here
if rVal.IsZero() {
return fmt.Errorf("%s is zero", name)
}
switch rVal.Kind() {
case reflect.Ptr, reflect.Interface:
return assertAllFieldsSetValue(name, rVal.Elem())
case reflect.Struct:
return assertAllFieldsSetStruct(name, rVal)
case reflect.Map:
if rVal.Len() == 0 {
return fmt.Errorf("%s (map type) is empty", name)
}
iter := rVal.MapRange()
for iter.Next() {
k := iter.Key()
v := iter.Value()
err := assertAllFieldsSetValue(fmt.Sprintf("%s[%s]", name, k), v)
if err != nil {
return err
}
}
case reflect.Slice:
if rVal.Len() == 0 {
return fmt.Errorf("%s (slice type) is empty", name)
}
for i := 0; i < rVal.Len(); i++ {
sliceVal := rVal.Index(i)
err := assertAllFieldsSetValue(fmt.Sprintf("%s[%d]", name, i), sliceVal)
if err != nil {
return err
}
}
}
return nil
}
func assertAllFieldsSetStruct(name string, rVal reflect.Value) error {
switch rVal.Type() {
case reflect.TypeOf(timestamppb.Timestamp{}):
ts := rVal.Interface().(timestamppb.Timestamp)
if ts.AsTime().IsZero() {
return fmt.Errorf("%s is zero", name)
}
return nil
default:
for i := 0; i < rVal.NumField(); i++ {
field := rVal.Field(i)
fieldName := rVal.Type().Field(i)
// Skip fields that aren't exported
if unicode.IsLower([]rune(fieldName.Name)[0]) {
continue
}
err := assertAllFieldsSetValue(fmt.Sprintf("%s.%s", name, fieldName.Name), field)
if err != nil {
return err
}
}
return nil
}
}
func intPtr(i int) *int {
return &i
}
func float64Ptr(f float64) *float64 {
return &f
}
func strPtr(str string) *string {
return &str
}
func newStructPb(t *testing.T, m map[string]interface{}) *structpb.Struct {
t.Helper()
s, err := structpb.NewStruct(m)
if err != nil {
t.Fatalf("Failed to convert map to struct: %s", err)
}
return s
}

View File

@@ -0,0 +1,178 @@
package dbplugin
import (
"context"
"time"
)
// Database to manipulate users within an external system (typically a database).
type Database interface {
// Initialize the database plugin. This is the equivalent of a constructor for the
// database object itself.
Initialize(ctx context.Context, req InitializeRequest) (InitializeResponse, error)
// NewUser creates a new user within the database. This user is temporary in that it
// will exist until the TTL expires.
NewUser(ctx context.Context, req NewUserRequest) (NewUserResponse, error)
// UpdateUser updates an existing user within the database.
UpdateUser(ctx context.Context, req UpdateUserRequest) (UpdateUserResponse, error)
// DeleteUser from the database. This should not error if the user didn't
// exist prior to this call.
DeleteUser(ctx context.Context, req DeleteUserRequest) (DeleteUserResponse, error)
// Type returns the Name for the particular database backend implementation.
// This type name is usually set as a constant within the database backend
// implementation, e.g. "mysql" for the MySQL database backend. This is used
// for things like metrics and logging. No behavior is switched on this.
Type() (string, error)
// Close attempts to close the underlying database connection that was
// established by the backend.
Close() error
}
// ///////////////////////////////////////////////////////////////////////////
// Database Request & Response Objects
// These request and response objects are *not* protobuf types because gRPC does not
// support all types that we need in a nice way. For instance, gRPC does not support
// map[string]interface{}. It does have an `Any` type, but converting it to a map
// requires extensive use of reflection and knowing what types to support ahead of
// time. Instead these types are made as user-friendly as possible so the conversion
// between protobuf types and request/response objects is handled by Vault developers
// rather than needing to be handled by external plugin developers.
// ///////////////////////////////////////////////////////////////////////////
// ///////////////////////////////////////////////////////
// Initialize()
// ///////////////////////////////////////////////////////
// InitializeRequest contains all information needed to initialize a database plugin.
type InitializeRequest struct {
// Config to initialize the database with. This can include things like connection details,
// a "root" username & password, etc. This will not include all configuration items specified
// when configuring the database. Some values will be stripped out by the database engine
// prior to being passed to the plugin.
Config map[string]interface{}
// VerifyConnection during initialization. If true, a connection should be made to the
// database to verify the connection can be made. If false, no connection should be made
// on initialization.
VerifyConnection bool
}
// InitializeResponse returns any information Vault needs to know after initializing
// a database plugin.
type InitializeResponse struct {
// Config that should be saved in Vault. This may differ from the config in the request,
// but should contain everything required to Initialize the database.
// REQUIRED in order to save the configuration into Vault after initialization
Config map[string]interface{}
}
// ///////////////////////////////////////////////////////
// NewUser()
// ///////////////////////////////////////////////////////
// NewUserRequest request a new user is created
type NewUserRequest struct {
// UsernameConfig is metadata that can be used to generate a username
// within the database plugin
UsernameConfig UsernameMetadata
// Statements is an ordered list of commands to run within the database when
// creating a new user. This frequently includes permissions to give the
// user or similar actions.
Statements Statements
// RollbackStatements is an ordered list of commands to run within the database
// if the new user creation process fails.
RollbackStatements Statements
// Password credentials to use when creating the user
Password string
// Expiration of the user. Not all database plugins will support this.
Expiration time.Time
}
// UsernameMetadata is metadata the database plugin can use to generate a username
type UsernameMetadata struct {
DisplayName string
RoleName string
}
// NewUserResponse returns any information Vault needs to know after creating a new user.
type NewUserResponse struct {
// Username of the user created within the database.
// REQUIRED so Vault knows the name of the user that was created
Username string
}
// ///////////////////////////////////////////////////////
// UpdateUser()
// ///////////////////////////////////////////////////////
type UpdateUserRequest struct {
// Username to make changes to.
Username string
// Password indicates the new password to change to.
// If nil, no change is requested.
Password *ChangePassword
// Expiration indicates the new expiration date to change to.
// If nil, no change is requested.
Expiration *ChangeExpiration
}
// ChangePassword of a given user
type ChangePassword struct {
// NewPassword for the user
NewPassword string
// Statements is an ordered list of commands to run within the database
// when changing the user's password.
Statements Statements
}
// ChangeExpiration of a given user
type ChangeExpiration struct {
// NewExpiration of the user
NewExpiration time.Time
// Statements is an ordered list of commands to run within the database
// when changing the user's expiration.
Statements Statements
}
type UpdateUserResponse struct{}
// ///////////////////////////////////////////////////////
// DeleteUser()
// ///////////////////////////////////////////////////////
type DeleteUserRequest struct {
// Username to delete from the database
Username string
// Statements is an ordered list of commands to run within the database
// when deleting a user.
Statements Statements
}
type DeleteUserResponse struct{}
// ///////////////////////////////////////////////////////
// Used across multiple functions
// ///////////////////////////////////////////////////////
// Statements wraps a collection of statements to run in a database when an
// operation is performed (create, update, etc.). This is a struct rather than
// a string slice so we can easily add more information to this in the future.
type Statements struct {
// Commands is an ordered list of commands to execute in the database.
// These commands may include templated fields such as {{username}} and {{password}}
Commands []string
}

View File

@@ -0,0 +1,254 @@
package dbplugin
import (
"context"
"errors"
"fmt"
"time"
"github.com/golang/protobuf/ptypes"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
)
var (
_ Database = gRPCClient{}
ErrPluginShutdown = errors.New("plugin shutdown")
)
type gRPCClient struct {
client proto.DatabaseClient
doneCtx context.Context
}
func (c gRPCClient) Initialize(ctx context.Context, req InitializeRequest) (InitializeResponse, error) {
rpcReq, err := initReqToProto(req)
if err != nil {
return InitializeResponse{}, err
}
rpcResp, err := c.client.Initialize(ctx, rpcReq)
if err != nil {
return InitializeResponse{}, fmt.Errorf("unable to initialize: %s", err.Error())
}
return initRespFromProto(rpcResp)
}
func initReqToProto(req InitializeRequest) (*proto.InitializeRequest, error) {
config, err := mapToStruct(req.Config)
if err != nil {
return nil, fmt.Errorf("unable to marshal config: %w", err)
}
rpcReq := &proto.InitializeRequest{
ConfigData: config,
VerifyConnection: req.VerifyConnection,
}
return rpcReq, nil
}
func initRespFromProto(rpcResp *proto.InitializeResponse) (InitializeResponse, error) {
newConfig := structToMap(rpcResp.GetConfigData())
resp := InitializeResponse{
Config: newConfig,
}
return resp, nil
}
func (c gRPCClient) NewUser(ctx context.Context, req NewUserRequest) (NewUserResponse, error) {
ctx, cancel := context.WithCancel(ctx)
quitCh := pluginutil.CtxCancelIfCanceled(cancel, c.doneCtx)
defer close(quitCh)
defer cancel()
rpcReq, err := newUserReqToProto(req)
if err != nil {
return NewUserResponse{}, err
}
rpcResp, err := c.client.NewUser(ctx, rpcReq)
if err != nil {
if c.doneCtx.Err() != nil {
return NewUserResponse{}, ErrPluginShutdown
}
return NewUserResponse{}, fmt.Errorf("unable to create new user: %w", err)
}
return newUserRespFromProto(rpcResp)
}
func newUserReqToProto(req NewUserRequest) (*proto.NewUserRequest, error) {
if req.Password == "" {
return nil, fmt.Errorf("missing password")
}
expiration, err := ptypes.TimestampProto(req.Expiration)
if err != nil {
return nil, fmt.Errorf("unable to marshal expiration date: %w", err)
}
rpcReq := &proto.NewUserRequest{
UsernameConfig: &proto.UsernameConfig{
DisplayName: req.UsernameConfig.DisplayName,
RoleName: req.UsernameConfig.RoleName,
},
Password: req.Password,
Expiration: expiration,
Statements: &proto.Statements{
Commands: req.Statements.Commands,
},
RollbackStatements: &proto.Statements{
Commands: req.RollbackStatements.Commands,
},
}
return rpcReq, nil
}
func newUserRespFromProto(rpcResp *proto.NewUserResponse) (NewUserResponse, error) {
resp := NewUserResponse{
Username: rpcResp.GetUsername(),
}
return resp, nil
}
func (c gRPCClient) UpdateUser(ctx context.Context, req UpdateUserRequest) (UpdateUserResponse, error) {
rpcReq, err := updateUserReqToProto(req)
if err != nil {
return UpdateUserResponse{}, err
}
rpcResp, err := c.client.UpdateUser(ctx, rpcReq)
if err != nil {
if c.doneCtx.Err() != nil {
return UpdateUserResponse{}, ErrPluginShutdown
}
return UpdateUserResponse{}, fmt.Errorf("unable to update user: %w", err)
}
return updateUserRespFromProto(rpcResp)
}
func updateUserReqToProto(req UpdateUserRequest) (*proto.UpdateUserRequest, error) {
if req.Username == "" {
return nil, fmt.Errorf("missing username")
}
if (req.Password == nil || req.Password.NewPassword == "") &&
(req.Expiration == nil || req.Expiration.NewExpiration.IsZero()) {
return nil, fmt.Errorf("missing changes")
}
expiration, err := expirationToProto(req.Expiration)
if err != nil {
return nil, fmt.Errorf("unable to parse new expiration date: %w", err)
}
var password *proto.ChangePassword
if req.Password != nil && req.Password.NewPassword != "" {
password = &proto.ChangePassword{
NewPassword: req.Password.NewPassword,
Statements: &proto.Statements{
Commands: req.Password.Statements.Commands,
},
}
}
rpcReq := &proto.UpdateUserRequest{
Username: req.Username,
Password: password,
Expiration: expiration,
}
return rpcReq, nil
}
func updateUserRespFromProto(rpcResp *proto.UpdateUserResponse) (UpdateUserResponse, error) {
// Placeholder for future conversion if data is returned
return UpdateUserResponse{}, nil
}
func expirationToProto(exp *ChangeExpiration) (*proto.ChangeExpiration, error) {
if exp == nil {
return nil, nil
}
expiration, err := ptypes.TimestampProto(exp.NewExpiration)
if err != nil {
return nil, err
}
changeExp := &proto.ChangeExpiration{
NewExpiration: expiration,
Statements: &proto.Statements{
Commands: exp.Statements.Commands,
},
}
return changeExp, nil
}
func (c gRPCClient) DeleteUser(ctx context.Context, req DeleteUserRequest) (DeleteUserResponse, error) {
rpcReq, err := deleteUserReqToProto(req)
if err != nil {
return DeleteUserResponse{}, err
}
rpcResp, err := c.client.DeleteUser(ctx, rpcReq)
if err != nil {
if c.doneCtx.Err() != nil {
return DeleteUserResponse{}, ErrPluginShutdown
}
return DeleteUserResponse{}, fmt.Errorf("unable to update user: %w", err)
}
return deleteUserRespFromProto(rpcResp)
}
func deleteUserReqToProto(req DeleteUserRequest) (*proto.DeleteUserRequest, error) {
if req.Username == "" {
return nil, fmt.Errorf("missing username")
}
rpcReq := &proto.DeleteUserRequest{
Username: req.Username,
Statements: &proto.Statements{
Commands: req.Statements.Commands,
},
}
return rpcReq, nil
}
func deleteUserRespFromProto(rpcResp *proto.DeleteUserResponse) (DeleteUserResponse, error) {
// Placeholder for future conversion if data is returned
return DeleteUserResponse{}, nil
}
func (c gRPCClient) Type() (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
typeResp, err := c.client.Type(ctx, &proto.Empty{})
if err != nil {
if c.doneCtx.Err() != nil {
return "", ErrPluginShutdown
}
return "", fmt.Errorf("unable to get database plugin type: %w", err)
}
return typeResp.GetType(), nil
}
func (c gRPCClient) Close() error {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
_, err := c.client.Close(ctx, &proto.Empty{})
if err != nil {
if c.doneCtx.Err() != nil {
return ErrPluginShutdown
}
return err
}
return nil
}

View File

@@ -0,0 +1,537 @@
package dbplugin
import (
"context"
"errors"
"reflect"
"testing"
"time"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"google.golang.org/grpc"
)
func TestGRPCClient_Initialize(t *testing.T) {
type testCase struct {
client proto.DatabaseClient
req InitializeRequest
expectedResp InitializeResponse
assertErr errorAssertion
}
tests := map[string]testCase{
"bad config": {
client: fakeClient{},
req: InitializeRequest{
Config: map[string]interface{}{
"foo": badJSONValue{},
},
},
assertErr: assertErrNotNil,
},
"database error": {
client: fakeClient{
initErr: errors.New("initialize error"),
},
req: InitializeRequest{
Config: map[string]interface{}{
"foo": "bar",
},
},
assertErr: assertErrNotNil,
},
"happy path": {
client: fakeClient{
initResp: &proto.InitializeResponse{
ConfigData: marshal(t, map[string]interface{}{
"foo": "bar",
"baz": "biz",
}),
},
},
req: InitializeRequest{
Config: map[string]interface{}{
"foo": "bar",
},
},
expectedResp: InitializeResponse{
Config: map[string]interface{}{
"foo": "bar",
"baz": "biz",
},
},
assertErr: assertErrNil,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
c := gRPCClient{
client: test.client,
doneCtx: nil,
}
// Context doesn't need to timeout since this is just passed through
ctx := context.Background()
resp, err := c.Initialize(ctx, test.req)
test.assertErr(t, err)
if !reflect.DeepEqual(resp, test.expectedResp) {
t.Fatalf("Actual response: %#v\nExpected response: %#v", resp, test.expectedResp)
}
})
}
}
func TestGRPCClient_NewUser(t *testing.T) {
runningCtx := context.Background()
cancelledCtx, cancel := context.WithCancel(context.Background())
cancel()
type testCase struct {
client proto.DatabaseClient
req NewUserRequest
doneCtx context.Context
expectedResp NewUserResponse
assertErr errorAssertion
}
tests := map[string]testCase{
"missing password": {
client: fakeClient{},
req: NewUserRequest{
Password: "",
Expiration: time.Now(),
},
doneCtx: runningCtx,
assertErr: assertErrNotNil,
},
"bad expiration": {
client: fakeClient{},
req: NewUserRequest{
Password: "njkvcb8y934u90grsnkjl",
Expiration: invalidExpiration,
},
doneCtx: runningCtx,
assertErr: assertErrNotNil,
},
"database error": {
client: fakeClient{
newUserErr: errors.New("new user error"),
},
req: NewUserRequest{
Password: "njkvcb8y934u90grsnkjl",
Expiration: time.Now(),
},
doneCtx: runningCtx,
assertErr: assertErrNotNil,
},
"plugin shut down": {
client: fakeClient{
newUserErr: errors.New("new user error"),
},
req: NewUserRequest{
Password: "njkvcb8y934u90grsnkjl",
Expiration: time.Now(),
},
doneCtx: cancelledCtx,
assertErr: assertErrEquals(ErrPluginShutdown),
},
"happy path": {
client: fakeClient{
newUserResp: &proto.NewUserResponse{
Username: "new_user",
},
},
req: NewUserRequest{
Password: "njkvcb8y934u90grsnkjl",
Expiration: time.Now(),
},
doneCtx: runningCtx,
expectedResp: NewUserResponse{
Username: "new_user",
},
assertErr: assertErrNil,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
c := gRPCClient{
client: test.client,
doneCtx: test.doneCtx,
}
ctx := context.Background()
resp, err := c.NewUser(ctx, test.req)
test.assertErr(t, err)
if !reflect.DeepEqual(resp, test.expectedResp) {
t.Fatalf("Actual response: %#v\nExpected response: %#v", resp, test.expectedResp)
}
})
}
}
func TestGRPCClient_UpdateUser(t *testing.T) {
runningCtx := context.Background()
cancelledCtx, cancel := context.WithCancel(context.Background())
cancel()
type testCase struct {
client proto.DatabaseClient
req UpdateUserRequest
doneCtx context.Context
assertErr errorAssertion
}
tests := map[string]testCase{
"missing username": {
client: fakeClient{},
req: UpdateUserRequest{},
doneCtx: runningCtx,
assertErr: assertErrNotNil,
},
"missing changes": {
client: fakeClient{},
req: UpdateUserRequest{
Username: "user",
},
doneCtx: runningCtx,
assertErr: assertErrNotNil,
},
"empty password": {
client: fakeClient{},
req: UpdateUserRequest{
Username: "user",
Password: &ChangePassword{
NewPassword: "",
},
},
doneCtx: runningCtx,
assertErr: assertErrNotNil,
},
"zero expiration": {
client: fakeClient{},
req: UpdateUserRequest{
Username: "user",
Expiration: &ChangeExpiration{
NewExpiration: time.Time{},
},
},
doneCtx: runningCtx,
assertErr: assertErrNotNil,
},
"bad expiration": {
client: fakeClient{},
req: UpdateUserRequest{
Username: "user",
Expiration: &ChangeExpiration{
NewExpiration: invalidExpiration,
},
},
doneCtx: runningCtx,
assertErr: assertErrNotNil,
},
"database error": {
client: fakeClient{
updateUserErr: errors.New("update user error"),
},
req: UpdateUserRequest{
Username: "user",
Password: &ChangePassword{
NewPassword: "asdf",
},
},
doneCtx: runningCtx,
assertErr: assertErrNotNil,
},
"plugin shut down": {
client: fakeClient{
updateUserErr: errors.New("update user error"),
},
req: UpdateUserRequest{
Username: "user",
Password: &ChangePassword{
NewPassword: "asdf",
},
},
doneCtx: cancelledCtx,
assertErr: assertErrEquals(ErrPluginShutdown),
},
"happy path - change password": {
client: fakeClient{},
req: UpdateUserRequest{
Username: "user",
Password: &ChangePassword{
NewPassword: "asdf",
},
},
doneCtx: runningCtx,
assertErr: assertErrNil,
},
"happy path - change expiration": {
client: fakeClient{},
req: UpdateUserRequest{
Username: "user",
Expiration: &ChangeExpiration{
NewExpiration: time.Now(),
},
},
doneCtx: runningCtx,
assertErr: assertErrNil,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
c := gRPCClient{
client: test.client,
doneCtx: test.doneCtx,
}
ctx := context.Background()
_, err := c.UpdateUser(ctx, test.req)
test.assertErr(t, err)
})
}
}
func TestGRPCClient_DeleteUser(t *testing.T) {
runningCtx := context.Background()
cancelledCtx, cancel := context.WithCancel(context.Background())
cancel()
type testCase struct {
client proto.DatabaseClient
req DeleteUserRequest
doneCtx context.Context
assertErr errorAssertion
}
tests := map[string]testCase{
"missing username": {
client: fakeClient{},
req: DeleteUserRequest{},
doneCtx: runningCtx,
assertErr: assertErrNotNil,
},
"database error": {
client: fakeClient{
deleteUserErr: errors.New("delete user error'"),
},
req: DeleteUserRequest{
Username: "user",
},
doneCtx: runningCtx,
assertErr: assertErrNotNil,
},
"plugin shut down": {
client: fakeClient{
deleteUserErr: errors.New("delete user error'"),
},
req: DeleteUserRequest{
Username: "user",
},
doneCtx: cancelledCtx,
assertErr: assertErrEquals(ErrPluginShutdown),
},
"happy path": {
client: fakeClient{},
req: DeleteUserRequest{
Username: "user",
},
doneCtx: runningCtx,
assertErr: assertErrNil,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
c := gRPCClient{
client: test.client,
doneCtx: test.doneCtx,
}
ctx := context.Background()
_, err := c.DeleteUser(ctx, test.req)
test.assertErr(t, err)
})
}
}
func TestGRPCClient_Type(t *testing.T) {
runningCtx := context.Background()
cancelledCtx, cancel := context.WithCancel(context.Background())
cancel()
type testCase struct {
client proto.DatabaseClient
doneCtx context.Context
expectedType string
assertErr errorAssertion
}
tests := map[string]testCase{
"database error": {
client: fakeClient{
typeErr: errors.New("type error"),
},
doneCtx: runningCtx,
assertErr: assertErrNotNil,
},
"plugin shut down": {
client: fakeClient{
typeErr: errors.New("type error"),
},
doneCtx: cancelledCtx,
assertErr: assertErrEquals(ErrPluginShutdown),
},
"happy path": {
client: fakeClient{
typeResp: &proto.TypeResponse{
Type: "test type",
},
},
doneCtx: runningCtx,
expectedType: "test type",
assertErr: assertErrNil,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
c := gRPCClient{
client: test.client,
doneCtx: test.doneCtx,
}
dbType, err := c.Type()
test.assertErr(t, err)
if dbType != test.expectedType {
t.Fatalf("Actual type: %s Expected type: %s", dbType, test.expectedType)
}
})
}
}
func TestGRPCClient_Close(t *testing.T) {
runningCtx := context.Background()
cancelledCtx, cancel := context.WithCancel(context.Background())
cancel()
type testCase struct {
client proto.DatabaseClient
doneCtx context.Context
assertErr errorAssertion
}
tests := map[string]testCase{
"database error": {
client: fakeClient{
typeErr: errors.New("type error"),
},
doneCtx: runningCtx,
assertErr: assertErrNotNil,
},
"plugin shut down": {
client: fakeClient{
typeErr: errors.New("type error"),
},
doneCtx: cancelledCtx,
assertErr: assertErrEquals(ErrPluginShutdown),
},
"happy path": {
client: fakeClient{},
doneCtx: runningCtx,
assertErr: assertErrNil,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
c := gRPCClient{
client: test.client,
doneCtx: test.doneCtx,
}
err := c.Close()
test.assertErr(t, err)
})
}
}
type errorAssertion func(*testing.T, error)
func assertErrNotNil(t *testing.T, err error) {
t.Helper()
if err == nil {
t.Fatalf("err expected, got nil")
}
}
func assertErrNil(t *testing.T, err error) {
t.Helper()
if err != nil {
t.Fatalf("no error expected, got: %s", err)
}
}
func assertErrEquals(expectedErr error) errorAssertion {
return func(t *testing.T, err error) {
t.Helper()
if err != expectedErr {
t.Fatalf("Actual err: %#v Expected err: %#v", err, expectedErr)
}
}
}
var _ proto.DatabaseClient = fakeClient{}
type fakeClient struct {
initResp *proto.InitializeResponse
initErr error
newUserResp *proto.NewUserResponse
newUserErr error
updateUserResp *proto.UpdateUserResponse
updateUserErr error
deleteUserResp *proto.DeleteUserResponse
deleteUserErr error
typeResp *proto.TypeResponse
typeErr error
closeErr error
}
func (f fakeClient) Initialize(context.Context, *proto.InitializeRequest, ...grpc.CallOption) (*proto.InitializeResponse, error) {
return f.initResp, f.initErr
}
func (f fakeClient) NewUser(context.Context, *proto.NewUserRequest, ...grpc.CallOption) (*proto.NewUserResponse, error) {
return f.newUserResp, f.newUserErr
}
func (f fakeClient) UpdateUser(context.Context, *proto.UpdateUserRequest, ...grpc.CallOption) (*proto.UpdateUserResponse, error) {
return f.updateUserResp, f.updateUserErr
}
func (f fakeClient) DeleteUser(context.Context, *proto.DeleteUserRequest, ...grpc.CallOption) (*proto.DeleteUserResponse, error) {
return f.deleteUserResp, f.deleteUserErr
}
func (f fakeClient) Type(context.Context, *proto.Empty, ...grpc.CallOption) (*proto.TypeResponse, error) {
return f.typeResp, f.typeErr
}
func (f fakeClient) Close(context.Context, *proto.Empty, ...grpc.CallOption) (*proto.Empty, error) {
return &proto.Empty{}, f.typeErr
}

View File

@@ -0,0 +1,42 @@
package dbplugin
import (
"context"
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"google.golang.org/grpc"
)
// handshakeConfigs are used to just do a basic handshake between
// a plugin and host. If the handshake fails, a user friendly error is shown.
// This prevents users from executing bad plugins or executing a plugin
// directory. It is a UX feature, not a security feature.
var handshakeConfig = plugin.HandshakeConfig{
ProtocolVersion: 5,
MagicCookieKey: "VAULT_DATABASE_PLUGIN",
MagicCookieValue: "926a0820-aea2-be28-51d6-83cdf00e8edb",
}
type GRPCDatabasePlugin struct {
Impl Database
// Embeding this will disable the netRPC protocol
plugin.NetRPCUnsupportedPlugin
}
var _ plugin.Plugin = &GRPCDatabasePlugin{}
var _ plugin.GRPCPlugin = &GRPCDatabasePlugin{}
func (d GRPCDatabasePlugin) GRPCServer(_ *plugin.GRPCBroker, s *grpc.Server) error {
proto.RegisterDatabaseServer(s, gRPCServer{impl: d.Impl})
return nil
}
func (GRPCDatabasePlugin) GRPCClient(doneCtx context.Context, _ *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
client := gRPCClient{
client: proto.NewDatabaseClient(c),
doneCtx: doneCtx,
}
return client, nil
}

View File

@@ -0,0 +1,190 @@
package dbplugin
import (
"context"
"fmt"
"time"
"github.com/golang/protobuf/ptypes"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var _ proto.DatabaseServer = gRPCServer{}
type gRPCServer struct {
impl Database
}
// Initialize the database plugin
func (g gRPCServer) Initialize(ctx context.Context, request *proto.InitializeRequest) (*proto.InitializeResponse, error) {
rawConfig := structToMap(request.ConfigData)
dbReq := InitializeRequest{
Config: rawConfig,
VerifyConnection: request.VerifyConnection,
}
dbResp, err := g.impl.Initialize(ctx, dbReq)
if err != nil {
return &proto.InitializeResponse{}, status.Errorf(codes.Internal, "failed to initialize: %s", err)
}
newConfig, err := mapToStruct(dbResp.Config)
if err != nil {
return &proto.InitializeResponse{}, status.Errorf(codes.Internal, "failed to marshal new config to JSON: %s", err)
}
resp := &proto.InitializeResponse{
ConfigData: newConfig,
}
return resp, nil
}
func (g gRPCServer) NewUser(ctx context.Context, req *proto.NewUserRequest) (*proto.NewUserResponse, error) {
if req.GetUsernameConfig() == nil {
return &proto.NewUserResponse{}, status.Errorf(codes.InvalidArgument, "missing username config")
}
var expiration time.Time
if req.GetExpiration() != nil {
exp, err := ptypes.Timestamp(req.GetExpiration())
if err != nil {
return &proto.NewUserResponse{}, status.Errorf(codes.InvalidArgument, "unable to parse expiration date: %s", err)
}
expiration = exp
}
dbReq := NewUserRequest{
UsernameConfig: UsernameMetadata{
DisplayName: req.GetUsernameConfig().GetDisplayName(),
RoleName: req.GetUsernameConfig().GetRoleName(),
},
Password: req.GetPassword(),
Expiration: expiration,
Statements: getStatementsFromProto(req.GetStatements()),
RollbackStatements: getStatementsFromProto(req.GetRollbackStatements()),
}
dbResp, err := g.impl.NewUser(ctx, dbReq)
if err != nil {
return &proto.NewUserResponse{}, status.Errorf(codes.Internal, "unable to create new user: %s", err)
}
resp := &proto.NewUserResponse{
Username: dbResp.Username,
}
return resp, nil
}
func (g gRPCServer) UpdateUser(ctx context.Context, req *proto.UpdateUserRequest) (*proto.UpdateUserResponse, error) {
if req.GetUsername() == "" {
return &proto.UpdateUserResponse{}, status.Errorf(codes.InvalidArgument, "no username provided")
}
dbReq, err := getUpdateUserRequest(req)
if err != nil {
return &proto.UpdateUserResponse{}, status.Errorf(codes.InvalidArgument, err.Error())
}
_, err = g.impl.UpdateUser(ctx, dbReq)
if err != nil {
return &proto.UpdateUserResponse{}, status.Errorf(codes.Internal, "unable to update user: %s", err)
}
return &proto.UpdateUserResponse{}, nil
}
func getUpdateUserRequest(req *proto.UpdateUserRequest) (UpdateUserRequest, error) {
var password *ChangePassword
if req.GetPassword() != nil && req.GetPassword().GetNewPassword() != "" {
password = &ChangePassword{
NewPassword: req.GetPassword().GetNewPassword(),
Statements: getStatementsFromProto(req.GetPassword().GetStatements()),
}
}
var expiration *ChangeExpiration
if req.GetExpiration() != nil && req.GetExpiration().GetNewExpiration() != nil {
newExpiration, err := ptypes.Timestamp(req.GetExpiration().GetNewExpiration())
if err != nil {
return UpdateUserRequest{}, fmt.Errorf("unable to parse new expiration: %w", err)
}
expiration = &ChangeExpiration{
NewExpiration: newExpiration,
Statements: getStatementsFromProto(req.GetExpiration().GetStatements()),
}
}
dbReq := UpdateUserRequest{
Username: req.GetUsername(),
Password: password,
Expiration: expiration,
}
if !hasChange(dbReq) {
return UpdateUserRequest{}, fmt.Errorf("update user request has no changes")
}
return dbReq, nil
}
func hasChange(dbReq UpdateUserRequest) bool {
if dbReq.Password != nil && dbReq.Password.NewPassword != "" {
return true
}
if dbReq.Expiration != nil && !dbReq.Expiration.NewExpiration.IsZero() {
return true
}
return false
}
func (g gRPCServer) DeleteUser(ctx context.Context, req *proto.DeleteUserRequest) (*proto.DeleteUserResponse, error) {
if req.GetUsername() == "" {
return &proto.DeleteUserResponse{}, status.Errorf(codes.InvalidArgument, "no username provided")
}
dbReq := DeleteUserRequest{
Username: req.GetUsername(),
Statements: getStatementsFromProto(req.GetStatements()),
}
_, err := g.impl.DeleteUser(ctx, dbReq)
if err != nil {
return &proto.DeleteUserResponse{}, status.Errorf(codes.Internal, "unable to delete user: %s", err)
}
return &proto.DeleteUserResponse{}, nil
}
func (g gRPCServer) Type(ctx context.Context, _ *proto.Empty) (*proto.TypeResponse, error) {
t, err := g.impl.Type()
if err != nil {
return &proto.TypeResponse{}, status.Errorf(codes.Internal, "unable to retrieve type: %s", err)
}
resp := &proto.TypeResponse{
Type: t,
}
return resp, nil
}
func (g gRPCServer) Close(ctx context.Context, _ *proto.Empty) (*proto.Empty, error) {
err := g.impl.Close()
if err != nil {
return &proto.Empty{}, status.Errorf(codes.Internal, "unable to close database plugin: %s", err)
}
return &proto.Empty{}, nil
}
func getStatementsFromProto(protoStmts *proto.Statements) (statements Statements) {
if protoStmts == nil {
return statements
}
cmds := protoStmts.GetCommands()
statements = Statements{
Commands: cmds,
}
return statements
}

View File

@@ -0,0 +1,692 @@
package dbplugin
import (
"context"
"errors"
"fmt"
"reflect"
"testing"
"time"
"google.golang.org/protobuf/types/known/structpb"
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/timestamp"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var (
// Before minValidSeconds in ptypes package
invalidExpiration = time.Date(0, 1, 1, 0, 0, 0, 0, time.UTC)
)
func TestGRPCServer_Initialize(t *testing.T) {
type testCase struct {
db Database
req *proto.InitializeRequest
expectedResp *proto.InitializeResponse
expectErr bool
expectCode codes.Code
}
tests := map[string]testCase{
"database errored": {
db: fakeDatabase{
initErr: errors.New("initialization error"),
},
req: &proto.InitializeRequest{},
expectedResp: &proto.InitializeResponse{},
expectErr: true,
expectCode: codes.Internal,
},
"newConfig can't marshal to JSON": {
db: fakeDatabase{
initResp: InitializeResponse{
Config: map[string]interface{}{
"bad-data": badJSONValue{},
},
},
},
req: &proto.InitializeRequest{},
expectedResp: &proto.InitializeResponse{},
expectErr: true,
expectCode: codes.Internal,
},
"happy path with config data": {
db: fakeDatabase{
initResp: InitializeResponse{
Config: map[string]interface{}{
"foo": "bar",
},
},
},
req: &proto.InitializeRequest{
ConfigData: marshal(t, map[string]interface{}{
"foo": "bar",
}),
},
expectedResp: &proto.InitializeResponse{
ConfigData: marshal(t, map[string]interface{}{
"foo": "bar",
}),
},
expectErr: false,
expectCode: codes.OK,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
g := gRPCServer{
impl: test.db,
}
// Context doesn't need to timeout since this is just passed through
ctx := context.Background()
resp, err := g.Initialize(ctx, test.req)
if test.expectErr && err == nil {
t.Fatalf("err expected, got nil")
}
if !test.expectErr && err != nil {
t.Fatalf("no error expected, got: %s", err)
}
actualCode := status.Code(err)
if actualCode != test.expectCode {
t.Fatalf("Actual code: %s Expected code: %s", actualCode, test.expectCode)
}
if !reflect.DeepEqual(resp, test.expectedResp) {
t.Fatalf("Actual response: %#v\nExpected response: %#v", resp, test.expectedResp)
}
})
}
}
func TestCoerceFloatsToInt(t *testing.T) {
type testCase struct {
input map[string]interface{}
expected map[string]interface{}
}
tests := map[string]testCase{
"no numbers": {
input: map[string]interface{}{
"foo": "bar",
},
expected: map[string]interface{}{
"foo": "bar",
},
},
"raw integers": {
input: map[string]interface{}{
"foo": 42,
},
expected: map[string]interface{}{
"foo": 42,
},
},
"floats ": {
input: map[string]interface{}{
"foo": 42.2,
},
expected: map[string]interface{}{
"foo": 42.2,
},
},
"floats coerced to ints": {
input: map[string]interface{}{
"foo": float64(42),
},
expected: map[string]interface{}{
"foo": int64(42),
},
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
actual := copyMap(test.input)
coerceFloatsToInt(actual)
if !reflect.DeepEqual(actual, test.expected) {
t.Fatalf("Actual: %#v\nExpected: %#v", actual, test.expected)
}
})
}
}
func copyMap(m map[string]interface{}) map[string]interface{} {
newMap := map[string]interface{}{}
for k, v := range m {
newMap[k] = v
}
return newMap
}
func TestGRPCServer_NewUser(t *testing.T) {
type testCase struct {
db Database
req *proto.NewUserRequest
expectedResp *proto.NewUserResponse
expectErr bool
expectCode codes.Code
}
tests := map[string]testCase{
"missing username config": {
db: fakeDatabase{},
req: &proto.NewUserRequest{},
expectedResp: &proto.NewUserResponse{},
expectErr: true,
expectCode: codes.InvalidArgument,
},
"bad expiration": {
db: fakeDatabase{},
req: &proto.NewUserRequest{
UsernameConfig: &proto.UsernameConfig{
DisplayName: "dispname",
RoleName: "rolename",
},
Expiration: &timestamp.Timestamp{
Seconds: invalidExpiration.Unix(),
},
},
expectedResp: &proto.NewUserResponse{},
expectErr: true,
expectCode: codes.InvalidArgument,
},
"database error": {
db: fakeDatabase{
newUserErr: errors.New("new user error"),
},
req: &proto.NewUserRequest{
UsernameConfig: &proto.UsernameConfig{
DisplayName: "dispname",
RoleName: "rolename",
},
Expiration: ptypes.TimestampNow(),
},
expectedResp: &proto.NewUserResponse{},
expectErr: true,
expectCode: codes.Internal,
},
"happy path with expiration": {
db: fakeDatabase{
newUserResp: NewUserResponse{
Username: "someuser_foo",
},
},
req: &proto.NewUserRequest{
UsernameConfig: &proto.UsernameConfig{
DisplayName: "dispname",
RoleName: "rolename",
},
Expiration: ptypes.TimestampNow(),
},
expectedResp: &proto.NewUserResponse{
Username: "someuser_foo",
},
expectErr: false,
expectCode: codes.OK,
},
"happy path without expiration": {
db: fakeDatabase{
newUserResp: NewUserResponse{
Username: "someuser_foo",
},
},
req: &proto.NewUserRequest{
UsernameConfig: &proto.UsernameConfig{
DisplayName: "dispname",
RoleName: "rolename",
},
},
expectedResp: &proto.NewUserResponse{
Username: "someuser_foo",
},
expectErr: false,
expectCode: codes.OK,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
g := gRPCServer{
impl: test.db,
}
// Context doesn't need to timeout since this is just passed through
ctx := context.Background()
resp, err := g.NewUser(ctx, test.req)
if test.expectErr && err == nil {
t.Fatalf("err expected, got nil")
}
if !test.expectErr && err != nil {
t.Fatalf("no error expected, got: %s", err)
}
actualCode := status.Code(err)
if actualCode != test.expectCode {
t.Fatalf("Actual code: %s Expected code: %s", actualCode, test.expectCode)
}
if !reflect.DeepEqual(resp, test.expectedResp) {
t.Fatalf("Actual response: %#v\nExpected response: %#v", resp, test.expectedResp)
}
})
}
}
func TestGRPCServer_UpdateUser(t *testing.T) {
type testCase struct {
db Database
req *proto.UpdateUserRequest
expectedResp *proto.UpdateUserResponse
expectErr bool
expectCode codes.Code
}
tests := map[string]testCase{
"missing username": {
db: fakeDatabase{},
req: &proto.UpdateUserRequest{},
expectedResp: &proto.UpdateUserResponse{},
expectErr: true,
expectCode: codes.InvalidArgument,
},
"missing changes": {
db: fakeDatabase{},
req: &proto.UpdateUserRequest{
Username: "someuser",
},
expectedResp: &proto.UpdateUserResponse{},
expectErr: true,
expectCode: codes.InvalidArgument,
},
"database error": {
db: fakeDatabase{
updateUserErr: errors.New("update user error"),
},
req: &proto.UpdateUserRequest{
Username: "someuser",
Password: &proto.ChangePassword{
NewPassword: "90ughaino",
},
},
expectedResp: &proto.UpdateUserResponse{},
expectErr: true,
expectCode: codes.Internal,
},
"bad expiration date": {
db: fakeDatabase{},
req: &proto.UpdateUserRequest{
Username: "someuser",
Expiration: &proto.ChangeExpiration{
NewExpiration: &timestamp.Timestamp{
// Before minValidSeconds in ptypes package
Seconds: invalidExpiration.Unix(),
},
},
},
expectedResp: &proto.UpdateUserResponse{},
expectErr: true,
expectCode: codes.InvalidArgument,
},
"change password happy path": {
db: fakeDatabase{},
req: &proto.UpdateUserRequest{
Username: "someuser",
Password: &proto.ChangePassword{
NewPassword: "90ughaino",
},
},
expectedResp: &proto.UpdateUserResponse{},
expectErr: false,
expectCode: codes.OK,
},
"change expiration happy path": {
db: fakeDatabase{},
req: &proto.UpdateUserRequest{
Username: "someuser",
Expiration: &proto.ChangeExpiration{
NewExpiration: ptypes.TimestampNow(),
},
},
expectedResp: &proto.UpdateUserResponse{},
expectErr: false,
expectCode: codes.OK,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
g := gRPCServer{
impl: test.db,
}
// Context doesn't need to timeout since this is just passed through
ctx := context.Background()
resp, err := g.UpdateUser(ctx, test.req)
if test.expectErr && err == nil {
t.Fatalf("err expected, got nil")
}
if !test.expectErr && err != nil {
t.Fatalf("no error expected, got: %s", err)
}
actualCode := status.Code(err)
if actualCode != test.expectCode {
t.Fatalf("Actual code: %s Expected code: %s", actualCode, test.expectCode)
}
if !reflect.DeepEqual(resp, test.expectedResp) {
t.Fatalf("Actual response: %#v\nExpected response: %#v", resp, test.expectedResp)
}
})
}
}
func TestGRPCServer_DeleteUser(t *testing.T) {
type testCase struct {
db Database
req *proto.DeleteUserRequest
expectedResp *proto.DeleteUserResponse
expectErr bool
expectCode codes.Code
}
tests := map[string]testCase{
"missing username": {
db: fakeDatabase{},
req: &proto.DeleteUserRequest{},
expectedResp: &proto.DeleteUserResponse{},
expectErr: true,
expectCode: codes.InvalidArgument,
},
"database error": {
db: fakeDatabase{
deleteUserErr: errors.New("delete user error"),
},
req: &proto.DeleteUserRequest{
Username: "someuser",
},
expectedResp: &proto.DeleteUserResponse{},
expectErr: true,
expectCode: codes.Internal,
},
"happy path": {
db: fakeDatabase{},
req: &proto.DeleteUserRequest{
Username: "someuser",
},
expectedResp: &proto.DeleteUserResponse{},
expectErr: false,
expectCode: codes.OK,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
g := gRPCServer{
impl: test.db,
}
// Context doesn't need to timeout since this is just passed through
ctx := context.Background()
resp, err := g.DeleteUser(ctx, test.req)
if test.expectErr && err == nil {
t.Fatalf("err expected, got nil")
}
if !test.expectErr && err != nil {
t.Fatalf("no error expected, got: %s", err)
}
actualCode := status.Code(err)
if actualCode != test.expectCode {
t.Fatalf("Actual code: %s Expected code: %s", actualCode, test.expectCode)
}
if !reflect.DeepEqual(resp, test.expectedResp) {
t.Fatalf("Actual response: %#v\nExpected response: %#v", resp, test.expectedResp)
}
})
}
}
func TestGRPCServer_Type(t *testing.T) {
type testCase struct {
db Database
expectedResp *proto.TypeResponse
expectErr bool
expectCode codes.Code
}
tests := map[string]testCase{
"database error": {
db: fakeDatabase{
typeErr: errors.New("type error"),
},
expectedResp: &proto.TypeResponse{},
expectErr: true,
expectCode: codes.Internal,
},
"happy path": {
db: fakeDatabase{
typeResp: "fake database",
},
expectedResp: &proto.TypeResponse{
Type: "fake database",
},
expectErr: false,
expectCode: codes.OK,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
g := gRPCServer{
impl: test.db,
}
// Context doesn't need to timeout since this is just passed through
ctx := context.Background()
resp, err := g.Type(ctx, &proto.Empty{})
if test.expectErr && err == nil {
t.Fatalf("err expected, got nil")
}
if !test.expectErr && err != nil {
t.Fatalf("no error expected, got: %s", err)
}
actualCode := status.Code(err)
if actualCode != test.expectCode {
t.Fatalf("Actual code: %s Expected code: %s", actualCode, test.expectCode)
}
if !reflect.DeepEqual(resp, test.expectedResp) {
t.Fatalf("Actual response: %#v\nExpected response: %#v", resp, test.expectedResp)
}
})
}
}
func TestGRPCServer_Close(t *testing.T) {
type testCase struct {
db Database
expectErr bool
expectCode codes.Code
}
tests := map[string]testCase{
"database error": {
db: fakeDatabase{
closeErr: errors.New("close error"),
},
expectErr: true,
expectCode: codes.Internal,
},
"happy path": {
db: fakeDatabase{},
expectErr: false,
expectCode: codes.OK,
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
g := gRPCServer{
impl: test.db,
}
// Context doesn't need to timeout since this is just passed through
ctx := context.Background()
_, err := g.Close(ctx, &proto.Empty{})
if test.expectErr && err == nil {
t.Fatalf("err expected, got nil")
}
if !test.expectErr && err != nil {
t.Fatalf("no error expected, got: %s", err)
}
actualCode := status.Code(err)
if actualCode != test.expectCode {
t.Fatalf("Actual code: %s Expected code: %s", actualCode, test.expectCode)
}
})
}
}
func marshal(t *testing.T, m map[string]interface{}) *structpb.Struct {
t.Helper()
strct, err := mapToStruct(m)
if err != nil {
t.Fatalf("unable to marshal to protobuf: %s", err)
}
return strct
}
type badJSONValue struct{}
func (badJSONValue) MarshalJSON() ([]byte, error) {
return nil, fmt.Errorf("this cannot be marshalled to JSON")
}
func (badJSONValue) UnmarshalJSON([]byte) error {
return fmt.Errorf("this cannot be unmarshalled from JSON")
}
var _ Database = fakeDatabase{}
type fakeDatabase struct {
initResp InitializeResponse
initErr error
newUserResp NewUserResponse
newUserErr error
updateUserResp UpdateUserResponse
updateUserErr error
deleteUserResp DeleteUserResponse
deleteUserErr error
typeResp string
typeErr error
closeErr error
}
func (e fakeDatabase) Initialize(ctx context.Context, req InitializeRequest) (InitializeResponse, error) {
return e.initResp, e.initErr
}
func (e fakeDatabase) NewUser(ctx context.Context, req NewUserRequest) (NewUserResponse, error) {
return e.newUserResp, e.newUserErr
}
func (e fakeDatabase) UpdateUser(ctx context.Context, req UpdateUserRequest) (UpdateUserResponse, error) {
return e.updateUserResp, e.updateUserErr
}
func (e fakeDatabase) DeleteUser(ctx context.Context, req DeleteUserRequest) (DeleteUserResponse, error) {
return e.deleteUserResp, e.deleteUserErr
}
func (e fakeDatabase) Type() (string, error) {
return e.typeResp, e.typeErr
}
func (e fakeDatabase) Close() error {
return e.closeErr
}
var _ Database = &recordingDatabase{}
type recordingDatabase struct {
initializeCalls int
newUserCalls int
updateUserCalls int
deleteUserCalls int
typeCalls int
closeCalls int
// recordingDatabase can act as middleware so we can record the calls to other test Database implementations
next Database
}
func (f *recordingDatabase) Initialize(ctx context.Context, req InitializeRequest) (InitializeResponse, error) {
f.initializeCalls++
if f.next == nil {
return InitializeResponse{}, nil
}
return f.next.Initialize(ctx, req)
}
func (f *recordingDatabase) NewUser(ctx context.Context, req NewUserRequest) (NewUserResponse, error) {
f.newUserCalls++
if f.next == nil {
return NewUserResponse{}, nil
}
return f.next.NewUser(ctx, req)
}
func (f *recordingDatabase) UpdateUser(ctx context.Context, req UpdateUserRequest) (UpdateUserResponse, error) {
f.updateUserCalls++
if f.next == nil {
return UpdateUserResponse{}, nil
}
return f.next.UpdateUser(ctx, req)
}
func (f *recordingDatabase) DeleteUser(ctx context.Context, req DeleteUserRequest) (DeleteUserResponse, error) {
f.deleteUserCalls++
if f.next == nil {
return DeleteUserResponse{}, nil
}
return f.next.DeleteUser(ctx, req)
}
func (f *recordingDatabase) Type() (string, error) {
f.typeCalls++
if f.next == nil {
return "recordingDatabase", nil
}
return f.next.Type()
}
func (f *recordingDatabase) Close() error {
f.closeCalls++
if f.next == nil {
return nil
}
return f.next.Close()
}

View File

@@ -0,0 +1,36 @@
package dbplugin
import (
"math"
"google.golang.org/protobuf/types/known/structpb"
)
func mapToStruct(m map[string]interface{}) (*structpb.Struct, error) {
return structpb.NewStruct(m)
}
func structToMap(strct *structpb.Struct) map[string]interface{} {
m := strct.AsMap()
coerceFloatsToInt(m)
return m
}
// coerceFloatsToInt if the floats can be coerced to an integer without losing data
func coerceFloatsToInt(m map[string]interface{}) {
for k, v := range m {
fVal, ok := v.(float64)
if !ok {
continue
}
if isInt(fVal) {
m[k] = int64(fVal)
}
}
}
// isInt attempts to determine if the given floating point number could be represented as an integer without losing data
// This does not work for very large floats, however in this usage that's okay since we don't expect numbers that large.
func isInt(f float64) bool {
return math.Floor(f) == f
}

View File

@@ -0,0 +1,274 @@
package dbplugin
import (
"context"
"errors"
"net/url"
"strings"
"time"
metrics "github.com/armon/go-metrics"
"github.com/hashicorp/errwrap"
log "github.com/hashicorp/go-hclog"
"google.golang.org/grpc/status"
)
// ///////////////////////////////////////////////////
// Tracing Middleware
// ///////////////////////////////////////////////////
var _ Database = databaseTracingMiddleware{}
// databaseTracingMiddleware wraps a implementation of Database and executes
// trace logging on function call.
type databaseTracingMiddleware struct {
next Database
logger log.Logger
}
func (mw databaseTracingMiddleware) Initialize(ctx context.Context, req InitializeRequest) (resp InitializeResponse, err error) {
defer func(then time.Time) {
mw.logger.Trace("initialize",
"status", "finished",
"verify", req.VerifyConnection,
"err", err,
"took", time.Since(then))
}(time.Now())
mw.logger.Trace("initialize", "status", "started")
return mw.next.Initialize(ctx, req)
}
func (mw databaseTracingMiddleware) NewUser(ctx context.Context, req NewUserRequest) (resp NewUserResponse, err error) {
defer func(then time.Time) {
mw.logger.Trace("create user",
"status", "finished",
"err", err,
"took", time.Since(then))
}(time.Now())
mw.logger.Trace("create user",
"status", "started")
return mw.next.NewUser(ctx, req)
}
func (mw databaseTracingMiddleware) UpdateUser(ctx context.Context, req UpdateUserRequest) (resp UpdateUserResponse, err error) {
defer func(then time.Time) {
mw.logger.Trace("update user",
"status", "finished",
"err", err,
"took", time.Since(then))
}(time.Now())
mw.logger.Trace("update user", "status", "started")
return mw.next.UpdateUser(ctx, req)
}
func (mw databaseTracingMiddleware) DeleteUser(ctx context.Context, req DeleteUserRequest) (resp DeleteUserResponse, err error) {
defer func(then time.Time) {
mw.logger.Trace("delete user",
"status", "finished",
"err", err,
"took", time.Since(then))
}(time.Now())
mw.logger.Trace("delete user",
"status", "started")
return mw.next.DeleteUser(ctx, req)
}
func (mw databaseTracingMiddleware) Type() (string, error) {
return mw.next.Type()
}
func (mw databaseTracingMiddleware) Close() (err error) {
defer func(then time.Time) {
mw.logger.Trace("close",
"status", "finished",
"err", err,
"took", time.Since(then))
}(time.Now())
mw.logger.Trace("close",
"status", "started")
return mw.next.Close()
}
// ///////////////////////////////////////////////////
// Metrics Middleware Domain
// ///////////////////////////////////////////////////
var _ Database = databaseMetricsMiddleware{}
// databaseMetricsMiddleware wraps an implementation of Databases and on
// function call logs metrics about this instance.
type databaseMetricsMiddleware struct {
next Database
typeStr string
}
func (mw databaseMetricsMiddleware) Initialize(ctx context.Context, req InitializeRequest) (resp InitializeResponse, err error) {
defer func(now time.Time) {
metrics.MeasureSince([]string{"database", "Initialize"}, now)
metrics.MeasureSince([]string{"database", mw.typeStr, "Initialize"}, now)
if err != nil {
metrics.IncrCounter([]string{"database", "Initialize", "error"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "Initialize", "error"}, 1)
}
}(time.Now())
metrics.IncrCounter([]string{"database", "Initialize"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "Initialize"}, 1)
return mw.next.Initialize(ctx, req)
}
func (mw databaseMetricsMiddleware) NewUser(ctx context.Context, req NewUserRequest) (resp NewUserResponse, err error) {
defer func(start time.Time) {
metrics.MeasureSince([]string{"database", "NewUser"}, start)
metrics.MeasureSince([]string{"database", mw.typeStr, "NewUser"}, start)
if err != nil {
metrics.IncrCounter([]string{"database", "NewUser", "error"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "NewUser", "error"}, 1)
}
}(time.Now())
metrics.IncrCounter([]string{"database", "NewUser"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "NewUser"}, 1)
return mw.next.NewUser(ctx, req)
}
func (mw databaseMetricsMiddleware) UpdateUser(ctx context.Context, req UpdateUserRequest) (resp UpdateUserResponse, err error) {
defer func(now time.Time) {
metrics.MeasureSince([]string{"database", "UpdateUser"}, now)
metrics.MeasureSince([]string{"database", mw.typeStr, "UpdateUser"}, now)
if err != nil {
metrics.IncrCounter([]string{"database", "UpdateUser", "error"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "UpdateUser", "error"}, 1)
}
}(time.Now())
metrics.IncrCounter([]string{"database", "UpdateUser"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "UpdateUser"}, 1)
return mw.next.UpdateUser(ctx, req)
}
func (mw databaseMetricsMiddleware) DeleteUser(ctx context.Context, req DeleteUserRequest) (resp DeleteUserResponse, err error) {
defer func(now time.Time) {
metrics.MeasureSince([]string{"database", "DeleteUser"}, now)
metrics.MeasureSince([]string{"database", mw.typeStr, "DeleteUser"}, now)
if err != nil {
metrics.IncrCounter([]string{"database", "DeleteUser", "error"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "DeleteUser", "error"}, 1)
}
}(time.Now())
metrics.IncrCounter([]string{"database", "DeleteUser"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "DeleteUser"}, 1)
return mw.next.DeleteUser(ctx, req)
}
func (mw databaseMetricsMiddleware) Type() (string, error) {
return mw.next.Type()
}
func (mw databaseMetricsMiddleware) Close() (err error) {
defer func(now time.Time) {
metrics.MeasureSince([]string{"database", "Close"}, now)
metrics.MeasureSince([]string{"database", mw.typeStr, "Close"}, now)
if err != nil {
metrics.IncrCounter([]string{"database", "Close", "error"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "Close", "error"}, 1)
}
}(time.Now())
metrics.IncrCounter([]string{"database", "Close"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "Close"}, 1)
return mw.next.Close()
}
// ///////////////////////////////////////////////////
// Error Sanitizer Middleware Domain
// ///////////////////////////////////////////////////
var _ Database = DatabaseErrorSanitizerMiddleware{}
// DatabaseErrorSanitizerMiddleware wraps an implementation of Databases and
// sanitizes returned error messages
type DatabaseErrorSanitizerMiddleware struct {
next Database
secretsFn secretsFn
}
type secretsFn func() map[string]string
func NewDatabaseErrorSanitizerMiddleware(next Database, secrets secretsFn) DatabaseErrorSanitizerMiddleware {
return DatabaseErrorSanitizerMiddleware{
next: next,
secretsFn: secrets,
}
}
func (mw DatabaseErrorSanitizerMiddleware) Initialize(ctx context.Context, req InitializeRequest) (resp InitializeResponse, err error) {
resp, err = mw.next.Initialize(ctx, req)
return resp, mw.sanitize(err)
}
func (mw DatabaseErrorSanitizerMiddleware) NewUser(ctx context.Context, req NewUserRequest) (resp NewUserResponse, err error) {
resp, err = mw.next.NewUser(ctx, req)
return resp, mw.sanitize(err)
}
func (mw DatabaseErrorSanitizerMiddleware) UpdateUser(ctx context.Context, req UpdateUserRequest) (UpdateUserResponse, error) {
resp, err := mw.next.UpdateUser(ctx, req)
return resp, mw.sanitize(err)
}
func (mw DatabaseErrorSanitizerMiddleware) DeleteUser(ctx context.Context, req DeleteUserRequest) (DeleteUserResponse, error) {
resp, err := mw.next.DeleteUser(ctx, req)
return resp, mw.sanitize(err)
}
func (mw DatabaseErrorSanitizerMiddleware) Type() (string, error) {
dbType, err := mw.next.Type()
return dbType, mw.sanitize(err)
}
func (mw DatabaseErrorSanitizerMiddleware) Close() (err error) {
return mw.sanitize(mw.next.Close())
}
// sanitize errors by removing any sensitive strings within their messages. This uses
// the secretsFn to determine what fields should be sanitized.
func (mw DatabaseErrorSanitizerMiddleware) sanitize(err error) error {
if err == nil {
return nil
}
if errwrap.ContainsType(err, new(url.Error)) {
return errors.New("unable to parse connection url")
}
if mw.secretsFn == nil {
return err
}
for find, replace := range mw.secretsFn() {
if find == "" {
continue
}
// Attempt to keep the status code attached to the
// error while changing the actual error message
s, ok := status.FromError(err)
if ok {
err = status.Error(s.Code(), strings.Replace(s.Message(), find, replace, -1))
continue
}
err = errors.New(strings.Replace(err.Error(), find, replace, -1))
}
return err
}

View File

@@ -0,0 +1,484 @@
package dbplugin
import (
"context"
"errors"
"net/url"
"reflect"
"testing"
"github.com/hashicorp/go-hclog"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func TestDatabaseErrorSanitizerMiddleware(t *testing.T) {
type testCase struct {
inputErr error
secretsFunc func() map[string]string
expectedError error
}
tests := map[string]testCase{
"nil error": {
inputErr: nil,
expectedError: nil,
},
"url error": {
inputErr: new(url.Error),
expectedError: errors.New("unable to parse connection url"),
},
"nil secrets func": {
inputErr: errors.New("here is my password: iofsd9473tg"),
expectedError: errors.New("here is my password: iofsd9473tg"),
},
"secrets with empty string": {
inputErr: errors.New("here is my password: iofsd9473tg"),
secretsFunc: secretFunc(t, "", ""),
expectedError: errors.New("here is my password: iofsd9473tg"),
},
"secrets that do not match": {
inputErr: errors.New("here is my password: iofsd9473tg"),
secretsFunc: secretFunc(t, "asdf", "<redacted>"),
expectedError: errors.New("here is my password: iofsd9473tg"),
},
"secrets that do match": {
inputErr: errors.New("here is my password: iofsd9473tg"),
secretsFunc: secretFunc(t, "iofsd9473tg", "<redacted>"),
expectedError: errors.New("here is my password: <redacted>"),
},
"multiple secrets": {
inputErr: errors.New("here is my password: iofsd9473tg"),
secretsFunc: secretFunc(t,
"iofsd9473tg", "<redacted>",
"password", "<this was the word password>",
),
expectedError: errors.New("here is my <this was the word password>: <redacted>"),
},
"gRPC status error": {
inputErr: status.Error(codes.InvalidArgument, "an error with a password iofsd9473tg"),
secretsFunc: secretFunc(t, "iofsd9473tg", "<redacted>"),
expectedError: status.Errorf(codes.InvalidArgument, "an error with a password <redacted>"),
},
}
for name, test := range tests {
t.Run(name, func(t *testing.T) {
db := fakeDatabase{}
mw := NewDatabaseErrorSanitizerMiddleware(db, test.secretsFunc)
actualErr := mw.sanitize(test.inputErr)
if !reflect.DeepEqual(actualErr, test.expectedError) {
t.Fatalf("Actual error: %s\nExpected error: %s", actualErr, test.expectedError)
}
})
}
t.Run("Initialize", func(t *testing.T) {
db := &recordingDatabase{
next: fakeDatabase{
initErr: errors.New("password: iofsd9473tg with some stuff after it"),
},
}
mw := DatabaseErrorSanitizerMiddleware{
next: db,
secretsFn: secretFunc(t, "iofsd9473tg", "<redacted>"),
}
expectedErr := errors.New("password: <redacted> with some stuff after it")
_, err := mw.Initialize(context.Background(), InitializeRequest{})
if !reflect.DeepEqual(err, expectedErr) {
t.Fatalf("Actual err: %s\n Expected err: %s", err, expectedErr)
}
assertEquals(t, db.initializeCalls, 1)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 0)
})
t.Run("NewUser", func(t *testing.T) {
db := &recordingDatabase{
next: fakeDatabase{
newUserErr: errors.New("password: iofsd9473tg with some stuff after it"),
},
}
mw := DatabaseErrorSanitizerMiddleware{
next: db,
secretsFn: secretFunc(t, "iofsd9473tg", "<redacted>"),
}
expectedErr := errors.New("password: <redacted> with some stuff after it")
_, err := mw.NewUser(context.Background(), NewUserRequest{})
if !reflect.DeepEqual(err, expectedErr) {
t.Fatalf("Actual err: %s\n Expected err: %s", err, expectedErr)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 1)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 0)
})
t.Run("UpdateUser", func(t *testing.T) {
db := &recordingDatabase{
next: fakeDatabase{
updateUserErr: errors.New("password: iofsd9473tg with some stuff after it"),
},
}
mw := DatabaseErrorSanitizerMiddleware{
next: db,
secretsFn: secretFunc(t, "iofsd9473tg", "<redacted>"),
}
expectedErr := errors.New("password: <redacted> with some stuff after it")
_, err := mw.UpdateUser(context.Background(), UpdateUserRequest{})
if !reflect.DeepEqual(err, expectedErr) {
t.Fatalf("Actual err: %s\n Expected err: %s", err, expectedErr)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 1)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 0)
})
t.Run("DeleteUser", func(t *testing.T) {
db := &recordingDatabase{
next: fakeDatabase{
deleteUserErr: errors.New("password: iofsd9473tg with some stuff after it"),
},
}
mw := DatabaseErrorSanitizerMiddleware{
next: db,
secretsFn: secretFunc(t, "iofsd9473tg", "<redacted>"),
}
expectedErr := errors.New("password: <redacted> with some stuff after it")
_, err := mw.DeleteUser(context.Background(), DeleteUserRequest{})
if !reflect.DeepEqual(err, expectedErr) {
t.Fatalf("Actual err: %s\n Expected err: %s", err, expectedErr)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 1)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 0)
})
t.Run("Type", func(t *testing.T) {
db := &recordingDatabase{
next: fakeDatabase{
typeErr: errors.New("password: iofsd9473tg with some stuff after it"),
},
}
mw := DatabaseErrorSanitizerMiddleware{
next: db,
secretsFn: secretFunc(t, "iofsd9473tg", "<redacted>"),
}
expectedErr := errors.New("password: <redacted> with some stuff after it")
_, err := mw.Type()
if !reflect.DeepEqual(err, expectedErr) {
t.Fatalf("Actual err: %s\n Expected err: %s", err, expectedErr)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 1)
assertEquals(t, db.closeCalls, 0)
})
t.Run("Close", func(t *testing.T) {
db := &recordingDatabase{
next: fakeDatabase{
closeErr: errors.New("password: iofsd9473tg with some stuff after it"),
},
}
mw := DatabaseErrorSanitizerMiddleware{
next: db,
secretsFn: secretFunc(t, "iofsd9473tg", "<redacted>"),
}
expectedErr := errors.New("password: <redacted> with some stuff after it")
err := mw.Close()
if !reflect.DeepEqual(err, expectedErr) {
t.Fatalf("Actual err: %s\n Expected err: %s", err, expectedErr)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 1)
})
}
func secretFunc(t *testing.T, vals ...string) func() map[string]string {
t.Helper()
if len(vals)%2 != 0 {
t.Fatalf("Test configuration error: secretFunc must be called with an even number of values")
}
m := map[string]string{}
for i := 0; i < len(vals); i += 2 {
key := vals[i]
m[key] = vals[i+1]
}
return func() map[string]string {
return m
}
}
func TestTracingMiddleware(t *testing.T) {
t.Run("Initialize", func(t *testing.T) {
db := &recordingDatabase{}
logger := hclog.NewNullLogger()
mw := databaseTracingMiddleware{
next: db,
logger: logger,
}
_, err := mw.Initialize(context.Background(), InitializeRequest{})
if err != nil {
t.Fatalf("Expected no error, but got: %s", err)
}
assertEquals(t, db.initializeCalls, 1)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 0)
})
t.Run("NewUser", func(t *testing.T) {
db := &recordingDatabase{}
logger := hclog.NewNullLogger()
mw := databaseTracingMiddleware{
next: db,
logger: logger,
}
_, err := mw.NewUser(context.Background(), NewUserRequest{})
if err != nil {
t.Fatalf("Expected no error, but got: %s", err)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 1)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 0)
})
t.Run("UpdateUser", func(t *testing.T) {
db := &recordingDatabase{}
logger := hclog.NewNullLogger()
mw := databaseTracingMiddleware{
next: db,
logger: logger,
}
_, err := mw.UpdateUser(context.Background(), UpdateUserRequest{})
if err != nil {
t.Fatalf("Expected no error, but got: %s", err)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 1)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 0)
})
t.Run("DeleteUser", func(t *testing.T) {
db := &recordingDatabase{}
logger := hclog.NewNullLogger()
mw := databaseTracingMiddleware{
next: db,
logger: logger,
}
_, err := mw.DeleteUser(context.Background(), DeleteUserRequest{})
if err != nil {
t.Fatalf("Expected no error, but got: %s", err)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 1)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 0)
})
t.Run("Type", func(t *testing.T) {
db := &recordingDatabase{}
logger := hclog.NewNullLogger()
mw := databaseTracingMiddleware{
next: db,
logger: logger,
}
_, err := mw.Type()
if err != nil {
t.Fatalf("Expected no error, but got: %s", err)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 1)
assertEquals(t, db.closeCalls, 0)
})
t.Run("Close", func(t *testing.T) {
db := &recordingDatabase{}
logger := hclog.NewNullLogger()
mw := databaseTracingMiddleware{
next: db,
logger: logger,
}
err := mw.Close()
if err != nil {
t.Fatalf("Expected no error, but got: %s", err)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 1)
})
}
func TestMetricsMiddleware(t *testing.T) {
t.Run("Initialize", func(t *testing.T) {
db := &recordingDatabase{}
mw := databaseMetricsMiddleware{
next: db,
typeStr: "metrics",
}
_, err := mw.Initialize(context.Background(), InitializeRequest{})
if err != nil {
t.Fatalf("Expected no error, but got: %s", err)
}
assertEquals(t, db.initializeCalls, 1)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 0)
})
t.Run("NewUser", func(t *testing.T) {
db := &recordingDatabase{}
mw := databaseMetricsMiddleware{
next: db,
typeStr: "metrics",
}
_, err := mw.NewUser(context.Background(), NewUserRequest{})
if err != nil {
t.Fatalf("Expected no error, but got: %s", err)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 1)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 0)
})
t.Run("UpdateUser", func(t *testing.T) {
db := &recordingDatabase{}
mw := databaseMetricsMiddleware{
next: db,
typeStr: "metrics",
}
_, err := mw.UpdateUser(context.Background(), UpdateUserRequest{})
if err != nil {
t.Fatalf("Expected no error, but got: %s", err)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 1)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 0)
})
t.Run("DeleteUser", func(t *testing.T) {
db := &recordingDatabase{}
mw := databaseMetricsMiddleware{
next: db,
typeStr: "metrics",
}
_, err := mw.DeleteUser(context.Background(), DeleteUserRequest{})
if err != nil {
t.Fatalf("Expected no error, but got: %s", err)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 1)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 0)
})
t.Run("Type", func(t *testing.T) {
db := &recordingDatabase{}
mw := databaseMetricsMiddleware{
next: db,
typeStr: "metrics",
}
_, err := mw.Type()
if err != nil {
t.Fatalf("Expected no error, but got: %s", err)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 1)
assertEquals(t, db.closeCalls, 0)
})
t.Run("Close", func(t *testing.T) {
db := &recordingDatabase{}
mw := databaseMetricsMiddleware{
next: db,
typeStr: "metrics",
}
err := mw.Close()
if err != nil {
t.Fatalf("Expected no error, but got: %s", err)
}
assertEquals(t, db.initializeCalls, 0)
assertEquals(t, db.newUserCalls, 0)
assertEquals(t, db.updateUserCalls, 0)
assertEquals(t, db.deleteUserCalls, 0)
assertEquals(t, db.typeCalls, 0)
assertEquals(t, db.closeCalls, 1)
})
}
func assertEquals(t *testing.T, actual, expected int) {
t.Helper()
if actual != expected {
t.Fatalf("Actual: %d Expected: %d", actual, expected)
}
}

View File

@@ -0,0 +1,81 @@
package dbplugin
import (
"context"
"errors"
"sync"
log "github.com/hashicorp/go-hclog"
plugin "github.com/hashicorp/go-plugin"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
)
// DatabasePluginClient embeds a databasePluginRPCClient and wraps it's Close
// method to also call Kill() on the plugin.Client.
type DatabasePluginClient struct {
client *plugin.Client
sync.Mutex
Database
}
// This wraps the Close call and ensures we both close the database connection
// and kill the plugin.
func (dc *DatabasePluginClient) Close() error {
err := dc.Database.Close()
dc.client.Kill()
return err
}
// NewPluginClient returns a databaseRPCClient with a connection to a running
// plugin. The client is wrapped in a DatabasePluginClient object to ensure the
// plugin is killed on call of Close().
func NewPluginClient(ctx context.Context, sys pluginutil.RunnerUtil, pluginRunner *pluginutil.PluginRunner, logger log.Logger, isMetadataMode bool) (Database, error) {
// pluginSets is the map of plugins we can dispense.
pluginSets := map[int]plugin.PluginSet{
5: plugin.PluginSet{
"database": new(GRPCDatabasePlugin),
},
}
client, err := pluginRunner.RunConfig(ctx,
pluginutil.Runner(sys),
pluginutil.PluginSets(pluginSets),
pluginutil.HandshakeConfig(handshakeConfig),
pluginutil.Logger(logger),
pluginutil.MetadataMode(isMetadataMode),
pluginutil.AutoMTLS(false),
)
if err != nil {
return nil, err
}
// Connect via RPC
rpcClient, err := client.Client()
if err != nil {
return nil, err
}
// Request the plugin
raw, err := rpcClient.Dispense("database")
if err != nil {
return nil, err
}
// We should have a database type now. This feels like a normal interface
// implementation but is in fact over an RPC connection.
var db Database
switch raw.(type) {
case gRPCClient:
db = raw.(gRPCClient)
default:
return nil, errors.New("unsupported client type")
}
// Wrap RPC implementation in DatabasePluginClient
return &DatabasePluginClient{
client: client,
Database: db,
}, nil
}

View File

@@ -0,0 +1,78 @@
package dbplugin
import (
"context"
"fmt"
"github.com/hashicorp/errwrap"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
)
// PluginFactory is used to build plugin database types. It wraps the database
// object in a logging and metrics middleware.
func PluginFactory(ctx context.Context, pluginName string, sys pluginutil.LookRunnerUtil, logger log.Logger) (Database, error) {
// Look for plugin in the plugin catalog
pluginRunner, err := sys.LookupPlugin(ctx, pluginName, consts.PluginTypeDatabase)
if err != nil {
return nil, err
}
namedLogger := logger.Named(pluginName)
var transport string
var db Database
if pluginRunner.Builtin {
// Plugin is builtin so we can retrieve an instance of the interface
// from the pluginRunner. Then cast it to a Database.
dbRaw, err := pluginRunner.BuiltinFactory()
if err != nil {
return nil, errwrap.Wrapf("error initializing plugin: {{err}}", err)
}
var ok bool
db, ok = dbRaw.(Database)
if !ok {
return nil, fmt.Errorf("unsupported database type: %q", pluginName)
}
transport = "builtin"
} else {
// create a DatabasePluginClient instance
db, err = NewPluginClient(ctx, sys, pluginRunner, namedLogger, false)
if err != nil {
return nil, err
}
// Switch on the underlying database client type to get the transport
// method.
switch db.(*DatabasePluginClient).Database.(type) {
case *gRPCClient:
transport = "gRPC"
}
}
typeStr, err := db.Type()
if err != nil {
return nil, errwrap.Wrapf("error getting plugin type: {{err}}", err)
}
// Wrap with metrics middleware
db = &databaseMetricsMiddleware{
next: db,
typeStr: typeStr,
}
// Wrap with tracing middleware
if namedLogger.IsTrace() {
db = &databaseTracingMiddleware{
next: db,
logger: namedLogger.With("transport", transport),
}
}
return db, nil
}

View File

@@ -0,0 +1,42 @@
package dbplugin
import (
"crypto/tls"
"fmt"
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
)
// Serve is called from within a plugin and wraps the provided
// Database implementation in a databasePluginRPCServer object and starts a
// RPC server.
func Serve(db Database, tlsProvider func() (*tls.Config, error)) {
plugin.Serve(ServeConfig(db, tlsProvider))
}
func ServeConfig(db Database, tlsProvider func() (*tls.Config, error)) *plugin.ServeConfig {
err := pluginutil.OptionallyEnableMlock()
if err != nil {
fmt.Println(err)
return nil
}
// pluginSets is the map of plugins we can dispense.
pluginSets := map[int]plugin.PluginSet{
5: plugin.PluginSet{
"database": &GRPCDatabasePlugin{
Impl: db,
},
},
}
conf := &plugin.ServeConfig{
HandshakeConfig: handshakeConfig,
VersionedPlugins: pluginSets,
GRPCServer: plugin.DefaultGRPCServer,
TLSProvider: tlsProvider,
}
return conf
}

View File

@@ -2,7 +2,7 @@
// versions:
// protoc-gen-go v1.23.0
// protoc v3.13.0
// source: sdk/database/newdbplugin/proto/database.proto
// source: sdk/database/dbplugin/v5/proto/database.proto
package proto
@@ -46,7 +46,7 @@ type InitializeRequest struct {
func (x *InitializeRequest) Reset() {
*x = InitializeRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[0]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -59,7 +59,7 @@ func (x *InitializeRequest) String() string {
func (*InitializeRequest) ProtoMessage() {}
func (x *InitializeRequest) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[0]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -72,7 +72,7 @@ func (x *InitializeRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use InitializeRequest.ProtoReflect.Descriptor instead.
func (*InitializeRequest) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{0}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{0}
}
func (x *InitializeRequest) GetConfigData() *_struct.Struct {
@@ -100,7 +100,7 @@ type InitializeResponse struct {
func (x *InitializeResponse) Reset() {
*x = InitializeResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[1]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -113,7 +113,7 @@ func (x *InitializeResponse) String() string {
func (*InitializeResponse) ProtoMessage() {}
func (x *InitializeResponse) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[1]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -126,7 +126,7 @@ func (x *InitializeResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use InitializeResponse.ProtoReflect.Descriptor instead.
func (*InitializeResponse) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{1}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{1}
}
func (x *InitializeResponse) GetConfigData() *_struct.Struct {
@@ -151,7 +151,7 @@ type NewUserRequest struct {
func (x *NewUserRequest) Reset() {
*x = NewUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[2]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -164,7 +164,7 @@ func (x *NewUserRequest) String() string {
func (*NewUserRequest) ProtoMessage() {}
func (x *NewUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[2]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -177,7 +177,7 @@ func (x *NewUserRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use NewUserRequest.ProtoReflect.Descriptor instead.
func (*NewUserRequest) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{2}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{2}
}
func (x *NewUserRequest) GetUsernameConfig() *UsernameConfig {
@@ -227,7 +227,7 @@ type UsernameConfig struct {
func (x *UsernameConfig) Reset() {
*x = UsernameConfig{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[3]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -240,7 +240,7 @@ func (x *UsernameConfig) String() string {
func (*UsernameConfig) ProtoMessage() {}
func (x *UsernameConfig) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[3]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -253,7 +253,7 @@ func (x *UsernameConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use UsernameConfig.ProtoReflect.Descriptor instead.
func (*UsernameConfig) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{3}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{3}
}
func (x *UsernameConfig) GetDisplayName() string {
@@ -281,7 +281,7 @@ type NewUserResponse struct {
func (x *NewUserResponse) Reset() {
*x = NewUserResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[4]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -294,7 +294,7 @@ func (x *NewUserResponse) String() string {
func (*NewUserResponse) ProtoMessage() {}
func (x *NewUserResponse) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[4]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -307,7 +307,7 @@ func (x *NewUserResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use NewUserResponse.ProtoReflect.Descriptor instead.
func (*NewUserResponse) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{4}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{4}
}
func (x *NewUserResponse) GetUsername() string {
@@ -333,7 +333,7 @@ type UpdateUserRequest struct {
func (x *UpdateUserRequest) Reset() {
*x = UpdateUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[5]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -346,7 +346,7 @@ func (x *UpdateUserRequest) String() string {
func (*UpdateUserRequest) ProtoMessage() {}
func (x *UpdateUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[5]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -359,7 +359,7 @@ func (x *UpdateUserRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use UpdateUserRequest.ProtoReflect.Descriptor instead.
func (*UpdateUserRequest) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{5}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{5}
}
func (x *UpdateUserRequest) GetUsername() string {
@@ -395,7 +395,7 @@ type ChangePassword struct {
func (x *ChangePassword) Reset() {
*x = ChangePassword{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[6]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -408,7 +408,7 @@ func (x *ChangePassword) String() string {
func (*ChangePassword) ProtoMessage() {}
func (x *ChangePassword) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[6]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -421,7 +421,7 @@ func (x *ChangePassword) ProtoReflect() protoreflect.Message {
// Deprecated: Use ChangePassword.ProtoReflect.Descriptor instead.
func (*ChangePassword) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{6}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{6}
}
func (x *ChangePassword) GetNewPassword() string {
@@ -450,7 +450,7 @@ type ChangeExpiration struct {
func (x *ChangeExpiration) Reset() {
*x = ChangeExpiration{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[7]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -463,7 +463,7 @@ func (x *ChangeExpiration) String() string {
func (*ChangeExpiration) ProtoMessage() {}
func (x *ChangeExpiration) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[7]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -476,7 +476,7 @@ func (x *ChangeExpiration) ProtoReflect() protoreflect.Message {
// Deprecated: Use ChangeExpiration.ProtoReflect.Descriptor instead.
func (*ChangeExpiration) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{7}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{7}
}
func (x *ChangeExpiration) GetNewExpiration() *timestamp.Timestamp {
@@ -502,7 +502,7 @@ type UpdateUserResponse struct {
func (x *UpdateUserResponse) Reset() {
*x = UpdateUserResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[8]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -515,7 +515,7 @@ func (x *UpdateUserResponse) String() string {
func (*UpdateUserResponse) ProtoMessage() {}
func (x *UpdateUserResponse) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[8]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -528,7 +528,7 @@ func (x *UpdateUserResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use UpdateUserResponse.ProtoReflect.Descriptor instead.
func (*UpdateUserResponse) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{8}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{8}
}
/////////////////
@@ -546,7 +546,7 @@ type DeleteUserRequest struct {
func (x *DeleteUserRequest) Reset() {
*x = DeleteUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[9]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -559,7 +559,7 @@ func (x *DeleteUserRequest) String() string {
func (*DeleteUserRequest) ProtoMessage() {}
func (x *DeleteUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[9]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -572,7 +572,7 @@ func (x *DeleteUserRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeleteUserRequest.ProtoReflect.Descriptor instead.
func (*DeleteUserRequest) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{9}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{9}
}
func (x *DeleteUserRequest) GetUsername() string {
@@ -598,7 +598,7 @@ type DeleteUserResponse struct {
func (x *DeleteUserResponse) Reset() {
*x = DeleteUserResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[10]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -611,7 +611,7 @@ func (x *DeleteUserResponse) String() string {
func (*DeleteUserResponse) ProtoMessage() {}
func (x *DeleteUserResponse) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[10]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -624,7 +624,7 @@ func (x *DeleteUserResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeleteUserResponse.ProtoReflect.Descriptor instead.
func (*DeleteUserResponse) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{10}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{10}
}
/////////////////
@@ -641,7 +641,7 @@ type TypeResponse struct {
func (x *TypeResponse) Reset() {
*x = TypeResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[11]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -654,7 +654,7 @@ func (x *TypeResponse) String() string {
func (*TypeResponse) ProtoMessage() {}
func (x *TypeResponse) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[11]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -667,7 +667,7 @@ func (x *TypeResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use TypeResponse.ProtoReflect.Descriptor instead.
func (*TypeResponse) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{11}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{11}
}
func (x *TypeResponse) GetType() string {
@@ -691,7 +691,7 @@ type Statements struct {
func (x *Statements) Reset() {
*x = Statements{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[12]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -704,7 +704,7 @@ func (x *Statements) String() string {
func (*Statements) ProtoMessage() {}
func (x *Statements) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[12]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -717,7 +717,7 @@ func (x *Statements) ProtoReflect() protoreflect.Message {
// Deprecated: Use Statements.ProtoReflect.Descriptor instead.
func (*Statements) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{12}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{12}
}
func (x *Statements) GetCommands() []string {
@@ -736,7 +736,7 @@ type Empty struct {
func (x *Empty) Reset() {
*x = Empty{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[13]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -749,7 +749,7 @@ func (x *Empty) String() string {
func (*Empty) ProtoMessage() {}
func (x *Empty) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[13]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -762,16 +762,16 @@ func (x *Empty) ProtoReflect() protoreflect.Message {
// Deprecated: Use Empty.ProtoReflect.Descriptor instead.
func (*Empty) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{13}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{13}
}
var File_sdk_database_newdbplugin_proto_database_proto protoreflect.FileDescriptor
var File_sdk_database_dbplugin_v5_proto_database_proto protoreflect.FileDescriptor
var file_sdk_database_newdbplugin_proto_database_proto_rawDesc = []byte{
0x0a, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x6e,
0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
var file_sdk_database_dbplugin_v5_proto_database_proto_rawDesc = []byte{
0x0a, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x64,
0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x0b, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x1a, 0x1c, 0x67, 0x6f,
0x0b, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x1a, 0x1c, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74,
0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65,
@@ -791,8 +791,8 @@ var file_sdk_database_newdbplugin_proto_database_proto_rawDesc = []byte{
0x66, 0x69, 0x67, 0x44, 0x61, 0x74, 0x61, 0x22, 0xb1, 0x02, 0x0a, 0x0e, 0x4e, 0x65, 0x77, 0x55,
0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x44, 0x0a, 0x0f, 0x75, 0x73,
0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69,
0x6e, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76,
0x35, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x3a, 0x0a, 0x0a,
@@ -800,12 +800,12 @@ var file_sdk_database_newdbplugin_proto_database_proto_rawDesc = []byte{
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78,
0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74,
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e,
0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65,
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x64,
0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65,
0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
0x73, 0x12, 0x48, 0x0a, 0x13, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x74,
0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,
0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x74, 0x61,
0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53, 0x74, 0x61,
0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x12, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63,
0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x50, 0x0a, 0x0e, 0x55,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x21, 0x0a,
@@ -820,18 +820,18 @@ var file_sdk_database_newdbplugin_proto_database_proto_rawDesc = []byte{
0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37,
0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43,
0x32, 0x1b, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x43,
0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x08, 0x70,
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x3d, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6e, 0x65,
0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x64, 0x62,
0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65,
0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x6c, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65,
0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x65, 0x77, 0x5f,
0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
0x6e, 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x37, 0x0a, 0x0a, 0x73,
0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x17, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x74,
0x17, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53, 0x74,
0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d,
0x65, 0x6e, 0x74, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x10, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45,
0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0e, 0x6e, 0x65, 0x77,
@@ -840,7 +840,7 @@ var file_sdk_database_newdbplugin_proto_database_proto_rawDesc = []byte{
0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e,
0x65, 0x77, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x0a,
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x17, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53,
0x32, 0x17, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53,
0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65,
0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55,
0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x68, 0x0a, 0x11, 0x44,
@@ -848,7 +848,7 @@ var file_sdk_database_newdbplugin_proto_database_proto_rawDesc = []byte{
0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x0a,
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x17, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53,
0x32, 0x17, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53,
0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65,
0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55,
0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x0a, 0x0c, 0x54,
@@ -859,93 +859,93 @@ var file_sdk_database_newdbplugin_proto_database_proto_rawDesc = []byte{
0x08, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70,
0x74, 0x79, 0x32, 0xa5, 0x03, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12,
0x4d, 0x0a, 0x0a, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x12, 0x1e, 0x2e,
0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x6e, 0x69, 0x74,
0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x49, 0x6e, 0x69, 0x74,
0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e,
0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x6e, 0x69, 0x74,
0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x49, 0x6e, 0x69, 0x74,
0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44,
0x0a, 0x07, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x6e, 0x65, 0x77, 0x64,
0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c,
0x75, 0x67, 0x69, 0x6e, 0x2e, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70,
0x0a, 0x07, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x64, 0x62, 0x70, 0x6c,
0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69,
0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73,
0x65, 0x72, 0x12, 0x1e, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
0x65, 0x72, 0x12, 0x1e, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35,
0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35,
0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65,
0x72, 0x12, 0x1e, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e,
0x72, 0x12, 0x1e, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e,
0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x1f, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e,
0x74, 0x1a, 0x1f, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e,
0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x2e, 0x6e, 0x65, 0x77,
0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19,
0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x54, 0x79, 0x70,
0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x2e, 0x64, 0x62, 0x70,
0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19,
0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x54, 0x79, 0x70,
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x05, 0x43, 0x6c, 0x6f,
0x73, 0x65, 0x12, 0x12, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c,
0x75, 0x67, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69,
0x73, 0x65, 0x12, 0x12, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35,
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69,
0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69,
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f,
0x72, 0x70, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x64, 0x61, 0x74,
0x61, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69,
0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x61, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x76,
0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_sdk_database_newdbplugin_proto_database_proto_rawDescOnce sync.Once
file_sdk_database_newdbplugin_proto_database_proto_rawDescData = file_sdk_database_newdbplugin_proto_database_proto_rawDesc
file_sdk_database_dbplugin_v5_proto_database_proto_rawDescOnce sync.Once
file_sdk_database_dbplugin_v5_proto_database_proto_rawDescData = file_sdk_database_dbplugin_v5_proto_database_proto_rawDesc
)
func file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP() []byte {
file_sdk_database_newdbplugin_proto_database_proto_rawDescOnce.Do(func() {
file_sdk_database_newdbplugin_proto_database_proto_rawDescData = protoimpl.X.CompressGZIP(file_sdk_database_newdbplugin_proto_database_proto_rawDescData)
func file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP() []byte {
file_sdk_database_dbplugin_v5_proto_database_proto_rawDescOnce.Do(func() {
file_sdk_database_dbplugin_v5_proto_database_proto_rawDescData = protoimpl.X.CompressGZIP(file_sdk_database_dbplugin_v5_proto_database_proto_rawDescData)
})
return file_sdk_database_newdbplugin_proto_database_proto_rawDescData
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescData
}
var file_sdk_database_newdbplugin_proto_database_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
var file_sdk_database_newdbplugin_proto_database_proto_goTypes = []interface{}{
(*InitializeRequest)(nil), // 0: newdbplugin.InitializeRequest
(*InitializeResponse)(nil), // 1: newdbplugin.InitializeResponse
(*NewUserRequest)(nil), // 2: newdbplugin.NewUserRequest
(*UsernameConfig)(nil), // 3: newdbplugin.UsernameConfig
(*NewUserResponse)(nil), // 4: newdbplugin.NewUserResponse
(*UpdateUserRequest)(nil), // 5: newdbplugin.UpdateUserRequest
(*ChangePassword)(nil), // 6: newdbplugin.ChangePassword
(*ChangeExpiration)(nil), // 7: newdbplugin.ChangeExpiration
(*UpdateUserResponse)(nil), // 8: newdbplugin.UpdateUserResponse
(*DeleteUserRequest)(nil), // 9: newdbplugin.DeleteUserRequest
(*DeleteUserResponse)(nil), // 10: newdbplugin.DeleteUserResponse
(*TypeResponse)(nil), // 11: newdbplugin.TypeResponse
(*Statements)(nil), // 12: newdbplugin.Statements
(*Empty)(nil), // 13: newdbplugin.Empty
var file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
var file_sdk_database_dbplugin_v5_proto_database_proto_goTypes = []interface{}{
(*InitializeRequest)(nil), // 0: dbplugin.v5.InitializeRequest
(*InitializeResponse)(nil), // 1: dbplugin.v5.InitializeResponse
(*NewUserRequest)(nil), // 2: dbplugin.v5.NewUserRequest
(*UsernameConfig)(nil), // 3: dbplugin.v5.UsernameConfig
(*NewUserResponse)(nil), // 4: dbplugin.v5.NewUserResponse
(*UpdateUserRequest)(nil), // 5: dbplugin.v5.UpdateUserRequest
(*ChangePassword)(nil), // 6: dbplugin.v5.ChangePassword
(*ChangeExpiration)(nil), // 7: dbplugin.v5.ChangeExpiration
(*UpdateUserResponse)(nil), // 8: dbplugin.v5.UpdateUserResponse
(*DeleteUserRequest)(nil), // 9: dbplugin.v5.DeleteUserRequest
(*DeleteUserResponse)(nil), // 10: dbplugin.v5.DeleteUserResponse
(*TypeResponse)(nil), // 11: dbplugin.v5.TypeResponse
(*Statements)(nil), // 12: dbplugin.v5.Statements
(*Empty)(nil), // 13: dbplugin.v5.Empty
(*_struct.Struct)(nil), // 14: google.protobuf.Struct
(*timestamp.Timestamp)(nil), // 15: google.protobuf.Timestamp
}
var file_sdk_database_newdbplugin_proto_database_proto_depIdxs = []int32{
14, // 0: newdbplugin.InitializeRequest.config_data:type_name -> google.protobuf.Struct
14, // 1: newdbplugin.InitializeResponse.config_data:type_name -> google.protobuf.Struct
3, // 2: newdbplugin.NewUserRequest.username_config:type_name -> newdbplugin.UsernameConfig
15, // 3: newdbplugin.NewUserRequest.expiration:type_name -> google.protobuf.Timestamp
12, // 4: newdbplugin.NewUserRequest.statements:type_name -> newdbplugin.Statements
12, // 5: newdbplugin.NewUserRequest.rollback_statements:type_name -> newdbplugin.Statements
6, // 6: newdbplugin.UpdateUserRequest.password:type_name -> newdbplugin.ChangePassword
7, // 7: newdbplugin.UpdateUserRequest.expiration:type_name -> newdbplugin.ChangeExpiration
12, // 8: newdbplugin.ChangePassword.statements:type_name -> newdbplugin.Statements
15, // 9: newdbplugin.ChangeExpiration.new_expiration:type_name -> google.protobuf.Timestamp
12, // 10: newdbplugin.ChangeExpiration.statements:type_name -> newdbplugin.Statements
12, // 11: newdbplugin.DeleteUserRequest.statements:type_name -> newdbplugin.Statements
0, // 12: newdbplugin.Database.Initialize:input_type -> newdbplugin.InitializeRequest
2, // 13: newdbplugin.Database.NewUser:input_type -> newdbplugin.NewUserRequest
5, // 14: newdbplugin.Database.UpdateUser:input_type -> newdbplugin.UpdateUserRequest
9, // 15: newdbplugin.Database.DeleteUser:input_type -> newdbplugin.DeleteUserRequest
13, // 16: newdbplugin.Database.Type:input_type -> newdbplugin.Empty
13, // 17: newdbplugin.Database.Close:input_type -> newdbplugin.Empty
1, // 18: newdbplugin.Database.Initialize:output_type -> newdbplugin.InitializeResponse
4, // 19: newdbplugin.Database.NewUser:output_type -> newdbplugin.NewUserResponse
8, // 20: newdbplugin.Database.UpdateUser:output_type -> newdbplugin.UpdateUserResponse
10, // 21: newdbplugin.Database.DeleteUser:output_type -> newdbplugin.DeleteUserResponse
11, // 22: newdbplugin.Database.Type:output_type -> newdbplugin.TypeResponse
13, // 23: newdbplugin.Database.Close:output_type -> newdbplugin.Empty
var file_sdk_database_dbplugin_v5_proto_database_proto_depIdxs = []int32{
14, // 0: dbplugin.v5.InitializeRequest.config_data:type_name -> google.protobuf.Struct
14, // 1: dbplugin.v5.InitializeResponse.config_data:type_name -> google.protobuf.Struct
3, // 2: dbplugin.v5.NewUserRequest.username_config:type_name -> dbplugin.v5.UsernameConfig
15, // 3: dbplugin.v5.NewUserRequest.expiration:type_name -> google.protobuf.Timestamp
12, // 4: dbplugin.v5.NewUserRequest.statements:type_name -> dbplugin.v5.Statements
12, // 5: dbplugin.v5.NewUserRequest.rollback_statements:type_name -> dbplugin.v5.Statements
6, // 6: dbplugin.v5.UpdateUserRequest.password:type_name -> dbplugin.v5.ChangePassword
7, // 7: dbplugin.v5.UpdateUserRequest.expiration:type_name -> dbplugin.v5.ChangeExpiration
12, // 8: dbplugin.v5.ChangePassword.statements:type_name -> dbplugin.v5.Statements
15, // 9: dbplugin.v5.ChangeExpiration.new_expiration:type_name -> google.protobuf.Timestamp
12, // 10: dbplugin.v5.ChangeExpiration.statements:type_name -> dbplugin.v5.Statements
12, // 11: dbplugin.v5.DeleteUserRequest.statements:type_name -> dbplugin.v5.Statements
0, // 12: dbplugin.v5.Database.Initialize:input_type -> dbplugin.v5.InitializeRequest
2, // 13: dbplugin.v5.Database.NewUser:input_type -> dbplugin.v5.NewUserRequest
5, // 14: dbplugin.v5.Database.UpdateUser:input_type -> dbplugin.v5.UpdateUserRequest
9, // 15: dbplugin.v5.Database.DeleteUser:input_type -> dbplugin.v5.DeleteUserRequest
13, // 16: dbplugin.v5.Database.Type:input_type -> dbplugin.v5.Empty
13, // 17: dbplugin.v5.Database.Close:input_type -> dbplugin.v5.Empty
1, // 18: dbplugin.v5.Database.Initialize:output_type -> dbplugin.v5.InitializeResponse
4, // 19: dbplugin.v5.Database.NewUser:output_type -> dbplugin.v5.NewUserResponse
8, // 20: dbplugin.v5.Database.UpdateUser:output_type -> dbplugin.v5.UpdateUserResponse
10, // 21: dbplugin.v5.Database.DeleteUser:output_type -> dbplugin.v5.DeleteUserResponse
11, // 22: dbplugin.v5.Database.Type:output_type -> dbplugin.v5.TypeResponse
13, // 23: dbplugin.v5.Database.Close:output_type -> dbplugin.v5.Empty
18, // [18:24] is the sub-list for method output_type
12, // [12:18] is the sub-list for method input_type
12, // [12:12] is the sub-list for extension type_name
@@ -953,13 +953,13 @@ var file_sdk_database_newdbplugin_proto_database_proto_depIdxs = []int32{
0, // [0:12] is the sub-list for field type_name
}
func init() { file_sdk_database_newdbplugin_proto_database_proto_init() }
func file_sdk_database_newdbplugin_proto_database_proto_init() {
if File_sdk_database_newdbplugin_proto_database_proto != nil {
func init() { file_sdk_database_dbplugin_v5_proto_database_proto_init() }
func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
if File_sdk_database_dbplugin_v5_proto_database_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*InitializeRequest); i {
case 0:
return &v.state
@@ -971,7 +971,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*InitializeResponse); i {
case 0:
return &v.state
@@ -983,7 +983,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NewUserRequest); i {
case 0:
return &v.state
@@ -995,7 +995,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UsernameConfig); i {
case 0:
return &v.state
@@ -1007,7 +1007,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NewUserResponse); i {
case 0:
return &v.state
@@ -1019,7 +1019,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateUserRequest); i {
case 0:
return &v.state
@@ -1031,7 +1031,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ChangePassword); i {
case 0:
return &v.state
@@ -1043,7 +1043,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ChangeExpiration); i {
case 0:
return &v.state
@@ -1055,7 +1055,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateUserResponse); i {
case 0:
return &v.state
@@ -1067,7 +1067,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteUserRequest); i {
case 0:
return &v.state
@@ -1079,7 +1079,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteUserResponse); i {
case 0:
return &v.state
@@ -1091,7 +1091,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TypeResponse); i {
case 0:
return &v.state
@@ -1103,7 +1103,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Statements); i {
case 0:
return &v.state
@@ -1115,7 +1115,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Empty); i {
case 0:
return &v.state
@@ -1132,20 +1132,20 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_sdk_database_newdbplugin_proto_database_proto_rawDesc,
RawDescriptor: file_sdk_database_dbplugin_v5_proto_database_proto_rawDesc,
NumEnums: 0,
NumMessages: 14,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_sdk_database_newdbplugin_proto_database_proto_goTypes,
DependencyIndexes: file_sdk_database_newdbplugin_proto_database_proto_depIdxs,
MessageInfos: file_sdk_database_newdbplugin_proto_database_proto_msgTypes,
GoTypes: file_sdk_database_dbplugin_v5_proto_database_proto_goTypes,
DependencyIndexes: file_sdk_database_dbplugin_v5_proto_database_proto_depIdxs,
MessageInfos: file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes,
}.Build()
File_sdk_database_newdbplugin_proto_database_proto = out.File
file_sdk_database_newdbplugin_proto_database_proto_rawDesc = nil
file_sdk_database_newdbplugin_proto_database_proto_goTypes = nil
file_sdk_database_newdbplugin_proto_database_proto_depIdxs = nil
File_sdk_database_dbplugin_v5_proto_database_proto = out.File
file_sdk_database_dbplugin_v5_proto_database_proto_rawDesc = nil
file_sdk_database_dbplugin_v5_proto_database_proto_goTypes = nil
file_sdk_database_dbplugin_v5_proto_database_proto_depIdxs = nil
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -1178,7 +1178,7 @@ func NewDatabaseClient(cc grpc.ClientConnInterface) DatabaseClient {
func (c *databaseClient) Initialize(ctx context.Context, in *InitializeRequest, opts ...grpc.CallOption) (*InitializeResponse, error) {
out := new(InitializeResponse)
err := c.cc.Invoke(ctx, "/newdbplugin.Database/Initialize", in, out, opts...)
err := c.cc.Invoke(ctx, "/dbplugin.v5.Database/Initialize", in, out, opts...)
if err != nil {
return nil, err
}
@@ -1187,7 +1187,7 @@ func (c *databaseClient) Initialize(ctx context.Context, in *InitializeRequest,
func (c *databaseClient) NewUser(ctx context.Context, in *NewUserRequest, opts ...grpc.CallOption) (*NewUserResponse, error) {
out := new(NewUserResponse)
err := c.cc.Invoke(ctx, "/newdbplugin.Database/NewUser", in, out, opts...)
err := c.cc.Invoke(ctx, "/dbplugin.v5.Database/NewUser", in, out, opts...)
if err != nil {
return nil, err
}
@@ -1196,7 +1196,7 @@ func (c *databaseClient) NewUser(ctx context.Context, in *NewUserRequest, opts .
func (c *databaseClient) UpdateUser(ctx context.Context, in *UpdateUserRequest, opts ...grpc.CallOption) (*UpdateUserResponse, error) {
out := new(UpdateUserResponse)
err := c.cc.Invoke(ctx, "/newdbplugin.Database/UpdateUser", in, out, opts...)
err := c.cc.Invoke(ctx, "/dbplugin.v5.Database/UpdateUser", in, out, opts...)
if err != nil {
return nil, err
}
@@ -1205,7 +1205,7 @@ func (c *databaseClient) UpdateUser(ctx context.Context, in *UpdateUserRequest,
func (c *databaseClient) DeleteUser(ctx context.Context, in *DeleteUserRequest, opts ...grpc.CallOption) (*DeleteUserResponse, error) {
out := new(DeleteUserResponse)
err := c.cc.Invoke(ctx, "/newdbplugin.Database/DeleteUser", in, out, opts...)
err := c.cc.Invoke(ctx, "/dbplugin.v5.Database/DeleteUser", in, out, opts...)
if err != nil {
return nil, err
}
@@ -1214,7 +1214,7 @@ func (c *databaseClient) DeleteUser(ctx context.Context, in *DeleteUserRequest,
func (c *databaseClient) Type(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TypeResponse, error) {
out := new(TypeResponse)
err := c.cc.Invoke(ctx, "/newdbplugin.Database/Type", in, out, opts...)
err := c.cc.Invoke(ctx, "/dbplugin.v5.Database/Type", in, out, opts...)
if err != nil {
return nil, err
}
@@ -1223,7 +1223,7 @@ func (c *databaseClient) Type(ctx context.Context, in *Empty, opts ...grpc.CallO
func (c *databaseClient) Close(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := c.cc.Invoke(ctx, "/newdbplugin.Database/Close", in, out, opts...)
err := c.cc.Invoke(ctx, "/dbplugin.v5.Database/Close", in, out, opts...)
if err != nil {
return nil, err
}
@@ -1277,7 +1277,7 @@ func _Database_Initialize_Handler(srv interface{}, ctx context.Context, dec func
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/newdbplugin.Database/Initialize",
FullMethod: "/dbplugin.v5.Database/Initialize",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DatabaseServer).Initialize(ctx, req.(*InitializeRequest))
@@ -1295,7 +1295,7 @@ func _Database_NewUser_Handler(srv interface{}, ctx context.Context, dec func(in
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/newdbplugin.Database/NewUser",
FullMethod: "/dbplugin.v5.Database/NewUser",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DatabaseServer).NewUser(ctx, req.(*NewUserRequest))
@@ -1313,7 +1313,7 @@ func _Database_UpdateUser_Handler(srv interface{}, ctx context.Context, dec func
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/newdbplugin.Database/UpdateUser",
FullMethod: "/dbplugin.v5.Database/UpdateUser",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DatabaseServer).UpdateUser(ctx, req.(*UpdateUserRequest))
@@ -1331,7 +1331,7 @@ func _Database_DeleteUser_Handler(srv interface{}, ctx context.Context, dec func
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/newdbplugin.Database/DeleteUser",
FullMethod: "/dbplugin.v5.Database/DeleteUser",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DatabaseServer).DeleteUser(ctx, req.(*DeleteUserRequest))
@@ -1349,7 +1349,7 @@ func _Database_Type_Handler(srv interface{}, ctx context.Context, dec func(inter
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/newdbplugin.Database/Type",
FullMethod: "/dbplugin.v5.Database/Type",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DatabaseServer).Type(ctx, req.(*Empty))
@@ -1367,7 +1367,7 @@ func _Database_Close_Handler(srv interface{}, ctx context.Context, dec func(inte
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/newdbplugin.Database/Close",
FullMethod: "/dbplugin.v5.Database/Close",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DatabaseServer).Close(ctx, req.(*Empty))
@@ -1376,7 +1376,7 @@ func _Database_Close_Handler(srv interface{}, ctx context.Context, dec func(inte
}
var _Database_serviceDesc = grpc.ServiceDesc{
ServiceName: "newdbplugin.Database",
ServiceName: "dbplugin.v5.Database",
HandlerType: (*DatabaseServer)(nil),
Methods: []grpc.MethodDesc{
{
@@ -1405,5 +1405,5 @@ var _Database_serviceDesc = grpc.ServiceDesc{
},
},
Streams: []grpc.StreamDesc{},
Metadata: "sdk/database/newdbplugin/proto/database.proto",
Metadata: "sdk/database/dbplugin/v5/proto/database.proto",
}

View File

@@ -1,7 +1,7 @@
syntax = "proto3";
package newdbplugin; // TODO: Update name
package dbplugin.v5;
option go_package = "github.com/hashicorp/vault/sdk/database/newdbplugin/proto";
option go_package = "github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";

View File

@@ -6,7 +6,7 @@ import (
"testing"
"time"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5"
)
func getRequestTimeout(t *testing.T) time.Duration {
@@ -22,7 +22,7 @@ func getRequestTimeout(t *testing.T) time.Duration {
return dur
}
func AssertInitialize(t *testing.T, db newdbplugin.Database, req newdbplugin.InitializeRequest) newdbplugin.InitializeResponse {
func AssertInitialize(t *testing.T, db dbplugin.Database, req dbplugin.InitializeRequest) dbplugin.InitializeResponse {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), getRequestTimeout(t))
@@ -35,7 +35,7 @@ func AssertInitialize(t *testing.T, db newdbplugin.Database, req newdbplugin.Ini
return resp
}
func AssertNewUser(t *testing.T, db newdbplugin.Database, req newdbplugin.NewUserRequest) newdbplugin.NewUserResponse {
func AssertNewUser(t *testing.T, db dbplugin.Database, req dbplugin.NewUserRequest) dbplugin.NewUserResponse {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), getRequestTimeout(t))
@@ -52,7 +52,7 @@ func AssertNewUser(t *testing.T, db newdbplugin.Database, req newdbplugin.NewUse
return resp
}
func AssertUpdateUser(t *testing.T, db newdbplugin.Database, req newdbplugin.UpdateUserRequest) {
func AssertUpdateUser(t *testing.T, db dbplugin.Database, req dbplugin.UpdateUserRequest) {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), getRequestTimeout(t))
@@ -64,7 +64,7 @@ func AssertUpdateUser(t *testing.T, db newdbplugin.Database, req newdbplugin.Upd
}
}
func AssertDeleteUser(t *testing.T, db newdbplugin.Database, req newdbplugin.DeleteUserRequest) {
func AssertDeleteUser(t *testing.T, db dbplugin.Database, req dbplugin.DeleteUserRequest) {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), getRequestTimeout(t))
@@ -76,7 +76,7 @@ func AssertDeleteUser(t *testing.T, db newdbplugin.Database, req newdbplugin.Del
}
}
func AssertClose(t *testing.T, db newdbplugin.Database) {
func AssertClose(t *testing.T, db dbplugin.Database) {
t.Helper()
err := db.Close()
if err != nil {

View File

@@ -8,7 +8,7 @@ import (
"time"
"unicode"
"github.com/hashicorp/vault/sdk/database/newdbplugin/proto"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/timestamppb"

View File

@@ -7,7 +7,7 @@ import (
"time"
"github.com/golang/protobuf/ptypes"
"github.com/hashicorp/vault/sdk/database/newdbplugin/proto"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
)

View File

@@ -7,7 +7,7 @@ import (
"testing"
"time"
"github.com/hashicorp/vault/sdk/database/newdbplugin/proto"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"google.golang.org/grpc"
)

View File

@@ -4,7 +4,7 @@ import (
"context"
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/vault/sdk/database/newdbplugin/proto"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"google.golang.org/grpc"
)

View File

@@ -6,7 +6,7 @@ import (
"time"
"github.com/golang/protobuf/ptypes"
"github.com/hashicorp/vault/sdk/database/newdbplugin/proto"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

View File

@@ -12,7 +12,7 @@ import (
"github.com/golang/protobuf/ptypes"
"github.com/golang/protobuf/ptypes/timestamp"
"github.com/hashicorp/vault/sdk/database/newdbplugin/proto"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

View File

@@ -6,7 +6,7 @@ import (
"testing"
"time"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5"
)
func getRequestTimeout(t *testing.T) time.Duration {
@@ -22,7 +22,7 @@ func getRequestTimeout(t *testing.T) time.Duration {
return dur
}
func AssertInitialize(t *testing.T, db newdbplugin.Database, req newdbplugin.InitializeRequest) newdbplugin.InitializeResponse {
func AssertInitialize(t *testing.T, db dbplugin.Database, req dbplugin.InitializeRequest) dbplugin.InitializeResponse {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), getRequestTimeout(t))
@@ -35,7 +35,7 @@ func AssertInitialize(t *testing.T, db newdbplugin.Database, req newdbplugin.Ini
return resp
}
func AssertNewUser(t *testing.T, db newdbplugin.Database, req newdbplugin.NewUserRequest) newdbplugin.NewUserResponse {
func AssertNewUser(t *testing.T, db dbplugin.Database, req dbplugin.NewUserRequest) dbplugin.NewUserResponse {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), getRequestTimeout(t))
@@ -52,7 +52,7 @@ func AssertNewUser(t *testing.T, db newdbplugin.Database, req newdbplugin.NewUse
return resp
}
func AssertUpdateUser(t *testing.T, db newdbplugin.Database, req newdbplugin.UpdateUserRequest) {
func AssertUpdateUser(t *testing.T, db dbplugin.Database, req dbplugin.UpdateUserRequest) {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), getRequestTimeout(t))
@@ -64,7 +64,7 @@ func AssertUpdateUser(t *testing.T, db newdbplugin.Database, req newdbplugin.Upd
}
}
func AssertDeleteUser(t *testing.T, db newdbplugin.Database, req newdbplugin.DeleteUserRequest) {
func AssertDeleteUser(t *testing.T, db dbplugin.Database, req dbplugin.DeleteUserRequest) {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), getRequestTimeout(t))
@@ -76,7 +76,7 @@ func AssertDeleteUser(t *testing.T, db newdbplugin.Database, req newdbplugin.Del
}
}
func AssertClose(t *testing.T, db newdbplugin.Database) {
func AssertClose(t *testing.T, db dbplugin.Database) {
t.Helper()
err := db.Close()
if err != nil {

View File

@@ -13,8 +13,8 @@ import (
"github.com/hashicorp/errwrap"
log "github.com/hashicorp/go-hclog"
multierror "github.com/hashicorp/go-multierror"
"github.com/hashicorp/vault/sdk/database/dbplugin"
"github.com/hashicorp/vault/sdk/database/newdbplugin"
v4 "github.com/hashicorp/vault/sdk/database/dbplugin"
v5 "github.com/hashicorp/vault/sdk/database/dbplugin/v5"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/jsonutil"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
@@ -109,7 +109,7 @@ func (c *PluginCatalog) getPluginTypeFromUnknown(ctx context.Context, logger log
func isDatabasePlugin(ctx context.Context, plugin *pluginutil.PluginRunner) error {
merr := &multierror.Error{}
// Attempt to run as database V5 plugin
v5Client, err := newdbplugin.NewPluginClient(ctx, nil, plugin, log.NewNullLogger(), true)
v5Client, err := v5.NewPluginClient(ctx, nil, plugin, log.NewNullLogger(), true)
if err == nil {
// Close the client and cleanup the plugin process
v5Client.Close()
@@ -117,7 +117,7 @@ func isDatabasePlugin(ctx context.Context, plugin *pluginutil.PluginRunner) erro
}
merr = multierror.Append(merr, fmt.Errorf("failed to load plugin as database v5: %w", err))
v4Client, err := dbplugin.NewPluginClient(ctx, nil, plugin, log.NewNullLogger(), true)
v4Client, err := v4.NewPluginClient(ctx, nil, plugin, log.NewNullLogger(), true)
if err == nil {
// Close the client and cleanup the plugin process
v4Client.Close()

View File

@@ -0,0 +1,178 @@
package dbplugin
import (
"context"
"time"
)
// Database to manipulate users within an external system (typically a database).
type Database interface {
// Initialize the database plugin. This is the equivalent of a constructor for the
// database object itself.
Initialize(ctx context.Context, req InitializeRequest) (InitializeResponse, error)
// NewUser creates a new user within the database. This user is temporary in that it
// will exist until the TTL expires.
NewUser(ctx context.Context, req NewUserRequest) (NewUserResponse, error)
// UpdateUser updates an existing user within the database.
UpdateUser(ctx context.Context, req UpdateUserRequest) (UpdateUserResponse, error)
// DeleteUser from the database. This should not error if the user didn't
// exist prior to this call.
DeleteUser(ctx context.Context, req DeleteUserRequest) (DeleteUserResponse, error)
// Type returns the Name for the particular database backend implementation.
// This type name is usually set as a constant within the database backend
// implementation, e.g. "mysql" for the MySQL database backend. This is used
// for things like metrics and logging. No behavior is switched on this.
Type() (string, error)
// Close attempts to close the underlying database connection that was
// established by the backend.
Close() error
}
// ///////////////////////////////////////////////////////////////////////////
// Database Request & Response Objects
// These request and response objects are *not* protobuf types because gRPC does not
// support all types that we need in a nice way. For instance, gRPC does not support
// map[string]interface{}. It does have an `Any` type, but converting it to a map
// requires extensive use of reflection and knowing what types to support ahead of
// time. Instead these types are made as user-friendly as possible so the conversion
// between protobuf types and request/response objects is handled by Vault developers
// rather than needing to be handled by external plugin developers.
// ///////////////////////////////////////////////////////////////////////////
// ///////////////////////////////////////////////////////
// Initialize()
// ///////////////////////////////////////////////////////
// InitializeRequest contains all information needed to initialize a database plugin.
type InitializeRequest struct {
// Config to initialize the database with. This can include things like connection details,
// a "root" username & password, etc. This will not include all configuration items specified
// when configuring the database. Some values will be stripped out by the database engine
// prior to being passed to the plugin.
Config map[string]interface{}
// VerifyConnection during initialization. If true, a connection should be made to the
// database to verify the connection can be made. If false, no connection should be made
// on initialization.
VerifyConnection bool
}
// InitializeResponse returns any information Vault needs to know after initializing
// a database plugin.
type InitializeResponse struct {
// Config that should be saved in Vault. This may differ from the config in the request,
// but should contain everything required to Initialize the database.
// REQUIRED in order to save the configuration into Vault after initialization
Config map[string]interface{}
}
// ///////////////////////////////////////////////////////
// NewUser()
// ///////////////////////////////////////////////////////
// NewUserRequest request a new user is created
type NewUserRequest struct {
// UsernameConfig is metadata that can be used to generate a username
// within the database plugin
UsernameConfig UsernameMetadata
// Statements is an ordered list of commands to run within the database when
// creating a new user. This frequently includes permissions to give the
// user or similar actions.
Statements Statements
// RollbackStatements is an ordered list of commands to run within the database
// if the new user creation process fails.
RollbackStatements Statements
// Password credentials to use when creating the user
Password string
// Expiration of the user. Not all database plugins will support this.
Expiration time.Time
}
// UsernameMetadata is metadata the database plugin can use to generate a username
type UsernameMetadata struct {
DisplayName string
RoleName string
}
// NewUserResponse returns any information Vault needs to know after creating a new user.
type NewUserResponse struct {
// Username of the user created within the database.
// REQUIRED so Vault knows the name of the user that was created
Username string
}
// ///////////////////////////////////////////////////////
// UpdateUser()
// ///////////////////////////////////////////////////////
type UpdateUserRequest struct {
// Username to make changes to.
Username string
// Password indicates the new password to change to.
// If nil, no change is requested.
Password *ChangePassword
// Expiration indicates the new expiration date to change to.
// If nil, no change is requested.
Expiration *ChangeExpiration
}
// ChangePassword of a given user
type ChangePassword struct {
// NewPassword for the user
NewPassword string
// Statements is an ordered list of commands to run within the database
// when changing the user's password.
Statements Statements
}
// ChangeExpiration of a given user
type ChangeExpiration struct {
// NewExpiration of the user
NewExpiration time.Time
// Statements is an ordered list of commands to run within the database
// when changing the user's expiration.
Statements Statements
}
type UpdateUserResponse struct{}
// ///////////////////////////////////////////////////////
// DeleteUser()
// ///////////////////////////////////////////////////////
type DeleteUserRequest struct {
// Username to delete from the database
Username string
// Statements is an ordered list of commands to run within the database
// when deleting a user.
Statements Statements
}
type DeleteUserResponse struct{}
// ///////////////////////////////////////////////////////
// Used across multiple functions
// ///////////////////////////////////////////////////////
// Statements wraps a collection of statements to run in a database when an
// operation is performed (create, update, etc.). This is a struct rather than
// a string slice so we can easily add more information to this in the future.
type Statements struct {
// Commands is an ordered list of commands to execute in the database.
// These commands may include templated fields such as {{username}} and {{password}}
Commands []string
}

View File

@@ -0,0 +1,254 @@
package dbplugin
import (
"context"
"errors"
"fmt"
"time"
"github.com/golang/protobuf/ptypes"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
)
var (
_ Database = gRPCClient{}
ErrPluginShutdown = errors.New("plugin shutdown")
)
type gRPCClient struct {
client proto.DatabaseClient
doneCtx context.Context
}
func (c gRPCClient) Initialize(ctx context.Context, req InitializeRequest) (InitializeResponse, error) {
rpcReq, err := initReqToProto(req)
if err != nil {
return InitializeResponse{}, err
}
rpcResp, err := c.client.Initialize(ctx, rpcReq)
if err != nil {
return InitializeResponse{}, fmt.Errorf("unable to initialize: %s", err.Error())
}
return initRespFromProto(rpcResp)
}
func initReqToProto(req InitializeRequest) (*proto.InitializeRequest, error) {
config, err := mapToStruct(req.Config)
if err != nil {
return nil, fmt.Errorf("unable to marshal config: %w", err)
}
rpcReq := &proto.InitializeRequest{
ConfigData: config,
VerifyConnection: req.VerifyConnection,
}
return rpcReq, nil
}
func initRespFromProto(rpcResp *proto.InitializeResponse) (InitializeResponse, error) {
newConfig := structToMap(rpcResp.GetConfigData())
resp := InitializeResponse{
Config: newConfig,
}
return resp, nil
}
func (c gRPCClient) NewUser(ctx context.Context, req NewUserRequest) (NewUserResponse, error) {
ctx, cancel := context.WithCancel(ctx)
quitCh := pluginutil.CtxCancelIfCanceled(cancel, c.doneCtx)
defer close(quitCh)
defer cancel()
rpcReq, err := newUserReqToProto(req)
if err != nil {
return NewUserResponse{}, err
}
rpcResp, err := c.client.NewUser(ctx, rpcReq)
if err != nil {
if c.doneCtx.Err() != nil {
return NewUserResponse{}, ErrPluginShutdown
}
return NewUserResponse{}, fmt.Errorf("unable to create new user: %w", err)
}
return newUserRespFromProto(rpcResp)
}
func newUserReqToProto(req NewUserRequest) (*proto.NewUserRequest, error) {
if req.Password == "" {
return nil, fmt.Errorf("missing password")
}
expiration, err := ptypes.TimestampProto(req.Expiration)
if err != nil {
return nil, fmt.Errorf("unable to marshal expiration date: %w", err)
}
rpcReq := &proto.NewUserRequest{
UsernameConfig: &proto.UsernameConfig{
DisplayName: req.UsernameConfig.DisplayName,
RoleName: req.UsernameConfig.RoleName,
},
Password: req.Password,
Expiration: expiration,
Statements: &proto.Statements{
Commands: req.Statements.Commands,
},
RollbackStatements: &proto.Statements{
Commands: req.RollbackStatements.Commands,
},
}
return rpcReq, nil
}
func newUserRespFromProto(rpcResp *proto.NewUserResponse) (NewUserResponse, error) {
resp := NewUserResponse{
Username: rpcResp.GetUsername(),
}
return resp, nil
}
func (c gRPCClient) UpdateUser(ctx context.Context, req UpdateUserRequest) (UpdateUserResponse, error) {
rpcReq, err := updateUserReqToProto(req)
if err != nil {
return UpdateUserResponse{}, err
}
rpcResp, err := c.client.UpdateUser(ctx, rpcReq)
if err != nil {
if c.doneCtx.Err() != nil {
return UpdateUserResponse{}, ErrPluginShutdown
}
return UpdateUserResponse{}, fmt.Errorf("unable to update user: %w", err)
}
return updateUserRespFromProto(rpcResp)
}
func updateUserReqToProto(req UpdateUserRequest) (*proto.UpdateUserRequest, error) {
if req.Username == "" {
return nil, fmt.Errorf("missing username")
}
if (req.Password == nil || req.Password.NewPassword == "") &&
(req.Expiration == nil || req.Expiration.NewExpiration.IsZero()) {
return nil, fmt.Errorf("missing changes")
}
expiration, err := expirationToProto(req.Expiration)
if err != nil {
return nil, fmt.Errorf("unable to parse new expiration date: %w", err)
}
var password *proto.ChangePassword
if req.Password != nil && req.Password.NewPassword != "" {
password = &proto.ChangePassword{
NewPassword: req.Password.NewPassword,
Statements: &proto.Statements{
Commands: req.Password.Statements.Commands,
},
}
}
rpcReq := &proto.UpdateUserRequest{
Username: req.Username,
Password: password,
Expiration: expiration,
}
return rpcReq, nil
}
func updateUserRespFromProto(rpcResp *proto.UpdateUserResponse) (UpdateUserResponse, error) {
// Placeholder for future conversion if data is returned
return UpdateUserResponse{}, nil
}
func expirationToProto(exp *ChangeExpiration) (*proto.ChangeExpiration, error) {
if exp == nil {
return nil, nil
}
expiration, err := ptypes.TimestampProto(exp.NewExpiration)
if err != nil {
return nil, err
}
changeExp := &proto.ChangeExpiration{
NewExpiration: expiration,
Statements: &proto.Statements{
Commands: exp.Statements.Commands,
},
}
return changeExp, nil
}
func (c gRPCClient) DeleteUser(ctx context.Context, req DeleteUserRequest) (DeleteUserResponse, error) {
rpcReq, err := deleteUserReqToProto(req)
if err != nil {
return DeleteUserResponse{}, err
}
rpcResp, err := c.client.DeleteUser(ctx, rpcReq)
if err != nil {
if c.doneCtx.Err() != nil {
return DeleteUserResponse{}, ErrPluginShutdown
}
return DeleteUserResponse{}, fmt.Errorf("unable to update user: %w", err)
}
return deleteUserRespFromProto(rpcResp)
}
func deleteUserReqToProto(req DeleteUserRequest) (*proto.DeleteUserRequest, error) {
if req.Username == "" {
return nil, fmt.Errorf("missing username")
}
rpcReq := &proto.DeleteUserRequest{
Username: req.Username,
Statements: &proto.Statements{
Commands: req.Statements.Commands,
},
}
return rpcReq, nil
}
func deleteUserRespFromProto(rpcResp *proto.DeleteUserResponse) (DeleteUserResponse, error) {
// Placeholder for future conversion if data is returned
return DeleteUserResponse{}, nil
}
func (c gRPCClient) Type() (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
typeResp, err := c.client.Type(ctx, &proto.Empty{})
if err != nil {
if c.doneCtx.Err() != nil {
return "", ErrPluginShutdown
}
return "", fmt.Errorf("unable to get database plugin type: %w", err)
}
return typeResp.GetType(), nil
}
func (c gRPCClient) Close() error {
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
_, err := c.client.Close(ctx, &proto.Empty{})
if err != nil {
if c.doneCtx.Err() != nil {
return ErrPluginShutdown
}
return err
}
return nil
}

View File

@@ -0,0 +1,42 @@
package dbplugin
import (
"context"
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"google.golang.org/grpc"
)
// handshakeConfigs are used to just do a basic handshake between
// a plugin and host. If the handshake fails, a user friendly error is shown.
// This prevents users from executing bad plugins or executing a plugin
// directory. It is a UX feature, not a security feature.
var handshakeConfig = plugin.HandshakeConfig{
ProtocolVersion: 5,
MagicCookieKey: "VAULT_DATABASE_PLUGIN",
MagicCookieValue: "926a0820-aea2-be28-51d6-83cdf00e8edb",
}
type GRPCDatabasePlugin struct {
Impl Database
// Embeding this will disable the netRPC protocol
plugin.NetRPCUnsupportedPlugin
}
var _ plugin.Plugin = &GRPCDatabasePlugin{}
var _ plugin.GRPCPlugin = &GRPCDatabasePlugin{}
func (d GRPCDatabasePlugin) GRPCServer(_ *plugin.GRPCBroker, s *grpc.Server) error {
proto.RegisterDatabaseServer(s, gRPCServer{impl: d.Impl})
return nil
}
func (GRPCDatabasePlugin) GRPCClient(doneCtx context.Context, _ *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
client := gRPCClient{
client: proto.NewDatabaseClient(c),
doneCtx: doneCtx,
}
return client, nil
}

View File

@@ -0,0 +1,190 @@
package dbplugin
import (
"context"
"fmt"
"time"
"github.com/golang/protobuf/ptypes"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
var _ proto.DatabaseServer = gRPCServer{}
type gRPCServer struct {
impl Database
}
// Initialize the database plugin
func (g gRPCServer) Initialize(ctx context.Context, request *proto.InitializeRequest) (*proto.InitializeResponse, error) {
rawConfig := structToMap(request.ConfigData)
dbReq := InitializeRequest{
Config: rawConfig,
VerifyConnection: request.VerifyConnection,
}
dbResp, err := g.impl.Initialize(ctx, dbReq)
if err != nil {
return &proto.InitializeResponse{}, status.Errorf(codes.Internal, "failed to initialize: %s", err)
}
newConfig, err := mapToStruct(dbResp.Config)
if err != nil {
return &proto.InitializeResponse{}, status.Errorf(codes.Internal, "failed to marshal new config to JSON: %s", err)
}
resp := &proto.InitializeResponse{
ConfigData: newConfig,
}
return resp, nil
}
func (g gRPCServer) NewUser(ctx context.Context, req *proto.NewUserRequest) (*proto.NewUserResponse, error) {
if req.GetUsernameConfig() == nil {
return &proto.NewUserResponse{}, status.Errorf(codes.InvalidArgument, "missing username config")
}
var expiration time.Time
if req.GetExpiration() != nil {
exp, err := ptypes.Timestamp(req.GetExpiration())
if err != nil {
return &proto.NewUserResponse{}, status.Errorf(codes.InvalidArgument, "unable to parse expiration date: %s", err)
}
expiration = exp
}
dbReq := NewUserRequest{
UsernameConfig: UsernameMetadata{
DisplayName: req.GetUsernameConfig().GetDisplayName(),
RoleName: req.GetUsernameConfig().GetRoleName(),
},
Password: req.GetPassword(),
Expiration: expiration,
Statements: getStatementsFromProto(req.GetStatements()),
RollbackStatements: getStatementsFromProto(req.GetRollbackStatements()),
}
dbResp, err := g.impl.NewUser(ctx, dbReq)
if err != nil {
return &proto.NewUserResponse{}, status.Errorf(codes.Internal, "unable to create new user: %s", err)
}
resp := &proto.NewUserResponse{
Username: dbResp.Username,
}
return resp, nil
}
func (g gRPCServer) UpdateUser(ctx context.Context, req *proto.UpdateUserRequest) (*proto.UpdateUserResponse, error) {
if req.GetUsername() == "" {
return &proto.UpdateUserResponse{}, status.Errorf(codes.InvalidArgument, "no username provided")
}
dbReq, err := getUpdateUserRequest(req)
if err != nil {
return &proto.UpdateUserResponse{}, status.Errorf(codes.InvalidArgument, err.Error())
}
_, err = g.impl.UpdateUser(ctx, dbReq)
if err != nil {
return &proto.UpdateUserResponse{}, status.Errorf(codes.Internal, "unable to update user: %s", err)
}
return &proto.UpdateUserResponse{}, nil
}
func getUpdateUserRequest(req *proto.UpdateUserRequest) (UpdateUserRequest, error) {
var password *ChangePassword
if req.GetPassword() != nil && req.GetPassword().GetNewPassword() != "" {
password = &ChangePassword{
NewPassword: req.GetPassword().GetNewPassword(),
Statements: getStatementsFromProto(req.GetPassword().GetStatements()),
}
}
var expiration *ChangeExpiration
if req.GetExpiration() != nil && req.GetExpiration().GetNewExpiration() != nil {
newExpiration, err := ptypes.Timestamp(req.GetExpiration().GetNewExpiration())
if err != nil {
return UpdateUserRequest{}, fmt.Errorf("unable to parse new expiration: %w", err)
}
expiration = &ChangeExpiration{
NewExpiration: newExpiration,
Statements: getStatementsFromProto(req.GetExpiration().GetStatements()),
}
}
dbReq := UpdateUserRequest{
Username: req.GetUsername(),
Password: password,
Expiration: expiration,
}
if !hasChange(dbReq) {
return UpdateUserRequest{}, fmt.Errorf("update user request has no changes")
}
return dbReq, nil
}
func hasChange(dbReq UpdateUserRequest) bool {
if dbReq.Password != nil && dbReq.Password.NewPassword != "" {
return true
}
if dbReq.Expiration != nil && !dbReq.Expiration.NewExpiration.IsZero() {
return true
}
return false
}
func (g gRPCServer) DeleteUser(ctx context.Context, req *proto.DeleteUserRequest) (*proto.DeleteUserResponse, error) {
if req.GetUsername() == "" {
return &proto.DeleteUserResponse{}, status.Errorf(codes.InvalidArgument, "no username provided")
}
dbReq := DeleteUserRequest{
Username: req.GetUsername(),
Statements: getStatementsFromProto(req.GetStatements()),
}
_, err := g.impl.DeleteUser(ctx, dbReq)
if err != nil {
return &proto.DeleteUserResponse{}, status.Errorf(codes.Internal, "unable to delete user: %s", err)
}
return &proto.DeleteUserResponse{}, nil
}
func (g gRPCServer) Type(ctx context.Context, _ *proto.Empty) (*proto.TypeResponse, error) {
t, err := g.impl.Type()
if err != nil {
return &proto.TypeResponse{}, status.Errorf(codes.Internal, "unable to retrieve type: %s", err)
}
resp := &proto.TypeResponse{
Type: t,
}
return resp, nil
}
func (g gRPCServer) Close(ctx context.Context, _ *proto.Empty) (*proto.Empty, error) {
err := g.impl.Close()
if err != nil {
return &proto.Empty{}, status.Errorf(codes.Internal, "unable to close database plugin: %s", err)
}
return &proto.Empty{}, nil
}
func getStatementsFromProto(protoStmts *proto.Statements) (statements Statements) {
if protoStmts == nil {
return statements
}
cmds := protoStmts.GetCommands()
statements = Statements{
Commands: cmds,
}
return statements
}

View File

@@ -0,0 +1,36 @@
package dbplugin
import (
"math"
"google.golang.org/protobuf/types/known/structpb"
)
func mapToStruct(m map[string]interface{}) (*structpb.Struct, error) {
return structpb.NewStruct(m)
}
func structToMap(strct *structpb.Struct) map[string]interface{} {
m := strct.AsMap()
coerceFloatsToInt(m)
return m
}
// coerceFloatsToInt if the floats can be coerced to an integer without losing data
func coerceFloatsToInt(m map[string]interface{}) {
for k, v := range m {
fVal, ok := v.(float64)
if !ok {
continue
}
if isInt(fVal) {
m[k] = int64(fVal)
}
}
}
// isInt attempts to determine if the given floating point number could be represented as an integer without losing data
// This does not work for very large floats, however in this usage that's okay since we don't expect numbers that large.
func isInt(f float64) bool {
return math.Floor(f) == f
}

View File

@@ -0,0 +1,274 @@
package dbplugin
import (
"context"
"errors"
"net/url"
"strings"
"time"
metrics "github.com/armon/go-metrics"
"github.com/hashicorp/errwrap"
log "github.com/hashicorp/go-hclog"
"google.golang.org/grpc/status"
)
// ///////////////////////////////////////////////////
// Tracing Middleware
// ///////////////////////////////////////////////////
var _ Database = databaseTracingMiddleware{}
// databaseTracingMiddleware wraps a implementation of Database and executes
// trace logging on function call.
type databaseTracingMiddleware struct {
next Database
logger log.Logger
}
func (mw databaseTracingMiddleware) Initialize(ctx context.Context, req InitializeRequest) (resp InitializeResponse, err error) {
defer func(then time.Time) {
mw.logger.Trace("initialize",
"status", "finished",
"verify", req.VerifyConnection,
"err", err,
"took", time.Since(then))
}(time.Now())
mw.logger.Trace("initialize", "status", "started")
return mw.next.Initialize(ctx, req)
}
func (mw databaseTracingMiddleware) NewUser(ctx context.Context, req NewUserRequest) (resp NewUserResponse, err error) {
defer func(then time.Time) {
mw.logger.Trace("create user",
"status", "finished",
"err", err,
"took", time.Since(then))
}(time.Now())
mw.logger.Trace("create user",
"status", "started")
return mw.next.NewUser(ctx, req)
}
func (mw databaseTracingMiddleware) UpdateUser(ctx context.Context, req UpdateUserRequest) (resp UpdateUserResponse, err error) {
defer func(then time.Time) {
mw.logger.Trace("update user",
"status", "finished",
"err", err,
"took", time.Since(then))
}(time.Now())
mw.logger.Trace("update user", "status", "started")
return mw.next.UpdateUser(ctx, req)
}
func (mw databaseTracingMiddleware) DeleteUser(ctx context.Context, req DeleteUserRequest) (resp DeleteUserResponse, err error) {
defer func(then time.Time) {
mw.logger.Trace("delete user",
"status", "finished",
"err", err,
"took", time.Since(then))
}(time.Now())
mw.logger.Trace("delete user",
"status", "started")
return mw.next.DeleteUser(ctx, req)
}
func (mw databaseTracingMiddleware) Type() (string, error) {
return mw.next.Type()
}
func (mw databaseTracingMiddleware) Close() (err error) {
defer func(then time.Time) {
mw.logger.Trace("close",
"status", "finished",
"err", err,
"took", time.Since(then))
}(time.Now())
mw.logger.Trace("close",
"status", "started")
return mw.next.Close()
}
// ///////////////////////////////////////////////////
// Metrics Middleware Domain
// ///////////////////////////////////////////////////
var _ Database = databaseMetricsMiddleware{}
// databaseMetricsMiddleware wraps an implementation of Databases and on
// function call logs metrics about this instance.
type databaseMetricsMiddleware struct {
next Database
typeStr string
}
func (mw databaseMetricsMiddleware) Initialize(ctx context.Context, req InitializeRequest) (resp InitializeResponse, err error) {
defer func(now time.Time) {
metrics.MeasureSince([]string{"database", "Initialize"}, now)
metrics.MeasureSince([]string{"database", mw.typeStr, "Initialize"}, now)
if err != nil {
metrics.IncrCounter([]string{"database", "Initialize", "error"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "Initialize", "error"}, 1)
}
}(time.Now())
metrics.IncrCounter([]string{"database", "Initialize"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "Initialize"}, 1)
return mw.next.Initialize(ctx, req)
}
func (mw databaseMetricsMiddleware) NewUser(ctx context.Context, req NewUserRequest) (resp NewUserResponse, err error) {
defer func(start time.Time) {
metrics.MeasureSince([]string{"database", "NewUser"}, start)
metrics.MeasureSince([]string{"database", mw.typeStr, "NewUser"}, start)
if err != nil {
metrics.IncrCounter([]string{"database", "NewUser", "error"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "NewUser", "error"}, 1)
}
}(time.Now())
metrics.IncrCounter([]string{"database", "NewUser"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "NewUser"}, 1)
return mw.next.NewUser(ctx, req)
}
func (mw databaseMetricsMiddleware) UpdateUser(ctx context.Context, req UpdateUserRequest) (resp UpdateUserResponse, err error) {
defer func(now time.Time) {
metrics.MeasureSince([]string{"database", "UpdateUser"}, now)
metrics.MeasureSince([]string{"database", mw.typeStr, "UpdateUser"}, now)
if err != nil {
metrics.IncrCounter([]string{"database", "UpdateUser", "error"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "UpdateUser", "error"}, 1)
}
}(time.Now())
metrics.IncrCounter([]string{"database", "UpdateUser"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "UpdateUser"}, 1)
return mw.next.UpdateUser(ctx, req)
}
func (mw databaseMetricsMiddleware) DeleteUser(ctx context.Context, req DeleteUserRequest) (resp DeleteUserResponse, err error) {
defer func(now time.Time) {
metrics.MeasureSince([]string{"database", "DeleteUser"}, now)
metrics.MeasureSince([]string{"database", mw.typeStr, "DeleteUser"}, now)
if err != nil {
metrics.IncrCounter([]string{"database", "DeleteUser", "error"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "DeleteUser", "error"}, 1)
}
}(time.Now())
metrics.IncrCounter([]string{"database", "DeleteUser"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "DeleteUser"}, 1)
return mw.next.DeleteUser(ctx, req)
}
func (mw databaseMetricsMiddleware) Type() (string, error) {
return mw.next.Type()
}
func (mw databaseMetricsMiddleware) Close() (err error) {
defer func(now time.Time) {
metrics.MeasureSince([]string{"database", "Close"}, now)
metrics.MeasureSince([]string{"database", mw.typeStr, "Close"}, now)
if err != nil {
metrics.IncrCounter([]string{"database", "Close", "error"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "Close", "error"}, 1)
}
}(time.Now())
metrics.IncrCounter([]string{"database", "Close"}, 1)
metrics.IncrCounter([]string{"database", mw.typeStr, "Close"}, 1)
return mw.next.Close()
}
// ///////////////////////////////////////////////////
// Error Sanitizer Middleware Domain
// ///////////////////////////////////////////////////
var _ Database = DatabaseErrorSanitizerMiddleware{}
// DatabaseErrorSanitizerMiddleware wraps an implementation of Databases and
// sanitizes returned error messages
type DatabaseErrorSanitizerMiddleware struct {
next Database
secretsFn secretsFn
}
type secretsFn func() map[string]string
func NewDatabaseErrorSanitizerMiddleware(next Database, secrets secretsFn) DatabaseErrorSanitizerMiddleware {
return DatabaseErrorSanitizerMiddleware{
next: next,
secretsFn: secrets,
}
}
func (mw DatabaseErrorSanitizerMiddleware) Initialize(ctx context.Context, req InitializeRequest) (resp InitializeResponse, err error) {
resp, err = mw.next.Initialize(ctx, req)
return resp, mw.sanitize(err)
}
func (mw DatabaseErrorSanitizerMiddleware) NewUser(ctx context.Context, req NewUserRequest) (resp NewUserResponse, err error) {
resp, err = mw.next.NewUser(ctx, req)
return resp, mw.sanitize(err)
}
func (mw DatabaseErrorSanitizerMiddleware) UpdateUser(ctx context.Context, req UpdateUserRequest) (UpdateUserResponse, error) {
resp, err := mw.next.UpdateUser(ctx, req)
return resp, mw.sanitize(err)
}
func (mw DatabaseErrorSanitizerMiddleware) DeleteUser(ctx context.Context, req DeleteUserRequest) (DeleteUserResponse, error) {
resp, err := mw.next.DeleteUser(ctx, req)
return resp, mw.sanitize(err)
}
func (mw DatabaseErrorSanitizerMiddleware) Type() (string, error) {
dbType, err := mw.next.Type()
return dbType, mw.sanitize(err)
}
func (mw DatabaseErrorSanitizerMiddleware) Close() (err error) {
return mw.sanitize(mw.next.Close())
}
// sanitize errors by removing any sensitive strings within their messages. This uses
// the secretsFn to determine what fields should be sanitized.
func (mw DatabaseErrorSanitizerMiddleware) sanitize(err error) error {
if err == nil {
return nil
}
if errwrap.ContainsType(err, new(url.Error)) {
return errors.New("unable to parse connection url")
}
if mw.secretsFn == nil {
return err
}
for find, replace := range mw.secretsFn() {
if find == "" {
continue
}
// Attempt to keep the status code attached to the
// error while changing the actual error message
s, ok := status.FromError(err)
if ok {
err = status.Error(s.Code(), strings.Replace(s.Message(), find, replace, -1))
continue
}
err = errors.New(strings.Replace(err.Error(), find, replace, -1))
}
return err
}

View File

@@ -0,0 +1,81 @@
package dbplugin
import (
"context"
"errors"
"sync"
log "github.com/hashicorp/go-hclog"
plugin "github.com/hashicorp/go-plugin"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
)
// DatabasePluginClient embeds a databasePluginRPCClient and wraps it's Close
// method to also call Kill() on the plugin.Client.
type DatabasePluginClient struct {
client *plugin.Client
sync.Mutex
Database
}
// This wraps the Close call and ensures we both close the database connection
// and kill the plugin.
func (dc *DatabasePluginClient) Close() error {
err := dc.Database.Close()
dc.client.Kill()
return err
}
// NewPluginClient returns a databaseRPCClient with a connection to a running
// plugin. The client is wrapped in a DatabasePluginClient object to ensure the
// plugin is killed on call of Close().
func NewPluginClient(ctx context.Context, sys pluginutil.RunnerUtil, pluginRunner *pluginutil.PluginRunner, logger log.Logger, isMetadataMode bool) (Database, error) {
// pluginSets is the map of plugins we can dispense.
pluginSets := map[int]plugin.PluginSet{
5: plugin.PluginSet{
"database": new(GRPCDatabasePlugin),
},
}
client, err := pluginRunner.RunConfig(ctx,
pluginutil.Runner(sys),
pluginutil.PluginSets(pluginSets),
pluginutil.HandshakeConfig(handshakeConfig),
pluginutil.Logger(logger),
pluginutil.MetadataMode(isMetadataMode),
pluginutil.AutoMTLS(false),
)
if err != nil {
return nil, err
}
// Connect via RPC
rpcClient, err := client.Client()
if err != nil {
return nil, err
}
// Request the plugin
raw, err := rpcClient.Dispense("database")
if err != nil {
return nil, err
}
// We should have a database type now. This feels like a normal interface
// implementation but is in fact over an RPC connection.
var db Database
switch raw.(type) {
case gRPCClient:
db = raw.(gRPCClient)
default:
return nil, errors.New("unsupported client type")
}
// Wrap RPC implementation in DatabasePluginClient
return &DatabasePluginClient{
client: client,
Database: db,
}, nil
}

View File

@@ -0,0 +1,78 @@
package dbplugin
import (
"context"
"fmt"
"github.com/hashicorp/errwrap"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/sdk/helper/consts"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
)
// PluginFactory is used to build plugin database types. It wraps the database
// object in a logging and metrics middleware.
func PluginFactory(ctx context.Context, pluginName string, sys pluginutil.LookRunnerUtil, logger log.Logger) (Database, error) {
// Look for plugin in the plugin catalog
pluginRunner, err := sys.LookupPlugin(ctx, pluginName, consts.PluginTypeDatabase)
if err != nil {
return nil, err
}
namedLogger := logger.Named(pluginName)
var transport string
var db Database
if pluginRunner.Builtin {
// Plugin is builtin so we can retrieve an instance of the interface
// from the pluginRunner. Then cast it to a Database.
dbRaw, err := pluginRunner.BuiltinFactory()
if err != nil {
return nil, errwrap.Wrapf("error initializing plugin: {{err}}", err)
}
var ok bool
db, ok = dbRaw.(Database)
if !ok {
return nil, fmt.Errorf("unsupported database type: %q", pluginName)
}
transport = "builtin"
} else {
// create a DatabasePluginClient instance
db, err = NewPluginClient(ctx, sys, pluginRunner, namedLogger, false)
if err != nil {
return nil, err
}
// Switch on the underlying database client type to get the transport
// method.
switch db.(*DatabasePluginClient).Database.(type) {
case *gRPCClient:
transport = "gRPC"
}
}
typeStr, err := db.Type()
if err != nil {
return nil, errwrap.Wrapf("error getting plugin type: {{err}}", err)
}
// Wrap with metrics middleware
db = &databaseMetricsMiddleware{
next: db,
typeStr: typeStr,
}
// Wrap with tracing middleware
if namedLogger.IsTrace() {
db = &databaseTracingMiddleware{
next: db,
logger: namedLogger.With("transport", transport),
}
}
return db, nil
}

View File

@@ -0,0 +1,42 @@
package dbplugin
import (
"crypto/tls"
"fmt"
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
)
// Serve is called from within a plugin and wraps the provided
// Database implementation in a databasePluginRPCServer object and starts a
// RPC server.
func Serve(db Database, tlsProvider func() (*tls.Config, error)) {
plugin.Serve(ServeConfig(db, tlsProvider))
}
func ServeConfig(db Database, tlsProvider func() (*tls.Config, error)) *plugin.ServeConfig {
err := pluginutil.OptionallyEnableMlock()
if err != nil {
fmt.Println(err)
return nil
}
// pluginSets is the map of plugins we can dispense.
pluginSets := map[int]plugin.PluginSet{
5: plugin.PluginSet{
"database": &GRPCDatabasePlugin{
Impl: db,
},
},
}
conf := &plugin.ServeConfig{
HandshakeConfig: handshakeConfig,
VersionedPlugins: pluginSets,
GRPCServer: plugin.DefaultGRPCServer,
TLSProvider: tlsProvider,
}
return conf
}

View File

@@ -2,7 +2,7 @@
// versions:
// protoc-gen-go v1.23.0
// protoc v3.13.0
// source: sdk/database/newdbplugin/proto/database.proto
// source: sdk/database/dbplugin/v5/proto/database.proto
package proto
@@ -46,7 +46,7 @@ type InitializeRequest struct {
func (x *InitializeRequest) Reset() {
*x = InitializeRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[0]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -59,7 +59,7 @@ func (x *InitializeRequest) String() string {
func (*InitializeRequest) ProtoMessage() {}
func (x *InitializeRequest) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[0]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -72,7 +72,7 @@ func (x *InitializeRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use InitializeRequest.ProtoReflect.Descriptor instead.
func (*InitializeRequest) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{0}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{0}
}
func (x *InitializeRequest) GetConfigData() *_struct.Struct {
@@ -100,7 +100,7 @@ type InitializeResponse struct {
func (x *InitializeResponse) Reset() {
*x = InitializeResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[1]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -113,7 +113,7 @@ func (x *InitializeResponse) String() string {
func (*InitializeResponse) ProtoMessage() {}
func (x *InitializeResponse) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[1]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -126,7 +126,7 @@ func (x *InitializeResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use InitializeResponse.ProtoReflect.Descriptor instead.
func (*InitializeResponse) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{1}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{1}
}
func (x *InitializeResponse) GetConfigData() *_struct.Struct {
@@ -151,7 +151,7 @@ type NewUserRequest struct {
func (x *NewUserRequest) Reset() {
*x = NewUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[2]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -164,7 +164,7 @@ func (x *NewUserRequest) String() string {
func (*NewUserRequest) ProtoMessage() {}
func (x *NewUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[2]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -177,7 +177,7 @@ func (x *NewUserRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use NewUserRequest.ProtoReflect.Descriptor instead.
func (*NewUserRequest) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{2}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{2}
}
func (x *NewUserRequest) GetUsernameConfig() *UsernameConfig {
@@ -227,7 +227,7 @@ type UsernameConfig struct {
func (x *UsernameConfig) Reset() {
*x = UsernameConfig{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[3]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -240,7 +240,7 @@ func (x *UsernameConfig) String() string {
func (*UsernameConfig) ProtoMessage() {}
func (x *UsernameConfig) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[3]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -253,7 +253,7 @@ func (x *UsernameConfig) ProtoReflect() protoreflect.Message {
// Deprecated: Use UsernameConfig.ProtoReflect.Descriptor instead.
func (*UsernameConfig) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{3}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{3}
}
func (x *UsernameConfig) GetDisplayName() string {
@@ -281,7 +281,7 @@ type NewUserResponse struct {
func (x *NewUserResponse) Reset() {
*x = NewUserResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[4]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -294,7 +294,7 @@ func (x *NewUserResponse) String() string {
func (*NewUserResponse) ProtoMessage() {}
func (x *NewUserResponse) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[4]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -307,7 +307,7 @@ func (x *NewUserResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use NewUserResponse.ProtoReflect.Descriptor instead.
func (*NewUserResponse) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{4}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{4}
}
func (x *NewUserResponse) GetUsername() string {
@@ -333,7 +333,7 @@ type UpdateUserRequest struct {
func (x *UpdateUserRequest) Reset() {
*x = UpdateUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[5]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -346,7 +346,7 @@ func (x *UpdateUserRequest) String() string {
func (*UpdateUserRequest) ProtoMessage() {}
func (x *UpdateUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[5]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -359,7 +359,7 @@ func (x *UpdateUserRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use UpdateUserRequest.ProtoReflect.Descriptor instead.
func (*UpdateUserRequest) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{5}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{5}
}
func (x *UpdateUserRequest) GetUsername() string {
@@ -395,7 +395,7 @@ type ChangePassword struct {
func (x *ChangePassword) Reset() {
*x = ChangePassword{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[6]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[6]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -408,7 +408,7 @@ func (x *ChangePassword) String() string {
func (*ChangePassword) ProtoMessage() {}
func (x *ChangePassword) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[6]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[6]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -421,7 +421,7 @@ func (x *ChangePassword) ProtoReflect() protoreflect.Message {
// Deprecated: Use ChangePassword.ProtoReflect.Descriptor instead.
func (*ChangePassword) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{6}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{6}
}
func (x *ChangePassword) GetNewPassword() string {
@@ -450,7 +450,7 @@ type ChangeExpiration struct {
func (x *ChangeExpiration) Reset() {
*x = ChangeExpiration{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[7]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -463,7 +463,7 @@ func (x *ChangeExpiration) String() string {
func (*ChangeExpiration) ProtoMessage() {}
func (x *ChangeExpiration) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[7]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -476,7 +476,7 @@ func (x *ChangeExpiration) ProtoReflect() protoreflect.Message {
// Deprecated: Use ChangeExpiration.ProtoReflect.Descriptor instead.
func (*ChangeExpiration) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{7}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{7}
}
func (x *ChangeExpiration) GetNewExpiration() *timestamp.Timestamp {
@@ -502,7 +502,7 @@ type UpdateUserResponse struct {
func (x *UpdateUserResponse) Reset() {
*x = UpdateUserResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[8]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[8]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -515,7 +515,7 @@ func (x *UpdateUserResponse) String() string {
func (*UpdateUserResponse) ProtoMessage() {}
func (x *UpdateUserResponse) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[8]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[8]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -528,7 +528,7 @@ func (x *UpdateUserResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use UpdateUserResponse.ProtoReflect.Descriptor instead.
func (*UpdateUserResponse) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{8}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{8}
}
/////////////////
@@ -546,7 +546,7 @@ type DeleteUserRequest struct {
func (x *DeleteUserRequest) Reset() {
*x = DeleteUserRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[9]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -559,7 +559,7 @@ func (x *DeleteUserRequest) String() string {
func (*DeleteUserRequest) ProtoMessage() {}
func (x *DeleteUserRequest) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[9]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -572,7 +572,7 @@ func (x *DeleteUserRequest) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeleteUserRequest.ProtoReflect.Descriptor instead.
func (*DeleteUserRequest) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{9}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{9}
}
func (x *DeleteUserRequest) GetUsername() string {
@@ -598,7 +598,7 @@ type DeleteUserResponse struct {
func (x *DeleteUserResponse) Reset() {
*x = DeleteUserResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[10]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -611,7 +611,7 @@ func (x *DeleteUserResponse) String() string {
func (*DeleteUserResponse) ProtoMessage() {}
func (x *DeleteUserResponse) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[10]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -624,7 +624,7 @@ func (x *DeleteUserResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use DeleteUserResponse.ProtoReflect.Descriptor instead.
func (*DeleteUserResponse) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{10}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{10}
}
/////////////////
@@ -641,7 +641,7 @@ type TypeResponse struct {
func (x *TypeResponse) Reset() {
*x = TypeResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[11]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -654,7 +654,7 @@ func (x *TypeResponse) String() string {
func (*TypeResponse) ProtoMessage() {}
func (x *TypeResponse) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[11]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -667,7 +667,7 @@ func (x *TypeResponse) ProtoReflect() protoreflect.Message {
// Deprecated: Use TypeResponse.ProtoReflect.Descriptor instead.
func (*TypeResponse) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{11}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{11}
}
func (x *TypeResponse) GetType() string {
@@ -691,7 +691,7 @@ type Statements struct {
func (x *Statements) Reset() {
*x = Statements{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[12]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -704,7 +704,7 @@ func (x *Statements) String() string {
func (*Statements) ProtoMessage() {}
func (x *Statements) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[12]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -717,7 +717,7 @@ func (x *Statements) ProtoReflect() protoreflect.Message {
// Deprecated: Use Statements.ProtoReflect.Descriptor instead.
func (*Statements) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{12}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{12}
}
func (x *Statements) GetCommands() []string {
@@ -736,7 +736,7 @@ type Empty struct {
func (x *Empty) Reset() {
*x = Empty{}
if protoimpl.UnsafeEnabled {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[13]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[13]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -749,7 +749,7 @@ func (x *Empty) String() string {
func (*Empty) ProtoMessage() {}
func (x *Empty) ProtoReflect() protoreflect.Message {
mi := &file_sdk_database_newdbplugin_proto_database_proto_msgTypes[13]
mi := &file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[13]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -762,16 +762,16 @@ func (x *Empty) ProtoReflect() protoreflect.Message {
// Deprecated: Use Empty.ProtoReflect.Descriptor instead.
func (*Empty) Descriptor() ([]byte, []int) {
return file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP(), []int{13}
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP(), []int{13}
}
var File_sdk_database_newdbplugin_proto_database_proto protoreflect.FileDescriptor
var File_sdk_database_dbplugin_v5_proto_database_proto protoreflect.FileDescriptor
var file_sdk_database_newdbplugin_proto_database_proto_rawDesc = []byte{
0x0a, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x6e,
0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
var file_sdk_database_dbplugin_v5_proto_database_proto_rawDesc = []byte{
0x0a, 0x2d, 0x73, 0x64, 0x6b, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x64,
0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x0b, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x1a, 0x1c, 0x67, 0x6f,
0x0b, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x1a, 0x1c, 0x67, 0x6f,
0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74,
0x72, 0x75, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65,
@@ -791,8 +791,8 @@ var file_sdk_database_newdbplugin_proto_database_proto_rawDesc = []byte{
0x66, 0x69, 0x67, 0x44, 0x61, 0x74, 0x61, 0x22, 0xb1, 0x02, 0x0a, 0x0e, 0x4e, 0x65, 0x77, 0x55,
0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x44, 0x0a, 0x0f, 0x75, 0x73,
0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69,
0x6e, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76,
0x35, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x52, 0x0e, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x3a, 0x0a, 0x0a,
@@ -800,12 +800,12 @@ var file_sdk_database_newdbplugin_proto_database_proto_rawDesc = []byte{
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78,
0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74,
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x6e,
0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65,
0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x64,
0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65,
0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
0x73, 0x12, 0x48, 0x0a, 0x13, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x5f, 0x73, 0x74,
0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,
0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x74, 0x61,
0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53, 0x74, 0x61,
0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x12, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63,
0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x50, 0x0a, 0x0e, 0x55,
0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x21, 0x0a,
@@ -820,18 +820,18 @@ var file_sdk_database_newdbplugin_proto_database_proto_rawDesc = []byte{
0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37,
0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1b, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43,
0x32, 0x1b, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x43,
0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x08, 0x70,
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x3d, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6e, 0x65,
0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x64, 0x62,
0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65,
0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69,
0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x6c, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65,
0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x6e, 0x65, 0x77, 0x5f,
0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b,
0x6e, 0x65, 0x77, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x37, 0x0a, 0x0a, 0x73,
0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x17, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53, 0x74,
0x17, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53, 0x74,
0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65, 0x6d,
0x65, 0x6e, 0x74, 0x73, 0x22, 0x8e, 0x01, 0x0a, 0x10, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45,
0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x41, 0x0a, 0x0e, 0x6e, 0x65, 0x77,
@@ -840,7 +840,7 @@ var file_sdk_database_newdbplugin_proto_database_proto_rawDesc = []byte{
0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x6e,
0x65, 0x77, 0x45, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x0a,
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x17, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53,
0x32, 0x17, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53,
0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65,
0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55,
0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x68, 0x0a, 0x11, 0x44,
@@ -848,7 +848,7 @@ var file_sdk_database_newdbplugin_proto_database_proto_rawDesc = []byte{
0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01,
0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x37, 0x0a, 0x0a,
0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x17, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x53,
0x32, 0x17, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x53,
0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x0a, 0x73, 0x74, 0x61, 0x74, 0x65,
0x6d, 0x65, 0x6e, 0x74, 0x73, 0x22, 0x14, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55,
0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x0a, 0x0c, 0x54,
@@ -859,93 +859,93 @@ var file_sdk_database_newdbplugin_proto_database_proto_rawDesc = []byte{
0x08, 0x43, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x73, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70,
0x74, 0x79, 0x32, 0xa5, 0x03, 0x0a, 0x08, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12,
0x4d, 0x0a, 0x0a, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x12, 0x1e, 0x2e,
0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x6e, 0x69, 0x74,
0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x49, 0x6e, 0x69, 0x74,
0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1f, 0x2e,
0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x49, 0x6e, 0x69, 0x74,
0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x49, 0x6e, 0x69, 0x74,
0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44,
0x0a, 0x07, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x6e, 0x65, 0x77, 0x64,
0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c,
0x75, 0x67, 0x69, 0x6e, 0x2e, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70,
0x0a, 0x07, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1b, 0x2e, 0x64, 0x62, 0x70, 0x6c,
0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69,
0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x4e, 0x65, 0x77, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0a, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73,
0x65, 0x72, 0x12, 0x1e, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
0x65, 0x72, 0x12, 0x1e, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35,
0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
0x73, 0x74, 0x1a, 0x1f, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35,
0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f,
0x6e, 0x73, 0x65, 0x12, 0x4d, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65,
0x72, 0x12, 0x1e, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e,
0x72, 0x12, 0x1e, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e,
0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x1f, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e,
0x74, 0x1a, 0x1f, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e,
0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x55, 0x73, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x2e, 0x6e, 0x65, 0x77,
0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19,
0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x54, 0x79, 0x70,
0x73, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x2e, 0x64, 0x62, 0x70,
0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x19,
0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x54, 0x79, 0x70,
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x05, 0x43, 0x6c, 0x6f,
0x73, 0x65, 0x12, 0x12, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e,
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c,
0x75, 0x67, 0x69, 0x6e, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69,
0x73, 0x65, 0x12, 0x12, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x76, 0x35,
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x12, 0x2e, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69,
0x6e, 0x2e, 0x76, 0x35, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x3b, 0x5a, 0x39, 0x67, 0x69,
0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f,
0x72, 0x70, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, 0x64, 0x61, 0x74,
0x61, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x6e, 0x65, 0x77, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69,
0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x61, 0x62, 0x61, 0x73, 0x65, 0x2f, 0x64, 0x62, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x76,
0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_sdk_database_newdbplugin_proto_database_proto_rawDescOnce sync.Once
file_sdk_database_newdbplugin_proto_database_proto_rawDescData = file_sdk_database_newdbplugin_proto_database_proto_rawDesc
file_sdk_database_dbplugin_v5_proto_database_proto_rawDescOnce sync.Once
file_sdk_database_dbplugin_v5_proto_database_proto_rawDescData = file_sdk_database_dbplugin_v5_proto_database_proto_rawDesc
)
func file_sdk_database_newdbplugin_proto_database_proto_rawDescGZIP() []byte {
file_sdk_database_newdbplugin_proto_database_proto_rawDescOnce.Do(func() {
file_sdk_database_newdbplugin_proto_database_proto_rawDescData = protoimpl.X.CompressGZIP(file_sdk_database_newdbplugin_proto_database_proto_rawDescData)
func file_sdk_database_dbplugin_v5_proto_database_proto_rawDescGZIP() []byte {
file_sdk_database_dbplugin_v5_proto_database_proto_rawDescOnce.Do(func() {
file_sdk_database_dbplugin_v5_proto_database_proto_rawDescData = protoimpl.X.CompressGZIP(file_sdk_database_dbplugin_v5_proto_database_proto_rawDescData)
})
return file_sdk_database_newdbplugin_proto_database_proto_rawDescData
return file_sdk_database_dbplugin_v5_proto_database_proto_rawDescData
}
var file_sdk_database_newdbplugin_proto_database_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
var file_sdk_database_newdbplugin_proto_database_proto_goTypes = []interface{}{
(*InitializeRequest)(nil), // 0: newdbplugin.InitializeRequest
(*InitializeResponse)(nil), // 1: newdbplugin.InitializeResponse
(*NewUserRequest)(nil), // 2: newdbplugin.NewUserRequest
(*UsernameConfig)(nil), // 3: newdbplugin.UsernameConfig
(*NewUserResponse)(nil), // 4: newdbplugin.NewUserResponse
(*UpdateUserRequest)(nil), // 5: newdbplugin.UpdateUserRequest
(*ChangePassword)(nil), // 6: newdbplugin.ChangePassword
(*ChangeExpiration)(nil), // 7: newdbplugin.ChangeExpiration
(*UpdateUserResponse)(nil), // 8: newdbplugin.UpdateUserResponse
(*DeleteUserRequest)(nil), // 9: newdbplugin.DeleteUserRequest
(*DeleteUserResponse)(nil), // 10: newdbplugin.DeleteUserResponse
(*TypeResponse)(nil), // 11: newdbplugin.TypeResponse
(*Statements)(nil), // 12: newdbplugin.Statements
(*Empty)(nil), // 13: newdbplugin.Empty
var file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes = make([]protoimpl.MessageInfo, 14)
var file_sdk_database_dbplugin_v5_proto_database_proto_goTypes = []interface{}{
(*InitializeRequest)(nil), // 0: dbplugin.v5.InitializeRequest
(*InitializeResponse)(nil), // 1: dbplugin.v5.InitializeResponse
(*NewUserRequest)(nil), // 2: dbplugin.v5.NewUserRequest
(*UsernameConfig)(nil), // 3: dbplugin.v5.UsernameConfig
(*NewUserResponse)(nil), // 4: dbplugin.v5.NewUserResponse
(*UpdateUserRequest)(nil), // 5: dbplugin.v5.UpdateUserRequest
(*ChangePassword)(nil), // 6: dbplugin.v5.ChangePassword
(*ChangeExpiration)(nil), // 7: dbplugin.v5.ChangeExpiration
(*UpdateUserResponse)(nil), // 8: dbplugin.v5.UpdateUserResponse
(*DeleteUserRequest)(nil), // 9: dbplugin.v5.DeleteUserRequest
(*DeleteUserResponse)(nil), // 10: dbplugin.v5.DeleteUserResponse
(*TypeResponse)(nil), // 11: dbplugin.v5.TypeResponse
(*Statements)(nil), // 12: dbplugin.v5.Statements
(*Empty)(nil), // 13: dbplugin.v5.Empty
(*_struct.Struct)(nil), // 14: google.protobuf.Struct
(*timestamp.Timestamp)(nil), // 15: google.protobuf.Timestamp
}
var file_sdk_database_newdbplugin_proto_database_proto_depIdxs = []int32{
14, // 0: newdbplugin.InitializeRequest.config_data:type_name -> google.protobuf.Struct
14, // 1: newdbplugin.InitializeResponse.config_data:type_name -> google.protobuf.Struct
3, // 2: newdbplugin.NewUserRequest.username_config:type_name -> newdbplugin.UsernameConfig
15, // 3: newdbplugin.NewUserRequest.expiration:type_name -> google.protobuf.Timestamp
12, // 4: newdbplugin.NewUserRequest.statements:type_name -> newdbplugin.Statements
12, // 5: newdbplugin.NewUserRequest.rollback_statements:type_name -> newdbplugin.Statements
6, // 6: newdbplugin.UpdateUserRequest.password:type_name -> newdbplugin.ChangePassword
7, // 7: newdbplugin.UpdateUserRequest.expiration:type_name -> newdbplugin.ChangeExpiration
12, // 8: newdbplugin.ChangePassword.statements:type_name -> newdbplugin.Statements
15, // 9: newdbplugin.ChangeExpiration.new_expiration:type_name -> google.protobuf.Timestamp
12, // 10: newdbplugin.ChangeExpiration.statements:type_name -> newdbplugin.Statements
12, // 11: newdbplugin.DeleteUserRequest.statements:type_name -> newdbplugin.Statements
0, // 12: newdbplugin.Database.Initialize:input_type -> newdbplugin.InitializeRequest
2, // 13: newdbplugin.Database.NewUser:input_type -> newdbplugin.NewUserRequest
5, // 14: newdbplugin.Database.UpdateUser:input_type -> newdbplugin.UpdateUserRequest
9, // 15: newdbplugin.Database.DeleteUser:input_type -> newdbplugin.DeleteUserRequest
13, // 16: newdbplugin.Database.Type:input_type -> newdbplugin.Empty
13, // 17: newdbplugin.Database.Close:input_type -> newdbplugin.Empty
1, // 18: newdbplugin.Database.Initialize:output_type -> newdbplugin.InitializeResponse
4, // 19: newdbplugin.Database.NewUser:output_type -> newdbplugin.NewUserResponse
8, // 20: newdbplugin.Database.UpdateUser:output_type -> newdbplugin.UpdateUserResponse
10, // 21: newdbplugin.Database.DeleteUser:output_type -> newdbplugin.DeleteUserResponse
11, // 22: newdbplugin.Database.Type:output_type -> newdbplugin.TypeResponse
13, // 23: newdbplugin.Database.Close:output_type -> newdbplugin.Empty
var file_sdk_database_dbplugin_v5_proto_database_proto_depIdxs = []int32{
14, // 0: dbplugin.v5.InitializeRequest.config_data:type_name -> google.protobuf.Struct
14, // 1: dbplugin.v5.InitializeResponse.config_data:type_name -> google.protobuf.Struct
3, // 2: dbplugin.v5.NewUserRequest.username_config:type_name -> dbplugin.v5.UsernameConfig
15, // 3: dbplugin.v5.NewUserRequest.expiration:type_name -> google.protobuf.Timestamp
12, // 4: dbplugin.v5.NewUserRequest.statements:type_name -> dbplugin.v5.Statements
12, // 5: dbplugin.v5.NewUserRequest.rollback_statements:type_name -> dbplugin.v5.Statements
6, // 6: dbplugin.v5.UpdateUserRequest.password:type_name -> dbplugin.v5.ChangePassword
7, // 7: dbplugin.v5.UpdateUserRequest.expiration:type_name -> dbplugin.v5.ChangeExpiration
12, // 8: dbplugin.v5.ChangePassword.statements:type_name -> dbplugin.v5.Statements
15, // 9: dbplugin.v5.ChangeExpiration.new_expiration:type_name -> google.protobuf.Timestamp
12, // 10: dbplugin.v5.ChangeExpiration.statements:type_name -> dbplugin.v5.Statements
12, // 11: dbplugin.v5.DeleteUserRequest.statements:type_name -> dbplugin.v5.Statements
0, // 12: dbplugin.v5.Database.Initialize:input_type -> dbplugin.v5.InitializeRequest
2, // 13: dbplugin.v5.Database.NewUser:input_type -> dbplugin.v5.NewUserRequest
5, // 14: dbplugin.v5.Database.UpdateUser:input_type -> dbplugin.v5.UpdateUserRequest
9, // 15: dbplugin.v5.Database.DeleteUser:input_type -> dbplugin.v5.DeleteUserRequest
13, // 16: dbplugin.v5.Database.Type:input_type -> dbplugin.v5.Empty
13, // 17: dbplugin.v5.Database.Close:input_type -> dbplugin.v5.Empty
1, // 18: dbplugin.v5.Database.Initialize:output_type -> dbplugin.v5.InitializeResponse
4, // 19: dbplugin.v5.Database.NewUser:output_type -> dbplugin.v5.NewUserResponse
8, // 20: dbplugin.v5.Database.UpdateUser:output_type -> dbplugin.v5.UpdateUserResponse
10, // 21: dbplugin.v5.Database.DeleteUser:output_type -> dbplugin.v5.DeleteUserResponse
11, // 22: dbplugin.v5.Database.Type:output_type -> dbplugin.v5.TypeResponse
13, // 23: dbplugin.v5.Database.Close:output_type -> dbplugin.v5.Empty
18, // [18:24] is the sub-list for method output_type
12, // [12:18] is the sub-list for method input_type
12, // [12:12] is the sub-list for extension type_name
@@ -953,13 +953,13 @@ var file_sdk_database_newdbplugin_proto_database_proto_depIdxs = []int32{
0, // [0:12] is the sub-list for field type_name
}
func init() { file_sdk_database_newdbplugin_proto_database_proto_init() }
func file_sdk_database_newdbplugin_proto_database_proto_init() {
if File_sdk_database_newdbplugin_proto_database_proto != nil {
func init() { file_sdk_database_dbplugin_v5_proto_database_proto_init() }
func file_sdk_database_dbplugin_v5_proto_database_proto_init() {
if File_sdk_database_dbplugin_v5_proto_database_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*InitializeRequest); i {
case 0:
return &v.state
@@ -971,7 +971,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*InitializeResponse); i {
case 0:
return &v.state
@@ -983,7 +983,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NewUserRequest); i {
case 0:
return &v.state
@@ -995,7 +995,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UsernameConfig); i {
case 0:
return &v.state
@@ -1007,7 +1007,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NewUserResponse); i {
case 0:
return &v.state
@@ -1019,7 +1019,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateUserRequest); i {
case 0:
return &v.state
@@ -1031,7 +1031,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ChangePassword); i {
case 0:
return &v.state
@@ -1043,7 +1043,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*ChangeExpiration); i {
case 0:
return &v.state
@@ -1055,7 +1055,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*UpdateUserResponse); i {
case 0:
return &v.state
@@ -1067,7 +1067,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteUserRequest); i {
case 0:
return &v.state
@@ -1079,7 +1079,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteUserResponse); i {
case 0:
return &v.state
@@ -1091,7 +1091,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*TypeResponse); i {
case 0:
return &v.state
@@ -1103,7 +1103,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Statements); i {
case 0:
return &v.state
@@ -1115,7 +1115,7 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
return nil
}
}
file_sdk_database_newdbplugin_proto_database_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Empty); i {
case 0:
return &v.state
@@ -1132,20 +1132,20 @@ func file_sdk_database_newdbplugin_proto_database_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_sdk_database_newdbplugin_proto_database_proto_rawDesc,
RawDescriptor: file_sdk_database_dbplugin_v5_proto_database_proto_rawDesc,
NumEnums: 0,
NumMessages: 14,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_sdk_database_newdbplugin_proto_database_proto_goTypes,
DependencyIndexes: file_sdk_database_newdbplugin_proto_database_proto_depIdxs,
MessageInfos: file_sdk_database_newdbplugin_proto_database_proto_msgTypes,
GoTypes: file_sdk_database_dbplugin_v5_proto_database_proto_goTypes,
DependencyIndexes: file_sdk_database_dbplugin_v5_proto_database_proto_depIdxs,
MessageInfos: file_sdk_database_dbplugin_v5_proto_database_proto_msgTypes,
}.Build()
File_sdk_database_newdbplugin_proto_database_proto = out.File
file_sdk_database_newdbplugin_proto_database_proto_rawDesc = nil
file_sdk_database_newdbplugin_proto_database_proto_goTypes = nil
file_sdk_database_newdbplugin_proto_database_proto_depIdxs = nil
File_sdk_database_dbplugin_v5_proto_database_proto = out.File
file_sdk_database_dbplugin_v5_proto_database_proto_rawDesc = nil
file_sdk_database_dbplugin_v5_proto_database_proto_goTypes = nil
file_sdk_database_dbplugin_v5_proto_database_proto_depIdxs = nil
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -1178,7 +1178,7 @@ func NewDatabaseClient(cc grpc.ClientConnInterface) DatabaseClient {
func (c *databaseClient) Initialize(ctx context.Context, in *InitializeRequest, opts ...grpc.CallOption) (*InitializeResponse, error) {
out := new(InitializeResponse)
err := c.cc.Invoke(ctx, "/newdbplugin.Database/Initialize", in, out, opts...)
err := c.cc.Invoke(ctx, "/dbplugin.v5.Database/Initialize", in, out, opts...)
if err != nil {
return nil, err
}
@@ -1187,7 +1187,7 @@ func (c *databaseClient) Initialize(ctx context.Context, in *InitializeRequest,
func (c *databaseClient) NewUser(ctx context.Context, in *NewUserRequest, opts ...grpc.CallOption) (*NewUserResponse, error) {
out := new(NewUserResponse)
err := c.cc.Invoke(ctx, "/newdbplugin.Database/NewUser", in, out, opts...)
err := c.cc.Invoke(ctx, "/dbplugin.v5.Database/NewUser", in, out, opts...)
if err != nil {
return nil, err
}
@@ -1196,7 +1196,7 @@ func (c *databaseClient) NewUser(ctx context.Context, in *NewUserRequest, opts .
func (c *databaseClient) UpdateUser(ctx context.Context, in *UpdateUserRequest, opts ...grpc.CallOption) (*UpdateUserResponse, error) {
out := new(UpdateUserResponse)
err := c.cc.Invoke(ctx, "/newdbplugin.Database/UpdateUser", in, out, opts...)
err := c.cc.Invoke(ctx, "/dbplugin.v5.Database/UpdateUser", in, out, opts...)
if err != nil {
return nil, err
}
@@ -1205,7 +1205,7 @@ func (c *databaseClient) UpdateUser(ctx context.Context, in *UpdateUserRequest,
func (c *databaseClient) DeleteUser(ctx context.Context, in *DeleteUserRequest, opts ...grpc.CallOption) (*DeleteUserResponse, error) {
out := new(DeleteUserResponse)
err := c.cc.Invoke(ctx, "/newdbplugin.Database/DeleteUser", in, out, opts...)
err := c.cc.Invoke(ctx, "/dbplugin.v5.Database/DeleteUser", in, out, opts...)
if err != nil {
return nil, err
}
@@ -1214,7 +1214,7 @@ func (c *databaseClient) DeleteUser(ctx context.Context, in *DeleteUserRequest,
func (c *databaseClient) Type(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*TypeResponse, error) {
out := new(TypeResponse)
err := c.cc.Invoke(ctx, "/newdbplugin.Database/Type", in, out, opts...)
err := c.cc.Invoke(ctx, "/dbplugin.v5.Database/Type", in, out, opts...)
if err != nil {
return nil, err
}
@@ -1223,7 +1223,7 @@ func (c *databaseClient) Type(ctx context.Context, in *Empty, opts ...grpc.CallO
func (c *databaseClient) Close(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := c.cc.Invoke(ctx, "/newdbplugin.Database/Close", in, out, opts...)
err := c.cc.Invoke(ctx, "/dbplugin.v5.Database/Close", in, out, opts...)
if err != nil {
return nil, err
}
@@ -1277,7 +1277,7 @@ func _Database_Initialize_Handler(srv interface{}, ctx context.Context, dec func
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/newdbplugin.Database/Initialize",
FullMethod: "/dbplugin.v5.Database/Initialize",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DatabaseServer).Initialize(ctx, req.(*InitializeRequest))
@@ -1295,7 +1295,7 @@ func _Database_NewUser_Handler(srv interface{}, ctx context.Context, dec func(in
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/newdbplugin.Database/NewUser",
FullMethod: "/dbplugin.v5.Database/NewUser",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DatabaseServer).NewUser(ctx, req.(*NewUserRequest))
@@ -1313,7 +1313,7 @@ func _Database_UpdateUser_Handler(srv interface{}, ctx context.Context, dec func
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/newdbplugin.Database/UpdateUser",
FullMethod: "/dbplugin.v5.Database/UpdateUser",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DatabaseServer).UpdateUser(ctx, req.(*UpdateUserRequest))
@@ -1331,7 +1331,7 @@ func _Database_DeleteUser_Handler(srv interface{}, ctx context.Context, dec func
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/newdbplugin.Database/DeleteUser",
FullMethod: "/dbplugin.v5.Database/DeleteUser",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DatabaseServer).DeleteUser(ctx, req.(*DeleteUserRequest))
@@ -1349,7 +1349,7 @@ func _Database_Type_Handler(srv interface{}, ctx context.Context, dec func(inter
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/newdbplugin.Database/Type",
FullMethod: "/dbplugin.v5.Database/Type",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DatabaseServer).Type(ctx, req.(*Empty))
@@ -1367,7 +1367,7 @@ func _Database_Close_Handler(srv interface{}, ctx context.Context, dec func(inte
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/newdbplugin.Database/Close",
FullMethod: "/dbplugin.v5.Database/Close",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DatabaseServer).Close(ctx, req.(*Empty))
@@ -1376,7 +1376,7 @@ func _Database_Close_Handler(srv interface{}, ctx context.Context, dec func(inte
}
var _Database_serviceDesc = grpc.ServiceDesc{
ServiceName: "newdbplugin.Database",
ServiceName: "dbplugin.v5.Database",
HandlerType: (*DatabaseServer)(nil),
Methods: []grpc.MethodDesc{
{
@@ -1405,5 +1405,5 @@ var _Database_serviceDesc = grpc.ServiceDesc{
},
},
Streams: []grpc.StreamDesc{},
Metadata: "sdk/database/newdbplugin/proto/database.proto",
Metadata: "sdk/database/dbplugin/v5/proto/database.proto",
}

View File

@@ -1,7 +1,7 @@
syntax = "proto3";
package newdbplugin; // TODO: Update name
package dbplugin.v5;
option go_package = "github.com/hashicorp/vault/sdk/database/newdbplugin/proto";
option go_package = "github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto";
import "google/protobuf/struct.proto";
import "google/protobuf/timestamp.proto";

View File

@@ -0,0 +1,85 @@
package dbtesting
import (
"context"
"os"
"testing"
"time"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5"
)
func getRequestTimeout(t *testing.T) time.Duration {
rawDur := os.Getenv("VAULT_TEST_DATABASE_REQUEST_TIMEOUT")
if rawDur == "" {
return 2 * time.Second
}
dur, err := time.ParseDuration(rawDur)
if err != nil {
t.Fatalf("Failed to parse custom request timeout %q: %s", rawDur, err)
}
return dur
}
func AssertInitialize(t *testing.T, db dbplugin.Database, req dbplugin.InitializeRequest) dbplugin.InitializeResponse {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), getRequestTimeout(t))
defer cancel()
resp, err := db.Initialize(ctx, req)
if err != nil {
t.Fatalf("Failed to initialize: %s", err)
}
return resp
}
func AssertNewUser(t *testing.T, db dbplugin.Database, req dbplugin.NewUserRequest) dbplugin.NewUserResponse {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), getRequestTimeout(t))
defer cancel()
resp, err := db.NewUser(ctx, req)
if err != nil {
t.Fatalf("Failed to create new user: %s", err)
}
if resp.Username == "" {
t.Fatalf("Missing username from NewUser response")
}
return resp
}
func AssertUpdateUser(t *testing.T, db dbplugin.Database, req dbplugin.UpdateUserRequest) {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), getRequestTimeout(t))
defer cancel()
_, err := db.UpdateUser(ctx, req)
if err != nil {
t.Fatalf("Failed to update user: %s", err)
}
}
func AssertDeleteUser(t *testing.T, db dbplugin.Database, req dbplugin.DeleteUserRequest) {
t.Helper()
ctx, cancel := context.WithTimeout(context.Background(), getRequestTimeout(t))
defer cancel()
_, err := db.DeleteUser(ctx, req)
if err != nil {
t.Fatalf("Failed to delete user %q: %s", req.Username, err)
}
}
func AssertClose(t *testing.T, db dbplugin.Database) {
t.Helper()
err := db.Close()
if err != nil {
t.Fatalf("Failed to close database: %s", err)
}
}

View File

@@ -7,7 +7,7 @@ import (
"time"
"github.com/golang/protobuf/ptypes"
"github.com/hashicorp/vault/sdk/database/newdbplugin/proto"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"github.com/hashicorp/vault/sdk/helper/pluginutil"
)

View File

@@ -4,7 +4,7 @@ import (
"context"
"github.com/hashicorp/go-plugin"
"github.com/hashicorp/vault/sdk/database/newdbplugin/proto"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"google.golang.org/grpc"
)

View File

@@ -6,7 +6,7 @@ import (
"time"
"github.com/golang/protobuf/ptypes"
"github.com/hashicorp/vault/sdk/database/newdbplugin/proto"
"github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

5
vendor/modules.txt vendored
View File

@@ -553,12 +553,13 @@ github.com/hashicorp/vault-plugin-secrets-openldap/client
github.com/hashicorp/vault/api
# github.com/hashicorp/vault/sdk v0.1.14-0.20201007132131-6a41edbf89f5 => ./sdk
github.com/hashicorp/vault/sdk/database/dbplugin
github.com/hashicorp/vault/sdk/database/dbplugin/v5
github.com/hashicorp/vault/sdk/database/dbplugin/v5/proto
github.com/hashicorp/vault/sdk/database/dbplugin/v5/testing
github.com/hashicorp/vault/sdk/database/helper/connutil
github.com/hashicorp/vault/sdk/database/helper/credsutil
github.com/hashicorp/vault/sdk/database/helper/dbutil
github.com/hashicorp/vault/sdk/database/newdbplugin
github.com/hashicorp/vault/sdk/database/newdbplugin/proto
github.com/hashicorp/vault/sdk/database/newdbplugin/testing
github.com/hashicorp/vault/sdk/framework
github.com/hashicorp/vault/sdk/helper/authmetadata
github.com/hashicorp/vault/sdk/helper/awsutil