From 206b6ebe0d902adbc53138c1548314690afd5d79 Mon Sep 17 00:00:00 2001 From: Matt Davis Date: Tue, 2 Jan 2018 20:25:46 -0800 Subject: [PATCH] fix PS type conversion failure when using "all" profiles (#34383) * obscure type promotion issue in some versions of Powershell causes [int]::MaxValue to be promoted to [int64] when doing a COM property get or set. Since the "All" profiles value of 0x7FFFFFFF is [int]::MaxValue, it would trigger "Specified cast is not valid" when modifying a rule that's already set to All Profiles or trying to be. * Fixed catch-all error handler to include exception detail * Added test converage for this case --- .../modules/windows/win_firewall_rule.ps1 | 16 +++++++++++++--- .../targets/win_firewall_rule/tasks/main.yml | 17 +++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/lib/ansible/modules/windows/win_firewall_rule.ps1 b/lib/ansible/modules/windows/win_firewall_rule.ps1 index f5f1760991..0ef7bc1935 100644 --- a/lib/ansible/modules/windows/win_firewall_rule.ps1 +++ b/lib/ansible/modules/windows/win_firewall_rule.ps1 @@ -137,7 +137,8 @@ function New-FWRule if ($remoteAddresses -and $remoteAddresses -ne "any") { $rule.RemoteAddresses = $remoteAddresses } if ($direction) { $rule.Direction = Parse-Direction -directionStr $direction } if ($action) { $rule.Action = Parse-Action -actionStr $action } - if ($profiles) { $rule.Profiles = Parse-Profiles -profilesList $profiles } + # Profiles value cannot be a uint32, but the "all profiles" value (0x7FFFFFFF) will often become a uint32, so must cast to [int] + if ($profiles) { $rule.Profiles = [int](Parse-Profiles -profilesList $profiles) } if ($interfaceTypes -and @(Compare-Object $interfaceTypes @("any")).Count -ne 0) { $rule.InterfaceTypes = Parse-InterfaceTypes -interfaceTypes $interfaceTypes } if ($edgeTraversalOptions -and $edgeTraversalOptions -ne "no") { # EdgeTraversalOptions property exists only from Windows 7/Windows Server 2008 R2: https://msdn.microsoft.com/en-us/library/windows/desktop/dd607256(v=vs.85).aspx @@ -260,7 +261,14 @@ try { } if (-not $check_mode) { - $existingRule.$prop = $rule.$prop + # Profiles value cannot be a uint32, but the "all profiles" value (0x7FFFFFFF) will often become a uint32, so must cast to [int] + # to prevent InvalidCastException under PS5+ + If($prop -eq 'Profiles') { + $existingRule.Profiles = [int] $rule.$prop + } + Else { + $existingRule.$prop = $rule.$prop + } } $result.changed = $true } @@ -274,7 +282,9 @@ try { } } } catch [Exception] { - Fail-Json $result $_.Exception.Message + $ex = $_ + $result['exception'] = $($ex | Out-String) + Fail-Json $result $ex.Exception.Message } Exit-Json $result diff --git a/test/integration/targets/win_firewall_rule/tasks/main.yml b/test/integration/targets/win_firewall_rule/tasks/main.yml index 6d69d4e237..b4d2d1c6b0 100644 --- a/test/integration/targets/win_firewall_rule/tasks/main.yml +++ b/test/integration/targets/win_firewall_rule/tasks/main.yml @@ -360,6 +360,23 @@ that: - add_firewall_rule_with_string_profiles.changed == true +- name: Set firewall rule profile back to 'all' + win_firewall_rule: + name: http + enabled: yes + state: present + localport: 80 + action: allow + direction: in + protocol: tcp + profiles: [Domain, Public, Private] + register: add_firewall_rule_with_string_profiles + +- name: Check that setting firewall rule profile back to 'all' succeeds with a change + assert: + that: + - add_firewall_rule_with_string_profiles.changed == true + - name: Add firewall rule with profiles in list format win_firewall_rule: name: http