mssql
This tool automates the creation of SQL Server database users with secure password management through Google Cloud Secret Manager. It uses a state machine pattern to ensure reliable, atomic operations for user provisioning and permission assignment.
Features
- ✅ Automated SQL Server user creation
- 🗑️ Safe user deletion with secret cleanup
- 🔄 Password rotation for existing users
- 🔐 Secure password generation and storage in GCP Secret Manager
- 🔑 Granular permission management (Read, ReadWrite, ReadWriteExecute)
- 🔄 State machine-based execution for reliability
Build
./zig/zig build mssqlUsage
Basic Command Structure
Create User
./mssql user create [username] \
--server [SQL_SERVER] \
--database [DATABASE_NAME] \
--environment [ENVIRONMENT] \
--permissions [PERMISSION_LEVEL]Delete User
./mssql user delete [username] \
--server [SQL_SERVER] \
--database [DATABASE_NAME] \
--environment [ENVIRONMENT]Rotate Password
./mssql user rotate-password [username] \
--server [SQL_SERVER] \
--database [DATABASE_NAME] \
--environment [ENVIRONMENT]Parameters
| Flag | Short | Required | Description |
|---|---|---|---|
--server |
-s |
✅ | SQL Server instance hostname |
--database |
-d |
⚠️ | Target database name (required unless --all-databases
is used) |
--all-databases |
-a |
⚠️ | Apply operation to all user databases on server (create only) |
--environment |
-e |
✅ | Environment: dev, staging, or
production (selects GCP secrets project) |
--permissions |
-p |
❌ | Permission level: r, rw, or
rwx (default: r) |
--verbose |
-v |
❌ | Enable debug logging |
Note: Either
--databaseor--all-databasesmust be specified for thecreatecommand, but not both.
Permission Levels
| Level | Description | SQL Server Roles |
|---|---|---|
r |
Read-only access | db_datareader |
rw |
Read and write access | db_datareader, db_datawriter |
rwx |
Read, write, and execute access | db_datareader, db_datawriter,
EXECUTE |
Examples
Create User Examples
# Create read-only user
./mssql user create app_readonly_user \
--server myserver.database.windows.net \
--database myapp_db \
--environment staging
# Create read-write user with verbose logging
./mssql user create app_service_user \
--server myserver.database.windows.net \
--database myapp_db \
--environment production \
--permissions rw \
--verbose
# Create user with full permissions
./mssql user create admin_user \
--server myserver.database.windows.net \
--database myapp_db \
--environment dev \
--permissions rwx
# Create user on ALL databases at once
./mssql user create app_service_user \
--server myserver.database.windows.net \
--all-databases \
--environment production \
--permissions rwDelete User Examples
# Delete user and associated secrets
./mssql user delete app_readonly_user \
--server myserver.database.windows.net \
--database myapp_db \
--environment staging
# Delete user with verbose logging
./mssql user delete old_service_user \
--server myserver.database.windows.net \
--database myapp_db \
--environment production \
--verboseRotate Password Examples
# Rotate password for existing user
./mssql user rotate-password app_service_user \
--server myserver.database.windows.net \
--database myapp_db \
--environment production
# Rotate password with verbose logging
./mssql user rotate-password admin_user \
--server myserver.database.windows.net \
--database myapp_db \
--environment dev \
--verboseServices
CreateUser
The CreateUser service handles the complete lifecycle of
creating a new SQL Server database user with secure password
management.
State Functions
- checkSqlUserExists: Verifies if the user already exists in the database
- createGcpSecret: Manages password creation/retrieval from GCP Secret Manager
- createDatabaseUser: Creates the SQL Server login and database user
- setUserPermissions: Assigns appropriate database permissions
graph TD
A[Start: checkSqlUserExists] --> B{User exists in DB?}
B -->|Yes| G[setUserPermissions]
B -->|No| C[createGcpSecret]
C --> D{Secret exists in GCP?}
D -->|Yes| E{Secret has value?}
D -->|No| F[Create new secret]
E -->|Yes| H[Use existing password]
E -->|No| I[Create new version]
F --> J[createDatabaseUser]
H --> J
I --> J
J --> K{User created successfully?}
K -->|Yes| G
K -->|No, already exists| G
K -->|Error| L[Return Error]
G --> M{Permissions set?}
M -->|Yes| N[Success: End]
M -->|No| L
style A fill:#1565c0,color:#fff
style N fill:#2e7d32,color:#fff
style L fill:#c62828,color:#fff
DeleteUser
The DeleteUser service handles the complete lifecycle of
deleting an existing SQL Server database user and cleaning up associated
password secrets from GCP Secret Manager.
State Functions
- checkSqlUserExistsDelete: Verifies if the user exists in the database
- deleteUserFromDatabase: Removes the user from the SQL Server database
- checkPasswordSecretExists: Checks if the password secret exists in GCP Secret Manager
- deletePasswordSecret: Removes the password secret from GCP (best-effort cleanup)
graph TD
A[Start: checkSqlUserExistsDelete] --> B{User exists in DB?}
B -->|No| C[Check for orphaned secrets]
B -->|Yes| D[deleteUserFromDatabase]
D --> E{User deleted successfully?}
E -->|No| L[Return Error]
E -->|Yes| F[checkPasswordSecretExists]
C --> F
F --> G{Secret exists in GCP?}
G -->|No| H[Success: End - No cleanup needed]
G -->|Error checking| I[Log warning, End - DB cleanup succeeded]
G -->|Yes| J[deletePasswordSecret]
J --> K{Secret deleted successfully?}
K -->|No| I
K -->|Yes| N[Success: End - Complete cleanup]
style A fill:#1565c0,color:#fff
style H fill:#2e7d32,color:#fff
style N fill:#2e7d32,color:#fff
style I fill:#e65100,color:#fff
style L fill:#c62828,color:#fff
RotatePassword
The RotatePassword service handles the complete
lifecycle of rotating passwords for existing SQL Server database users
with secure password management and rollback capabilities.
State Functions
- checkSqlUserExistsRotate: Verifies the target user exists in the database
- checkPasswordSecret: Validates the existing password secret in GCP Secret Manager
- createPasswordVersionRotate: Generates a new password and creates a new secret version
- updateUserPassword: Updates the database user password with rollback on failure
- cleanupOldVersions: Destroys old password versions, keeping only the latest
graph TD
A[Start: checkSqlUserExistsRotate] --> B{User exists in DB?}
B -->|No| L[Return Error: User not found]
B -->|Yes| C[checkPasswordSecret]
C --> D{Secret exists in GCP?}
D -->|No| M[Return Error: Secret not found]
D -->|Yes| E{Latest version accessible?}
E -->|No| F[Set OldPassword = empty]
E -->|Yes| G[Set OldPassword = current]
F --> H[createPasswordVersionRotate]
G --> H
H --> I[Generate new password]
I --> J[Create new secret version]
J --> K[updateUserPassword]
K --> N{DB update successful?}
N -->|No| O[Rollback: Delete new secret version]
N -->|Yes| P[cleanupOldVersions]
O --> L
P --> Q[List all secret versions]
Q --> R[Sort versions numerically]
R --> S[Destroy all except latest]
S --> T[Success: End]
style A fill:#1565c0,color:#fff
style T fill:#2e7d32,color:#fff
style L fill:#c62828,color:#fff
style O fill:#e65100,color:#fff
Testing
The tool includes comprehensive test coverage with mock implementations:
# Run all tests
go test ./...Make tool accessible from anywhere in your terminal
# build
./zig/zig build mssql
# move
sudo mv ./mssql /usr/local/bin/mssql
# now accessible globally
which mssql