mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-06 14:47:01 +02:00
database/mssql: set default root rotation stmt for contained db (#29399)
* database/mssql: set default root rotation stmt for contained db * changelog * add rotate root test * fix test * update passwords to make mssql happy * create admin user * update contained user create query * remove test
This commit is contained in:
parent
9d31bb8586
commit
04e75372fb
3
changelog/29399.txt
Normal file
3
changelog/29399.txt
Normal file
@ -0,0 +1,3 @@
|
||||
```release-note:bug
|
||||
database/mssql: Fix a bug where contained databases would silently fail root rotation if a custom root rotation statement was not provided.
|
||||
```
|
@ -345,8 +345,11 @@ func (m *MSSQL) UpdateUser(ctx context.Context, req dbplugin.UpdateUserRequest)
|
||||
|
||||
func (m *MSSQL) updateUserPass(ctx context.Context, username string, changePass *dbplugin.ChangePassword) error {
|
||||
stmts := changePass.Statements.Commands
|
||||
if len(stmts) == 0 && !m.containedDB {
|
||||
if len(stmts) == 0 {
|
||||
stmts = []string{alterLoginSQL}
|
||||
if m.containedDB {
|
||||
stmts = []string{alterUserContainedSQL}
|
||||
}
|
||||
}
|
||||
|
||||
password := changePass.NewPassword
|
||||
@ -384,6 +387,11 @@ func (m *MSSQL) updateUserPass(ctx context.Context, username string, changePass
|
||||
_ = tx.Rollback()
|
||||
}()
|
||||
|
||||
if len(stmts) == 0 {
|
||||
// should not happen, but guard against it anyway
|
||||
return errors.New("no statement provided")
|
||||
}
|
||||
|
||||
for _, stmt := range stmts {
|
||||
for _, query := range strutil.ParseArbitraryStringSlice(stmt, ";") {
|
||||
query = strings.TrimSpace(query)
|
||||
@ -431,3 +439,7 @@ EXEC (@stmt)`
|
||||
const alterLoginSQL = `
|
||||
ALTER LOGIN [{{username}}] WITH PASSWORD = '{{password}}'
|
||||
`
|
||||
|
||||
const alterUserContainedSQL = `
|
||||
ALTER USER [{{username}}] WITH PASSWORD = '{{password}}'
|
||||
`
|
||||
|
@ -20,7 +20,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestInitialize(t *testing.T) {
|
||||
func TestMSSQLInitialize(t *testing.T) {
|
||||
cleanup, connURL := mssqlhelper.PrepareMSSQLTestContainer(t)
|
||||
defer cleanup()
|
||||
|
||||
@ -79,7 +79,7 @@ func TestInitialize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewUser(t *testing.T) {
|
||||
func TestMSSQLNewUser(t *testing.T) {
|
||||
cleanup, connURL := mssqlhelper.PrepareMSSQLTestContainer(t)
|
||||
defer cleanup()
|
||||
|
||||
@ -185,7 +185,7 @@ func TestNewUser(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateUser_password(t *testing.T) {
|
||||
func TestMSSQLUpdateUser_password(t *testing.T) {
|
||||
type testCase struct {
|
||||
req dbplugin.UpdateUserRequest
|
||||
expectErr bool
|
||||
@ -312,7 +312,7 @@ func TestUpdateUser_password(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteUser(t *testing.T) {
|
||||
func TestMSSQLDeleteUser(t *testing.T) {
|
||||
cleanup, connURL := mssqlhelper.PrepareMSSQLTestContainer(t)
|
||||
defer cleanup()
|
||||
|
||||
@ -358,7 +358,7 @@ func TestDeleteUser(t *testing.T) {
|
||||
assertCredsDoNotExist(t, connURL, dbUser, initPassword)
|
||||
}
|
||||
|
||||
func TestDeleteUserContainedDB(t *testing.T) {
|
||||
func TestMSSQLDeleteUserContainedDB(t *testing.T) {
|
||||
cleanup, connURL := mssqlhelper.PrepareMSSQLTestContainer(t)
|
||||
defer cleanup()
|
||||
|
||||
@ -405,7 +405,7 @@ func TestDeleteUserContainedDB(t *testing.T) {
|
||||
assertContainedDBCredsDoNotExist(t, connURL, dbUser)
|
||||
}
|
||||
|
||||
func TestContainedDBSQLSanitization(t *testing.T) {
|
||||
func TestMSSQLContainedDBSQLSanitization(t *testing.T) {
|
||||
cleanup, connURL := mssqlhelper.PrepareMSSQLTestContainer(t)
|
||||
defer cleanup()
|
||||
|
||||
@ -443,7 +443,7 @@ func TestContainedDBSQLSanitization(t *testing.T) {
|
||||
assert.EqualError(t, err, "mssql: Cannot alter the login 'vaultuser]', because it does not exist or you do not have permission.")
|
||||
}
|
||||
|
||||
func TestSQLSanitization(t *testing.T) {
|
||||
func TestMSSQLSanitization(t *testing.T) {
|
||||
cleanup, connURL := mssqlhelper.PrepareMSSQLTestContainer(t)
|
||||
defer cleanup()
|
||||
|
||||
@ -576,3 +576,11 @@ const testMSSQLContainedLogin = `
|
||||
CREATE LOGIN [{{name}}] WITH PASSWORD = '{{password}}';
|
||||
CREATE USER [{{name}}] FOR LOGIN [{{name}}];
|
||||
`
|
||||
|
||||
const testMSSQLContainedLoginAdmin = `
|
||||
CREATE USER [{{name}}] WITH PASSWORD = '{{password}}';
|
||||
|
||||
ALTER ROLE db_datareader ADD MEMBER [{{name}}];
|
||||
ALTER ROLE db_datawriter ADD MEMBER [{{name}}];
|
||||
ALTER ROLE db_owner ADD MEMBER [{{name}}];
|
||||
`
|
||||
|
@ -115,13 +115,23 @@ the proper permission, it can generate credentials.
|
||||
|
||||
## Example for Azure SQL database
|
||||
|
||||
Here is a complete example using Azure SQL Database. Note that databases in Azure SQL Database are [contained databases](https://docs.microsoft.com/en-us/sql/relational-databases/databases/contained-databases) and that we do not create a login for the user; instead, we associate the password directly with the user itself. Also note that you will need a separate connection and role for each Azure SQL database for which you want to generate dynamic credentials. You can use a single database backend mount for all these databases or use a separate mount for each of them. In this example, we use a custom path for the database backend.
|
||||
Here is a complete example using Azure SQL Database. Note that databases in
|
||||
Azure SQL Database are [contained databases](https://docs.microsoft.com/en-us/sql/relational-databases/databases/contained-databases)
|
||||
and that we do not create a login for the user; instead, we associate the
|
||||
password directly with the user itself. Also note that you will need a separate
|
||||
connection and role for each Azure SQL database for which you want to generate
|
||||
dynamic credentials. You can use a single database backend mount for all these
|
||||
databases or use a separate mount for each of them. In this example, we use a
|
||||
custom path for the database backend.
|
||||
|
||||
<Note>
|
||||
Azure SQL databases may use different authentication mechanism that are configured on the SQL server. Vault only supports SQL authentication. Azure AD authentication is not supported.
|
||||
</Note>
|
||||
|
||||
First, we mount a database backend at the azuresql path with `vault secrets enable -path=azuresql database`. Then we configure a connection called "testvault" to connect to a database called "test-vault", using "azuresql" at the beginning of our path:
|
||||
First, we mount a database backend at the azuresql path with `vault secrets
|
||||
enable -path=azuresql database`. Then we configure a connection called
|
||||
"testvault" to connect to a database called "test-vault", using "azuresql" at
|
||||
the beginning of our path and set the `contained_db` field:
|
||||
|
||||
~> Note: If you are using a windows vault client with cmd.exe, change the single quotes to double quotes in the connection string. Windows cmd.exe does not interpret single quotes as a continous string
|
||||
|
||||
@ -129,6 +139,7 @@ First, we mount a database backend at the azuresql path with `vault secrets enab
|
||||
$ vault write azuresql/config/testvault \
|
||||
plugin_name=mssql-database-plugin \
|
||||
connection_url='server=hashisqlserver.database.windows.net;port=1433;user id=admin;password=pAssw0rd;database=test-vault;app name=vault;' \
|
||||
contained_db=true \
|
||||
allowed_roles="test"
|
||||
```
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user