mirror of https://github.com/ansible/ansible.git
Add modules to manage Remote Desktop Services (#43406)
* Add windows module win_rds_settings * Add windows module win_rds_rap * Add windows module win_rds_cap * Add tests for module win_rds_settings * Add tests for module win_rds_rap * Add tests for module win_rds_cap * Validate user and computer groups in module win_rds_cap * Validate user groups in module win_rds_rap * Support additional formats (UPN, Down-Level Login Name, SID and Login Name) for user and computer group names in module win_rds_cap * Support additional formats (UPN, Down-Level Login Name, SID and Login Name) for user group names in module win_rds_rap * Validate computer group parameter and support additional formats (UPN, Down-Level Login Name, SID and Login Name) in module win_rds_rap * Validate allowed ports parameter in module win_rds_rap * Ensure user group list is not empty in module win_rds_rap * Remove unwanted value in result object * Ensure user group list is not empty in module win_rds_cap * Ensure order parameter value never exceed the number of existing CAPs in module win_rds_cap * Add diff mode support to win_rds_cap * Add diff mode support to win_rds_rap * Add diff mode support to win_rds_settings * Add SSL bridging and messaging policy settings to module win_rds_settings * Fix copyright [skip ci] * Add missing trailing dots in documentation [skip ci] * Fix incorrect variable passed to Fail-Json * Minor changes and doc update * Avoid using Powershell aliases * Use WMI instead of PSProvider to handle group names to avoid conversion in UPN form * Use CIM instead of WMI cmdletspull/49005/head
parent
27dc399885
commit
5d15a539c7
@ -0,0 +1,357 @@
|
|||||||
|
#!powershell
|
||||||
|
|
||||||
|
# Copyright: (c) 2018, Kevin Subileau (@ksubileau)
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
#Requires -Module Ansible.ModuleUtils.Legacy
|
||||||
|
#Requires -Module Ansible.ModuleUtils.SID
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
# List of authentication methods as string. Used for parameter validation and conversion to integer flag, so order is important!
|
||||||
|
$auth_methods_set = @("none", "password", "smartcard", "both")
|
||||||
|
# List of session timeout actions as string. Used for parameter validation and conversion to integer flag, so order is important!
|
||||||
|
$session_timeout_actions_set = @("disconnect", "reauth")
|
||||||
|
|
||||||
|
$params = Parse-Args -arguments $args -supports_check_mode $true
|
||||||
|
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
|
||||||
|
$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
|
||||||
|
|
||||||
|
$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true
|
||||||
|
$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "absent","present","enabled","disabled"
|
||||||
|
$auth_method = Get-AnsibleParam -obj $params -name "auth_method" -type "str" -validateset $auth_methods_set
|
||||||
|
$order = Get-AnsibleParam -obj $params -name "order" -type "int"
|
||||||
|
$session_timeout = Get-AnsibleParam -obj $params -name "session_timeout" -type "int"
|
||||||
|
$session_timeout_action = Get-AnsibleParam -obj $params -name "session_timeout_action" -type "str" -default "disconnect" -validateset $session_timeout_actions_set
|
||||||
|
$idle_timeout = Get-AnsibleParam -obj $params -name "idle_timeout" -type "int"
|
||||||
|
$allow_only_sdrts_servers = Get-AnsibleParam -obj $params -name "allow_only_sdrts_servers" -type "bool"
|
||||||
|
$user_groups = Get-AnsibleParam -obj $params -name "user_groups" -type "list"
|
||||||
|
$computer_groups = Get-AnsibleParam -obj $params -name "computer_groups" -type "list"
|
||||||
|
|
||||||
|
# Device redirections
|
||||||
|
$redirect_clipboard = Get-AnsibleParam -obj $params -name "redirect_clipboard" -type "bool"
|
||||||
|
$redirect_drives = Get-AnsibleParam -obj $params -name "redirect_drives" -type "bool"
|
||||||
|
$redirect_printers = Get-AnsibleParam -obj $params -name "redirect_printers" -type "bool"
|
||||||
|
$redirect_serial = Get-AnsibleParam -obj $params -name "redirect_serial" -type "bool"
|
||||||
|
$redirect_pnp = Get-AnsibleParam -obj $params -name "redirect_pnp" -type "bool"
|
||||||
|
|
||||||
|
|
||||||
|
function Get-CAP([string] $name) {
|
||||||
|
$cap_path = "RDS:\GatewayServer\CAP\$name"
|
||||||
|
$cap = @{
|
||||||
|
Name = $name
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch CAP properties
|
||||||
|
Get-ChildItem -Path $cap_path | ForEach-Object { $cap.Add($_.Name,$_.CurrentValue) }
|
||||||
|
# Convert boolean values
|
||||||
|
$cap.Enabled = $cap.Status -eq 1
|
||||||
|
$cap.Remove("Status")
|
||||||
|
$cap.AllowOnlySDRTSServers = $cap.AllowOnlySDRTSServers -eq 1
|
||||||
|
|
||||||
|
# Convert multiple choices values
|
||||||
|
$cap.AuthMethod = $auth_methods_set[$cap.AuthMethod]
|
||||||
|
$cap.SessionTimeoutAction = $session_timeout_actions_set[$cap.SessionTimeoutAction]
|
||||||
|
|
||||||
|
# Fetch CAP device redirection settings
|
||||||
|
$cap.DeviceRedirection = @{}
|
||||||
|
Get-ChildItem -Path "$cap_path\DeviceRedirection" | ForEach-Object { $cap.DeviceRedirection.Add($_.Name, ($_.CurrentValue -eq 1)) }
|
||||||
|
|
||||||
|
# Fetch CAP user and computer groups in Down-Level Logon format
|
||||||
|
$cap.UserGroups = @(
|
||||||
|
Get-ChildItem -Path "$cap_path\UserGroups" |
|
||||||
|
Select-Object -ExpandProperty Name |
|
||||||
|
ForEach-Object { Convert-FromSID -sid (Convert-ToSID -account_name $_) }
|
||||||
|
)
|
||||||
|
$cap.ComputerGroups = @(
|
||||||
|
Get-ChildItem -Path "$cap_path\ComputerGroups" |
|
||||||
|
Select-Object -ExpandProperty Name |
|
||||||
|
ForEach-Object { Convert-FromSID -sid (Convert-ToSID -account_name $_) }
|
||||||
|
)
|
||||||
|
|
||||||
|
return $cap
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-CAPPropertyValue {
|
||||||
|
[CmdletBinding(SupportsShouldProcess=$true)]
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string] $name,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string] $property,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
$value,
|
||||||
|
[Parameter()]
|
||||||
|
$resultobj = @{}
|
||||||
|
)
|
||||||
|
|
||||||
|
$cap_path = "RDS:\GatewayServer\CAP\$name"
|
||||||
|
|
||||||
|
try {
|
||||||
|
Set-Item -Path "$cap_path\$property" -Value $value -ErrorAction Stop
|
||||||
|
} catch {
|
||||||
|
Fail-Json -obj $resultobj -message "Failed to set property $property of CAP ${name}: $($_.Exception.Message)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = @{
|
||||||
|
changed = $false
|
||||||
|
}
|
||||||
|
$diff_text = $null
|
||||||
|
|
||||||
|
# Validate CAP name
|
||||||
|
if ($name -match "[*/\\;:?`"<>|\t]+") {
|
||||||
|
Fail-Json -obj $result -message "Invalid character in CAP name."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validate user groups
|
||||||
|
if ($null -ne $user_groups) {
|
||||||
|
if ($user_groups.Count -lt 1) {
|
||||||
|
Fail-Json -obj $result -message "Parameter 'user_groups' cannot be an empty list."
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_groups = $user_groups | ForEach-Object {
|
||||||
|
$group = $_
|
||||||
|
# Test that the group is resolvable on the local machine
|
||||||
|
$sid = Convert-ToSID -account_name $group
|
||||||
|
if (!$sid) {
|
||||||
|
Fail-Json -obj $result -message "$group is not a valid user group on the host machine or domain"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Return the normalized group name in Down-Level Logon format
|
||||||
|
Convert-FromSID -sid $sid
|
||||||
|
}
|
||||||
|
$user_groups = @($user_groups)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validate computer groups
|
||||||
|
if ($null -ne $computer_groups) {
|
||||||
|
$computer_groups = $computer_groups | ForEach-Object {
|
||||||
|
$group = $_
|
||||||
|
# Test that the group is resolvable on the local machine
|
||||||
|
$sid = Convert-ToSID -account_name $group
|
||||||
|
if (!$sid) {
|
||||||
|
Fail-Json -obj $result -message "$group is not a valid computer group on the host machine or domain"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Return the normalized group name in Down-Level Logon format
|
||||||
|
Convert-FromSID -sid $sid
|
||||||
|
}
|
||||||
|
$computer_groups = @($computer_groups)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validate order parameter
|
||||||
|
if ($null -ne $order -and $order -lt 1) {
|
||||||
|
Fail-Json -obj $result -message "Parameter 'order' must be a strictly positive integer."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure RemoteDesktopServices module is loaded
|
||||||
|
if ((Get-Module -Name RemoteDesktopServices -ErrorAction SilentlyContinue) -eq $null) {
|
||||||
|
Import-Module -Name RemoteDesktopServices
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if a CAP with the given name already exists
|
||||||
|
$cap_exist = Test-Path -Path "RDS:\GatewayServer\CAP\$name"
|
||||||
|
|
||||||
|
if ($state -eq 'absent') {
|
||||||
|
if ($cap_exist) {
|
||||||
|
Remove-Item -Path "RDS:\GatewayServer\CAP\$name" -Recurse -WhatIf:$check_mode
|
||||||
|
$diff_text += "-[$name]"
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$diff_text_added_prefix = ''
|
||||||
|
if (-not $cap_exist) {
|
||||||
|
if ($null -eq $user_groups) {
|
||||||
|
Fail-Json -obj $result -message "User groups must be defined to create a new CAP."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Auth method is required when creating a new CAP. Set it to password by default.
|
||||||
|
if ($null -eq $auth_method) {
|
||||||
|
$auth_method = "password"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a new CAP
|
||||||
|
if (-not $check_mode) {
|
||||||
|
$CapArgs = @{
|
||||||
|
Name = $name
|
||||||
|
UserGroupNames = $user_groups -join ';'
|
||||||
|
}
|
||||||
|
$return = Invoke-CimMethod -Namespace Root\CIMV2\TerminalServices -ClassName Win32_TSGatewayConnectionAuthorizationPolicy -MethodName Create -Arguments $CapArgs
|
||||||
|
if ($return.ReturnValue -ne 0) {
|
||||||
|
Fail-Json -obj $result -message "Failed to create CAP $name (code: $($return.ReturnValue))"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$cap_exist = -not $check_mode
|
||||||
|
|
||||||
|
$diff_text_added_prefix = '+'
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
$diff_text += "$diff_text_added_prefix[$name]`n"
|
||||||
|
|
||||||
|
# We cannot configure a CAP that was created above in check mode as it won't actually exist
|
||||||
|
if($cap_exist) {
|
||||||
|
$cap = Get-CAP -Name $name
|
||||||
|
$wmi_cap = Get-CimInstance -ClassName Win32_TSGatewayConnectionAuthorizationPolicy -Namespace Root\CIMv2\TerminalServices -Filter "name='$($name)'"
|
||||||
|
|
||||||
|
if ($state -in @('disabled', 'enabled')) {
|
||||||
|
$cap_enabled = $state -ne 'disabled'
|
||||||
|
if ($cap.Enabled -ne $cap_enabled) {
|
||||||
|
$diff_text += "-State = $(@('disabled', 'enabled')[[int]$cap.Enabled])`n+State = $state`n"
|
||||||
|
Set-CAPPropertyValue -Name $name -Property Status -Value ([int]$cap_enabled) -ResultObj $result -WhatIf:$check_mode
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $auth_method -and $auth_method -ne $cap.AuthMethod) {
|
||||||
|
$diff_text += "-AuthMethod = $($cap.AuthMethod)`n+AuthMethod = $auth_method`n"
|
||||||
|
Set-CAPPropertyValue -Name $name -Property AuthMethod -Value ([array]::IndexOf($auth_methods_set, $auth_method)) -ResultObj $result -WhatIf:$check_mode
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $order -and $order -ne $cap.EvaluationOrder) {
|
||||||
|
# Order cannot be greater than the total number of existing CAPs (InvalidArgument exception)
|
||||||
|
$cap_count = (Get-ChildItem -Path "RDS:\GatewayServer\CAP").Count
|
||||||
|
if($order -gt $cap_count) {
|
||||||
|
Add-Warning -obj $result -message "Given value '$order' for parameter 'order' is greater than the number of existing CAPs. The actual order will be capped to '$cap_count'."
|
||||||
|
$order = $cap_count
|
||||||
|
}
|
||||||
|
|
||||||
|
$diff_text += "-Order = $($cap.EvaluationOrder)`n+Order = $order`n"
|
||||||
|
Set-CAPPropertyValue -Name $name -Property EvaluationOrder -Value $order -ResultObj $result -WhatIf:$check_mode
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $session_timeout -and ($session_timeout -ne $cap.SessionTimeout -or $session_timeout_action -ne $cap.SessionTimeoutAction)) {
|
||||||
|
try {
|
||||||
|
Set-Item -Path "RDS:\GatewayServer\CAP\$name\SessionTimeout" `
|
||||||
|
-Value $session_timeout `
|
||||||
|
-SessionTimeoutAction ([array]::IndexOf($session_timeout_actions_set, $session_timeout_action)) `
|
||||||
|
-ErrorAction Stop `
|
||||||
|
-WhatIf:$check_mode
|
||||||
|
} catch {
|
||||||
|
Fail-Json -obj $result -message "Failed to set property ComputerGroupType of RAP ${name}: $($_.Exception.Message)"
|
||||||
|
}
|
||||||
|
|
||||||
|
$diff_text += "-SessionTimeoutAction = $($cap.SessionTimeoutAction)`n+SessionTimeoutAction = $session_timeout_action`n"
|
||||||
|
$diff_text += "-SessionTimeout = $($cap.SessionTimeout)`n+SessionTimeout = $session_timeout`n"
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $idle_timeout -and $idle_timeout -ne $cap.IdleTimeout) {
|
||||||
|
$diff_text += "-IdleTimeout = $($cap.IdleTimeout)`n+IdleTimeout = $idle_timeout`n"
|
||||||
|
Set-CAPPropertyValue -Name $name -Property IdleTimeout -Value $idle_timeout -ResultObj $result -WhatIf:$check_mode
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $allow_only_sdrts_servers -and $allow_only_sdrts_servers -ne $cap.AllowOnlySDRTSServers) {
|
||||||
|
$diff_text += "-AllowOnlySDRTSServers = $($cap.AllowOnlySDRTSServers)`n+AllowOnlySDRTSServers = $allow_only_sdrts_servers`n"
|
||||||
|
Set-CAPPropertyValue -Name $name -Property AllowOnlySDRTSServers -Value ([int]$allow_only_sdrts_servers) -ResultObj $result -WhatIf:$check_mode
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $redirect_clipboard -and $redirect_clipboard -ne $cap.DeviceRedirection.Clipboard) {
|
||||||
|
$diff_text += "-RedirectClipboard = $($cap.DeviceRedirection.Clipboard)`n+RedirectClipboard = $redirect_clipboard`n"
|
||||||
|
Set-CAPPropertyValue -Name $name -Property "DeviceRedirection\Clipboard" -Value ([int]$redirect_clipboard) -ResultObj $result -WhatIf:$check_mode
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $redirect_drives -and $redirect_drives -ne $cap.DeviceRedirection.DiskDrives) {
|
||||||
|
$diff_text += "-RedirectDrives = $($cap.DeviceRedirection.DiskDrives)`n+RedirectDrives = $redirect_drives`n"
|
||||||
|
Set-CAPPropertyValue -Name $name -Property "DeviceRedirection\DiskDrives" -Value ([int]$redirect_drives) -ResultObj $result -WhatIf:$check_mode
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $redirect_printers -and $redirect_printers -ne $cap.DeviceRedirection.Printers) {
|
||||||
|
$diff_text += "-RedirectPrinters = $($cap.DeviceRedirection.Printers)`n+RedirectPrinters = $redirect_printers`n"
|
||||||
|
Set-CAPPropertyValue -Name $name -Property "DeviceRedirection\Printers" -Value ([int]$redirect_printers) -ResultObj $result -WhatIf:$check_mode
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $redirect_serial -and $redirect_serial -ne $cap.DeviceRedirection.SerialPorts) {
|
||||||
|
$diff_text += "-RedirectSerial = $($cap.DeviceRedirection.SerialPorts)`n+RedirectSerial = $redirect_serial`n"
|
||||||
|
Set-CAPPropertyValue -Name $name -Property "DeviceRedirection\SerialPorts" -Value ([int]$redirect_serial) -ResultObj $result -WhatIf:$check_mode
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $redirect_pnp -and $redirect_pnp -ne $cap.DeviceRedirection.PlugAndPlayDevices) {
|
||||||
|
$diff_text += "-RedirectPnP = $($cap.DeviceRedirection.PlugAndPlayDevices)`n+RedirectPnP = $redirect_pnp`n"
|
||||||
|
Set-CAPPropertyValue -Name $name -Property "DeviceRedirection\PlugAndPlayDevices" -Value ([int]$redirect_pnp) -ResultObj $result -WhatIf:$check_mode
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $user_groups) {
|
||||||
|
$groups_to_remove = @($cap.UserGroups | Where-Object { $user_groups -notcontains $_ })
|
||||||
|
$groups_to_add = @($user_groups | Where-Object { $cap.UserGroups -notcontains $_ })
|
||||||
|
|
||||||
|
$user_groups_diff = $null
|
||||||
|
foreach($group in $groups_to_add) {
|
||||||
|
if (-not $check_mode) {
|
||||||
|
$return = $wmi_cap | Invoke-CimMethod -MethodName AddUserGroupNames -Arguments @{ UserGroupNames = $group }
|
||||||
|
if ($return.ReturnValue -ne 0) {
|
||||||
|
Fail-Json -obj $result -message "Failed to add user group $($group) (code: $($return.ReturnValue))"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$user_groups_diff += " +$group`n"
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($group in $groups_to_remove) {
|
||||||
|
if (-not $check_mode) {
|
||||||
|
$return = $wmi_cap | Invoke-CimMethod -MethodName RemoveUserGroupNames -Arguments @{ UserGroupNames = $group }
|
||||||
|
if ($return.ReturnValue -ne 0) {
|
||||||
|
Fail-Json -obj $result -message "Failed to remove user group $($group) (code: $($return.ReturnValue))"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$user_groups_diff += " -$group`n"
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if($user_groups_diff) {
|
||||||
|
$diff_text += "~UserGroups`n$user_groups_diff"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $computer_groups) {
|
||||||
|
$groups_to_remove = @($cap.ComputerGroups | Where-Object { $computer_groups -notcontains $_ })
|
||||||
|
$groups_to_add = @($computer_groups | Where-Object { $cap.ComputerGroups -notcontains $_ })
|
||||||
|
|
||||||
|
$computer_groups_diff = $null
|
||||||
|
foreach($group in $groups_to_add) {
|
||||||
|
if (-not $check_mode) {
|
||||||
|
$return = $wmi_cap | Invoke-CimMethod -MethodName AddComputerGroupNames -Arguments @{ ComputerGroupNames = $group }
|
||||||
|
if ($return.ReturnValue -ne 0) {
|
||||||
|
Fail-Json -obj $result -message "Failed to add computer group $($group) (code: $($return.ReturnValue))"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$computer_groups_diff += " +$group`n"
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($group in $groups_to_remove) {
|
||||||
|
if (-not $check_mode) {
|
||||||
|
$return = $wmi_cap | Invoke-CimMethod -MethodName RemoveComputerGroupNames -Arguments @{ ComputerGroupNames = $group }
|
||||||
|
if ($return.ReturnValue -ne 0) {
|
||||||
|
Fail-Json -obj $result -message "Failed to remove computer group $($group) (code: $($return.ReturnValue))"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$computer_groups_diff += " -$group`n"
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if($computer_groups_diff) {
|
||||||
|
$diff_text += "~ComputerGroups`n$computer_groups_diff"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($diff_mode -and $result.changed -eq $true) {
|
||||||
|
$result.diff = @{
|
||||||
|
prepared = $diff_text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Exit-Json $result
|
@ -0,0 +1,123 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright: (c) 2018, Kevin Subileau (@ksubileau)
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||||
|
'status': ['preview'],
|
||||||
|
'supported_by': 'community'}
|
||||||
|
|
||||||
|
DOCUMENTATION = r'''
|
||||||
|
---
|
||||||
|
module: win_rds_cap
|
||||||
|
short_description: Manage Connection Authorization Policies (CAP) on a Remote Desktop Gateway server
|
||||||
|
description:
|
||||||
|
- Creates, removes and configures a Remote Desktop connection authorization policy (RD CAP).
|
||||||
|
- A RD CAP allows you to specify the users who can connect to a Remote Desktop Gateway server.
|
||||||
|
version_added: "2.8"
|
||||||
|
author:
|
||||||
|
- Kevin Subileau (@ksubileau)
|
||||||
|
options:
|
||||||
|
name:
|
||||||
|
description:
|
||||||
|
- Name of the connection authorization policy.
|
||||||
|
required: yes
|
||||||
|
state:
|
||||||
|
description:
|
||||||
|
- The state of connection authorization policy.
|
||||||
|
- If C(absent) will ensure the policy is removed.
|
||||||
|
- If C(present) will ensure the policy is configured and exists.
|
||||||
|
- If C(enabled) will ensure the policy is configured, exists and enabled.
|
||||||
|
- If C(disabled) will ensure the policy is configured, exists, but disabled.
|
||||||
|
choices: [ absent, present, enabled, disabled ]
|
||||||
|
default: present
|
||||||
|
auth_method:
|
||||||
|
description:
|
||||||
|
- Specifies how the RD Gateway server authenticates users.
|
||||||
|
- When a new CAP is created, the default value is C(password).
|
||||||
|
choices: [ password, smartcard, both, none ]
|
||||||
|
order:
|
||||||
|
description:
|
||||||
|
- Evaluation order of the policy.
|
||||||
|
- The CAP in which I(order) is set to a value of '1' is evaluated first.
|
||||||
|
- By default, a newly created CAP will take the first position.
|
||||||
|
- If the given value exceed the total number of existing policies,
|
||||||
|
the policy will take the last position but the evaluation order
|
||||||
|
will be capped to this number.
|
||||||
|
type: int
|
||||||
|
session_timeout:
|
||||||
|
description:
|
||||||
|
- The maximum time, in minutes, that a session can be idle.
|
||||||
|
- A value of zero disables session timeout.
|
||||||
|
type: int
|
||||||
|
session_timeout_action:
|
||||||
|
description:
|
||||||
|
- The action the server takes when a session times out.
|
||||||
|
- 'C(disconnect): disconnect the session.'
|
||||||
|
- 'C(reauth): silently reauthenticate and reauthorize the session.'
|
||||||
|
choices: [ disconnect, reauth ]
|
||||||
|
default: disconnect
|
||||||
|
idle_timeout:
|
||||||
|
description:
|
||||||
|
- Specifies the time interval, in minutes, after which an idle session is disconnected.
|
||||||
|
- A value of zero disables idle timeout.
|
||||||
|
type: int
|
||||||
|
allow_only_sdrts_servers:
|
||||||
|
description:
|
||||||
|
- Specifies whether connections are allowed only to Remote Desktop Session Host servers that
|
||||||
|
enforce Remote Desktop Gateway redirection policy.
|
||||||
|
type: bool
|
||||||
|
user_groups:
|
||||||
|
description:
|
||||||
|
- A list of user groups that is allowed to connect to the Remote Gateway server.
|
||||||
|
- Required when a new CAP is created.
|
||||||
|
type: list
|
||||||
|
computer_groups:
|
||||||
|
description:
|
||||||
|
- A list of computer groups that is allowed to connect to the Remote Gateway server.
|
||||||
|
type: list
|
||||||
|
redirect_clipboard:
|
||||||
|
description:
|
||||||
|
- Allow clipboard redirection.
|
||||||
|
type: bool
|
||||||
|
redirect_drives:
|
||||||
|
description:
|
||||||
|
- Allow disk drive redirection.
|
||||||
|
type: bool
|
||||||
|
redirect_printers:
|
||||||
|
description:
|
||||||
|
- Allow printers redirection.
|
||||||
|
type: bool
|
||||||
|
redirect_serial:
|
||||||
|
description:
|
||||||
|
- Allow serial port redirection.
|
||||||
|
type: bool
|
||||||
|
redirect_pnp:
|
||||||
|
description:
|
||||||
|
- Allow Plug and Play devices redirection.
|
||||||
|
type: bool
|
||||||
|
requirements:
|
||||||
|
- Windows Server 2008R2 (6.1) or higher.
|
||||||
|
- The Windows Feature "RDS-Gateway" must be enabled.
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = r'''
|
||||||
|
- name: Create a new RDS CAP with a 30 minutes timeout and clipboard redirection enabled
|
||||||
|
win_rds_cap:
|
||||||
|
name: My CAP
|
||||||
|
user_groups:
|
||||||
|
- BUILTIN\users
|
||||||
|
session_timeout: 30
|
||||||
|
session_timeout_action: disconnect
|
||||||
|
allow_only_sdrts_servers: true
|
||||||
|
redirect_clipboard: true
|
||||||
|
redirect_drives: false
|
||||||
|
redirect_printers: false
|
||||||
|
redirect_serial: false
|
||||||
|
redirect_pnp: false
|
||||||
|
state: enabled
|
||||||
|
'''
|
||||||
|
|
||||||
|
RETURN = r'''
|
||||||
|
'''
|
@ -0,0 +1,282 @@
|
|||||||
|
#!powershell
|
||||||
|
|
||||||
|
# Copyright: (c) 2018, Kevin Subileau (@ksubileau)
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
#Requires -Module Ansible.ModuleUtils.Legacy
|
||||||
|
#Requires -Module Ansible.ModuleUtils.SID
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
# List of authentication methods as string. Used for parameter validation and conversion to integer flag, so order is important!
|
||||||
|
$computer_group_types = @("rdg_group", "ad_network_resource_group", "allow_any")
|
||||||
|
$computer_group_types_wmi = @{rdg_group = "RG"; ad_network_resource_group = "CG"; allow_any = "ALL"}
|
||||||
|
|
||||||
|
$params = Parse-Args -arguments $args -supports_check_mode $true
|
||||||
|
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
|
||||||
|
$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
|
||||||
|
|
||||||
|
$name = Get-AnsibleParam -obj $params -name "name" -type "str" -failifempty $true
|
||||||
|
$description = Get-AnsibleParam -obj $params -name "description" -type "str"
|
||||||
|
$state = Get-AnsibleParam -obj $params -name "state" -type "str" -default "present" -validateset "absent","present","enabled","disabled"
|
||||||
|
$computer_group_type = Get-AnsibleParam -obj $params -name "computer_group_type" -type "str" -validateset $computer_group_types
|
||||||
|
$computer_group = Get-AnsibleParam -obj $params -name "computer_group" -type "str" -failifempty ($computer_group_type -eq "ad_network_resource_group" -or $computer_group_type -eq "rdg_group")
|
||||||
|
$user_groups = Get-AnsibleParam -obj $params -name "user_groups" -type "list"
|
||||||
|
$allowed_ports = Get-AnsibleParam -obj $params -name "allowed_ports" -type "list"
|
||||||
|
|
||||||
|
|
||||||
|
function Get-RAP([string] $name) {
|
||||||
|
$rap_path = "RDS:\GatewayServer\RAP\$name"
|
||||||
|
$rap = @{
|
||||||
|
Name = $name
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch RAP properties
|
||||||
|
Get-ChildItem -Path $rap_path | ForEach-Object { $rap.Add($_.Name,$_.CurrentValue) }
|
||||||
|
# Convert boolean values
|
||||||
|
$rap.Enabled = $rap.Status -eq 1
|
||||||
|
$rap.Remove("Status")
|
||||||
|
|
||||||
|
# Convert computer group name from UPN to Down-Level Logon format
|
||||||
|
if($rap.ComputerGroupType -ne 2) {
|
||||||
|
$rap.ComputerGroup = Convert-FromSID -sid (Convert-ToSID -account_name $rap.ComputerGroup)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Convert multiple choices values
|
||||||
|
$rap.ComputerGroupType = $computer_group_types[$rap.ComputerGroupType]
|
||||||
|
|
||||||
|
# Convert allowed ports from string to list
|
||||||
|
if($rap.PortNumbers -eq '*') {
|
||||||
|
$rap.PortNumbers = @("any")
|
||||||
|
} else {
|
||||||
|
$rap.PortNumbers = @($rap.PortNumbers -split ',')
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fetch RAP user groups in Down-Level Logon format
|
||||||
|
$rap.UserGroups = @(
|
||||||
|
Get-ChildItem -Path "$rap_path\UserGroups" |
|
||||||
|
Select-Object -ExpandProperty Name |
|
||||||
|
ForEach-Object { Convert-FromSID -sid (Convert-ToSID -account_name $_) }
|
||||||
|
)
|
||||||
|
|
||||||
|
return $rap
|
||||||
|
}
|
||||||
|
|
||||||
|
function Set-RAPPropertyValue {
|
||||||
|
[CmdletBinding(SupportsShouldProcess=$true)]
|
||||||
|
param (
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string] $name,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
[string] $property,
|
||||||
|
[Parameter(Mandatory=$true)]
|
||||||
|
$value,
|
||||||
|
[Parameter()]
|
||||||
|
$resultobj = @{}
|
||||||
|
)
|
||||||
|
|
||||||
|
$rap_path = "RDS:\GatewayServer\RAP\$name"
|
||||||
|
|
||||||
|
try {
|
||||||
|
Set-Item -Path "$rap_path\$property" -Value $value -ErrorAction stop
|
||||||
|
} catch {
|
||||||
|
Fail-Json -obj $resultobj -message "Failed to set property $property of RAP ${name}: $($_.Exception.Message)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = @{
|
||||||
|
changed = $false
|
||||||
|
}
|
||||||
|
$diff_text = $null
|
||||||
|
|
||||||
|
# Validate RAP name
|
||||||
|
if ($name -match "[*/\\;:?`"<>|\t]+") {
|
||||||
|
Fail-Json -obj $result -message "Invalid character in RAP name."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validate user groups
|
||||||
|
if ($null -ne $user_groups) {
|
||||||
|
if ($user_groups.Count -lt 1) {
|
||||||
|
Fail-Json -obj $result -message "Parameter 'user_groups' cannot be an empty list."
|
||||||
|
}
|
||||||
|
|
||||||
|
$user_groups = $user_groups | ForEach-Object {
|
||||||
|
$group = $_
|
||||||
|
# Test that the group is resolvable on the local machine
|
||||||
|
$sid = Convert-ToSID -account_name $group
|
||||||
|
if (!$sid) {
|
||||||
|
Fail-Json -obj $result -message "$group is not a valid user group on the host machine or domain."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Return the normalized group name in Down-Level Logon format
|
||||||
|
Convert-FromSID -sid $sid
|
||||||
|
}
|
||||||
|
$user_groups = @($user_groups)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validate computer group parameter
|
||||||
|
if ($computer_group_type -eq "allow_any" -and $null -ne $computer_group) {
|
||||||
|
Add-Warning -obj $result -message "Parameter 'computer_group' ignored because the computer_group_type is set to allow_any."
|
||||||
|
} elseif ($computer_group_type -eq "rdg_group" -and -not (Test-Path -Path "RDS:\GatewayServer\GatewayManagedComputerGroups\$computer_group")) {
|
||||||
|
Fail-Json -obj $result -message "$computer_group is not a valid gateway managed computer group"
|
||||||
|
} elseif ($computer_group_type -eq "ad_network_resource_group") {
|
||||||
|
$sid = Convert-ToSID -account_name $computer_group
|
||||||
|
if (!$sid) {
|
||||||
|
Fail-Json -obj $result -message "$computer_group is not a valid computer group on the host machine or domain."
|
||||||
|
}
|
||||||
|
# Ensure the group name is in Down-Level Logon format
|
||||||
|
$computer_group = Convert-FromSID -sid $sid
|
||||||
|
}
|
||||||
|
|
||||||
|
# Validate port numbers
|
||||||
|
if ($null -ne $allowed_ports) {
|
||||||
|
foreach ($port in $allowed_ports) {
|
||||||
|
if (-not ($port -eq "any" -or ($port -is [int] -and $port -ge 1 -and $port -le 65535))) {
|
||||||
|
Fail-Json -obj $result -message "$port is not a valid port number."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure RemoteDesktopServices module is loaded
|
||||||
|
if ((Get-Module -Name RemoteDesktopServices -ErrorAction SilentlyContinue) -eq $null) {
|
||||||
|
Import-Module -Name RemoteDesktopServices
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if a RAP with the given name already exists
|
||||||
|
$rap_exist = Test-Path -Path "RDS:\GatewayServer\RAP\$name"
|
||||||
|
|
||||||
|
if ($state -eq 'absent') {
|
||||||
|
if ($rap_exist) {
|
||||||
|
Remove-Item -Path "RDS:\GatewayServer\RAP\$name" -Recurse -WhatIf:$check_mode
|
||||||
|
$diff_text += "-[$name]"
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$diff_text_added_prefix = ''
|
||||||
|
if (-not $rap_exist) {
|
||||||
|
if ($null -eq $user_groups) {
|
||||||
|
Fail-Json -obj $result -message "User groups must be defined to create a new RAP."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Computer group type is required when creating a new RAP. Set it to allow connect to any resource by default.
|
||||||
|
if ($null -eq $computer_group_type) {
|
||||||
|
$computer_group_type = "allow_any"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Create a new RAP
|
||||||
|
if (-not $check_mode) {
|
||||||
|
$RapArgs = @{
|
||||||
|
Name = $name
|
||||||
|
ResourceGroupType = 'ALL'
|
||||||
|
UserGroupNames = $user_groups -join ';'
|
||||||
|
ProtocolNames = 'RDP'
|
||||||
|
PortNumbers = '*'
|
||||||
|
}
|
||||||
|
$return = Invoke-CimMethod -Namespace Root\CIMV2\TerminalServices -ClassName Win32_TSGatewayResourceAuthorizationPolicy -MethodName Create -Arguments $RapArgs
|
||||||
|
if ($return.ReturnValue -ne 0) {
|
||||||
|
Fail-Json -obj $result -message "Failed to create RAP $name (code: $($return.ReturnValue))"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$rap_exist = -not $check_mode
|
||||||
|
|
||||||
|
$diff_text_added_prefix = '+'
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
$diff_text += "$diff_text_added_prefix[$name]`n"
|
||||||
|
|
||||||
|
# We cannot configure a RAP that was created above in check mode as it won't actually exist
|
||||||
|
if($rap_exist) {
|
||||||
|
$rap = Get-RAP -Name $name
|
||||||
|
$wmi_rap = Get-CimInstance -ClassName Win32_TSGatewayResourceAuthorizationPolicy -Namespace Root\CIMv2\TerminalServices -Filter "name='$($name)'"
|
||||||
|
|
||||||
|
if ($state -in @('disabled', 'enabled')) {
|
||||||
|
$rap_enabled = $state -ne 'disabled'
|
||||||
|
if ($rap.Enabled -ne $rap_enabled) {
|
||||||
|
$diff_text += "-State = $(@('disabled', 'enabled')[[int]$rap.Enabled])`n+State = $state`n"
|
||||||
|
Set-RAPPropertyValue -Name $name -Property Status -Value ([int]$rap_enabled) -ResultObj $result -WhatIf:$check_mode
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $description -and $description -ne $rap.Description) {
|
||||||
|
Set-RAPPropertyValue -Name $name -Property Description -Value $description -ResultObj $result -WhatIf:$check_mode
|
||||||
|
$diff_text += "-Description = $($rap.Description)`n+Description = $description`n"
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $allowed_ports -and @(Compare-Object $rap.PortNumbers $allowed_ports -SyncWindow 0).Count -ne 0) {
|
||||||
|
$diff_text += "-AllowedPorts = [$($rap.PortNumbers -join ',')]`n+AllowedPorts = [$($allowed_ports -join ',')]`n"
|
||||||
|
if ($allowed_ports -contains 'any') { $allowed_ports = '*' }
|
||||||
|
Set-RAPPropertyValue -Name $name -Property PortNumbers -Value $allowed_ports -ResultObj $result -WhatIf:$check_mode
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $computer_group_type -and $computer_group_type -ne $rap.ComputerGroupType) {
|
||||||
|
$diff_text += "-ComputerGroupType = $($rap.ComputerGroupType)`n+ComputerGroupType = $computer_group_type`n"
|
||||||
|
if ($computer_group_type -ne "allow_any") {
|
||||||
|
$diff_text += "+ComputerGroup = $computer_group`n"
|
||||||
|
}
|
||||||
|
$return = $wmi_rap | Invoke-CimMethod -MethodName SetResourceGroup -Arguments @{
|
||||||
|
ResourceGroupName = $computer_group
|
||||||
|
ResourceGroupType = $computer_group_types_wmi.$($computer_group_type)
|
||||||
|
}
|
||||||
|
if ($return.ReturnValue -ne 0) {
|
||||||
|
Fail-Json -obj $result -message "Failed to set computer group type to $($computer_group_type) (code: $($return.ReturnValue))"
|
||||||
|
}
|
||||||
|
|
||||||
|
$result.changed = $true
|
||||||
|
|
||||||
|
} elseif ($null -ne $computer_group -and $computer_group -ne $rap.ComputerGroup) {
|
||||||
|
$diff_text += "-ComputerGroup = $($rap.ComputerGroup)`n+ComputerGroup = $computer_group`n"
|
||||||
|
$return = $wmi_rap | Invoke-CimMethod -MethodName SetResourceGroup -Arguments @{
|
||||||
|
ResourceGroupName = $computer_group
|
||||||
|
ResourceGroupType = $computer_group_types_wmi.$($rap.ComputerGroupType)
|
||||||
|
}
|
||||||
|
if ($return.ReturnValue -ne 0) {
|
||||||
|
Fail-Json -obj $result -message "Failed to set computer group name to $($computer_group) (code: $($return.ReturnValue))"
|
||||||
|
}
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $user_groups) {
|
||||||
|
$groups_to_remove = @($rap.UserGroups | Where-Object { $user_groups -notcontains $_ })
|
||||||
|
$groups_to_add = @($user_groups | Where-Object { $rap.UserGroups -notcontains $_ })
|
||||||
|
|
||||||
|
$user_groups_diff = $null
|
||||||
|
foreach($group in $groups_to_add) {
|
||||||
|
if (-not $check_mode) {
|
||||||
|
$return = $wmi_rap | Invoke-CimMethod -MethodName AddUserGroupNames -Arguments @{ UserGroupNames = $group }
|
||||||
|
if ($return.ReturnValue -ne 0) {
|
||||||
|
Fail-Json -obj $result -message "Failed to add user group $($group) (code: $($return.ReturnValue))"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$user_groups_diff += " +$group`n"
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach($group in $groups_to_remove) {
|
||||||
|
if (-not $check_mode) {
|
||||||
|
$return = $wmi_rap | Invoke-CimMethod -MethodName RemoveUserGroupNames -Arguments @{ UserGroupNames = $group }
|
||||||
|
if ($return.ReturnValue -ne 0) {
|
||||||
|
Fail-Json -obj $result -message "Failed to remove user group $($group) (code: $($return.ReturnValue))"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$user_groups_diff += " -$group`n"
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
if($user_groups_diff) {
|
||||||
|
$diff_text += "~UserGroups`n$user_groups_diff"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($diff_mode -and $result.changed -eq $true) {
|
||||||
|
$result.diff = @{
|
||||||
|
prepared = $diff_text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Exit-Json $result
|
@ -0,0 +1,81 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright: (c) 2018, Kevin Subileau (@ksubileau)
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||||
|
'status': ['preview'],
|
||||||
|
'supported_by': 'community'}
|
||||||
|
|
||||||
|
DOCUMENTATION = r'''
|
||||||
|
---
|
||||||
|
module: win_rds_rap
|
||||||
|
short_description: Manage Resource Authorization Policies (RAP) on a Remote Desktop Gateway server
|
||||||
|
description:
|
||||||
|
- Creates, removes and configures a Remote Desktop resource authorization policy (RD RAP).
|
||||||
|
- A RD RAP allows you to specify the network resources (computers) that users can connect
|
||||||
|
to remotely through a Remote Desktop Gateway server.
|
||||||
|
version_added: "2.8"
|
||||||
|
author:
|
||||||
|
- Kevin Subileau (@ksubileau)
|
||||||
|
options:
|
||||||
|
name:
|
||||||
|
description:
|
||||||
|
- Name of the resource authorization policy.
|
||||||
|
required: yes
|
||||||
|
state:
|
||||||
|
description:
|
||||||
|
- The state of resource authorization policy.
|
||||||
|
- If C(absent) will ensure the policy is removed.
|
||||||
|
- If C(present) will ensure the policy is configured and exists.
|
||||||
|
- If C(enabled) will ensure the policy is configured, exists and enabled.
|
||||||
|
- If C(disabled) will ensure the policy is configured, exists, but disabled.
|
||||||
|
choices: [ absent, present, enabled, disabled ]
|
||||||
|
default: present
|
||||||
|
description:
|
||||||
|
description:
|
||||||
|
- Optionnal description of the resource authorization policy.
|
||||||
|
user_groups:
|
||||||
|
description:
|
||||||
|
- List of user groups that are associated with this resource authorization policy (RAP).
|
||||||
|
A user must belong to one of these groups to access the RD Gateway server.
|
||||||
|
- Required when a new RAP is created.
|
||||||
|
type: list
|
||||||
|
allowed_ports:
|
||||||
|
description:
|
||||||
|
- List of port numbers through which connections are allowed for this policy.
|
||||||
|
- To allow connections through any port, specify 'any'.
|
||||||
|
type: list
|
||||||
|
computer_group_type:
|
||||||
|
description:
|
||||||
|
- 'The computer group type:'
|
||||||
|
- 'C(rdg_group): RD Gateway-managed group'
|
||||||
|
- 'C(ad_network_resource_group): Active Directory Domain Services network resource group'
|
||||||
|
- 'C(allow_any): Allow users to connect to any network resource.'
|
||||||
|
choices: [ rdg_group, ad_network_resource_group, allow_any ]
|
||||||
|
computer_group:
|
||||||
|
description:
|
||||||
|
- The computer group name that is associated with this resource authorization policy (RAP).
|
||||||
|
- This is required when I(computer_group_type) is C(rdg_group) or C(ad_network_resource_group).
|
||||||
|
requirements:
|
||||||
|
- Windows Server 2008R2 (6.1) or higher.
|
||||||
|
- The Windows Feature "RDS-Gateway" must be enabled.
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = r'''
|
||||||
|
- name: Create a new RDS RAP
|
||||||
|
win_rds_rap:
|
||||||
|
name: My RAP
|
||||||
|
description: 'Allow all users to connect to any resource through ports 3389 and 3390'
|
||||||
|
user_groups:
|
||||||
|
- BUILTIN\users
|
||||||
|
computer_group_type: allow_any
|
||||||
|
allowed_ports:
|
||||||
|
- 3389
|
||||||
|
- 3390
|
||||||
|
state: enabled
|
||||||
|
'''
|
||||||
|
|
||||||
|
RETURN = r'''
|
||||||
|
'''
|
@ -0,0 +1,100 @@
|
|||||||
|
#!powershell
|
||||||
|
|
||||||
|
# Copyright: (c) 2018, Kevin Subileau (@ksubileau)
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
#Requires -Module Ansible.ModuleUtils.Legacy
|
||||||
|
|
||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
# List of ssl bridging methods as string. Used for parameter validation and conversion to integer flag, so order is important!
|
||||||
|
$ssl_bridging_methods = @("none", "https_http", "https_https")
|
||||||
|
|
||||||
|
$params = Parse-Args -arguments $args -supports_check_mode $true
|
||||||
|
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
|
||||||
|
$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
|
||||||
|
|
||||||
|
$certificate = Get-AnsibleParam $params -name "certificate_hash" -type "str"
|
||||||
|
$max_connections = Get-AnsibleParam $params -name "max_connections" -type "int"
|
||||||
|
$ssl_bridging = Get-AnsibleParam -obj $params -name "ssl_bridging" -type "str" -validateset $ssl_bridging_methods
|
||||||
|
$enable_only_messaging_capable_clients = Get-AnsibleParam $params -name "enable_only_messaging_capable_clients" -type "bool"
|
||||||
|
|
||||||
|
$result = @{
|
||||||
|
changed = $false
|
||||||
|
}
|
||||||
|
$diff_text = $null
|
||||||
|
|
||||||
|
# Ensure RemoteDesktopServices module is loaded
|
||||||
|
if ((Get-Module -Name RemoteDesktopServices -ErrorAction SilentlyContinue) -eq $null) {
|
||||||
|
Import-Module -Name RemoteDesktopServices
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $certificate)
|
||||||
|
{
|
||||||
|
# Validate cert path
|
||||||
|
$cert_path = "cert:\LocalMachine\My\$certificate"
|
||||||
|
If (-not (Test-Path $cert_path) )
|
||||||
|
{
|
||||||
|
Fail-Json -obj $result -message "Unable to locate certificate at $cert_path"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get current certificate hash
|
||||||
|
$current_cert = (Get-Item -Path "RDS:\GatewayServer\SSLCertificate\Thumbprint").CurrentValue
|
||||||
|
if ($current_cert -ne $certificate) {
|
||||||
|
Set-Item -Path "RDS:\GatewayServer\SSLCertificate\Thumbprint" -Value $certificate -WhatIf:$check_mode
|
||||||
|
$diff_text += "-Certificate = $current_cert`n+Certificate = $certificate`n"
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $max_connections)
|
||||||
|
{
|
||||||
|
# Set the correct value for unlimited connections
|
||||||
|
# TODO Use a more explicit value, maybe a string (ex: "max", "none" or "unlimited") ?
|
||||||
|
If ($max_connections -eq -1)
|
||||||
|
{
|
||||||
|
$max_connections = (Get-Item -Path "RDS:\GatewayServer\MaxConnectionsAllowed").CurrentValue
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get current connections limit
|
||||||
|
$current_max_connections = (Get-Item -Path "RDS:\GatewayServer\MaxConnections").CurrentValue
|
||||||
|
if ($current_max_connections -ne $max_connections) {
|
||||||
|
Set-Item -Path "RDS:\GatewayServer\MaxConnections" -Value $max_connections -WhatIf:$check_mode
|
||||||
|
$diff_text += "-MaxConnections = $current_max_connections`n+MaxConnections = $max_connections`n"
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $ssl_bridging)
|
||||||
|
{
|
||||||
|
$current_ssl_bridging = (Get-Item -Path "RDS:\GatewayServer\SSLBridging").CurrentValue
|
||||||
|
# Convert the integer value to its representative string
|
||||||
|
$current_ssl_bridging_str = $ssl_bridging_methods[$current_ssl_bridging]
|
||||||
|
|
||||||
|
if ($current_ssl_bridging_str -ne $ssl_bridging) {
|
||||||
|
Set-Item -Path "RDS:\GatewayServer\SSLBridging" -Value ([array]::IndexOf($ssl_bridging_methods, $ssl_bridging)) -WhatIf:$check_mode
|
||||||
|
$diff_text += "-SSLBridging = $current_ssl_bridging_str`n+SSLBridging = $ssl_bridging`n"
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($null -ne $enable_only_messaging_capable_clients)
|
||||||
|
{
|
||||||
|
$current_enable_only_messaging_capable_clients = (Get-Item -Path "RDS:\GatewayServer\EnableOnlyMessagingCapableClients").CurrentValue
|
||||||
|
# Convert the integer value to boolean
|
||||||
|
$current_enable_only_messaging_capable_clients = $current_enable_only_messaging_capable_clients -eq 1
|
||||||
|
|
||||||
|
if ($current_enable_only_messaging_capable_clients -ne $enable_only_messaging_capable_clients) {
|
||||||
|
Set-Item -Path "RDS:\GatewayServer\EnableOnlyMessagingCapableClients" -Value ([int]$enable_only_messaging_capable_clients) -WhatIf:$check_mode
|
||||||
|
$diff_text += "-EnableOnlyMessagingCapableClients = $current_enable_only_messaging_capable_clients`n+EnableOnlyMessagingCapableClients = $enable_only_messaging_capable_clients`n"
|
||||||
|
$result.changed = $true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($diff_mode -and $result.changed -eq $true) {
|
||||||
|
$result.diff = @{
|
||||||
|
prepared = $diff_text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Exit-Json $result
|
@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Copyright: (c) 2018, Kevin Subileau (@ksubileau)
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
ANSIBLE_METADATA = {'metadata_version': '1.1',
|
||||||
|
'status': ['preview'],
|
||||||
|
'supported_by': 'community'}
|
||||||
|
|
||||||
|
DOCUMENTATION = r'''
|
||||||
|
---
|
||||||
|
module: win_rds_settings
|
||||||
|
short_description: Manage main settings of a Remote Desktop Gateway server
|
||||||
|
description:
|
||||||
|
- Configure general settings of a Remote Desktop Gateway server.
|
||||||
|
version_added: "2.8"
|
||||||
|
author:
|
||||||
|
- Kevin Subileau (@ksubileau)
|
||||||
|
options:
|
||||||
|
certificate_hash:
|
||||||
|
description:
|
||||||
|
- Certificate hash (thumbprint) for the Remote Desktop Gateway server. The certificate hash is the unique identifier for the certificate.
|
||||||
|
max_connections:
|
||||||
|
description:
|
||||||
|
- The maximum number of connections allowed.
|
||||||
|
- If set to C(0), no new connections are allowed.
|
||||||
|
- If set to C(-1), the number of connections is unlimited.
|
||||||
|
ssl_bridging:
|
||||||
|
description:
|
||||||
|
- Specifies whether to use SSL Bridging.
|
||||||
|
- 'C(none): no SSL bridging.'
|
||||||
|
- 'C(https_http): HTTPS-HTTP bridging.'
|
||||||
|
- 'C(https_https): HTTPS-HTTPS bridging.'
|
||||||
|
choices: [ none, https_http, https_https ]
|
||||||
|
enable_only_messaging_capable_clients:
|
||||||
|
description:
|
||||||
|
- If enabled, only clients that support logon messages and administrator messages can connect.
|
||||||
|
type: bool
|
||||||
|
requirements:
|
||||||
|
- Windows Server 2008R2 (6.1) or higher.
|
||||||
|
- The Windows Feature "RDS-Gateway" must be enabled.
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXAMPLES = r'''
|
||||||
|
- name: Configure the Remote Desktop Gateway
|
||||||
|
win_rds_settings:
|
||||||
|
certificate_hash: B0D0FA8408FC67B230338FCA584D03792DA73F4C
|
||||||
|
max_connections: 50
|
||||||
|
notify:
|
||||||
|
- Restart TSGateway service
|
||||||
|
'''
|
||||||
|
|
||||||
|
RETURN = r'''
|
||||||
|
'''
|
@ -0,0 +1 @@
|
|||||||
|
shippable/windows/group4
|
@ -0,0 +1 @@
|
|||||||
|
test_win_rds_cap_name: Ansible Test CAP
|
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
# Cannot use win_feature to install RDS on Server 2008.
|
||||||
|
# Run a brief check and skip hosts that don't support
|
||||||
|
# that operation
|
||||||
|
- name: check if win_feature will work on test host
|
||||||
|
win_command: powershell.exe "exit (-not (Get-Command -Name Add-WindowsFeature -ErrorAction SilentlyContinue))"
|
||||||
|
register: module_available
|
||||||
|
failed_when: False
|
||||||
|
|
||||||
|
# Run actual tests
|
||||||
|
- block:
|
||||||
|
- name: ensure Remote Desktop Gateway services are installed
|
||||||
|
win_feature:
|
||||||
|
name: RDS-Gateway,RDS-Licensing,RDS-RD-Server
|
||||||
|
state: present
|
||||||
|
include_management_tools: True
|
||||||
|
register: rds_install
|
||||||
|
|
||||||
|
- name: reboot server if needed
|
||||||
|
win_reboot:
|
||||||
|
post_reboot_delay: 10
|
||||||
|
when: rds_install.reboot_required
|
||||||
|
|
||||||
|
- include_tasks: tests.yml
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: delete all CAPs
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Remove-Item -Path RDS:\GatewayServer\CAP\* -Recurse
|
||||||
|
|
||||||
|
when: module_available.rc == 0
|
@ -0,0 +1,264 @@
|
|||||||
|
---
|
||||||
|
- name: test create a new CAP (check mode)
|
||||||
|
win_rds_cap:
|
||||||
|
name: '{{ test_win_rds_cap_name }}'
|
||||||
|
user_groups:
|
||||||
|
- administrators
|
||||||
|
- users@builtin
|
||||||
|
state: present
|
||||||
|
register: new_cap_check
|
||||||
|
check_mode: yes
|
||||||
|
|
||||||
|
- name: get result of create a new CAP (check mode)
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Test-Path "RDS:\GatewayServer\CAP\{{ test_win_rds_cap_name }}")
|
||||||
|
register: new_cap_actual_check
|
||||||
|
|
||||||
|
- name: assert results of create a new CAP (check mode)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- new_cap_check.changed == true
|
||||||
|
- new_cap_actual_check.stdout_lines[0] == "False"
|
||||||
|
|
||||||
|
- name: test create a new CAP
|
||||||
|
win_rds_cap:
|
||||||
|
name: '{{ test_win_rds_cap_name }}'
|
||||||
|
user_groups:
|
||||||
|
- administrators
|
||||||
|
- users@builtin
|
||||||
|
state: present
|
||||||
|
register: new_cap
|
||||||
|
|
||||||
|
- name: get result of create a new CAP
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Test-Path "RDS:\GatewayServer\CAP\{{ test_win_rds_cap_name }}")
|
||||||
|
register: new_cap_actual
|
||||||
|
|
||||||
|
- name: assert results of create a new CAP
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- new_cap.changed == true
|
||||||
|
- new_cap_actual.stdout_lines[0] == "True"
|
||||||
|
|
||||||
|
- name: test create a new CAP (idempotent)
|
||||||
|
win_rds_cap:
|
||||||
|
name: '{{ test_win_rds_cap_name }}'
|
||||||
|
user_groups:
|
||||||
|
- administrators
|
||||||
|
- users@builtin
|
||||||
|
state: present
|
||||||
|
register: new_cap_again
|
||||||
|
|
||||||
|
- name: get result of create a new CAP (idempotent)
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Test-Path "RDS:\GatewayServer\CAP\{{ test_win_rds_cap_name }}")
|
||||||
|
register: new_cap_actual_again
|
||||||
|
|
||||||
|
- name: assert results of create a new CAP (idempotent)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- new_cap_again.changed == false
|
||||||
|
- new_cap_actual_again.stdout_lines[0] == "True"
|
||||||
|
|
||||||
|
- name: test edit a CAP
|
||||||
|
win_rds_cap:
|
||||||
|
name: '{{ test_win_rds_cap_name }}'
|
||||||
|
user_groups:
|
||||||
|
# Test with different group name formats
|
||||||
|
- users@builtin
|
||||||
|
- .\guests
|
||||||
|
computer_groups:
|
||||||
|
- administrators
|
||||||
|
auth_method: both
|
||||||
|
session_timeout: 20
|
||||||
|
session_timeout_action: reauth
|
||||||
|
allow_only_sdrts_servers: true
|
||||||
|
idle_timeout: 10
|
||||||
|
redirect_clipboard: false
|
||||||
|
redirect_drives: false
|
||||||
|
redirect_printers: false
|
||||||
|
redirect_serial: false
|
||||||
|
redirect_pnp: false
|
||||||
|
state: disabled
|
||||||
|
register: edit_cap
|
||||||
|
|
||||||
|
- name: get result of edit a CAP
|
||||||
|
win_shell: |
|
||||||
|
Import-Module RemoteDesktopServices;
|
||||||
|
$cap_path = "RDS:\GatewayServer\CAP\{{ test_win_rds_cap_name }}"
|
||||||
|
$cap = @{}
|
||||||
|
Get-ChildItem -Path "$cap_path" | foreach { $cap.Add($_.Name,$_.CurrentValue) }
|
||||||
|
$cap.DeviceRedirection = @{}
|
||||||
|
Get-ChildItem -Path "$cap_path\DeviceRedirection" | foreach { $cap.DeviceRedirection.Add($_.Name, ($_.CurrentValue -eq 1)) }
|
||||||
|
$cap.UserGroups = @(Get-ChildItem -Path "$cap_path\UserGroups" | Select -ExpandProperty Name)
|
||||||
|
$cap.ComputerGroups = @(Get-ChildItem -Path "$cap_path\ComputerGroups" | Select -ExpandProperty Name)
|
||||||
|
$cap | ConvertTo-Json
|
||||||
|
register: edit_cap_actual_json
|
||||||
|
|
||||||
|
- name: parse result of edit a CAP.
|
||||||
|
set_fact:
|
||||||
|
edit_cap_actual: '{{ edit_cap_actual_json.stdout | from_json }}'
|
||||||
|
|
||||||
|
- name: assert results of edit a CAP
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- edit_cap.changed == true
|
||||||
|
- edit_cap_actual.Status == "0"
|
||||||
|
- edit_cap_actual.EvaluationOrder == "1"
|
||||||
|
- edit_cap_actual.AllowOnlySDRTSServers == "1"
|
||||||
|
- edit_cap_actual.AuthMethod == "3"
|
||||||
|
- edit_cap_actual.IdleTimeout == "10"
|
||||||
|
- edit_cap_actual.SessionTimeoutAction == "1"
|
||||||
|
- edit_cap_actual.SessionTimeout == "20"
|
||||||
|
- edit_cap_actual.DeviceRedirection.Clipboard == false
|
||||||
|
- edit_cap_actual.DeviceRedirection.DiskDrives == false
|
||||||
|
- edit_cap_actual.DeviceRedirection.PlugAndPlayDevices == false
|
||||||
|
- edit_cap_actual.DeviceRedirection.Printers == false
|
||||||
|
- edit_cap_actual.DeviceRedirection.SerialPorts == false
|
||||||
|
- edit_cap_actual.UserGroups | length == 2
|
||||||
|
- edit_cap_actual.UserGroups[0] == "Users@BUILTIN"
|
||||||
|
- edit_cap_actual.UserGroups[1] == "Guests@BUILTIN"
|
||||||
|
- edit_cap_actual.ComputerGroups | length == 1
|
||||||
|
- edit_cap_actual.ComputerGroups[0] == "Administrators@BUILTIN"
|
||||||
|
|
||||||
|
- name: test remove all computer groups of CAP
|
||||||
|
win_rds_cap:
|
||||||
|
name: '{{ test_win_rds_cap_name }}'
|
||||||
|
computer_groups: []
|
||||||
|
register: remove_computer_groups_cap
|
||||||
|
|
||||||
|
- name: get result of remove all computer groups of CAP
|
||||||
|
win_shell: |
|
||||||
|
Import-Module RemoteDesktopServices;
|
||||||
|
$cap_path = "RDS:\GatewayServer\CAP\{{ test_win_rds_cap_name }}"
|
||||||
|
Write-Host @(Get-ChildItem -Path "$cap_path\ComputerGroups" | Select -ExpandProperty Name).Count
|
||||||
|
register: remove_computer_groups_cap_actual
|
||||||
|
|
||||||
|
- name: assert results of remove all computer groups of CAP
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- remove_computer_groups_cap.changed == true
|
||||||
|
- remove_computer_groups_cap_actual.stdout_lines[0] == "0"
|
||||||
|
|
||||||
|
- name: test create a CAP in second position
|
||||||
|
win_rds_cap:
|
||||||
|
name: '{{ test_win_rds_cap_name }} Second'
|
||||||
|
user_groups:
|
||||||
|
- users@builtin
|
||||||
|
order: 2
|
||||||
|
state: present
|
||||||
|
register: second_cap
|
||||||
|
|
||||||
|
- name: get result of create a CAP in second position
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Get-Item "RDS:\GatewayServer\CAP\{{ test_win_rds_cap_name }} Second\EvaluationOrder").CurrentValue
|
||||||
|
register: second_cap_actual
|
||||||
|
|
||||||
|
- name: assert results of create a CAP in second position
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- second_cap.changed == true
|
||||||
|
- second_cap.warnings is not defined
|
||||||
|
- second_cap_actual.stdout_lines[0] == "2"
|
||||||
|
|
||||||
|
- name: test create a CAP with order greater than existing CAP count
|
||||||
|
win_rds_cap:
|
||||||
|
name: '{{ test_win_rds_cap_name }} Last'
|
||||||
|
user_groups:
|
||||||
|
- users@builtin
|
||||||
|
order: 50
|
||||||
|
state: present
|
||||||
|
register: cap_big_order
|
||||||
|
|
||||||
|
- name: get result of create a CAP with order greater than existing CAP count
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Get-Item "RDS:\GatewayServer\CAP\{{ test_win_rds_cap_name }} Last\EvaluationOrder").CurrentValue
|
||||||
|
register: cap_big_order_actual
|
||||||
|
|
||||||
|
- name: assert results of create a CAP with order greater than existing CAP count
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- cap_big_order.changed == true
|
||||||
|
- cap_big_order.warnings | length == 1
|
||||||
|
- cap_big_order_actual.stdout_lines[0] == "3"
|
||||||
|
|
||||||
|
- name: test remove CAP (check mode)
|
||||||
|
win_rds_cap:
|
||||||
|
name: '{{ test_win_rds_cap_name }}'
|
||||||
|
state: absent
|
||||||
|
register: remove_cap_check
|
||||||
|
check_mode: yes
|
||||||
|
|
||||||
|
- name: get result of remove CAP (check mode)
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Test-Path "RDS:\GatewayServer\CAP\{{ test_win_rds_cap_name }}")
|
||||||
|
register: remove_cap_actual_check
|
||||||
|
|
||||||
|
- name: assert results of remove CAP (check mode)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- remove_cap_check.changed == true
|
||||||
|
- remove_cap_actual_check.stdout_lines[0] == "True"
|
||||||
|
|
||||||
|
- name: test remove CAP
|
||||||
|
win_rds_cap:
|
||||||
|
name: '{{ test_win_rds_cap_name }}'
|
||||||
|
state: absent
|
||||||
|
register: remove_cap_check
|
||||||
|
|
||||||
|
- name: get result of remove CAP
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Test-Path "RDS:\GatewayServer\CAP\{{ test_win_rds_cap_name }}")
|
||||||
|
register: remove_cap_actual_check
|
||||||
|
|
||||||
|
- name: assert results of remove CAP
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- remove_cap_check.changed == true
|
||||||
|
- remove_cap_actual_check.stdout_lines[0] == "False"
|
||||||
|
|
||||||
|
- name: test remove CAP (idempotent)
|
||||||
|
win_rds_cap:
|
||||||
|
name: '{{ test_win_rds_cap_name }}'
|
||||||
|
state: absent
|
||||||
|
register: remove_cap_check
|
||||||
|
|
||||||
|
- name: get result of remove CAP (idempotent)
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Test-Path "RDS:\GatewayServer\CAP\{{ test_win_rds_cap_name }}")
|
||||||
|
register: remove_cap_actual_check
|
||||||
|
|
||||||
|
- name: assert results of remove CAP (idempotent)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- remove_cap_check.changed == false
|
||||||
|
- remove_cap_actual_check.stdout_lines[0] == "False"
|
||||||
|
|
||||||
|
- name: fail when create a new CAP without user group
|
||||||
|
win_rds_cap:
|
||||||
|
name: '{{ test_win_rds_cap_name }}'
|
||||||
|
state: present
|
||||||
|
register: new_cap_without_group
|
||||||
|
check_mode: yes
|
||||||
|
failed_when: "new_cap_without_group.msg != 'User groups must be defined to create a new CAP.'"
|
||||||
|
|
||||||
|
- name: fail when create a new CAP with an empty user group list
|
||||||
|
win_rds_cap:
|
||||||
|
name: '{{ test_win_rds_cap_name }}'
|
||||||
|
user_groups: []
|
||||||
|
state: present
|
||||||
|
register: new_cap_empty_group_list
|
||||||
|
check_mode: yes
|
||||||
|
failed_when: "new_cap_empty_group_list.msg is not search('cannot be an empty list')"
|
||||||
|
|
||||||
|
- name: fail when create a new CAP with an invalid user group
|
||||||
|
win_rds_cap:
|
||||||
|
name: '{{ test_win_rds_cap_name }}'
|
||||||
|
user_groups:
|
||||||
|
- fake_group
|
||||||
|
state: present
|
||||||
|
register: new_cap_invalid_user_group
|
||||||
|
check_mode: yes
|
||||||
|
failed_when: new_cap_invalid_user_group.changed != false or new_cap_invalid_user_group.msg is not search('is not a valid account')
|
||||||
|
|
||||||
|
- name: fail when create a new CAP with an invalid computer group
|
||||||
|
win_rds_cap:
|
||||||
|
name: '{{ test_win_rds_cap_name }}'
|
||||||
|
computer_groups:
|
||||||
|
- fake_group
|
||||||
|
state: present
|
||||||
|
register: new_cap_invalid_computer_group
|
||||||
|
check_mode: yes
|
||||||
|
failed_when: new_cap_invalid_computer_group.changed != false or new_cap_invalid_computer_group.msg is not search('is not a valid account')
|
@ -0,0 +1 @@
|
|||||||
|
shippable/windows/group4
|
@ -0,0 +1 @@
|
|||||||
|
test_win_rds_rap_name: Ansible Test RAP
|
@ -0,0 +1,30 @@
|
|||||||
|
---
|
||||||
|
# Cannot use win_feature to install RDS on Server 2008.
|
||||||
|
# Run a brief check and skip hosts that don't support
|
||||||
|
# that operation
|
||||||
|
- name: check if win_feature will work on test host
|
||||||
|
win_command: powershell.exe "exit (-not (Get-Command -Name Add-WindowsFeature -ErrorAction SilentlyContinue))"
|
||||||
|
register: module_available
|
||||||
|
failed_when: False
|
||||||
|
|
||||||
|
# Run actual tests
|
||||||
|
- block:
|
||||||
|
- name: ensure Remote Desktop Gateway services are installed
|
||||||
|
win_feature:
|
||||||
|
name: RDS-Gateway,RDS-Licensing,RDS-RD-Server
|
||||||
|
state: present
|
||||||
|
include_management_tools: True
|
||||||
|
register: rds_install
|
||||||
|
|
||||||
|
- name: reboot server if needed
|
||||||
|
win_reboot:
|
||||||
|
post_reboot_delay: 10
|
||||||
|
when: rds_install.reboot_required
|
||||||
|
|
||||||
|
- include_tasks: tests.yml
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: delete all RAPs
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Remove-Item -Path RDS:\GatewayServer\RAP\* -Recurse
|
||||||
|
|
||||||
|
when: module_available.rc == 0
|
@ -0,0 +1,254 @@
|
|||||||
|
---
|
||||||
|
- name: test create a new RAP (check mode)
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
user_groups:
|
||||||
|
- administrators
|
||||||
|
- users@builtin
|
||||||
|
state: present
|
||||||
|
register: new_rap_check
|
||||||
|
check_mode: yes
|
||||||
|
|
||||||
|
- name: get result of create a new RAP (check mode)
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Test-Path "RDS:\GatewayServer\RAP\{{ test_win_rds_rap_name }}")
|
||||||
|
register: new_rap_actual_check
|
||||||
|
|
||||||
|
- name: assert results of create a new RAP (check mode)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- new_rap_check.changed == true
|
||||||
|
- new_rap_actual_check.stdout_lines[0] == "False"
|
||||||
|
|
||||||
|
- name: test create a new RAP
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
user_groups:
|
||||||
|
- administrators
|
||||||
|
- users@builtin
|
||||||
|
state: present
|
||||||
|
register: new_rap
|
||||||
|
|
||||||
|
- name: get result of create a new RAP
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Test-Path "RDS:\GatewayServer\RAP\{{ test_win_rds_rap_name }}")
|
||||||
|
register: new_rap_actual
|
||||||
|
|
||||||
|
- name: assert results of create a new RAP
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- new_rap.changed == true
|
||||||
|
- new_rap_actual.stdout_lines[0] == "True"
|
||||||
|
|
||||||
|
- name: test create a new RAP (idempotent)
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
user_groups:
|
||||||
|
- administrators
|
||||||
|
- users@builtin
|
||||||
|
state: present
|
||||||
|
register: new_rap_again
|
||||||
|
|
||||||
|
- name: get result of create a new RAP (idempotent)
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Test-Path "RDS:\GatewayServer\RAP\{{ test_win_rds_rap_name }}")
|
||||||
|
register: new_rap_actual_again
|
||||||
|
|
||||||
|
- name: assert results of create a new RAP (idempotent)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- new_rap_again.changed == false
|
||||||
|
- new_rap_actual_again.stdout_lines[0] == "True"
|
||||||
|
|
||||||
|
- name: test edit a RAP
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
description: 'Description of {{ test_win_rds_rap_name }}'
|
||||||
|
user_groups:
|
||||||
|
# Test with different group name formats
|
||||||
|
- users@builtin
|
||||||
|
- .\guests
|
||||||
|
computer_group_type: ad_network_resource_group
|
||||||
|
computer_group: administrators
|
||||||
|
allowed_ports:
|
||||||
|
- 3389
|
||||||
|
- 3390
|
||||||
|
- 3391
|
||||||
|
state: disabled
|
||||||
|
register: edit_rap
|
||||||
|
|
||||||
|
- name: get result of edit a RAP
|
||||||
|
win_shell: |
|
||||||
|
Import-Module RemoteDesktopServices;
|
||||||
|
$rap_path = "RDS:\GatewayServer\RAP\{{ test_win_rds_rap_name }}"
|
||||||
|
$rap = @{}
|
||||||
|
Get-ChildItem -Path "$rap_path" | foreach { $rap.Add($_.Name,$_.CurrentValue) }
|
||||||
|
$rap.UserGroups = @(Get-ChildItem -Path "$rap_path\UserGroups" | Select -ExpandProperty Name)
|
||||||
|
$rap | ConvertTo-Json
|
||||||
|
register: edit_rap_actual_json
|
||||||
|
|
||||||
|
- name: parse result of edit a RAP.
|
||||||
|
set_fact:
|
||||||
|
edit_rap_actual: '{{ edit_rap_actual_json.stdout | from_json }}'
|
||||||
|
|
||||||
|
- name: assert results of edit a RAP
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- edit_rap.changed == true
|
||||||
|
- edit_rap_actual.Status == "0"
|
||||||
|
- edit_rap_actual.Description == "Description of {{ test_win_rds_rap_name }}"
|
||||||
|
- edit_rap_actual.PortNumbers == "3389,3390,3391"
|
||||||
|
- edit_rap_actual.UserGroups | length == 2
|
||||||
|
- edit_rap_actual.UserGroups[0] == "Users@BUILTIN"
|
||||||
|
- edit_rap_actual.UserGroups[1] == "Guests@BUILTIN"
|
||||||
|
- edit_rap_actual.ComputerGroupType == "1"
|
||||||
|
- edit_rap_actual.ComputerGroup == "Administrators@BUILTIN"
|
||||||
|
|
||||||
|
- name: test edit a RAP (indempotent)
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
description: 'Description of {{ test_win_rds_rap_name }}'
|
||||||
|
user_groups:
|
||||||
|
- users@builtin
|
||||||
|
- guests@builtin
|
||||||
|
computer_group_type: ad_network_resource_group
|
||||||
|
computer_group: Administrators@BUILTIN
|
||||||
|
allowed_ports:
|
||||||
|
- 3389
|
||||||
|
- 3390
|
||||||
|
- 3391
|
||||||
|
state: disabled
|
||||||
|
register: edit_rap_again
|
||||||
|
|
||||||
|
- name: assert results of edit a RAP (indempotent)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- edit_rap_again.changed == false
|
||||||
|
|
||||||
|
- name: test allow all ports
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
allowed_ports: any
|
||||||
|
register: edit_rap_allow_all_ports
|
||||||
|
|
||||||
|
- name: get result of allow all ports
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Get-Item "RDS:\GatewayServer\RAP\{{ test_win_rds_rap_name }}\PortNumbers").CurrentValue
|
||||||
|
register: edit_rap_allow_all_ports_actual
|
||||||
|
|
||||||
|
- name: assert results of allow all ports
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- edit_rap_allow_all_ports.changed == true
|
||||||
|
- edit_rap_allow_all_ports_actual.stdout_lines[0] == "*"
|
||||||
|
|
||||||
|
- name: test remove RAP (check mode)
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
state: absent
|
||||||
|
register: remove_rap_check
|
||||||
|
check_mode: yes
|
||||||
|
|
||||||
|
- name: get result of remove RAP (check mode)
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Test-Path "RDS:\GatewayServer\RAP\{{ test_win_rds_rap_name }}")
|
||||||
|
register: remove_rap_actual_check
|
||||||
|
|
||||||
|
- name: assert results of remove RAP (check mode)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- remove_rap_check.changed == true
|
||||||
|
- remove_rap_actual_check.stdout_lines[0] == "True"
|
||||||
|
|
||||||
|
- name: test remove RAP
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
state: absent
|
||||||
|
register: remove_rap
|
||||||
|
|
||||||
|
- name: get result of remove RAP
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Test-Path "RDS:\GatewayServer\RAP\{{ test_win_rds_rap_name }}")
|
||||||
|
register: remove_rap_actual
|
||||||
|
|
||||||
|
- name: assert results of remove RAP
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- remove_rap.changed == true
|
||||||
|
- remove_rap_actual.stdout_lines[0] == "False"
|
||||||
|
|
||||||
|
- name: test remove RAP (idempotent)
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
state: absent
|
||||||
|
register: remove_rap_again
|
||||||
|
|
||||||
|
- name: get result of remove RAP (idempotent)
|
||||||
|
win_shell: Import-Module RemoteDesktopServices; Write-Host (Test-Path "RDS:\GatewayServer\RAP\{{ test_win_rds_rap_name }}")
|
||||||
|
register: remove_rap_actual_again
|
||||||
|
|
||||||
|
- name: assert results of remove RAP (idempotent)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- remove_rap_again.changed == false
|
||||||
|
- remove_rap_actual_again.stdout_lines[0] == "False"
|
||||||
|
|
||||||
|
- name: fail when create a new RAP without user group
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
state: present
|
||||||
|
register: new_rap_without_group
|
||||||
|
check_mode: yes
|
||||||
|
failed_when: "new_rap_without_group.msg != 'User groups must be defined to create a new RAP.'"
|
||||||
|
|
||||||
|
- name: fail when create a new RAP with an empty user group list
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
user_groups: []
|
||||||
|
state: present
|
||||||
|
register: new_rap_empty_group_list
|
||||||
|
check_mode: yes
|
||||||
|
failed_when: "new_rap_empty_group_list.msg is not search('cannot be an empty list')"
|
||||||
|
|
||||||
|
- name: fail when create a new RAP with an invalid user group
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
user_groups:
|
||||||
|
- fake_group
|
||||||
|
state: present
|
||||||
|
register: new_rap_invalid_group
|
||||||
|
check_mode: yes
|
||||||
|
failed_when: new_rap_invalid_group.changed != false or new_rap_invalid_group.msg is not search('is not a valid account')
|
||||||
|
|
||||||
|
- name: fail when create a new RAP with an invalid AD computer group
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
user_groups:
|
||||||
|
- administrators
|
||||||
|
computer_group_type: ad_network_resource_group
|
||||||
|
computer_group: fake_ad_group
|
||||||
|
state: present
|
||||||
|
register: new_rap_invalid_ad_computer_group
|
||||||
|
check_mode: yes
|
||||||
|
failed_when: new_rap_invalid_ad_computer_group.changed != false or new_rap_invalid_ad_computer_group.msg is not search('is not a valid account')
|
||||||
|
|
||||||
|
- name: fail when create a new RAP with an invalid gateway managed computer group
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
user_groups:
|
||||||
|
- administrators
|
||||||
|
computer_group_type: rdg_group
|
||||||
|
computer_group: fake_rdg_group
|
||||||
|
state: present
|
||||||
|
register: new_rap_invalid_rdg_computer_group
|
||||||
|
check_mode: yes
|
||||||
|
failed_when: new_rap_invalid_rdg_computer_group.changed != false or new_rap_invalid_rdg_computer_group.msg is not search('is not a valid gateway managed computer group')
|
||||||
|
|
||||||
|
- name: fail when create a new RAP with invalid port numbers
|
||||||
|
win_rds_rap:
|
||||||
|
name: '{{ test_win_rds_rap_name }}'
|
||||||
|
user_groups:
|
||||||
|
- administrators
|
||||||
|
allowed_ports:
|
||||||
|
- '{{ item }}'
|
||||||
|
state: present
|
||||||
|
loop:
|
||||||
|
- invalid_port_number
|
||||||
|
- 65536
|
||||||
|
register: new_rap_invalid_port
|
||||||
|
check_mode: yes
|
||||||
|
failed_when: new_rap_invalid_port.changed != false or new_rap_invalid_port.msg is not search('is not a valid port number')
|
@ -0,0 +1 @@
|
|||||||
|
shippable/windows/group4
|
@ -0,0 +1,2 @@
|
|||||||
|
test_win_rds_settings_path: '{{win_output_dir}}\win_rds_settings'
|
||||||
|
rds_cert_suject: rdg.test.com
|
@ -0,0 +1,88 @@
|
|||||||
|
---
|
||||||
|
# Cannot use win_feature to install RDS on Server 2008.
|
||||||
|
# Run a brief check and skip hosts that don't support
|
||||||
|
# that operation
|
||||||
|
- name: check if win_feature will work on test host
|
||||||
|
win_command: powershell.exe "exit (-not (Get-Command -Name Add-WindowsFeature -ErrorAction SilentlyContinue))"
|
||||||
|
register: module_available
|
||||||
|
failed_when: False
|
||||||
|
|
||||||
|
# Run actual tests
|
||||||
|
- block:
|
||||||
|
- name: gather facts
|
||||||
|
setup:
|
||||||
|
filter: ansible_hostname
|
||||||
|
|
||||||
|
- name: ensure Remote Desktop Gateway services are installed
|
||||||
|
win_feature:
|
||||||
|
name: RDS-Gateway,RDS-Licensing,RDS-RD-Server
|
||||||
|
state: present
|
||||||
|
include_management_tools: True
|
||||||
|
register: rds_install
|
||||||
|
|
||||||
|
- name: reboot server if needed
|
||||||
|
win_reboot:
|
||||||
|
post_reboot_delay: 10
|
||||||
|
when: rds_install.reboot_required
|
||||||
|
|
||||||
|
- name: ensure testing folders exists
|
||||||
|
win_file:
|
||||||
|
path: '{{test_win_rds_settings_path}}'
|
||||||
|
state: directory
|
||||||
|
|
||||||
|
- name: deploy test artifacts
|
||||||
|
win_template:
|
||||||
|
src: '{{item}}.j2'
|
||||||
|
dest: '{{test_win_rds_settings_path}}\{{item | basename}}'
|
||||||
|
with_items:
|
||||||
|
- rds_base_cfg.xml
|
||||||
|
|
||||||
|
- name: import RDS test configuration
|
||||||
|
win_shell: |
|
||||||
|
$ts = Get-WmiObject Win32_TSGatewayServer -namespace root\cimv2\TerminalServices
|
||||||
|
$import_xml = Get-Content {{test_win_rds_settings_path}}\rds_base_cfg.xml
|
||||||
|
$import_result = $ts.Import(45, $import_xml)
|
||||||
|
exit $import_result.ReturnValue
|
||||||
|
|
||||||
|
- name: write certreq file
|
||||||
|
win_copy:
|
||||||
|
content: |-
|
||||||
|
[NewRequest]
|
||||||
|
Subject = "CN={{ rds_cert_suject }}"
|
||||||
|
KeyLength = 2048
|
||||||
|
KeyAlgorithm = RSA
|
||||||
|
MachineKeySet = true
|
||||||
|
RequestType = Cert
|
||||||
|
KeyUsage = 0xA0 ; Digital Signature, Key Encipherment
|
||||||
|
[EnhancedKeyUsageExtension]
|
||||||
|
OID=1.3.6.1.5.5.7.3.1 ; Server Authentication
|
||||||
|
dest: '{{test_win_rds_settings_path}}\certreq.txt'
|
||||||
|
|
||||||
|
- name: create self signed cert from certreq
|
||||||
|
win_command: certreq -new -machine {{test_win_rds_settings_path}}\certreq.txt {{test_win_rds_settings_path}}\certreqresp.txt
|
||||||
|
|
||||||
|
- name: register certificate thumbprint
|
||||||
|
raw: '(gci Cert:\LocalMachine\my | ? {$_.subject -eq "CN={{ rds_cert_suject }}"})[0].Thumbprint'
|
||||||
|
register: rds_cert_thumbprint
|
||||||
|
|
||||||
|
- include_tasks: tests.yml
|
||||||
|
|
||||||
|
always:
|
||||||
|
- name: restore RDS base configuration
|
||||||
|
win_shell: |
|
||||||
|
$ts = Get-WmiObject Win32_TSGatewayServer -namespace root\cimv2\TerminalServices
|
||||||
|
$import_xml = Get-Content {{test_win_rds_settings_path}}\rds_base_cfg.xml
|
||||||
|
$import_result = $ts.Import(45, $import_xml)
|
||||||
|
exit $import_result.ReturnValue
|
||||||
|
|
||||||
|
- name: remove certificate
|
||||||
|
raw: 'remove-item cert:\localmachine\my\{{ item }} -force -ea silentlycontinue'
|
||||||
|
with_items:
|
||||||
|
- "{{ rds_cert_thumbprint.stdout_lines[0] }}"
|
||||||
|
|
||||||
|
- name: cleanup test artifacts
|
||||||
|
win_file:
|
||||||
|
path: '{{test_win_rds_settings_path}}'
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
when: module_available.rc == 0
|
@ -0,0 +1,89 @@
|
|||||||
|
---
|
||||||
|
- name: test change RDS settings (check mode)
|
||||||
|
win_rds_settings:
|
||||||
|
max_connections: 50
|
||||||
|
certificate_hash: '{{rds_cert_thumbprint.stdout_lines[0]}}'
|
||||||
|
ssl_bridging: https_https
|
||||||
|
enable_only_messaging_capable_clients: yes
|
||||||
|
register: configure_rds_check
|
||||||
|
check_mode: yes
|
||||||
|
|
||||||
|
- name: get result of change RDS settings (check mode)
|
||||||
|
win_shell: |
|
||||||
|
Import-Module RemoteDesktopServices
|
||||||
|
(Get-Item RDS:\GatewayServer\MaxConnections).CurrentValue
|
||||||
|
(Get-Item RDS:\GatewayServer\SSLCertificate\Thumbprint).CurrentValue
|
||||||
|
(Get-Item RDS:\GatewayServer\SSLBridging).CurrentValue
|
||||||
|
(Get-Item RDS:\GatewayServer\EnableOnlyMessagingCapableClients).CurrentValue
|
||||||
|
register: configure_rds_actual_check
|
||||||
|
|
||||||
|
- name: assert results of change RDS settings (check mode)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- configure_rds_check.changed == true
|
||||||
|
- configure_rds_actual_check.stdout_lines[0] != "50"
|
||||||
|
- configure_rds_actual_check.stdout_lines[1] != rds_cert_thumbprint.stdout_lines[0]
|
||||||
|
- configure_rds_actual_check.stdout_lines[2] == "0"
|
||||||
|
- configure_rds_actual_check.stdout_lines[3] == "0"
|
||||||
|
|
||||||
|
- name: test change RDS settings
|
||||||
|
win_rds_settings:
|
||||||
|
max_connections: 50
|
||||||
|
certificate_hash: '{{rds_cert_thumbprint.stdout_lines[0]}}'
|
||||||
|
ssl_bridging: https_https
|
||||||
|
enable_only_messaging_capable_clients: yes
|
||||||
|
register: configure_rds
|
||||||
|
|
||||||
|
- name: get result of change RDS settings
|
||||||
|
win_shell: |
|
||||||
|
Import-Module RemoteDesktopServices
|
||||||
|
(Get-Item RDS:\GatewayServer\MaxConnections).CurrentValue
|
||||||
|
(Get-Item RDS:\GatewayServer\SSLCertificate\Thumbprint).CurrentValue
|
||||||
|
(Get-Item RDS:\GatewayServer\SSLBridging).CurrentValue
|
||||||
|
(Get-Item RDS:\GatewayServer\EnableOnlyMessagingCapableClients).CurrentValue
|
||||||
|
register: configure_rds_actual
|
||||||
|
|
||||||
|
- name: assert results of change RDS settings
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- configure_rds.changed == true
|
||||||
|
- configure_rds_actual.stdout_lines[0] == "50"
|
||||||
|
- configure_rds_actual.stdout_lines[1] == rds_cert_thumbprint.stdout_lines[0]
|
||||||
|
- configure_rds_actual.stdout_lines[2] == "2"
|
||||||
|
- configure_rds_actual.stdout_lines[3] == "1"
|
||||||
|
|
||||||
|
- name: test change RDS settings (idempotent)
|
||||||
|
win_rds_settings:
|
||||||
|
max_connections: 50
|
||||||
|
certificate_hash: '{{rds_cert_thumbprint.stdout_lines[0]}}'
|
||||||
|
ssl_bridging: https_https
|
||||||
|
enable_only_messaging_capable_clients: yes
|
||||||
|
register: configure_rds_again
|
||||||
|
|
||||||
|
- name: assert results of change RDS settings (idempotent)
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- configure_rds_again.changed == false
|
||||||
|
|
||||||
|
- name: test disable connection limit
|
||||||
|
win_rds_settings:
|
||||||
|
max_connections: -1
|
||||||
|
register: disable_limit
|
||||||
|
|
||||||
|
- name: get result of disable connection limit
|
||||||
|
win_shell: |
|
||||||
|
Import-Module RemoteDesktopServices
|
||||||
|
(Get-Item RDS:\GatewayServer\MaxConnections).CurrentValue -eq (Get-Item RDS:\GatewayServer\MaxConnectionsAllowed).CurrentValue
|
||||||
|
register: disable_limit_actual
|
||||||
|
|
||||||
|
- name: assert results of disable connection limit
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- disable_limit.changed == true
|
||||||
|
- disable_limit_actual.stdout_lines[0] == "True"
|
||||||
|
|
||||||
|
- name: fail with invalid certificate thumbprint
|
||||||
|
win_rds_settings:
|
||||||
|
certificate_hash: 72E8BD0216FA14100192A3E8B7B150C65B4B0817
|
||||||
|
register: fail_invalid_cert
|
||||||
|
failed_when: fail_invalid_cert.msg is not search('Unable to locate certificate')
|
@ -0,0 +1,58 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-16"?>
|
||||||
|
<?TSGateway version="1.0"?>
|
||||||
|
<TsgServer>
|
||||||
|
<ServerName>{{ ansible_hostname }}</ServerName>
|
||||||
|
<ServerSettings>
|
||||||
|
<MaxConnections>4294967295</MaxConnections>
|
||||||
|
<UnlimitedConnections>1</UnlimitedConnections>
|
||||||
|
<CentralCapEnabled>0</CentralCapEnabled>
|
||||||
|
<RequestSOH>0</RequestSOH>
|
||||||
|
<OnlyConsentCapableClients>0</OnlyConsentCapableClients>
|
||||||
|
<LogEvents>
|
||||||
|
<LogEvent>
|
||||||
|
<Name>LogChannelDisconnect</Name>
|
||||||
|
<Enabled>1</Enabled>
|
||||||
|
</LogEvent>
|
||||||
|
<LogEvent>
|
||||||
|
<Name>LogFailureChannelConnect</Name>
|
||||||
|
<Enabled>1</Enabled>
|
||||||
|
</LogEvent>
|
||||||
|
<LogEvent>
|
||||||
|
<Name>LogFailureConnectionAuthorizationCheck</Name>
|
||||||
|
<Enabled>1</Enabled>
|
||||||
|
</LogEvent>
|
||||||
|
<LogEvent>
|
||||||
|
<Name>LogFailureResourceAuthorizationCheck</Name>
|
||||||
|
<Enabled>1</Enabled>
|
||||||
|
</LogEvent>
|
||||||
|
<LogEvent>
|
||||||
|
<Name>LogSuccessfulChannelConnect</Name>
|
||||||
|
<Enabled>1</Enabled>
|
||||||
|
</LogEvent>
|
||||||
|
<LogEvent>
|
||||||
|
<Name>LogSuccessfulConnectionAuthorizationCheck</Name>
|
||||||
|
<Enabled>1</Enabled>
|
||||||
|
</LogEvent>
|
||||||
|
<LogEvent>
|
||||||
|
<Name>LogSuccessfulResourceAuthorizationCheck</Name>
|
||||||
|
<Enabled>1</Enabled>
|
||||||
|
</LogEvent>
|
||||||
|
</LogEvents>
|
||||||
|
<AuthenticationPlugin>native</AuthenticationPlugin>
|
||||||
|
<AuthorizationPlugin>native</AuthorizationPlugin>
|
||||||
|
<ConsentMessageText/>
|
||||||
|
<AdminMessageText/>
|
||||||
|
<AdminMsgStartDate/>
|
||||||
|
<AdminMsgEndDate/>
|
||||||
|
<SslBridging>0</SslBridging>
|
||||||
|
<HttpIPAddress>*</HttpIPAddress>
|
||||||
|
<UdpIPAddress>*</UdpIPAddress>
|
||||||
|
<HttpPort>443</HttpPort>
|
||||||
|
<UdpPort>3391</UdpPort>
|
||||||
|
<IsUdpEnabled>1</IsUdpEnabled>
|
||||||
|
<EnforceChannelBinding>1</EnforceChannelBinding>
|
||||||
|
</ServerSettings>
|
||||||
|
<Caps/>
|
||||||
|
<Raps/>
|
||||||
|
<ResourceGroups/>
|
||||||
|
</TsgServer>
|
Loading…
Reference in New Issue