mirror of
				https://github.com/optim-enterprises-bv/vault.git
				synced 2025-10-31 02:28:09 +00:00 
			
		
		
		
	Database gRPC plugins (#3666)
* Start work on context aware backends * Start work on moving the database plugins to gRPC in order to pass context * Add context to builtin database plugins * use byte slice instead of string * Context all the things * Move proto messages to the dbplugin package * Add a grpc mechanism for running backend plugins * Serve the GRPC plugin * Add backwards compatibility to the database plugins * Remove backend plugin changes * Remove backend plugin changes * Cleanup the transport implementations * If grpc connection is in an unexpected state restart the plugin * Fix tests * Fix tests * Remove context from the request object, replace it with context.TODO * Add a test to verify netRPC plugins still work * Remove unused mapstructure call * Code review fixes * Code review fixes * Code review fixes
This commit is contained in:
		| @@ -1,6 +1,7 @@ | ||||
| package mysql | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"database/sql" | ||||
| 	"strings" | ||||
| 	"time" | ||||
| @@ -30,6 +31,8 @@ var ( | ||||
| 	LegacyUsernameLen int = 16 | ||||
| ) | ||||
|  | ||||
| var _ dbplugin.Database = &MySQL{} | ||||
|  | ||||
| type MySQL struct { | ||||
| 	connutil.ConnectionProducer | ||||
| 	credsutil.CredentialsProducer | ||||
| @@ -88,8 +91,8 @@ func (m *MySQL) Type() (string, error) { | ||||
| 	return mySQLTypeName, nil | ||||
| } | ||||
|  | ||||
| func (m *MySQL) getConnection() (*sql.DB, error) { | ||||
| 	db, err := m.Connection() | ||||
| func (m *MySQL) getConnection(ctx context.Context) (*sql.DB, error) { | ||||
| 	db, err := m.Connection(ctx) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| @@ -97,13 +100,13 @@ func (m *MySQL) getConnection() (*sql.DB, error) { | ||||
| 	return db.(*sql.DB), nil | ||||
| } | ||||
|  | ||||
| func (m *MySQL) CreateUser(statements dbplugin.Statements, usernameConfig dbplugin.UsernameConfig, expiration time.Time) (username string, password string, err error) { | ||||
| func (m *MySQL) CreateUser(ctx context.Context, statements dbplugin.Statements, usernameConfig dbplugin.UsernameConfig, expiration time.Time) (username string, password string, err error) { | ||||
| 	// Grab the lock | ||||
| 	m.Lock() | ||||
| 	defer m.Unlock() | ||||
|  | ||||
| 	// Get the connection | ||||
| 	db, err := m.getConnection() | ||||
| 	db, err := m.getConnection(ctx) | ||||
| 	if err != nil { | ||||
| 		return "", "", err | ||||
| 	} | ||||
| @@ -128,7 +131,7 @@ func (m *MySQL) CreateUser(statements dbplugin.Statements, usernameConfig dbplug | ||||
| 	} | ||||
|  | ||||
| 	// Start a transaction | ||||
| 	tx, err := db.Begin() | ||||
| 	tx, err := db.BeginTx(ctx, nil) | ||||
| 	if err != nil { | ||||
| 		return "", "", err | ||||
| 	} | ||||
| @@ -146,7 +149,7 @@ func (m *MySQL) CreateUser(statements dbplugin.Statements, usernameConfig dbplug | ||||
| 			"expiration": expirationStr, | ||||
| 		}) | ||||
|  | ||||
| 		stmt, err := tx.Prepare(query) | ||||
| 		stmt, err := tx.PrepareContext(ctx, query) | ||||
| 		if err != nil { | ||||
| 			// If the error code we get back is Error 1295: This command is not | ||||
| 			// supported in the prepared statement protocol yet, we will execute | ||||
| @@ -155,7 +158,7 @@ func (m *MySQL) CreateUser(statements dbplugin.Statements, usernameConfig dbplug | ||||
| 			// prepare supported commands. If there is no error when running we | ||||
| 			// will continue to the next statement. | ||||
| 			if e, ok := err.(*stdmysql.MySQLError); ok && e.Number == 1295 { | ||||
| 				_, err = tx.Exec(query) | ||||
| 				_, err = tx.ExecContext(ctx, query) | ||||
| 				if err != nil { | ||||
| 					return "", "", err | ||||
| 				} | ||||
| @@ -165,7 +168,7 @@ func (m *MySQL) CreateUser(statements dbplugin.Statements, usernameConfig dbplug | ||||
| 			return "", "", err | ||||
| 		} | ||||
| 		defer stmt.Close() | ||||
| 		if _, err := stmt.Exec(); err != nil { | ||||
| 		if _, err := stmt.ExecContext(ctx); err != nil { | ||||
| 			return "", "", err | ||||
| 		} | ||||
| 	} | ||||
| @@ -179,17 +182,17 @@ func (m *MySQL) CreateUser(statements dbplugin.Statements, usernameConfig dbplug | ||||
| } | ||||
|  | ||||
| // NOOP | ||||
| func (m *MySQL) RenewUser(statements dbplugin.Statements, username string, expiration time.Time) error { | ||||
| func (m *MySQL) RenewUser(ctx context.Context, statements dbplugin.Statements, username string, expiration time.Time) error { | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func (m *MySQL) RevokeUser(statements dbplugin.Statements, username string) error { | ||||
| func (m *MySQL) RevokeUser(ctx context.Context, statements dbplugin.Statements, username string) error { | ||||
| 	// Grab the read lock | ||||
| 	m.Lock() | ||||
| 	defer m.Unlock() | ||||
|  | ||||
| 	// Get the connection | ||||
| 	db, err := m.getConnection() | ||||
| 	db, err := m.getConnection(ctx) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -201,7 +204,7 @@ func (m *MySQL) RevokeUser(statements dbplugin.Statements, username string) erro | ||||
| 	} | ||||
|  | ||||
| 	// Start a transaction | ||||
| 	tx, err := db.Begin() | ||||
| 	tx, err := db.BeginTx(ctx, nil) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| @@ -217,7 +220,7 @@ func (m *MySQL) RevokeUser(statements dbplugin.Statements, username string) erro | ||||
| 		// 1295: This command is not supported in the prepared statement protocol yet | ||||
| 		// Reference https://mariadb.com/kb/en/mariadb/prepare-statement/ | ||||
| 		query = strings.Replace(query, "{{name}}", username, -1) | ||||
| 		_, err = tx.Exec(query) | ||||
| 		_, err = tx.ExecContext(ctx, query) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| package mysql | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"database/sql" | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| @@ -108,7 +109,7 @@ func TestMySQL_Initialize(t *testing.T) { | ||||
| 	db := dbRaw.(*MySQL) | ||||
| 	connProducer := db.ConnectionProducer.(*connutil.SQLConnectionProducer) | ||||
|  | ||||
| 	err := db.Initialize(connectionDetails, true) | ||||
| 	err := db.Initialize(context.Background(), connectionDetails, true) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
| @@ -128,7 +129,7 @@ func TestMySQL_Initialize(t *testing.T) { | ||||
| 		"max_open_connections": "5", | ||||
| 	} | ||||
|  | ||||
| 	err = db.Initialize(connectionDetails, true) | ||||
| 	err = db.Initialize(context.Background(), connectionDetails, true) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
| @@ -146,7 +147,7 @@ func TestMySQL_CreateUser(t *testing.T) { | ||||
| 	dbRaw, _ := f() | ||||
| 	db := dbRaw.(*MySQL) | ||||
|  | ||||
| 	err := db.Initialize(connectionDetails, true) | ||||
| 	err := db.Initialize(context.Background(), connectionDetails, true) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
| @@ -157,7 +158,7 @@ func TestMySQL_CreateUser(t *testing.T) { | ||||
| 	} | ||||
|  | ||||
| 	// Test with no configured Creation Statememt | ||||
| 	_, _, err = db.CreateUser(dbplugin.Statements{}, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	_, _, err = db.CreateUser(context.Background(), dbplugin.Statements{}, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	if err == nil { | ||||
| 		t.Fatal("Expected error when no creation statement is provided") | ||||
| 	} | ||||
| @@ -166,7 +167,7 @@ func TestMySQL_CreateUser(t *testing.T) { | ||||
| 		CreationStatements: testMySQLRoleWildCard, | ||||
| 	} | ||||
|  | ||||
| 	username, password, err := db.CreateUser(statements, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	username, password, err := db.CreateUser(context.Background(), statements, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
| @@ -176,7 +177,7 @@ func TestMySQL_CreateUser(t *testing.T) { | ||||
| 	} | ||||
|  | ||||
| 	// Test a second time to make sure usernames don't collide | ||||
| 	username, password, err = db.CreateUser(statements, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	username, password, err = db.CreateUser(context.Background(), statements, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
| @@ -188,7 +189,7 @@ func TestMySQL_CreateUser(t *testing.T) { | ||||
| 	// Test with a manualy prepare statement | ||||
| 	statements.CreationStatements = testMySQLRolePreparedStmt | ||||
|  | ||||
| 	username, password, err = db.CreateUser(statements, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	username, password, err = db.CreateUser(context.Background(), statements, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
| @@ -211,7 +212,7 @@ func TestMySQL_CreateUser_Legacy(t *testing.T) { | ||||
| 	dbRaw, _ := f() | ||||
| 	db := dbRaw.(*MySQL) | ||||
|  | ||||
| 	err := db.Initialize(connectionDetails, true) | ||||
| 	err := db.Initialize(context.Background(), connectionDetails, true) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
| @@ -222,7 +223,7 @@ func TestMySQL_CreateUser_Legacy(t *testing.T) { | ||||
| 	} | ||||
|  | ||||
| 	// Test with no configured Creation Statememt | ||||
| 	_, _, err = db.CreateUser(dbplugin.Statements{}, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	_, _, err = db.CreateUser(context.Background(), dbplugin.Statements{}, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	if err == nil { | ||||
| 		t.Fatal("Expected error when no creation statement is provided") | ||||
| 	} | ||||
| @@ -231,7 +232,7 @@ func TestMySQL_CreateUser_Legacy(t *testing.T) { | ||||
| 		CreationStatements: testMySQLRoleWildCard, | ||||
| 	} | ||||
|  | ||||
| 	username, password, err := db.CreateUser(statements, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	username, password, err := db.CreateUser(context.Background(), statements, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
| @@ -241,7 +242,7 @@ func TestMySQL_CreateUser_Legacy(t *testing.T) { | ||||
| 	} | ||||
|  | ||||
| 	// Test a second time to make sure usernames don't collide | ||||
| 	username, password, err = db.CreateUser(statements, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	username, password, err = db.CreateUser(context.Background(), statements, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
| @@ -263,7 +264,7 @@ func TestMySQL_RevokeUser(t *testing.T) { | ||||
| 	dbRaw, _ := f() | ||||
| 	db := dbRaw.(*MySQL) | ||||
|  | ||||
| 	err := db.Initialize(connectionDetails, true) | ||||
| 	err := db.Initialize(context.Background(), connectionDetails, true) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
| @@ -277,7 +278,7 @@ func TestMySQL_RevokeUser(t *testing.T) { | ||||
| 		RoleName:    "test", | ||||
| 	} | ||||
|  | ||||
| 	username, password, err := db.CreateUser(statements, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	username, password, err := db.CreateUser(context.Background(), statements, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
| @@ -287,7 +288,7 @@ func TestMySQL_RevokeUser(t *testing.T) { | ||||
| 	} | ||||
|  | ||||
| 	// Test default revoke statememts | ||||
| 	err = db.RevokeUser(statements, username) | ||||
| 	err = db.RevokeUser(context.Background(), statements, username) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
| @@ -297,7 +298,7 @@ func TestMySQL_RevokeUser(t *testing.T) { | ||||
| 	} | ||||
|  | ||||
| 	statements.CreationStatements = testMySQLRoleWildCard | ||||
| 	username, password, err = db.CreateUser(statements, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	username, password, err = db.CreateUser(context.Background(), statements, usernameConfig, time.Now().Add(time.Minute)) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
| @@ -308,7 +309,7 @@ func TestMySQL_RevokeUser(t *testing.T) { | ||||
|  | ||||
| 	// Test custom revoke statements | ||||
| 	statements.RevocationStatements = testMySQLRevocationSQL | ||||
| 	err = db.RevokeUser(statements, username) | ||||
| 	err = db.RevokeUser(context.Background(), statements, username) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("err: %s", err) | ||||
| 	} | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Brian Kassouf
					Brian Kassouf