Skip to content

Commit

Permalink
feat: Add server role module (#293)
Browse files Browse the repository at this point in the history
* feat: add login_role module

* feat: add tests

* Update login_role.ps1

* typos

* Update login_role.py

* Update main.yml

* Update login_role.ps1

* Update main.yml

* Update login_role.ps1

* chore: update version
  • Loading branch information
lowlydba authored Dec 16, 2024
1 parent 837012b commit 8ee35a3
Show file tree
Hide file tree
Showing 10 changed files with 309 additions and 1 deletion.
18 changes: 18 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,24 @@ lowlydba.sqlserver Release Notes

.. contents:: Topics

v2.5.0
======

Release Summary
---------------

New login_role module for managing server role members!

Minor Changes
-------------

- Add new `login_role` module to add/remove server roles for logins (https://github.com/lowlydba/lowlydba.sqlserver/pull/293).

New Modules
-----------

- login_role - Configures a login's server roles.

v2.4.0
======

Expand Down
12 changes: 12 additions & 0 deletions changelogs/changelog.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -544,3 +544,15 @@ releases:
name: user_role
namespace: ''
release_date: '2024-12-15'
2.5.0:
changes:
minor_changes:
- Add new `login_role` module to add/remove server roles for logins (https://github.com/lowlydba/lowlydba.sqlserver/pull/293).
release_summary: New login_role module for managing server role members!
fragments:
- 293-login-role-module.yml
modules:
- description: Configures a login's server roles.
name: login_role
namespace: ''
release_date: '2024-12-15'
2 changes: 1 addition & 1 deletion galaxy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace: lowlydba
name: sqlserver
version: 2.4.0
version: 2.5.0
readme: README.md
authors:
- John McCall (github.com/lowlydba)
Expand Down
113 changes: 113 additions & 0 deletions plugins/modules/login_role.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
#!powershell
# -*- coding: utf-8 -*-

# (c) 2022, John McCall (@lowlydba)
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

#AnsibleRequires -CSharpUtil Ansible.Basic
#AnsibleRequires -PowerShell ansible_collections.lowlydba.sqlserver.plugins.module_utils._SqlServerUtils
#Requires -Modules @{ ModuleName="dbatools"; ModuleVersion="2.0.0" }

$ErrorActionPreference = "Stop"

$spec = @{
supports_check_mode = $true
options = @{
login = @{type = 'str'; required = $true }
server_role = @{type = 'str'; required = $true }
state = @{type = 'str'; required = $false; default = 'present'; choices = @('present', 'absent') }
}
}

$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec, @(Get-LowlyDbaSqlServerAuthSpec))
$sqlInstance, $sqlCredential = Get-SqlCredential -Module $module
$login = $module.Params.login
$serverRole = $module.Params.server_role
$state = $module.Params.state
$checkMode = $module.CheckMode

$module.Result.changed = $false

$getLoginSplat = @{
SqlInstance = $sqlInstance
SqlCredential = $sqlCredential
Login = $login
EnableException = $true
}
$getRoleSplat = @{
SqlInstance = $sqlInstance
SqlCredential = $sqlCredential
ServerRole = $serverRole
EnableException = $true
}
$getRoleMemberSplat = @{
SqlInstance = $sqlInstance
SqlCredential = $sqlCredential
Login = $login
ServerRole = $serverRole
EnableException = $true
}

$existingLogin = Get-DbaLogin @getLoginSplat
if ($null -eq $existingLogin) {
$module.FailJson("Login [$login] does not exist.")
}
$existingRole = Get-DbaServerRole @getRoleSplat
if ($null -eq $existingRole) {
$module.FailJson("Server role [$serverRole] does not exist.")
}

# Get role member
$existingRoleMember = Get-DbaServerRoleMember @getRoleMemberSplat

if ($state -eq "absent") {
if ($null -ne $existingRoleMember) {
try {
$removeRoleMemberSplat = @{
SqlInstance = $sqlInstance
SqlCredential = $sqlCredential
Login = $login
ServerRole = $serverRole
EnableException = $true
WhatIf = $checkMode
Confirm = $false
}
$output = Remove-DbaServerRoleMember @removeRoleMemberSplat
$module.Result.changed = $true
}
catch {
$module.FailJson("Removing login [$login] from server role [$serverRole] failed: $($_.Exception.Message)", $_)
}
}
}
elseif ($state -eq "present") {
# Add user to role
if ($null -eq $existingRoleMember) {
try {
$addRoleMemberSplat = @{
SqlInstance = $sqlInstance
SqlCredential = $sqlCredential
Login = $login
ServerRole = $serverRole
EnableException = $true
WhatIf = $checkMode
Confirm = $false
}
$output = Add-DbaServerRoleMember @addRoleMemberSplat
$module.Result.changed = $true
}
catch {
$module.FailJson("Adding login [$login] to server role [$serverRole] failed: $($_.Exception.Message)", $_)
}
}
}
try {
if ($null -ne $output) {
$resultData = ConvertTo-SerializableObject -InputObject $output
$module.Result.data = $resultData
}
$module.ExitJson()
}
catch {
$module.FailJson("Failure: $($_.Exception.Message)", $_)
}
61 changes: 61 additions & 0 deletions plugins/modules/login_role.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-

# (c) 2022, John McCall (@lowlydba)
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

DOCUMENTATION = r'''
---
module: login_role
short_description: Configures a login's server roles.
description:
- Adds or removes a login's server role.
version_added: 2.5.0
options:
login:
description:
- Name of the login.
type: str
required: true
server_role:
description:
- The server role for the login to be modified.
type: str
required: true
author: "John McCall (@lowlydba)"
requirements:
- L(dbatools,https://www.powershellgallery.com/packages/dbatools/) PowerShell module
extends_documentation_fragment:
- lowlydba.sqlserver.sql_credentials
- lowlydba.sqlserver.attributes.check_mode
- lowlydba.sqlserver.attributes.platform_all
- lowlydba.sqlserver.state
'''

EXAMPLES = r'''
- name: Add a user to a fixed server role
lowlydba.sqlserver.login_role:
sql_instance: sql-01.myco.io
login: TheIntern
server_role: sysadmin
- name: Remove a user from a fixed server role
lowlydba.sqlserver.login_role:
sql_instance: sql-01.myco.io
login: TheIntern
server_role: sysadmin
state: absent
- name: Add a user to a custom server role
lowlydba.sqlserver.login_role:
sql_instance: sql-01.myco.io
login: TheIntern
server_role: demi-admin
'''

RETURN = r'''
data:
description: Output from the C(Remove-DbaServerRoleMember), (Get-DbaServerRoleMember), or C(Add-DbaServerRoleMember) functions.
returned: success, but not in check_mode.
type: dict
'''
2 changes: 2 additions & 0 deletions tests/integration/targets/login_role/aliases
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
context/target
setup/once/setup_sqlserver
3 changes: 3 additions & 0 deletions tests/integration/targets/login_role/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
dependencies:
- setup_sqlserver_test_plugins
91 changes: 91 additions & 0 deletions tests/integration/targets/login_role/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
---
- name: Var block
vars:
login_name: "PhillipJFryDeuce"
plain_password: "P0pS3cret!23$%"
password_expiration_enabled: false
password_policy_enforced: false
password_must_change: false
enabled: false
default_database: "master"
language: "us_english"
default_schema: "dbo"
database: "master"
server_role: "dbcreator"
module_defaults:
lowlydba.sqlserver.login:
sql_instance: "{{ sqlserver_instance }}"
sql_username: "{{ sqlserver_username }}"
sql_password: "{{ sqlserver_password }}"
default_database: "{{ default_database }}"
login: "{{ login_name }}"
password: "{{ plain_password }}"
password_expiration_enabled: "{{ password_expiration_enabled }}"
password_must_change: "{{ password_must_change }}"
enabled: "{{ enabled }}"
language: "{{ language }}"
state: present
lowlydba.sqlserver.login_role:
sql_instance: "{{ sqlserver_instance }}"
sql_username: "{{ sqlserver_username }}"
sql_password: "{{ sqlserver_password }}"
server_role: "{{ server_role }}"
login: "{{ login_name }}"
state: present
tags: ["sqlserver.user"]
block:
- name: Create login
lowlydba.sqlserver.login:
register: result
- assert:
that:
- result.data != None

- name: Add login to server role
lowlydba.sqlserver.login_role:
register: result
- assert:
that:
- result is changed

- name: Add login to non-existent server role
lowlydba.sqlserver.login_role:
server_role: IMadeThisOneUp
register: error_result
failed_when: error_result.failed
ignore_errors: true
- assert:
that:
- error_result.failed == true
- "'Server role [IMadeThisOneUp] does not exist' in error_result.msg"

- name: Add non-existent login to server role
lowlydba.sqlserver.login_role:
login: NewUserWhoThis
register: error_result
failed_when: error_result.failed
ignore_errors: true
- assert:
that:
- error_result.failed == true
- "'Login [NewUserWhoThis] does not exist' in error_result.msg"

- name: Add Login again to database role
lowlydba.sqlserver.login_role:
register: result
- assert:
that:
- result is not changed

- name: Remove login from server role
lowlydba.sqlserver.login_role:
state: "absent"
register: result
- assert:
that:
- result is changed

always:
- name: Drop login
lowlydba.sqlserver.login:
state: "absent"
5 changes: 5 additions & 0 deletions tests/integration/targets/win_login_role/aliases
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
windows/all
windows/group/2
context/target
setup/once/setup_win_sqlserver
needs/target/login_role
3 changes: 3 additions & 0 deletions tests/integration/targets/win_login_role/meta/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
dependencies:
- login_role

0 comments on commit 8ee35a3

Please sign in to comment.