Repository: ansible/ansible
Pull request: win_iis_webbinding rewrite
##### SUMMARY
<!--- Describe the change, including rationale and design decisions -->

<!---
If you are fixing an existing issue, please include "Fixes #nnn" in your
commit message and your description; but you should still explain what
the change does.
-->

I'm expecting that this will probably fail the Shippable testing until this is fixed: https://github.com/ansible/ansible/issues/33273, but figured I'd do the PR while it's fresh to start the discussion.

- Added better error handling
- Added check mode
- Added testing
- Added the ability to modify existing ssl bindings (cert and ssl flags)
- Added the ability to set SNI
- Added some new useful return info
- Added the ability to bulk remove bindings based on port/protocol
- Updated docs

The core functionality is mostly the same, but here is what has changed:

- Removed "stat" functionality. It became too complicated to keep it in. Without adding a new param called "stat" or something along those lines, it was impossible to determine at what point you just return data versus making a modification. It also didn't feel like it belonged there.
- Changed the way data was being returned. Previously it was getting put into a json object with a different top level identifier based on the operation type (added, matched, removed). Now it always returns into binding_info and there is a new return called operation_type.


##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - New Module Pull Request

##### COMPONENT NAME
<!--- Name of the module, plugin, module or task -->
win_iis_webbinding

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```

```


##### ADDITIONAL INFORMATION
<!---
Include additional information to help people understand the change here.
For bugs that don't have a linked bug report, a step-by-step reproduction
of the problem is helpful.
  -->
This one felt like it took a bit more error handling than usual, but it was mostly due to poor PowerShell support for things revolving around bindings...particularly the https ones. Generally the "naked" commands either won't error on invalid actions (letting do things like make conflicting bindings), or if they do, they'd return odd errors that didn't explain what was going on.
<!--- Paste verbatim command output below, e.g. before and after your change -->
```

```


Problem statement:
windows: ansible fails to connect after IIS binding with SNI enabled is added
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Bug Report


##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
ansible winrm connections

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
ansible 2.5.0 (win_iis_webbinding_rewrite e61d361743) last updated 2017/11/22 21:51:05 (GMT +000)
  config file = None
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /opt/ansible/lib/ansible
  executable location = /opt/ansible/bin/ansible
  python version = 2.7.12 (default, Nov  2 2017, 19:20:38) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]

```
I've also tested with 2.4 and 2.3 stable and issue is present in both.

##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste the results of "ansible-config dump --only-changed"

Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).

-->
no settings changed. 

##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->
ansible: amazon linux latest

targets: server 2012r2 and 2016. I've tested against both the current images and ones that are several months old with same results.

##### SUMMARY
<!--- Explain the problem briefly -->
Adding a binding to a website in IIS with SNI enabled causes ansible to begin failing to connect with the following message:

```
2k12 | UNREACHABLE! => {
    "changed": false,
    "msg": "ssl: ('Connection aborted.', error(104, 'Connection reset by peer'))",
    "unreachable": true
}
```

I've verified that the binding is valid. The website is still accessible without issue. I'm able to connect via Powershell Remoting without issue. Nothing is logged anywhere in the event viewer on the server in regards to the connection failure. I've tested against 2k12 and 2k16 with both old and current images in AWS.

Bindings without SNI do not seem to cause any problems

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

Using the gui, add an https binding in IIS with
- protocol: https
- ip: *
- port: 443
- hostheader: test.com
- enable SNI checked
- pick any certificate available. If none are present go to the iis root > certificates > create self signed

Just run win_ping against it and it will fail with the error above

running the following in powershell will fix the problem...obviously dont do this on a server that matters.

get-webbinding | remove-webbinding
gci iis:\sslbindings | ? port -eq 443 | remove-item
reboot-computer

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
ping success

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
<!--- Paste verbatim command output between quotes below -->
```
[root@ip-10-5-10-122 ansible]# ansible -i test/integration/inventory.winrm 2k12 -m win_ping -vvvv
ansible 2.5.0 (win_iis_webbinding_rewrite e61d361743) last updated 2017/11/22 21:51:05 (GMT +000)
  config file = None
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /opt/ansible/lib/ansible
  executable location = /opt/ansible/bin/ansible
  python version = 2.7.12 (default, Nov  2 2017, 19:20:38) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
No config file found; using defaults
setting up inventory plugins
Parsed /opt/ansible/test/integration/inventory.winrm inventory source with ini plugin
Loading callback plugin minimal of type stdout, v2.0 from /opt/ansible/lib/ansible/plugins/callback/__init__.pyc
META: ran handlers
Using module file /opt/ansible/lib/ansible/modules/windows/win_ping.ps1
<10.5.10.16> ESTABLISH WINRM CONNECTION FOR USER: administrator on PORT 5986 TO 10.5.10.16
2k12 | UNREACHABLE! => {
    "changed": false,
    "msg": "ssl: ('Connection aborted.', error(104, 'Connection reset by peer'))",
    "unreachable": true
}

```

Hints from issue discussion:
Files identified in the description:
* [lib/ansible/plugins/connection](https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/connection)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
pinging @nitzmahone 
Was this working previously?
Off the top of my head, it's probably an issue with OpenSSL/urllib3 on Amazon Linux puking on the SNI handshake, especially if you're using an OS-packaged version of requests (since they're often ancient and have the normally-vendored bits that might have some hope of supporting SNI stripped out). 

Curious how you installed requests/urllib3 and pywinrm, and if you're able to repro on something like Fedora or Ubuntu Xenial+ with pip-installed requests and pywinrm...
Also, you said you were able to connect via PS remoting, but did you force it to use 5986/SSL? If not, it's probably doing message encryption over 5985, as that's the default...
@alikins  Thanks. I was able to reproduce it in 2.3 and 2.4.

@nitzmahone Thanks. I did try 5986 and was able to connect using psremoting while Ansible was failing on port 5986. I checked and it looks like pip installed urllib 1.22...I tested it with both python 2.7 and 3.5. I'll see if I can get a test done using Ubuntu today and update with more info after that.

I'm wondering if it's some issue with ansible checking for the compatibility listener on 443? It seems strange that changes to a port other than what's defined in the inventory as winrm would cause ansible to begin failing. 
It's been awhile since I played with SNI on Windows, but IIRC the http.sys SNI handshake option is global and disabled by default; if you've turned it on, everything that uses http.sys will include the SNI handshake stuff even if the listener in question (eg winrm) is only configured for a single cert. 

Regardless, the connection handling is several layers below Ansible's code, so assuming it truly is a client issue and not a server config issue, tracking down precisely where will be "fun".
Darn =/

Unfortunately I was able to reproduce it on Ubuntu Xenial

1. Launch new instance from quick start ubuntu 16 ami
2. apt install python python-setuptools
3. easy_install pip
4. cloned ansible
5. cd to ansible pip install -r requirements.txt
6. pip install urllib3 xmltodict pywinrm
7. copy over inventory.winrm file to test/integration/
8. ran win_ping got same error

On the windows side:

1. Launch new 2012r2 instance from quick start ami's
2. 
```
Install-WindowsFeature web-server -IncludeAllSubFeature -IncludeManagementTools
(curl https://raw.githubusercontent.com/ansible/ansible/devel/examples/scripts/ConfigureRemotingForAnsible.ps1).content > C:\AnsibleWinRM.ps1
C:\AnsibleWinRM.ps1 -SubjectName $HostName -CertValidityDays 3650 -Verbose
```
3. manually add SNI enabled https binding in IIS via the gui with settings described above

I'll keep troubleshooting but getting fairly stumped at this point

Just curious- what happens if you do the WinRM enable script *after* SNI is live? I know that's probably not a realistic process for you, but just wondering if the late SNI enable is what's screwing up the listener config (if so, we could probably add a -EnableSNI switch or something to the script)
I'm still pretty sure this is a client stack issue of some sort, but would like to prune the low-hanging fruit first :D

Commit message: updated test to remove tests as filters

Patch to review:
diff --git a/lib/ansible/modules/windows/win_iis_webbinding.ps1 b/lib/ansible/modules/windows/win_iis_webbinding.ps1
index 9b212ff968f3e1..8f020c31961709 100644
--- a/lib/ansible/modules/windows/win_iis_webbinding.ps1
+++ b/lib/ansible/modules/windows/win_iis_webbinding.ps1
@@ -1,131 +1,454 @@
 #!powershell
 
-# (c) 2015, Henrik Wallström <henrik@wallstroms.nu>
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
-
-
-# WANT_JSON
-# POWERSHELL_COMMON
-
-$params = Parse-Args $args;
-
-$name = Get-AnsibleParam $params -name "name" -failifempty $true
-$state = Get-AnsibleParam $params "state" -default "present" -validateSet "present","absent"
-$host_header = Get-AnsibleParam $params -name "host_header"
-$protocol = Get-AnsibleParam $params -name "protocol"
-$port = Get-AnsibleParam $params -name "port"
-$ip = Get-AnsibleParam $params -name "ip"
-$certificatehash = Get-AnsibleParam $params -name "certificate_hash" -default $false
-$certificateStoreName = Get-AnsibleParam $params -name "certificate_store_name" -default "MY"
+# Copyright: (c) 2017, Noah Sparks <nsparks@outlook.com>
+# Copyright: (c) 2015, Henrik Wallström <henrik@wallstroms.nu>
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
 
-$binding_parameters = @{
-  Name = $name
-};
+#Requires -Module Ansible.ModuleUtils.Legacy
+
+$params = Parse-Args -arguments $args -supports_check_mode $true
+$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
+
+$name = Get-AnsibleParam $params -name "name" -type str -failifempty $true -aliases 'website'
+$state = Get-AnsibleParam $params "state" -default "present" -validateSet "present","absent"
+$host_header = Get-AnsibleParam $params -name "host_header" -type str
+$protocol = Get-AnsibleParam $params -name "protocol" -type str -default 'http'
+$port = Get-AnsibleParam $params -name "port" -default '80'
+$ip = Get-AnsibleParam $params -name "ip" -default '*'
+$certificateHash = Get-AnsibleParam $params -name "certificate_hash" -type str -default ([string]::Empty)
+$certificateStoreName = Get-AnsibleParam $params -name "certificate_store_name" -type str -default ([string]::Empty)
+$sslFlags = Get-AnsibleParam $params -name "ssl_flags" -default '0' -ValidateSet '0','1','2','3'
 
-If ($host_header) {
-  $binding_parameters.HostHeader = $host_header
+$result = @{
+  changed = $false
 }
 
-If ($protocol) {
-  $binding_parameters.Protocol = $protocol
+#################
+### Functions ###
+#################
+function Create-BindingInfo {
+    $ht = @{
+        'bindingInformation' = $args[0].bindingInformation
+        'ip' = $args[0].bindingInformation.split(':')[0]
+        'port' = [int]$args[0].bindingInformation.split(':')[1]
+        'hostheader' = $args[0].bindingInformation.split(':')[2]
+        #'isDsMapperEnabled' = $args[0].isDsMapperEnabled
+        'protocol' = $args[0].protocol
+        'certificateStoreName' = $args[0].certificateStoreName
+        'certificateHash' = $args[0].certificateHash
+    }
+
+    #handle sslflag support
+    If ([version][System.Environment]::OSVersion.Version -lt [version]'6.2')
+    {
+        $ht.sslFlags = 'not supported'
+    }
+    Else
+    {
+        $ht.sslFlags = [int]$args[0].sslFlags
+    }
+
+    Return $ht
 }
 
-If ($port) {
-  $binding_parameters.Port = $port
+# Used instead of get-webbinding to ensure we always return a single binding
+# pass it $binding_parameters hashtable
+function Get-SingleWebBinding {
+    $bind_search_splat = @{
+        'name' = $args[0].name
+        'protocol' = $args[0].protocol
+        'port' = $args[0].port
+        'ip' = $args[0].ip
+        'hostheader' = $args[0].hostheader
+    }
+
+    # if no bindings exist, get-webbinding fails with an error that can't be ignored via error actions on older systems
+    # let's ignore that specific error
+    If (-not $bind_search_splat['hostheader'])
+    {
+        Try {
+            Get-WebBinding @bind_search_splat | Where-Object {$_.BindingInformation.Split(':')[-1] -eq [string]::Empty}
+        }
+        Catch {
+            If (-not $_.Exception.Message.CompareTo('Cannot process argument because the value of argument "obj" is null. Change the value of argument "obj" to a non-null value'))
+            {
+                Throw $_.Exception.Message
+            }
+        }
+    }
+    Else
+    {
+        Try {
+            Get-WebBinding @bind_search_splat
+        }
+        Catch {
+            If (-not $_.Exception.Message.CompareTo('Cannot process argument because the value of argument "obj" is null. Change the value of argument "obj" to a non-null value'))
+            {
+                Throw $_.Exception.Message
+            }
+        }
+    }
 }
 
-If ($ip) {
-  $binding_parameters.IPAddress = $ip
+Function Get-CertificateSubjects {
+Param (
+[string]$CertPath
+)
+    If (-Not (Test-Path $CertPath) )
+    {
+        Fail-Json -obj $result -message "Unable to locate certificate at $CertPath"
+    }
+
+    $cert = get-item $CertPath
+
+    If ([version][System.Environment]::OSVersion.Version -ge [version]6.2)
+    {
+        $cert.DnsNameList.unicode
+    }
+    Else
+    {
+        $san = $cert.extensions | Where-Object {$_.Oid.FriendlyName -eq 'Subject Alternative Name'}
+        If ($san)
+        {
+            $san.Format(1) -split '\r\n' | Where-Object {$_} | ForEach-Object {
+                ($_ -split '=')[-1]
+            }
+        }
+        Else
+        {
+            If ($cert.subject -like "*,*")
+            {
+                ($cert.Subject | Select-String "CN=(.*?),?").matches.groups[-1].value
+            }
+            Else
+            {
+                $cert.subject -replace "CN=",''
+            }
+        }
+    }
 }
 
+
+
+#############################
+### Pre-Action Validation ###
+#############################
+$os_version = [version][System.Environment]::OSVersion.Version
+
 # Ensure WebAdministration module is loaded
-if ((Get-Module "WebAdministration" -ErrorAction SilentlyContinue) -eq $null){
-  Import-Module WebAdministration
+If ($os_version -lt [version]'6.1')
+{
+    Try {
+        Add-PSSnapin WebAdministration
+    }
+    Catch {
+        Fail-Json -obj $result -message "The WebAdministration snap-in is not present. Please make sure it is installed."
+    }
 }
-
-function Create-Binding-Info {
-  return @{
-    "bindingInformation" = $args[0].bindingInformation
-    "certificateHash" = $args[0].certificateHash
-    "certificateStoreName" = $args[0].certificateStoreName
-    "isDsMapperEnabled" = $args[0].isDsMapperEnabled
-    "protocol" = $args[0].protocol
-    "sslFlags" = $args[0].sslFlags
-  }
+Else
+{
+    Try {
+        Import-Module WebAdministration
+    }
+    Catch {
+        Fail-Json -obj $result -message "Failed to load WebAdministration module. Is IIS installed? $($_.Exception.Message)"
+    }
 }
 
-# Result
-$result = @{
-  changed = $false
-  parameters = $binding_parameters
-  matched = @()
-  removed = @()
-  added = @()
-};
+# ensure website targetted exists. -Name filter doesn't work on 2k8r2 so do where-object instead
+$website_check = get-website | Where-Object {$_.name -eq $name}
+If (-not $website_check)
+{
+    Fail-Json -obj $result -message "Unable to retrieve website with name $Name. Make sure the website name is valid and exists."
+}
 
-# Get bindings matching parameters
-$curent_bindings = Get-WebBinding @binding_parameters
-$curent_bindings | Foreach {
-  $result.matched += Create-Binding-Info $_
+# if OS older than 2012 (6.2) and ssl flags are set, fail. Otherwise toggle sni_support
+If ($os_version -lt [version]'6.2')
+{
+    If ($sslFlags -ne 0)
+    {
+        Fail-Json -obj $result -message "SNI and Certificate Store support is not available for systems older than 2012 (6.2)"
+    }
+    $sni_support = $false #will cause the sslflags check later to skip
+}
+Else
+{
+    $sni_support = $true
 }
 
-try {
-  # Add
-  if (-not $curent_bindings -and $state -eq 'present') {
-    New-WebBinding @binding_parameters -Force
+# make sure ssl flags only specified with https protocol
+If ($protocol -ne 'https' -and $sslFlags -gt 0)
+{
+    Fail-Json -obj $result -message "SSLFlags can only be set for HTTPS protocol"
+}
 
-    # Select certificate
-    if($certificateHash -ne $FALSE) {
+# validate certificate details if provided
+# we don't do anything with cert on state: absent, so only validate present
+If ($certificateHash -and $state -eq 'present')
+{
+    If ($protocol -ne 'https')
+    {
+        Fail-Json -obj $result -message "You can  only provide a certificate thumbprint when protocol is set to https"
+    }
 
-      $ip = $binding_parameters["IPAddress"]
-      if((!$ip) -or ($ip -eq "*")) {
-        $ip = "0.0.0.0"
-      }
+    #apply default for cert store name
+    If (-Not $certificateStoreName)
+    {
+        $certificateStoreName = 'my'
+    }
 
-      $port = $binding_parameters["Port"]
-      if(!$port) {
-        $port = 443
-      }
+    #validate cert path
+    $cert_path = "cert:\LocalMachine\$certificateStoreName\$certificateHash"
+    If (-Not (Test-Path $cert_path) )
+    {
+        Fail-Json -obj $result -message "Unable to locate certificate at $cert_path"
+    }
 
-      $result.port = $port
-      $result.ip = $ip
+    #check if cert is wildcard and update results with useful info.
+    $cert_subjects = Get-CertificateSubjects $cert_path
+    $result.certificate_subjects = $cert_subjects
+    If ($cert_subjects | Where-Object {$_ -match '^\*'})
+    {
+        $cert_is_wildcard = $true
+        $result.cert_is_wildcard = $cert_is_wildcard
+    }
+    Else
+    {
+        $cert_is_wildcard = $false
+        $result.cert_is_wildcard = $cert_is_wildcard
+    }
 
-      Push-Location IIS:\SslBindings\
-      Get-Item Cert:\LocalMachine\$certificateStoreName\$certificateHash | New-Item  "$($ip)!$($port)"
-      Pop-Location
+    If ($os_version -lt [version]6.2 -and $host_header -and -not $cert_is_wildcard)
+    {
+        Fail-Json -obj $result -message "You cannot specify host headers with SSL unless it is a wildcard certificate."
     }
+    Elseif ($os_version -ge [version]6.2 -and $host_header -and (-not $cert_is_wildcard -and $sslFlags -eq 0))
+    {
+        Fail-Json -obj $result -message "You cannot specify host headers with SSL unless it is a wildcard certificate or SNI is enabled."
+    }
+}
 
-    $result.added += Create-Binding-Info (Get-WebBinding @binding_parameters)
-    $result.changed = $true
-  }
+# make sure binding info is valid for central cert store if sslflags -gt 1
+If ($sslFlags -gt 1 -and ($certificateHash -ne [string]::Empty -or $certificateStoreName -ne [string]::Empty))
+{
+    Fail-Json -obj $result -message "You set sslFlags to $sslFlags. This indicates you wish to use the Central Certificate Store feature.
+    This cannot be used in combination with certficiate_hash and certificate_store_name. When using the Central Certificate Store feature,
+    the certificate is automatically retrieved from the store rather than manually assigned to the binding."
+}
+
+# make sure host_header: '*' only present when state: absent
+If ($host_header -match '^\*$' -and $state -ne 'absent')
+{
+    Fail-Json -obj $result -message "host_header: '*' can only be used in combinaiton with state: absent"
+}
+
+##########################
+### start action items ###
+##########################
+
+# create binding search splat
+$binding_parameters = @{
+  Name = $name
+  Protocol = $protocol
+  Port = $port
+  IPAddress = $ip
+}
 
-  # Remove
-  if ($curent_bindings -and $state -eq 'absent') {
-    $curent_bindings | foreach {
-      Remove-WebBinding -InputObject $_
-      $result.removed += Create-Binding-Info $_
+# insert host header to search if specified, otherwise it will return * (all bindings matching protocol/ip)
+If ($host_header)
+{
+    $binding_parameters.HostHeader = $host_header
+}
+
+# Get bindings matching parameters
+Try {
+    $current_bindings = Get-SingleWebBinding $binding_parameters
+}
+Catch {
+    Fail-Json -obj $result -message "Failed to retrieve bindings with Get-SingleWebBinding - $($_.Exception.Message)"
+}
+
+################################################
+### Remove binding or exit if already absent ###
+################################################
+If ($current_bindings -and $state -eq 'absent')
+{
+    Try {
+        # will remove multiple objects in the case of * host header
+        $current_bindings | Remove-WebBinding -WhatIf:$check_mode
+        $result.changed = $true
+    }
+    Catch {
+        Fail-Json -obj $result -message "Failed to remove the binding from IIS - $($_.Exception.Message)"
     }
-    $result.changed = $true
-  }
 
+    # removing bindings from iis may not also remove them from iis:\sslbindings
 
+    $result.operation_type = 'removed'
+    $result.binding_info = $current_bindings | ForEach-Object {Create-BindingInfo $_}
+    Exit-Json -obj $result
 }
-catch {
-  Fail-Json $result $_.Exception.Message
+ElseIf (-Not $current_bindings -and $state -eq 'absent')
+{
+    # exit changed: false since it's already gone
+    Exit-Json -obj $result
+}
+
+
+################################
+### Modify existing bindings ###
+################################
+<#
+since we have already.binding_info the parameters available to get-webbinding,
+we just need to check here for the ones that are not available which are the
+ssl settings (hash, store, sslflags). If they aren't set we update here, or
+exit with changed: false
+#>
+ElseIf ($current_bindings)
+{
+    #ran into a strange edge case in testing where I was able to retrieve bindings but not expand all the properties
+    #when adding a self-signed wildcard cert to a binding. it seemed to permanently break the binding. only removing it
+    #would cause the error to stop.
+    Try {
+        $null = $current_bindings |  Select-Object *
+    }
+    Catch {
+        Fail-Json -obj $result -message "Found a matching binding, but failed to expand it's properties (get-binding | FL *). In testing, this was caused by using a self-signed wildcard certificate. $($_.Exception.Message)"
+    }
+
+    # check if there is a match on the ssl parameters
+    If ( ($current_bindings.sslFlags -ne $sslFlags -and $sni_support) -or
+        $current_bindings.certificateHash -ne $certificateHash -or
+        $current_bindings.certificateStoreName -ne $certificateStoreName)
+    {
+        # match/update SNI
+        If ($current_bindings.sslFlags -ne $sslFlags -and $sni_support)
+        {
+            Try {
+                Set-WebBinding -Name $name -IPAddress $ip -Port $port -HostHeader $host_header -PropertyName sslFlags -value $sslFlags -whatif:$check_mode
+                $result.changed = $true
+            }
+            Catch {
+                Fail-Json -obj $result -message "Failed to update sslFlags on binding - $($_.Exception.Message)"
+            }
+
+            # Refresh the binding object since it has been changed
+            Try {
+                $current_bindings = Get-SingleWebBinding $binding_parameters
+            }
+            Catch {
+                Fail-Json -obj $result -message "Failed to refresh bindings after setting sslFlags - $($_.Exception.Message)"
+            }
+        }
+        # match/update certificate
+        If ($current_bindings.certificateHash -ne $certificateHash -or $current_bindings.certificateStoreName -ne $certificateStoreName)
+        {
+            If (-Not $check_mode)
+            {
+                Try {
+                    $current_bindings.AddSslCertificate($certificateHash,$certificateStoreName)
+                }
+                Catch {
+                    Fail-Json -obj $result -message "Failed to set new SSL certificate - $($_.Exception.Message)"
+                }
+            }
+        }
+        $result.changed = $true
+        $result.operation_type = 'updated'
+        $result.website_state = (Get-Website | Where-Object {$_.Name -eq $Name}).State
+        $result.binding_info = Create-BindingInfo (Get-SingleWebBinding $binding_parameters)
+        Exit-Json -obj $result #exit changed true
+    }
+    Else
+    {
+        $result.operation_type = 'matched'
+        $result.website_state = (Get-Website | Where-Object {$_.Name -eq $Name}).State
+        $result.binding_info = Create-BindingInfo (Get-SingleWebBinding $binding_parameters)
+        Exit-Json -obj $result #exit changed false
+    }
 }
 
-Exit-Json $result
+########################
+### Add new bindings ###
+########################
+ElseIf (-not $current_bindings -and $state -eq 'present')
+{
+    If ($certificateHash)
+    {
+        <#
+        Make sure a valid binding is specified. It's possible for another site to have a binding on the same IP:PORT. If
+        we bind to that same ip port without hostheader/sni it will cause a collision. Note, this check only matters for
+        https. Http will generate an error when new-webbinding is called if there is a conflict, unlike https.
+
+        I couldn't think of a good way to handle scenarios involving wildcards. There's just too many to think about and I
+        wouldn't want to potentially hard fail valid scenarios here that I did not consider...so those can still collide. We just skip
+        validation anytime an existing binding is a wildcard.
+
+        If a collision does occur, the website will be stopped. To help with this we'll return the website state into results.
+        #>
+
+        #use this instead of get-webbinding. on 2k8r2 get-webbinding fails with an error if a site with no bindings exists
+        $binding_matches = (Get-Website).bindings.collection | Where-Object {$_.BindingInformation -eq "$ip`:$port`:"}
+
+        #get dns names for all certs in matching bindings
+        $subjects = Foreach ($binding in $binding_matches)
+        {
+            $cert_path = "cert:\localmachine\$($binding.certificatestorename)\$($binding.certificatehash)"
+            Get-CertificateSubjects $cert_path
+        }
+
+        #skip validating scenarios where existing certs are wildcard
+        If (-not ($subjects | Where-Object {$_ -match "^\*"}))
+        {
+            If ($sslFlags -eq 0 -and $binding_matches -and $os_version -gt [version]6.2)
+            {
+                Fail-Json -obj $result -message "A conflicting binding has been found on the same ip $ip and port $port. To continue, you will either have to remove the offending binding or enable sni"
+            }
+            ElseIf ($binding_matches -and $os_version -lt [version]6.2)
+            {
+                Fail-Json -obj $result -message "A conflicting binding has been found on the same ip $ip and port $port. To continue you will need to remove the existing binding or assign a new IP or Port to this one"
+            }
+        }
+    }
+
+    # add binding. this creates the binding, but does not apply a certificate to it.
+    Try
+    {
+        If (-not $check_mode)
+        {
+            If ($sni_support)
+            {
+                New-WebBinding @binding_parameters -SslFlags $sslFlags -Force
+            }
+            Else
+            {
+                New-WebBinding @binding_parameters -Force
+            }
+        }
+        $result.changed = $true
+    }
+    Catch
+    {
+        $result.website_state = (Get-Website | Where-Object {$_.Name -eq $Name}).State
+        Fail-Json -obj $result -message "Failed at creating new binding (note: creating binding and adding ssl are separate steps) - $($_.Exception.Message)"
+    }
+
+    # add certificate to binding
+    If ($certificateHash -and -not $check_mode)
+    {
+        Try {
+            $new_binding = get-webbinding -Name $name -IPAddress $ip -port $port -Protocol $protocol -hostheader $host_header
+            $new_binding.addsslcertificate($certificateHash,$certificateStoreName)
+        }
+        Catch {
+            $result.website_state = (Get-Website | Where-Object {$_.Name -eq $Name}).State
+            Fail-Json -obj $result -message "Failed to set new SSL certificate - $($_.Exception.Message)"
+        }
+    }
+
+    $result.changed = $true
+    $result.operation_type = 'added'
+    $result.website_state = (Get-Website | Where-Object {$_.Name -eq $Name}).State
+    $result.binding_info = Create-BindingInfo (Get-SingleWebBinding $binding_parameters)
+    Exit-Json $result
+}
diff --git a/lib/ansible/modules/windows/win_iis_webbinding.py b/lib/ansible/modules/windows/win_iis_webbinding.py
index 24a666f0a92c29..8e709c5002c63c 100644
--- a/lib/ansible/modules/windows/win_iis_webbinding.py
+++ b/lib/ansible/modules/windows/win_iis_webbinding.py
@@ -1,22 +1,9 @@
 #!/usr/bin/python
 # -*- coding: utf-8 -*-
 
-# (c) 2015, Henrik Wallström <henrik@wallstroms.nu>
-#
-# This file is part of Ansible
-#
-# Ansible is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Ansible is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with Ansible.  If not, see <http://www.gnu.org/licenses/>.
+# Copyright: (c) 2017, Noah Sparks <nsparks@outlook.com>
+# Copyright: (c) 2017, Henrik Wallström <henrik@wallstroms.nu>
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
 
 
 ANSIBLE_METADATA = {'metadata_version': '1.1',
@@ -28,7 +15,7 @@
 ---
 module: win_iis_webbinding
 version_added: "2.0"
-short_description: Configures a IIS Web site.
+short_description: Configures a IIS Web site binding.
 description:
      - Creates, Removes and configures a binding to an existing IIS Web site
 options:
@@ -36,66 +23,50 @@
     description:
       - Names of web site
     required: true
-    default: null
-    aliases: []
+    aliases: website
   state:
     description:
       - State of the binding
     choices:
       - present
       - absent
-    required: false
-    default: null
-    aliases: []
+    default: present
   port:
     description:
       - The port to bind to / use for the new site.
-    required: false
-    default: null
-    aliases: []
+    default: 80
   ip:
     description:
       - The IP address to bind to / use for the new site.
-    required: false
-    default: null
-    aliases: []
+    default: '*'
   host_header:
     description:
       - The host header to bind to / use for the new site.
-    required: false
-    default: null
-    aliases: []
+      - For state absent, you can use '*' here to remove all bindings for a particular
+        protocol/ip/port combination.
   protocol:
     description:
       - The protocol to be used for the Web binding (usually HTTP, HTTPS, or FTP).
-    required: false
-    default: null
-    aliases: []
+    default: http
   certificate_hash:
     description:
-      - Certificate hash for the SSL binding. The certificate hash is the unique identifier for the certificate.
-    required: false
-    default: null
-    aliases: []
+      - Certificate hash (thumbprint) for the SSL binding. The certificate hash is the unique identifier for the certificate.
   certificate_store_name:
     description:
-      -  Name of the certificate store where the certificate for the binding is located.
-    required: false
-    default: "My"
-    aliases: []
-author: Henrik Wallström
+      - Name of the certificate store where the certificate for the binding is located.
+    default: "my"
+  ssl_flags:
+    description:
+      - This parameter is only valid on Server 2012 and newer.
+      - Primarily used for enabling and disabling server name indication (SNI).
+      - Set to 0 to disable SNI.
+      - Set to 1 to enable SNI.
+author:
+  - Noah Sparks (@nwsparks)
+  - Henrik Wallström
 '''
 
 EXAMPLES = r'''
-- name: Return binding information for an existing host
-  win_iis_webbinding:
-    name: Default Web Site
-
-- name: Return the HTTPS binding information for an existing host
-  win_iis_webbinding:
-    name: Default Web Site
-    protocol: https
-
 - name: Add a HTTP binding on port 9090
   win_iis_webbinding:
     name: Default Web Site
@@ -112,20 +83,76 @@
   win_iis_webbinding:
     name: Default Web Site
     protocol: https
+    port: 443
+    certificate_hash: B0D0FA8408FC67B230338FCA584D03792DA73F4C
     state: present
 
-- name: Add a HTTPS binding and select certificate to use
+- name: Add a HTTPS binding with host header and SNI enabled
   win_iis_webbinding:
     name: Default Web Site
     protocol: https
-    certificate_hash: B0D0FA8408FC67B230338FCA584D03792DA73F4C
+    port: 443
+    host_header: test.com
+    ssl_flags: 1
+    certificate_hash: D1A3AF8988FD32D1A3AF8988FD323792DA73F4C
     state: present
 
-- name: Website https biding to specific port
+- name: Remove all https bindings on port 443
   win_iis_webbinding:
     name: Default Web Site
     protocol: https
     port: 443
-    certificate_hash: D1A3AF8988FD32D1A3AF8988FD323792DA73F4C
-    state: present
+    host_header: '*'
+    state: absent
+'''
+
+RETURN = r'''
+cert_is_wildcard:
+  description:
+    - Tells you if the certificate you are using is a wildcard
+  returned: when certificate_hash is defined
+  type: boolean
+  sample: false
+  version_added: "2.5"
+certificate_subjects:
+  description:
+    - All of the subject names for the certificate you are using
+  returned: when certificate_hash is defined
+  type: list
+  sample: ["*.test.com","test.com"]
+  version_added: "2.5"
+website_state:
+  description:
+    - The state of the website being targetted
+    - Can be helpful in case you accidentally cause a binding collision
+      which can result in the targetted site being stopped
+  returned: always
+  type: string
+  sample: "Started"
+  version_added: "2.5"
+operation_type:
+  description:
+    - The type of operation performed
+    - Can be removed, updated, matched, or added
+  returned: on success
+  type: string
+  sample: "removed"
+  version_added: "2.5"
+binding_info:
+  description:
+    - Information on the binding being manipulated
+  returned: on success
+  type: dictionary
+  sample: |-
+    "binding_info": {
+      "bindingInformation": "127.0.0.1:443:",
+      "certificateHash": "FF3910CE089397F1B5A77EB7BAFDD8F44CDE77DD",
+      "certificateStoreName": "MY",
+      "hostheader": "",
+      "ip": "127.0.0.1",
+      "port": 443,
+      "protocol": "https",
+      "sslFlags": "not supported"
+    }
+  version_added: "2.5"
 '''
diff --git a/test/integration/targets/win_iis_webbinding/aliases b/test/integration/targets/win_iis_webbinding/aliases
new file mode 100644
index 00000000000000..ee0ed5974e96de
--- /dev/null
+++ b/test/integration/targets/win_iis_webbinding/aliases
@@ -0,0 +1 @@
+windows/ci/group2
diff --git a/test/integration/targets/win_iis_webbinding/defaults/main.yml b/test/integration/targets/win_iis_webbinding/defaults/main.yml
new file mode 100644
index 00000000000000..13f0bc333fa02d
--- /dev/null
+++ b/test/integration/targets/win_iis_webbinding/defaults/main.yml
@@ -0,0 +1,30 @@
+test_iis_site_name: default web site
+
+http_vars:
+  protocol: http
+  port: 80
+  ip: '*'
+
+http_header_vars:
+  protocol: http
+  port: 80
+  ip: '*'
+  header: test.com
+
+https_vars:
+  protocol: https
+  port: 443
+  ip: '*'
+
+https_header_vars:
+  protocol: https
+  port: 443
+  ip: '*'
+  header: test.com
+  ssl_flags: 1
+
+https_wc_vars:
+  protocol: https
+  port: 443
+  ip: '127.0.0.1'
+  header: wc.test.com
diff --git a/test/integration/targets/win_iis_webbinding/library/test_get_webbindings.ps1 b/test/integration/targets/win_iis_webbinding/library/test_get_webbindings.ps1
new file mode 100644
index 00000000000000..084b6a10574840
--- /dev/null
+++ b/test/integration/targets/win_iis_webbinding/library/test_get_webbindings.ps1
@@ -0,0 +1,122 @@
+#!powershell
+
+# Copyright: (c) 2017, Noah Sparks <nsparks@outlook.com>
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+#Requires -Module Ansible.ModuleUtils.Legacy
+#
+$params = Parse-Args -arguments $args -supports_check_mode $true
+$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
+
+$name = Get-AnsibleParam $params -name "name" -type str -failifempty $true -aliases 'website'
+#$state = Get-AnsibleParam $params "state" -default "present" -validateSet "present","absent"
+$host_header = Get-AnsibleParam $params -name "host_header" -type str
+$protocol = Get-AnsibleParam $params -name "protocol" -type str -default 'http'
+$port = Get-AnsibleParam $params -name "port" -type int -default '80'
+$ip = Get-AnsibleParam $params -name "ip" -default '*'
+$certificateHash = Get-AnsibleParam $params -name "certificate_hash" -type str
+$certificateStoreName = Get-AnsibleParam $params -name "certificate_store_name" -type str
+$sslFlags = Get-AnsibleParam $params -name "ssl_flags" -type int -default '0' -ValidateSet '0','1','2','3'
+
+$result = @{
+  changed = $false
+}
+
+function Create-BindingInfo {
+    $ht = @{
+        'bindingInformation' = $args[0].bindingInformation
+        'ip' = $args[0].bindingInformation.split(':')[0]
+        'port' = [int]$args[0].bindingInformation.split(':')[1]
+        'hostheader' = $args[0].bindingInformation.split(':')[2]
+        'isDsMapperEnabled' = $args[0].isDsMapperEnabled
+        'protocol' = $args[0].protocol
+        'certificateStoreName' = $args[0].certificateStoreName
+        'certificateHash' = $args[0].certificateHash
+    }
+
+    #handle sslflag support
+    If ([version][System.Environment]::OSVersion.Version -lt [version]'6.2')
+    {
+        $ht.sslFlags = 'not supported'
+    }
+    Else
+    {
+        $ht.sslFlags = [int]$args[0].sslFlags
+    }
+
+    Return $ht
+}
+
+# Used instead of get-webbinding to ensure we always return a single binding
+# pass it $binding_parameters hashtable
+function Get-SingleWebBinding {
+    $bind_search_splat = @{
+        'name' = $args[0].name
+        'protocol' = $args[0].protocol
+        'port' = $args[0].port
+        'ip' = $args[0].ip
+        'hostheader' = $args[0].hostheader
+    }
+
+    # if no bindings exist, get-webbinding fails with an error that can't be ignored via error actions on older systems
+    # let's ignore that specific error
+    If (-not $bind_search_splat['hostheader'])
+    {
+        Try {
+            Get-WebBinding @bind_search_splat | Where-Object {$_.BindingInformation.Split(':')[-1] -eq [string]::Empty}
+        }
+        Catch {
+            If (-not $_.Exception.Message.CompareTo('Cannot process argument because the value of argument "obj" is null. Change the value of argument "obj" to a non-null value'))
+            {
+                Throw $_.Exception.Message
+            }
+        }
+    }
+    Else
+    {
+        Try {
+            Get-WebBinding @bind_search_splat
+        }
+        Catch {
+            If (-not $_.Exception.Message.CompareTo('Cannot process argument because the value of argument "obj" is null. Change the value of argument "obj" to a non-null value'))
+            {
+                Throw $_.Exception.Message
+            }
+        }
+    }
+}
+
+# create binding search splat
+$binding_parameters = @{
+  Name = $name
+  Protocol = $protocol
+  Port = $port
+  IPAddress = $ip
+}
+
+# insert host header to search if specified, otherwise it will return * (all bindings matching protocol/ip)
+If ($host_header)
+{
+    $binding_parameters.HostHeader = $host_header
+}
+
+# Get bindings matching parameters
+Try {
+    $current_bindings = Get-SingleWebBinding $binding_parameters
+}
+Catch {
+    Fail-Json -obj $result -message "Failed to retrieve bindings with Get-SingleWebBinding - $($_.Exception.Message)"
+}
+
+If ($current_bindings)
+{
+    Try {
+        $binding_info = Create-BindingInfo $current_bindings
+    }
+    Catch {
+        Fail-Json -obj $result -message "Failed to create binding info - $($_.Exception.Message)"
+    }
+
+    $result.binding = $binding_info
+}
+exit-json -obj $result
diff --git a/test/integration/targets/win_iis_webbinding/tasks/failures.yml b/test/integration/targets/win_iis_webbinding/tasks/failures.yml
new file mode 100644
index 00000000000000..61753f5ab7b852
--- /dev/null
+++ b/test/integration/targets/win_iis_webbinding/tasks/failures.yml
@@ -0,0 +1,74 @@
+- name: failure check bind with host header but no wc or sni
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    host_header: test.com
+    protocol: https
+    ip: '*'
+    port: 443
+    certificate_hash: "{{ thumbprint1.stdout_lines[0] }}"
+    ssl_flags: 0
+  register: failure
+  failed_when:
+    - failure.msg != "You cannot specify host headers with SSL unless it is a wildcard certificate."
+    - failure.msg != "You cannot specify host headers with SSL unless it is a wildcard certificate or SNI is enabled."
+
+- debug:
+    var: failure
+    verbosity: 1
+
+- block:
+  - name: get all websites from server
+    raw: powershell.exe "(get-website).name"
+    register: existing_sites
+
+  - name: ensure all sites are removed for clean testing
+    win_iis_website:
+      name: "{{ item }}"
+      state: absent
+    with_items:
+      - "{{ existing_sites.stdout_lines }}"
+
+  - name: add sites
+    win_iis_website:
+      name: "{{ item.name }}"
+      state: started
+      ip: 127.0.0.1
+      port: "{{ item.port }}"
+      physical_path: c:\inetpub\wwwroot
+    with_items:
+      - {name: testconflict1, port: 8080}
+      - {name: testconflict2, port: 8081}
+
+  - name: add https binding to testconflict1
+    win_iis_webbinding:
+      name: testconflict1
+      state: present
+      protocol: https
+      port: 443
+      ip: 127.0.0.1
+      certificate_hash: "{{ thumbprint1.stdout_lines[0] }}"
+
+  - name: add https binding to testconflict2 (expect failure)
+    win_iis_webbinding:
+      name: testconflict2
+      state: present
+      protocol: https
+      ip: 127.0.0.1
+      port: 443
+      certificate_hash: "{{ thumbprint1.stdout_lines[0] }}"
+    register: failure
+    failed_when: '"A conflicting binding has been found on the same ip" not in failure.msg'
+
+  - debug:
+      var: failure
+      verbosity: 1
+
+  always:
+  - name: remove websites
+    win_iis_website:
+      name: "{{ item }}"
+      state: absent
+    with_items:
+      - testconflict1
+      - testconflict2
diff --git a/test/integration/targets/win_iis_webbinding/tasks/http.yml b/test/integration/targets/win_iis_webbinding/tasks/http.yml
new file mode 100644
index 00000000000000..c11d6a35355bce
--- /dev/null
+++ b/test/integration/targets/win_iis_webbinding/tasks/http.yml
@@ -0,0 +1,371 @@
+#cm add
+#changed true, check nothing present
+- name: CM add http binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    protocol: "{{ http_vars.protocol }}"
+    ip: "{{ http_vars.ip }}"
+    port: "{{ http_vars.port }}"
+  register: http_no_header
+  check_mode: yes
+
+- name: CM get binding info no header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ http_vars.protocol }}"
+    ip: "{{ http_vars.ip }}"
+    port: "{{ http_vars.port }}"
+  register: get_http_no_header
+  changed_when: false
+
+- name: CM add http binding with header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    host_header: "{{ http_header_vars.header }}"
+    protocol: "{{ http_header_vars.protocol }}"
+    ip: "{{ http_header_vars.ip }}"
+    port: "{{ http_header_vars.port }}"
+  register: http_header
+  check_mode: yes
+
+- name: CM get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    host_header: "{{ http_header_vars.header }}"
+    protocol: "{{ http_header_vars.protocol }}"
+    ip: "{{ http_header_vars.ip }}"
+    port: "{{ http_header_vars.port }}"
+  register: get_http_header
+  changed_when: false
+
+- name: CM assert changed, but not added
+  assert:
+    that:
+    - http_no_header is changed
+    - http_no_header.binding_info is none
+    - get_http_no_header.binding is not defined
+    - http_header is changed
+    - http_header.binding_info is none
+    - get_http_header.binding is not defined
+
+#add
+#changed true, new bindings present
+- name: add http binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    protocol: "{{ http_vars.protocol }}"
+    ip: "{{ http_vars.ip }}"
+    port: "{{ http_vars.port }}"
+  register: http_no_header
+
+- name: get binding info no header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ http_vars.protocol }}"
+    ip: "{{ http_vars.ip }}"
+    port: "{{ http_vars.port }}"
+  register: get_http_no_header
+  changed_when: false
+
+- name: add http binding with header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    host_header: "{{ http_header_vars.header }}"
+    protocol: "{{ http_header_vars.protocol }}"
+    ip: "{{ http_header_vars.ip }}"
+    port: "{{ http_header_vars.port }}"
+  register: http_header
+
+- name: get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    host_header: "{{ http_header_vars.header }}"
+    protocol: "{{ http_header_vars.protocol }}"
+    ip: "{{ http_header_vars.ip }}"
+    port: "{{ http_header_vars.port }}"
+  register: get_http_header
+  changed_when: false
+
+- name: assert changed and added
+  assert:
+    that:
+    - http_no_header is changed
+    - http_no_header.binding_info is defined
+    - http_no_header.operation_type == 'added'
+    - http_no_header.binding_info.ip == "{{ http_vars.ip }}"
+    - http_no_header.binding_info.port == {{ http_vars.port }}
+    - http_no_header.binding_info.protocol == "{{ http_vars.protocol }}"
+    - http_header is changed
+    - http_header.binding_info is defined
+    - http_header.operation_type == 'added'
+    - http_header.binding_info.ip == "{{ http_header_vars.ip }}"
+    - http_header.binding_info.port == {{ http_header_vars.port }}
+    - http_header.binding_info.protocol == "{{ http_header_vars.protocol }}"
+    - http_header.binding_info.hostheader == "{{ http_header_vars.header }}"
+
+#add idem
+#changed false
+- name: idem add http binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    protocol: "{{ http_vars.protocol }}"
+    ip: "{{ http_vars.ip }}"
+    port: "{{ http_vars.port }}"
+  register: http_no_header
+
+- name: idem add http binding with header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    host_header: "{{ http_header_vars.header }}"
+    protocol: "{{ http_header_vars.protocol }}"
+    ip: "{{ http_header_vars.ip }}"
+    port: "{{ http_header_vars.port }}"
+  register: http_header
+
+- name: idem assert not changed
+  assert:
+    that:
+    -  http_no_header is not changed
+    -  http_header is not changed
+
+#modify
+#can't test modify for http, it will add a new binding instead since
+#there's no way to match existing bindings against the new parameters
+
+#cm remove
+#changed true, bindings still present
+- name: cm remove http binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    protocol: "{{ http_vars.protocol }}"
+    ip: "{{ http_vars.ip }}"
+    port: "{{ http_vars.port }}"
+  register: http_no_header
+  check_mode: yes
+
+- name: get binding info no header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ http_vars.protocol }}"
+    ip: "{{ http_vars.ip }}"
+    port: "{{ http_vars.port }}"
+  register: get_http_no_header
+  changed_when: false
+
+- name: cm remove http binding with header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    host_header: "{{ http_header_vars.header }}"
+    protocol: "{{ http_header_vars.protocol }}"
+    ip: "{{ http_header_vars.ip }}"
+    port: "{{ http_header_vars.port }}"
+  register: http_header
+  check_mode: yes
+
+- name: get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    host_header: "{{ http_header_vars.header }}"
+    protocol: "{{ http_header_vars.protocol }}"
+    ip: "{{ http_header_vars.ip }}"
+    port: "{{ http_header_vars.port }}"
+  register: get_http_header
+  changed_when: false
+
+- name: cm remove assert changed, but still present
+  assert:
+    that:
+    - http_no_header is changed
+    - http_no_header.binding_info is defined
+    - http_no_header.operation_type == 'removed'
+    - http_no_header.binding_info.ip == "{{ http_vars.ip }}"
+    - http_no_header.binding_info.port == {{ http_vars.port }}
+    - http_no_header.binding_info.protocol == "{{ http_vars.protocol }}"
+    - get_http_no_header.binding is defined
+    - get_http_no_header.binding.ip == "{{ http_vars.ip }}"
+    - get_http_no_header.binding.port == {{ http_vars.port }}
+    - get_http_no_header.binding.protocol == "{{ http_vars.protocol }}"
+    - http_header is changed
+    - http_header.binding_info is defined
+    - http_header.operation_type == 'removed'
+    - http_header.binding_info.ip == "{{ http_header_vars.ip }}"
+    - http_header.binding_info.port == {{ http_header_vars.port }}
+    - http_header.binding_info.protocol == "{{ http_header_vars.protocol }}"
+    - http_header.binding_info.hostheader == "{{ http_header_vars.header }}"
+    - get_http_header.binding is defined
+    - get_http_header.binding.ip == "{{ http_header_vars.ip }}"
+    - get_http_header.binding.port == {{ http_header_vars.port }}
+    - get_http_header.binding.protocol == "{{ http_header_vars.protocol }}"
+    - get_http_header.binding.hostheader == "{{ http_header_vars.header }}"
+
+
+#remove
+#changed true, bindings gone
+- name: remove http binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    protocol: "{{ http_vars.protocol }}"
+    ip: "{{ http_vars.ip }}"
+    port: "{{ http_vars.port }}"
+  register: http_no_header
+
+- name: get binding info no header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ http_vars.protocol }}"
+    ip: "{{ http_vars.ip }}"
+    port: "{{ http_vars.port }}"
+  register: get_http_no_header
+  changed_when: false
+
+- name: remove http binding with header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    host_header: "{{ http_header_vars.header }}"
+    protocol: "{{ http_header_vars.protocol }}"
+    ip: "{{ http_header_vars.ip }}"
+    port: "{{ http_header_vars.port }}"
+  register: http_header
+
+- name: get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    host_header: "{{ http_header_vars.header }}"
+    protocol: "{{ http_header_vars.protocol }}"
+    ip: "{{ http_header_vars.ip }}"
+    port: "{{ http_header_vars.port }}"
+  register: get_http_header
+  changed_when: false
+
+- name: remove assert changed and gone
+  assert:
+    that:
+    - http_no_header is changed
+    - http_no_header.operation_type == 'removed'
+    - http_no_header.binding_info is defined
+    - http_no_header.binding_info.ip == "{{ http_vars.ip }}"
+    - http_no_header.binding_info.port == {{ http_vars.port }}
+    - http_no_header.binding_info.protocol == "{{ http_vars.protocol }}"
+    - get_http_no_header.binding is not defined
+    - http_header is changed
+    - http_header.binding_info is defined
+    - http_header.operation_type == 'removed'
+    - http_header.binding_info.ip == "{{ http_header_vars.ip }}"
+    - http_header.binding_info.port == {{ http_header_vars.port }}
+    - http_header.binding_info.protocol == "{{ http_header_vars.protocol }}"
+    - http_header.binding_info.hostheader == "{{ http_header_vars.header }}"
+    - get_http_header.binding is not defined
+
+#remove idem
+#change false, bindings gone
+- name: idem remove http binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    protocol: "{{ http_vars.protocol }}"
+    ip: "{{ http_vars.ip }}"
+    port: "{{ http_vars.port }}"
+  register: http_no_header
+
+- name: get binding info no header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ http_vars.protocol }}"
+    ip: "{{ http_vars.ip }}"
+    port: "{{ http_vars.port }}"
+  register: get_http_no_header
+  changed_when: false
+
+- name: idem remove http binding with header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    host_header: "{{ http_header_vars.header }}"
+    protocol: "{{ http_header_vars.protocol }}"
+    ip: "{{ http_header_vars.ip }}"
+    port: "{{ http_header_vars.port }}"
+  register: http_header
+
+- name: get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    host_header: "{{ http_header_vars.header }}"
+    protocol: "{{ http_header_vars.protocol }}"
+    ip: "{{ http_header_vars.ip }}"
+    port: "{{ http_header_vars.port }}"
+  register: get_http_header
+  changed_when: false
+
+- name: idem remove assert changed and gone
+  assert:
+    that:
+    -  http_no_header is not changed
+    - http_no_header.binding_info is not defined
+    - get_http_no_header.binding is not defined
+    -  http_header is not changed
+    - http_header.binding_info is not defined
+    - get_http_header.binding is not defined
+
+#bulk remove cm
+#add multiple bindings - verify they're present
+- name: bulk add http binding with header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    host_header: "{{ item }}"
+    protocol: http
+    ip: '*'
+    port: 80
+  register: http_header
+  with_items:
+   - test1.com
+   - test2.com
+   - test3.com
+
+- assert:
+    that:
+    - http_header is changed
+    - http_header | json_query('results[*].binding_info') | length == 3
+
+#cm remove with host_header: '*' - verify changed true and that bulk remove tries to get them all
+#remove with host_header: '*'
+
+- name: bulk remove http binding with header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    host_header: '*'
+    protocol: http
+    ip: '*'
+    port: 80
+  register: http_header
+
+- name: get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    host_header: "{{ item }}"
+    protocol: http
+    ip: '*'
+    port: 80
+  register: get_http_header
+  changed_when: false
+  with_items:
+   - test1.com
+   - test2.com
+   - test3.com
+
+- name: bulk remove assert that bindings are gone
+  assert:
+    that:
+    - http_header is changed
+    - http_header.binding_info | length == 3
diff --git a/test/integration/targets/win_iis_webbinding/tasks/https-ge6.2.yml b/test/integration/targets/win_iis_webbinding/tasks/https-ge6.2.yml
new file mode 100644
index 00000000000000..17b44e9ce06cff
--- /dev/null
+++ b/test/integration/targets/win_iis_webbinding/tasks/https-ge6.2.yml
@@ -0,0 +1,459 @@
+##############
+### CM Add ###
+##############
+#changed true, check nothing present
+- name: CM add https binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+    certificate_hash: "{{ thumbprint1.stdout_lines[0] }}"
+  register: https_no_header
+  check_mode: yes
+
+- name: CM get binding info no header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: get_https_no_header
+  changed_when: false
+
+- name: CM add https binding with header and SNI
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+    ssl_flags: 1
+    certificate_hash: "{{ thumbprint1.stdout_lines[0] }}"
+  register: https_header
+  check_mode: yes
+
+- name: CM get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+  register: get_https_header
+  changed_when: false
+
+- name: CM assert changed, but not added
+  assert:
+    that:
+    - https_no_header is changed
+    - https_no_header.operation_type == 'added'
+    - https_no_header.binding_info is none
+    - get_https_no_header.binding is not defined
+    - https_header is changed
+    - https_header.operation_type == 'added'
+    - https_header.binding_info is none
+    - get_https_header.binding is not defined
+
+###########
+### Add ###
+###########
+#changed true, new bindings present
+- name: add https binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+    certificate_hash: "{{ thumbprint1.stdout_lines[0] }}"
+  register: https_no_header
+
+- name: get binding info no header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: get_https_no_header
+  changed_when: false
+
+- name: add https binding with header SNI
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+    ssl_flags: 1
+    certificate_hash: "{{ thumbprint1.stdout_lines[0] }}"
+  register: https_header
+
+- name: get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+  register: get_https_header
+  changed_when: false
+
+- name: assert changed and added
+  assert:
+    that:
+    - https_no_header is changed
+    - https_no_header.operation_type == 'added'
+    - https_no_header.binding_info is defined
+    - https_no_header.binding_info.protocol == "{{ https_vars.protocol }}"
+    - https_no_header.binding_info.ip == "{{ https_vars.ip }}"
+    - https_no_header.binding_info.port == {{ https_vars.port }}
+    - https_no_header.binding_info.hostheader == ''
+    - https_no_header.binding_info.certificateHash == "{{ thumbprint1.stdout_lines[0] }}"
+    - https_header is changed
+    - https_header.operation_type == 'added'
+    - https_header.binding_info is defined
+    - https_header.binding_info.hostheader == "{{ https_header_vars.header }}"
+    - https_header.binding_info.protocol == "{{ https_header_vars.protocol }}"
+    - https_header.binding_info.ip == "{{ https_header_vars.ip }}"
+    - https_header.binding_info.port == {{ https_header_vars.port }}
+    - https_header.binding_info.certificateHash == "{{ thumbprint1.stdout_lines[0] }}"
+    - https_header.binding_info.sslFlags == 1
+
+################
+### Idem Add ###
+################
+#changed false
+- name: idem add https binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    protocol: https
+    ip: '*'
+    port: 443
+    certificate_hash: "{{ thumbprint1.stdout_lines[0] }}"
+  register: https_no_header
+
+- name: idem add https binding with header and SNI
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    host_header: test.com
+    protocol: https
+    ip: '*'
+    port: 443
+    ssl_flags: 1
+    certificate_hash: "{{ thumbprint1.stdout_lines[0] }}"
+  register: https_header
+
+- name: idem assert not changed
+  assert:
+    that:
+    -  https_no_header is not changed
+    -  https_header is not changed
+
+#################
+### CM Modify ###
+#################
+# changed true, verify no changes occurred
+
+#modify sni
+- name: CM modify https binding with header, change cert
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+    ssl_flags: 1
+    certificate_hash: "{{ thumbprint2.stdout_lines[0] }}"
+  register: https_header
+  check_mode: yes
+
+- name: get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+  register: get_https_header
+  changed_when: false
+
+- name: CM assert changed but old cert
+  assert:
+    that:
+    - https_header is changed
+    - https_header.operation_type == 'updated'
+    - https_header.binding_info is defined
+    - https_header.binding_info.ip == "{{ https_header_vars.ip }}"
+    - https_header.binding_info.port == {{ https_header_vars.port }}
+    - https_header.binding_info.protocol == "{{ https_header_vars.protocol }}"
+    - https_header.binding_info.hostheader == "{{ https_header_vars.header }}"
+    - https_header.binding_info.certificateHash == "{{ thumbprint1.stdout_lines[0] }}"
+    - https_header.binding_info.sslFlags == 1
+    - get_https_header.binding is defined
+    - get_https_header.binding.ip == "{{ https_header_vars.ip }}"
+    - get_https_header.binding.port == {{ https_header_vars.port }}
+    - get_https_header.binding.protocol == "{{ https_header_vars.protocol }}"
+    - get_https_header.binding.hostheader == "{{ https_header_vars.header }}"
+    - get_https_header.binding.certificateHash == "{{ thumbprint1.stdout_lines[0] }}"
+    - get_https_header.binding.sslFlags == 1
+
+##############
+### Modify ###
+##############
+# modify ssl flags
+- name:  modify https binding with header, change cert
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+    ssl_flags: 1
+    certificate_hash: "{{ thumbprint2.stdout_lines[0] }}"
+  register: https_header
+
+- name: get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+  register: get_https_header
+  changed_when: false
+
+- name:  modify assert changed and new cert
+  assert:
+    that:
+    - https_header is changed
+    - https_header.operation_type == 'updated'
+    - https_header.binding_info is defined
+    - https_header.binding_info.ip == "{{ https_header_vars.ip }}"
+    - https_header.binding_info.port == {{ https_header_vars.port }}
+    - https_header.binding_info.protocol == "{{ https_header_vars.protocol }}"
+    - https_header.binding_info.hostheader == "{{ https_header_vars.header }}"
+    - https_header.binding_info.certificateHash == "{{ thumbprint2.stdout_lines[0] }}"
+    - https_header.binding_info.sslFlags == 1
+    - get_https_header.binding is defined
+    - get_https_header.binding.ip == "{{ https_header_vars.ip }}"
+    - get_https_header.binding.port == {{ https_header_vars.port }}
+    - get_https_header.binding.protocol == "{{ https_header_vars.protocol }}"
+    - get_https_header.binding.hostheader == "{{ https_header_vars.header }}"
+    - get_https_header.binding.certificateHash == "{{ thumbprint2.stdout_lines[0] }}"
+    - get_https_header.binding.sslFlags == 1
+
+###################
+### Idem Modify ###
+###################
+#changed false
+
+#idem modify ssl flags
+- name: idem modify https binding with header, enable SNI and change cert
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+    ssl_flags: 1
+    certificate_hash: "{{ thumbprint2.stdout_lines[0] }}"
+  register: https_header
+
+- name: idem assert not changed
+  assert:
+    that:
+    -  https_header is not changed
+
+#################
+### CM Remove ###
+#################
+#changed true, bindings still present
+- name: cm remove https binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: https_no_header
+  check_mode: yes
+
+- name: get binding info no header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: get_https_no_header
+  changed_when: false
+
+- name: cm remove https binding with header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+  register: https_header
+  check_mode: yes
+
+- name: get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+  register: get_https_header
+  changed_when: false
+
+- name: cm remove assert changed, but still present
+  assert:
+    that:
+    - https_no_header is changed
+    - https_no_header.operation_type == 'removed'
+    - https_no_header.binding_info is defined
+    - https_no_header.binding_info.ip == "{{ https_vars.ip }}"
+    - https_no_header.binding_info.port == {{ https_vars.port }}
+    - https_no_header.binding_info.protocol == "{{ https_vars.protocol }}"
+    - get_https_no_header.binding is defined
+    - get_https_no_header.binding.ip == "{{ https_vars.ip }}"
+    - get_https_no_header.binding.port == {{ https_vars.port }}
+    - get_https_no_header.binding.protocol == "{{ https_vars.protocol }}"
+    - get_https_no_header.binding.certificateHash == "{{ thumbprint1.stdout_lines[0] }}"
+    - https_header is changed
+    - https_header.binding_info is defined
+    - https_header.operation_type == 'removed'
+    - https_header.binding_info.ip == "{{ https_header_vars.ip }}"
+    - https_header.binding_info.port == {{ https_header_vars.port }}
+    - https_header.binding_info.protocol == "{{ https_header_vars.protocol }}"
+    - https_header.binding_info.hostheader == "{{ https_header_vars.header }}"
+    - get_https_header.binding is defined
+    - get_https_header.binding.ip == "{{ https_header_vars.ip }}"
+    - get_https_header.binding.port == {{ https_header_vars.port }}
+    - get_https_header.binding.protocol == "{{ https_header_vars.protocol }}"
+    - get_https_header.binding.hostheader == "{{ https_header_vars.header }}"
+    - get_https_header.binding.certificateHash == "{{ thumbprint2.stdout_lines[0] }}"
+
+##############
+### remove ###
+##############
+#changed true, bindings gone
+- name: remove https binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: https_no_header
+
+- name: get binding info no header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: get_https_no_header
+  changed_when: false
+
+- name: remove https binding with header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+  register: https_header
+
+- name: get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+  register: get_https_header
+  changed_when: false
+
+- name: remove assert changed and gone
+  assert:
+    that:
+    - https_no_header is changed
+    - https_no_header.binding_info is defined
+    - https_no_header.operation_type == 'removed'
+    - https_no_header.binding_info.ip == "{{ https_vars.ip }}"
+    - https_no_header.binding_info.port == {{ https_vars.port }}
+    - https_no_header.binding_info.protocol == "{{ https_vars.protocol }}"
+    - get_https_no_header.binding is not defined
+    - https_header is changed
+    - https_header.binding_info is defined
+    - https_header.operation_type == 'removed'
+    - https_header.binding_info.ip == "{{ https_header_vars.ip }}"
+    - https_header.binding_info.port == {{ https_header_vars.port }}
+    - https_header.binding_info.protocol == "{{ https_header_vars.protocol }}"
+    - https_header.binding_info.hostheader == "{{ https_header_vars.header }}"
+    - get_https_header.binding is not defined
+
+###################
+### remove idem ###
+###################
+#change false, bindings gone
+- name: idem remove https binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: https_no_header
+
+- name: get binding info no header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: get_https_no_header
+  changed_when: false
+
+- name: idem remove https binding with header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+  register: https_header
+
+- name: get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    host_header: "{{ https_header_vars.header }}"
+    protocol: "{{ https_header_vars.protocol }}"
+    ip: "{{ https_header_vars.ip }}"
+    port: "{{ https_header_vars.port }}"
+  register: get_https_header
+  changed_when: false
+
+- name: idem remove assert changed and gone
+  assert:
+    that:
+    -  https_no_header is not changed
+    - https_no_header.binding_info is not defined
+    - get_https_no_header.binding is not defined
+    -  https_header is not changed
+    - https_header.binding_info is not defined
+    - get_https_header.binding is not defined
diff --git a/test/integration/targets/win_iis_webbinding/tasks/https-lt6.2.yml b/test/integration/targets/win_iis_webbinding/tasks/https-lt6.2.yml
new file mode 100644
index 00000000000000..888083a1964e61
--- /dev/null
+++ b/test/integration/targets/win_iis_webbinding/tasks/https-lt6.2.yml
@@ -0,0 +1,423 @@
+##############
+### CM Add ###
+##############
+#changed true, check nothing present
+- name: CM add https binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+    certificate_hash: "{{ thumbprint1.stdout_lines[0] }}"
+  register: https_no_header
+  check_mode: yes
+
+- name: CM get binding info no header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: get_https_no_header
+  changed_when: false
+
+- name: CM assert changed, but not added
+  assert:
+    that:
+    - https_no_header is changed
+    - https_no_header.operation_type == 'added'
+    - https_no_header.binding_info is none
+    - get_https_no_header.binding is not defined
+
+###########
+### Add ###
+###########
+#changed true, new bindings present
+- name: add https binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+    certificate_hash: "{{ thumbprint1.stdout_lines[0] }}"
+  register: https_no_header
+
+- name: assert changed and added
+  assert:
+    that:
+    - https_no_header is changed
+    - https_no_header.binding_info is defined
+    - https_no_header.operation_type == 'added'
+    - https_no_header.binding_info.ip == "{{ https_vars.ip }}"
+    - https_no_header.binding_info.port == {{ https_vars.port }}
+    - https_no_header.binding_info.protocol == "{{ https_vars.protocol }}"
+    - https_no_header.binding_info.hostheader == ''
+    - https_no_header.binding_info.certificateHash == "{{ thumbprint1.stdout_lines[0] }}"
+
+################
+### Idem Add ###
+################
+#changed false
+- name: idem add https binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+    certificate_hash: "{{ thumbprint1.stdout_lines[0] }}"
+  register: https_no_header
+
+- name: idem assert not changed
+  assert:
+    that:
+    -  https_no_header is not changed
+
+#################
+### CM Modify ###
+#################
+# changed true, verify no changes occurred
+
+#modify sni
+- name: CM modify https binding change cert
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+    certificate_hash: "{{ thumbprint2.stdout_lines[0] }}"
+  register: https_no_header
+  check_mode: yes
+
+- name: get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: get_https_no_header
+  changed_when: false
+
+- name: CM assert changed but old cert
+  assert:
+    that:
+    - https_no_header is changed
+    - https_no_header.operation_type == 'updated'
+    - https_no_header.binding_info is defined
+    - https_no_header.binding_info.ip == "{{ https_vars.ip }}"
+    - https_no_header.binding_info.port == {{ https_vars.port }}
+    - https_no_header.binding_info.protocol == "{{ https_vars.protocol }}"
+    - https_no_header.binding_info.certificateHash == "{{ thumbprint1.stdout_lines[0] }}"
+    - get_https_no_header.binding is defined
+    - get_https_no_header.binding.ip == "{{ https_vars.ip }}"
+    - get_https_no_header.binding.port == {{ https_vars.port }}
+    - get_https_no_header.binding.protocol == "{{ https_vars.protocol }}"
+    - get_https_no_header.binding.certificateHash == "{{ thumbprint1.stdout_lines[0] }}"
+
+##############
+### Modify ###
+##############
+# modify ssl flags
+- name:  modify https binding, change cert
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+    certificate_hash: "{{ thumbprint2.stdout_lines[0] }}"
+  register: https_no_header
+
+- name: get binding info header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: get_https_no_header
+  changed_when: false
+
+- name:  modify assert changed and new cert
+  assert:
+    that:
+    - https_no_header is changed
+    - https_no_header.operation_type == 'updated'
+    - https_no_header.binding_info is defined
+    - https_no_header.binding_info.ip == "{{ https_vars.ip }}"
+    - https_no_header.binding_info.port == {{ https_vars.port }}
+    - https_no_header.binding_info.protocol == "{{ https_vars.protocol }}"
+    - https_no_header.binding_info.certificateHash == "{{ thumbprint2.stdout_lines[0] }}"
+    - get_https_no_header.binding is defined
+    - get_https_no_header.binding.ip == "{{ https_vars.ip }}"
+    - get_https_no_header.binding.port == {{ https_vars.port }}
+    - get_https_no_header.binding.protocol == "{{ https_vars.protocol }}"
+    - get_https_no_header.binding.hostheader == ''
+    - get_https_no_header.binding.certificateHash == "{{ thumbprint2.stdout_lines[0] }}"
+
+###################
+### Idem Modify ###
+###################
+#changed false
+
+#idem modify ssl flags
+- name: idem modify https binding and change cert
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: present
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+    certificate_hash: "{{ thumbprint2.stdout_lines[0] }}"
+  register: https_header
+
+- name: idem assert not changed
+  assert:
+    that:
+    -  https_header is not changed
+
+#################
+### CM Remove ###
+#################
+#changed true, bindings still present
+- name: cm remove https binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: https_no_header
+  check_mode: yes
+
+- name: get binding info no header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: get_https_no_header
+  changed_when: false
+
+- name: cm remove assert changed, but still present
+  assert:
+    that:
+    - https_no_header is changed
+    - https_no_header.operation_type == 'removed'
+    - https_no_header.binding_info is defined
+    - https_no_header.binding_info.ip == "{{ https_vars.ip }}"
+    - https_no_header.binding_info.port == {{ https_vars.port }}
+    - https_no_header.binding_info.protocol == "{{ https_vars.protocol }}"
+    - https_no_header.binding_info.certificateHash == "{{ thumbprint2.stdout_lines[0] }}"
+    - get_https_no_header.binding is defined
+    - get_https_no_header.binding.ip == "{{ https_vars.ip }}"
+    - get_https_no_header.binding.port == {{ https_vars.port }}
+    - get_https_no_header.binding.protocol == "{{ https_vars.protocol }}"
+    - get_https_no_header.binding.certificateHash == "{{ thumbprint2.stdout_lines[0] }}"
+
+##############
+### remove ###
+##############
+#changed true, bindings gone
+- name: remove https binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: https_no_header
+
+- name: get binding info no header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: get_https_no_header
+  changed_when: false
+
+- name: remove assert changed and gone
+  assert:
+    that:
+    - https_no_header is changed
+    - https_no_header.operation_type == 'removed'
+    - https_no_header.binding_info is defined
+    - https_no_header.binding_info.ip == "{{ https_vars.ip }}"
+    - https_no_header.binding_info.port == {{ https_vars.port }}
+    - https_no_header.binding_info.protocol == "{{ https_vars.protocol }}"
+    - get_https_no_header.binding is not defined
+
+###################
+### remove idem ###
+###################
+#change false, bindings gone
+- name: idem remove https binding no header
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: https_no_header
+
+- name: get binding info no header
+  test_get_webbindings:
+    name: "{{ test_iis_site_name }}"
+    protocol: "{{ https_vars.protocol }}"
+    ip: "{{ https_vars.ip }}"
+    port: "{{ https_vars.port }}"
+  register: get_https_no_header
+  changed_when: false
+
+- name: idem remove assert changed and gone
+  assert:
+    that:
+    -  https_no_header is not changed
+    - https_no_header.binding_info is not defined
+    - get_https_no_header.binding is not defined
+
+
+##################
+### WC Testing ###
+##################
+
+# Unfortunately this does not work due to some strange errors
+# that are caused when using a self signed wildcard cert.
+# I'm leaving this here in case someone finds a solution in the
+# future.
+
+# - name: add https binding wildcard with header
+#   win_iis_webbinding:
+#     name: "{{ test_iis_site_name }}"
+#     state: present
+#     host_header: "{{ https_wc_vars.header }}"
+#     protocol: "{{ https_wc_vars.protocol }}"
+#     ip: "{{ https_wc_vars.ip }}"
+#     port: "{{ https_wc_vars.port }}"
+#     certificate_hash: "{{ thumbprint_wc.stdout_lines[0] }}"
+#   register: https_header
+
+# - name: assert changed and added
+#   assert:
+#     that:
+#     - https_header is changed
+#     - https_header.added is defined
+#     - https_header.added.ip == "{{ https_wc_vars.ip }}"
+#     - https_header.added.port == {{ https_wc_vars.port }}
+#     - https_header.added.protocol == "{{ https_wc_vars.protocol }}"
+#     - https_header.added.hostheader == "{{ https_wc_vars.header }}"
+#     - https_header.added.certificateHash == "{{ thumbprint_wc.stdout_lines[0] }}"
+
+
+# - name: idem add https binding wildcard with header
+#   win_iis_webbinding:
+#     name: "{{ test_iis_site_name }}"
+#     state: present
+#     host_header: "{{ https_wc_vars.header }}"
+#     protocol: "{{ https_wc_vars.protocol }}"
+#     ip: "{{ https_wc_vars.ip }}"
+#     port: "{{ https_wc_vars.port }}"
+#     certificate_hash: "{{ thumbprint_wc.stdout_lines[0] }}"
+#   register: https_header
+
+
+# - name: cm remove wildcard https binding
+#   win_iis_webbinding:
+#     name: "{{ test_iis_site_name }}"
+#     state: absent
+#     host_header: "{{ https_wc_vars.header }}"
+#     protocol: "{{ https_wc_vars.protocol }}"
+#     ip: "{{ https_wc_vars.ip }}"
+#     port: "{{ https_wc_vars.port }}"
+#   register: https_header
+#   check_mode: yes
+
+# - name: get binding info header
+#   test_get_webbindings:
+#     name: "{{ test_iis_site_name }}"
+#     host_header: "{{ https_wc_vars.header }}"
+#     protocol: "{{ https_wc_vars.protocol }}"
+#     ip: "{{ https_wc_vars.ip }}"
+#     port: "{{ https_wc_vars.port }}"
+#   register: get_https_header
+#   changed_when: false
+
+# - name: cm remove assert changed, but still present
+#   assert:
+#     that:
+#     - https_header is changed
+#     - https_header.removed is defined
+#     - https_header.removed.ip == "{{ https_wc_vars.ip }}"
+#     - https_header.removed.port == {{ https_wc_vars.port }}
+#     - https_header.removed.protocol == "{{ https_wc_vars.protocol }}"
+#     - https_header.removed.hostheader == "{{ https_wc_vars.header }}"
+#     - https_header.removed.certificateHash == "{{ thumbprint_wc.stdout_lines[0] }}"
+#     - get_https_header.binding is defined
+#     - get_https_header.removed.ip == "{{ https_wc_vars.ip }}"
+#     - get_https_header.removed.port == {{ https_wc_vars.port }}
+#     - get_https_header.removed.protocol == "{{ https_wc_vars.protocol }}"
+#     - get_https_header.removed.hostheader == "{{ https_wc_vars.header }}"
+#     - get_https_header.removed.certificateHash == "{{ thumbprint_wc.stdout_lines[0] }}"
+
+# - name: remove wildcard https binding
+#   win_iis_webbinding:
+#     name: "{{ test_iis_site_name }}"
+#     state: absent
+#     host_header: "{{ https_wc_vars.header }}"
+#     protocol: "{{ https_wc_vars.protocol }}"
+#     ip: "{{ https_wc_vars.ip }}"
+#     port: "{{ https_wc_vars.port }}"
+#   register: https_header
+
+# - name: get binding info header
+#   test_get_webbindings:
+#     name: "{{ test_iis_site_name }}"
+#     host_header: "{{ https_wc_vars.header }}"
+#     protocol: "{{ https_wc_vars.protocol }}"
+#     ip: "{{ https_wc_vars.ip }}"
+#     port: "{{ https_wc_vars.port }}"
+#   register: get_https_header
+#   changed_when: false
+
+
+# - name: remove assert changed and gone
+#   assert:
+#     that:
+#     - https_header is changed
+#     - https_header.removed is defined
+#     - https_header.removed.ip == "{{ https_wc_vars.ip }}"
+#     - https_header.removed.port == {{ https_wc_vars.port }}
+#     - https_header.removed.protocol == "{{ https_wc_vars.protocol }}"
+#     - https_header.removed.hostheader == "{{ https_wc_vars.header }}"
+#     - https_header.removed.certificateHash == "{{ thumbprint_wc.stdout_lines[0] }}"
+#     - get_https_header.binding is not defined
+
+# - name: idem remove wildcard https binding
+#   win_iis_webbinding:
+#     name: "{{ test_iis_site_name }}"
+#     state: absent
+#     host_header: "{{ https_wc_vars.header }}"
+#     protocol: "{{ https_wc_vars.protocol }}"
+#     ip: "{{ https_wc_vars.ip }}"
+#     port: "{{ https_wc_vars.port }}"
+#   register: https_header
+
+# - name: get binding info header
+#   test_get_webbindings:
+#     name: "{{ test_iis_site_name }}"
+#     host_header: "{{ https_wc_vars.header }}"
+#     protocol: "{{ https_wc_vars.protocol }}"
+#     ip: "{{ https_wc_vars.ip }}"
+#     port: "{{ https_wc_vars.port }}"
+#   register: get_https_header
+#   changed_when: false
+
+# - name: idem remove assert changed and gone
+#   assert:
+#     that:
+#     -  https_header is not changed
+#     - https_header.removed is not defined
+#     - get_https_header.binding is not defined
diff --git a/test/integration/targets/win_iis_webbinding/tasks/main.yml b/test/integration/targets/win_iis_webbinding/tasks/main.yml
new file mode 100644
index 00000000000000..a561112a463f53
--- /dev/null
+++ b/test/integration/targets/win_iis_webbinding/tasks/main.yml
@@ -0,0 +1,62 @@
+---
+# Cannot use win_feature to install IIS on Server 2008.
+# Run a brief check and skip hosts that don't support
+# that operation
+#seems "raw" is the only module that works on 2008 non-r2. win_command and win_shell both failed
+- name: register os version (seems integration tests don't gather this fact)
+  raw: powershell.exe "gwmi Win32_OperatingSystem | select -expand version"
+  register: os_version
+  changed_when: False
+
+- block:
+  - include_tasks: setup.yml
+  - include_tasks: http.yml
+  - include_tasks: https-lt6.2.yml
+    when: os_version.stdout_lines[0] | version_compare('6.2','lt')
+  - include_tasks: https-ge6.2.yml
+    when: os_version.stdout_lines[0] | version_compare('6.2','ge')
+  - include_tasks: failures.yml
+
+  always:
+  - name: get all websites from server
+    raw: powershell.exe "(get-website).name"
+    register: existing_sites
+
+  - name: ensure all sites are removed for clean testing
+    win_iis_website:
+      name: "{{ item }}"
+      state: absent
+    with_items:
+      - "{{ existing_sites.stdout_lines }}"
+
+  - name: cleanup certreq files
+    win_file:
+      path: "{{ item }}"
+      state: absent
+    with_items:
+      - c:\windows\temp\certreq1.txt
+      - c:\windows\temp\certreq2.txt
+      - c:\windows\temp\certreqwc.txt
+      - c:\windows\temp\certreqresp1.txt
+      - c:\windows\temp\certreqresp2.txt
+      - c:\windows\temp\certreqrespwc.txt
+
+  - name: remove certs
+    raw: 'remove-item cert:\localmachine\my\{{ item }} -force -ea silentlycontinue'
+    with_items:
+      - "{{ thumbprint1.stdout_lines[0] }}"
+      - "{{ thumbprint2.stdout_lines[0] }}"
+      - "{{ thumbprint_wc.stdout_lines[0] }}"
+
+  - name: remove IIS features after test
+    win_feature:
+      name: Web-Server
+      state: absent
+      includ_sub_features: True
+      include_management_tools: True
+    register: feature_uninstall
+
+  - name: reboot after feature install
+    win_reboot:
+    when: feature_uninstall.reboot_required
+  when: os_version.stdout_lines[0] | version_compare('6.1','gt')
diff --git a/test/integration/targets/win_iis_webbinding/tasks/setup.yml b/test/integration/targets/win_iis_webbinding/tasks/setup.yml
new file mode 100644
index 00000000000000..96e9cbd344bbf6
--- /dev/null
+++ b/test/integration/targets/win_iis_webbinding/tasks/setup.yml
@@ -0,0 +1,88 @@
+- name: reboot before feature install to ensure server is in clean state
+  win_reboot:
+
+- name: ensure IIS features are installed
+  win_feature:
+    name: Web-Server
+    state: present
+    includ_sub_features: True
+    include_management_tools: True
+  register: feature_install
+
+- name: reboot after feature install
+  win_reboot:
+  when: feature_install.reboot_required
+
+- name: get all websites from server
+  raw: powershell.exe "(get-website).name"
+  register: existing_sites
+
+- name: ensure all sites are removed for clean testing
+  win_iis_website:
+    name: "{{ item }}"
+    state: absent
+  with_items:
+    - "{{ existing_sites.stdout_lines }}"
+
+- name: add testing site {{ test_iis_site_name }}
+  win_iis_website:
+    name: "{{ test_iis_site_name }}"
+    physical_path: c:\inetpub\wwwroot
+
+- name: ensure all bindings are removed prior to starting testing
+  win_iis_webbinding:
+    name: "{{ test_iis_site_name }}"
+    state: absent
+    protocol: "{{ item.protocol }}"
+    port: "{{ item.port }}"
+    host_header: '*'
+  with_items:
+    - {protocol: http, port: 80}
+    - {protocol: https, port: 443}
+
+- name: copy certreq file
+  win_copy:
+    content: |-
+      [NewRequest]
+      Subject = "CN={{ item.name }}"
+      KeyLength = 2048
+      KeyAlgorithm = RSA
+      MachineKeySet = true
+      RequestType = Cert
+    dest: "{{ item.dest }}"
+  with_items:
+    - {name: test.com, dest: 'c:\windows\temp\certreq1.txt'}
+    - {name: test1.com, dest: 'c:\windows\temp\certreq2.txt'}
+    - {name: '*.test.com', dest: 'c:\windows\temp\certreqwc.txt'}
+
+- name: make sure response files are absent
+  win_file:
+    path: "{{ item }}"
+    state: absent
+  with_items:
+  - 'c:\windows\temp\certreqresp1.txt'
+  - 'c:\windows\temp\certreqresp2.txt'
+  - 'c:\windows\temp\certreqrespwc.txt'
+
+- name: create self signed cert from certreq
+  win_command: certreq -new -machine {{ item.req }} {{ item.resp }}
+  with_items:
+    - {req: 'c:\windows\temp\certreq1.txt', resp: 'c:\windows\temp\certreqresp1.txt'}
+    - {req: 'c:\windows\temp\certreq2.txt', resp: 'c:\windows\temp\certreqresp2.txt'}
+    - {req: 'c:\windows\temp\certreqwc.txt', resp: 'c:\windows\temp\certreqrespwc.txt'}
+
+- name: register certificate thumbprint1
+  raw: '(gci Cert:\LocalMachine\my | ? {$_.subject -eq "CN=test.com"})[0].Thumbprint'
+  register: thumbprint1
+
+- name: register certificate thumbprint2
+  raw: '(gci Cert:\LocalMachine\my | ? {$_.subject -eq "CN=test1.com"})[0].Thumbprint'
+  register: thumbprint2
+
+- name: register certificate thumbprint_wc
+  raw: '(gci Cert:\LocalMachine\my | ? {$_.subject -eq "CN=*.test.com"})[0].Thumbprint'
+  register: thumbprint_wc
+
+- debug: var=thumbprint1.stdout
+- debug: var=thumbprint2.stdout
+- debug: var=thumbprint_wc.stdout


Code review comments:
diff_hunk: @@ -28,74 +15,58 @@
 ---
 module: win_iis_webbinding
 version_added: "2.0"
-short_description: Configures a IIS Web site.
+short_description: Configures a IIS Web site binding.
 description:
      - Creates, Removes and configures a binding to an existing IIS Web site
 options:
   name:
     description:
       - Names of web site
     required: true
-    default: null
-    aliases: []
+    aliases: website
path: lib/ansible/modules/windows/win_iis_webbinding.py
text: @user1:
`aliases: [website]` should fix the Shippable issue

@author:
thanks

diff_hunk: @@ -28,74 +15,58 @@
 ---
 module: win_iis_webbinding
 version_added: "2.0"
-short_description: Configures a IIS Web site.
+short_description: Configures a IIS Web site binding.
 description:
      - Creates, Removes and configures a binding to an existing IIS Web site
 options:
   name:
     description:
       - Names of web site
     required: true
-    default: null
-    aliases: []
+    aliases: website
   state:
     description:
       - State of the binding
     choices:
       - present
       - absent
-    required: false
-    default: null
-    aliases: []
+    default: present
   port:
     description:
       - The port to bind to / use for the new site.
-    required: false
-    default: null
-    aliases: []
+    default: 80
   ip:
     description:
       - The IP address to bind to / use for the new site.
-    required: false
-    default: null
-    aliases: []
+    default: '*'
   host_header:
     description:
       - The host header to bind to / use for the new site.
-    required: false
-    default: null
-    aliases: []
+      - For state absent, you can use '*' here to remove all bindings for a particular
path: lib/ansible/modules/windows/win_iis_webbinding.py
text: @user1:
`C(*)`
or `C('*')`  if it needs quoting

http://docs.ansible.com/ansible/devel/dev_guide/developing_modules_documenting.html#formatting-options