Fix MSSQL Default Revocation to use Least Privilege Metadata Query (#13528) (#14328)

* Fix mssql lease revocation

* Add changelog

* Update comments

Co-authored-by: sachin-chand01 <sachin.chand@hashicorp.com>
This commit is contained in:
Vault Automation 2026-04-29 11:11:23 -06:00 committed by GitHub
parent 57d45e4981
commit 58656a160c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 24 additions and 6 deletions

3
changelog/_13528.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
database/mssql: Fix "sysadmin" requirement during lease revocation by replacing the undocumented `sp_msloginmappings` procedure with a granular metadata query. This allows the plugin to function with `VIEW ANY DEFINITION` instead of full `sysadmin` privileges.
```

View File

@ -272,12 +272,17 @@ func (m *MSSQL) revokeUserDefault(ctx context.Context, username string) error {
revokeStmts = append(revokeStmts, fmt.Sprintf("KILL %d;", sessionID))
}
// Query for database users using undocumented stored procedure for now since
// it is the easiest way to get this information;
// we need to drop the database users before we can drop the login and the role
// This isn't done in a transaction because even if we fail along the way,
// we want to remove as much access as possible
stmt, err := db.PrepareContext(ctx, "EXEC master.dbo.sp_msloginmappings @p1;")
// selectUserSQL identifies database-level users associated with a server login.
// We use a join on sys.server_principals and sys.database_principals instead
// of the undocumented sp_msloginmappings procedure. This allows revocation
// to function with 'VIEW ANY DEFINITION' instead of 'sysadmin' privileges,
// supporting "Least Privilege" security models.
//
// Note: This identifies users within the current database context. We must
// drop these database users before the server-level login can be removed.
// We execute this outside of a transaction to ensure we revoke as much
// access as possible, even if a single DROP statement fails.
stmt, err := db.PrepareContext(ctx, selectUserSQL)
if err != nil {
return err
}
@ -443,3 +448,13 @@ ALTER LOGIN [{{username}}] WITH PASSWORD = '{{password}}'
const alterUserContainedSQL = `
ALTER USER [{{username}}] WITH PASSWORD = '{{password}}'
`
const selectUserSQL = ` SELECT
l.name AS LoginName,
DB_NAME() AS DBName,
u.name AS UserName,
'Member' AS UserOrAlias
FROM sys.server_principals l
JOIN sys.database_principals u ON l.sid = u.sid
WHERE l.name = @p1;
`