Skip to content

Commit 0a70f48

Browse files
Migrate win_iis_website and win_iis_webbinding
1 parent 1c833e7 commit 0a70f48

File tree

28 files changed

+1445
-2383
lines changed

28 files changed

+1445
-2383
lines changed

plugins/modules/website.ps1

Lines changed: 264 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,285 @@
11
#!powershell
22

3-
# Copyright: (c) 2024, Ansible Project
3+
# Copyright: (c) 2015, Henrik Wallström <[email protected]>
44
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
55

66
#AnsibleRequires -CSharpUtil Ansible.Basic
77

8+
# Define Bindings Options
9+
$binding_options = @{
10+
type = 'list'
11+
elements = 'dict'
12+
options = @{
13+
ip = @{ type = 'str' }
14+
port = @{ type = 'int' }
15+
hostname = @{ type = 'str' }
16+
protocol = @{ type = 'str' ; default = 'http' ; choices = @('http','https') }
17+
ssl_flags = @{ type = 'str' ; default = '0' ; choices = @('0','1','2','3') }
18+
certificate_hash = @{ type = 'str' ; default = ([string]::Empty) }
19+
certificate_store_name = @{ type = 'str' ; default = ([string]::Empty) }
20+
}
21+
}
22+
823
$spec = @{
924
options = @{
1025
name = @{
1126
required = $true
12-
type = 'str'
27+
type = "str"
28+
}
29+
state = @{
30+
type = "str"
31+
default = "started"
32+
choices = @("absent", "restarted", "started", "stopped")
33+
}
34+
site_id = @{
35+
type = "str"
36+
}
37+
application_pool = @{
38+
type = "str"
39+
}
40+
physical_path = @{
41+
type = "str"
42+
}
43+
parameters = @{
44+
type = "str"
45+
}
46+
bindings = @{
47+
default = @{}
48+
type = 'dict'
49+
options = @{
50+
add = $binding_options
51+
set = $binding_options
52+
remove = @{
53+
type = 'list'
54+
elements = 'dict'
55+
options = @{
56+
ip = @{ type = 'str' }
57+
port = @{ type = 'int' }
58+
hostname = @{ type = 'str' }
59+
}
60+
}
61+
}
1362
}
1463
}
1564
supports_check_mode = $true
1665
}
17-
1866
$module = [Ansible.Basic.AnsibleModule]::Create($args, $spec)
1967

2068
$name = $module.Params.name
69+
$state = $module.Params.state
70+
$site_id = $module.Params.site_id
71+
$application_pool = $module.Params.application_pool
72+
$physical_path = $module.Params.physical_path
73+
$bindings = $module.Params.bindings
74+
75+
# Custom site Parameters from string where properties are separated by a pipe and property name/values by colon.
76+
# Ex. "foo:1|bar:2"
77+
$parameters = $module.Params.parameters
78+
if ($null -ne $parameters) {
79+
$parameters = @($parameters -split '\|' | ForEach-Object {
80+
return , ($_ -split "\:", 2)
81+
})
82+
}
83+
84+
$check_mode = $module.CheckMode
85+
$module.Result.changed = $false
86+
87+
if ($check_mode){
88+
Write-Output "in check mode"
89+
}
90+
91+
# Ensure WebAdministration module is loaded
92+
if ($null -eq (Get-Module "WebAdministration" -ErrorAction SilentlyContinue)) {
93+
Import-Module WebAdministration
94+
}
95+
96+
# Site info
97+
$site = Get-Website | Where-Object { $_.Name -eq $name }
98+
99+
Try {
100+
# Add site
101+
If (($state -ne 'absent') -and (-not $site)) {
102+
If (-not $physical_path) {
103+
$module.FailJson("missing required arguments: physical_path $($_.Exception.Message)")
104+
}
105+
ElseIf (-not (Test-Path -LiteralPath $physical_path)) {
106+
$module.FailJson("specified folder must already exist: physical_path $($_.Exception.Message)")
107+
}
108+
109+
$site_parameters = @{
110+
Name = $name
111+
PhysicalPath = $physical_path
112+
}
113+
114+
If ($application_pool) {
115+
$site_parameters.ApplicationPool = $application_pool
116+
}
117+
118+
If ($site_id) {
119+
$site_parameters.ID = $site_id
120+
}
121+
122+
# Fix for error "New-Item : Index was outside the bounds of the array."
123+
# This is a bug in the New-WebSite commandlet. Apparently there must be at least one site configured in IIS otherwise New-WebSite crashes.
124+
# For more details, see http://stackoverflow.com/questions/3573889/ps-c-new-website-blah-throws-index-was-outside-the-bounds-of-the-array
125+
$sites_list = Get-ChildItem -LiteralPath IIS:\sites
126+
if ($null -eq $sites_list) {
127+
if ($site_id) {
128+
$site_parameters.ID = $site_id
129+
}
130+
else {
131+
$site_parameters.ID = 1
132+
}
133+
}
134+
if ( -not $check_mode) {
135+
$site = New-Website @site_parameters -Force
136+
}
137+
# Verify that initial site has no binding
138+
Get-WebBinding -Name $site.Name | Remove-WebBinding -WhatIf:$check_mode
139+
$module.Result.changed = $true
140+
}
141+
142+
# Remove site
143+
If ($state -eq 'absent' -and $site) {
144+
$site = Remove-Website -Name $name -WhatIf:$check_mode
145+
$module.Result.changed = $true
146+
}
147+
148+
$site = Get-Website | Where-Object { $_.Name -eq $name }
149+
If ($site) {
150+
# Change Physical Path if needed
151+
if ($physical_path) {
152+
If (-not (Test-Path -LiteralPath $physical_path)) {
153+
$module.FailJson("specified folder must already exist: physical_path $($_.Exception.Message)")
154+
}
21155

22-
$module.Diff.before = $null
23-
$module.Diff.after = @{
24-
name = $name
156+
$folder = Get-Item -LiteralPath $physical_path
157+
If ($folder.FullName -ne $site.PhysicalPath) {
158+
Set-ItemProperty -LiteralPath "IIS:\Sites\$($site.Name)" -name physicalPath -value $folder.FullName -WhatIf:$check_mode
159+
$module.Result.changed = $true
160+
}
161+
}
162+
163+
# Change Application Pool if needed
164+
if ($application_pool) {
165+
If ($application_pool -ne $site.applicationPool) {
166+
Set-ItemProperty -LiteralPath "IIS:\Sites\$($site.Name)" -name applicationPool -value $application_pool -WhatIf:$check_mode
167+
$module.Result.changed = $true
168+
}
169+
}
170+
# Add Remove or Set bindings if needed
171+
if ($bindings) {
172+
$site_bindings = (Get-ItemProperty -LiteralPath "IIS:\Sites\$($site.Name)").Bindings.Collection
173+
$user_bindings = if ($Module.Params.bindings.add) { $Module.Params.bindings.add }
174+
elseif ($Module.Params.bindings.remove) { $Module.Params.bindings.remove }
175+
elseif ($Module.Params.bindings.set) { $Module.Params.bindings.set }
176+
# Validate User Bindings Information
177+
$user_bindings | ForEach-Object {
178+
# Make sure ssl flags only specified with https protocol
179+
If ($_.protocol -ne 'https' -and $_.ssl_flags -gt 0) {
180+
$module.FailJson("SSLFlags can only be set for https protocol")
181+
}
182+
# Validate certificate details if provided
183+
If ($_.certificate_hash -and $_.operation -ne 'remove') {
184+
If ($_.protocol -ne 'https') {
185+
$module.FailJson("You can only provide a certificate thumbprint when protocol is set to https")
186+
}
187+
# Apply default for cert store name
188+
If (-Not $_.certificate_store_name) {
189+
$_.certificate_store_name = 'my'
190+
}
191+
# Validate cert path
192+
$cert_path = "cert:\LocalMachine\$($_.certificate_store_name)\$($_.certificate_hash)"
193+
If (-Not (Test-Path -LiteralPath $cert_path) ) {
194+
$module.FailJson("Unable to locate certificate at $cert_path")
195+
}
196+
}
197+
# Make sure binding info is valid for central cert store if sslflags -gt 1
198+
If ($_.ssl_flags -gt 1 -and ($_.certificate_hash -ne [string]::Empty -or $_.certificate_store_name -ne [string]::Empty)) {
199+
$module.FailJson("You set sslFlags to $($_.ssl_flags). This indicates you wish to use the Central Certificate Store feature.
200+
This cannot be used in combination with certficiate_hash and certificate_store_name. When using the Central Certificate Store feature,
201+
the certificate is automatically retrieved from the store rather than manually assigned to the binding.")
202+
}
203+
}
204+
if ($null -ne $bindings.add) {
205+
$add_binding = $user_bindings | Where-Object { -not ($site_bindings.bindingInformation -contains "$($_.ip):$($_.port):$($_.hostname)") }
206+
if ($add_binding) {
207+
$add_binding | ForEach-Object {
208+
if (-not $check_mode) {
209+
New-WebBinding -Name $site.Name -IPAddress $_.ip -Port $_.port -HostHeader $_.hostname -Protocol $_.protocol -SslFlags $_.ssl_flags
210+
If ($_.certificate_hash) {
211+
$new_binding = Get-WebBinding -Name $site.Name -IPAddress $_.ip -Port $_.port -HostHeader $_.hostname
212+
$new_binding.AddSslCertificate($_.certificate_hash, $_.certificate_store_name)
213+
}
214+
}
215+
$module.Result.changed = $true
216+
}
217+
}
218+
}
219+
if ($null -ne $bindings.remove) {
220+
$remove_binding = $user_bindings | Where-Object { ($site_bindings.bindingInformation -contains "$($_.ip):$($_.port):$($_.hostname)") }
221+
if ($remove_binding) {
222+
$remove_binding | ForEach-Object {
223+
Get-WebBinding -Name $site.Name -IPAddress $_.ip -Port $_.port -HostHeader $_.hostname | Remove-WebBinding -WhatIf:$check_mode
224+
$module.Result.changed = $true
225+
}
226+
}
227+
}
228+
if ($null -ne $bindings.set) {
229+
$set_binding = $user_bindings | ForEach-Object { "$($_.ip):$($_.port):$($_.hostname)" }
230+
$diff = Compare-Object -ReferenceObject @($set_binding | Select-Object) -DifferenceObject @($site_bindings.bindingInformation | Select-Object)
231+
if ($diff.Count -ne 0) {
232+
# Remove All Bindings
233+
Get-WebBinding -Name $site.Name | Remove-WebBinding -WhatIf:$check_mode
234+
# Set Bindings
235+
$user_bindings | ForEach-Object {
236+
if (-not $check_mode) {
237+
New-WebBinding -Name $site.Name -IPAddress $_.ip -Port $_.port -HostHeader $_.hostname -Protocol $_.protocol -SslFlags $_.ssl_flags
238+
If ($_.certificate_hash) {
239+
$new_binding = Get-WebBinding -Name $site.Name -IPAddress $_.ip -Port $_.port -HostHeader $_.hostname
240+
$new_binding.AddSslCertificate($_.certificate_hash, $_.certificate_store_name)
241+
}
242+
}
243+
}
244+
$module.Result.changed = $true
245+
}
246+
}
247+
}
248+
249+
# Set properties
250+
if ($parameters) {
251+
$parameters | ForEach-Object {
252+
$property_value = Get-ItemProperty -LiteralPath "IIS:\Sites\$($site.Name)" $_[0]
253+
254+
switch ($property_value.GetType().Name) {
255+
"ConfigurationAttribute" { $parameter_value = $property_value.value }
256+
"String" { $parameter_value = $property_value }
257+
}
258+
259+
if ((-not $parameter_value) -or ($parameter_value) -ne $_[1]) {
260+
Set-ItemProperty -LiteralPath "IIS:\Sites\$($site.Name)" $_[0] $_[1] -WhatIf:$check_mode
261+
$module.Result.changed = $true
262+
}
263+
}
264+
}
265+
266+
# Set run state
267+
if ((($state -eq 'stopped') -or ($state -eq 'restarted')) -and ($site.State -eq 'Started')) {
268+
if (-not $check_mode) {
269+
Stop-Website -Name $name -ErrorAction Stop
270+
}
271+
$module.Result.changed = $true
272+
}
273+
if ((($state -eq 'started') -and ($site.State -eq 'Stopped')) -or ($state -eq 'restarted')) {
274+
if (-not $check_mode) {
275+
Start-Website -Name $name -ErrorAction Stop
276+
}
277+
$module.Result.changed = $true
278+
}
279+
}
280+
}
281+
Catch {
282+
$module.FailJson("$($module.Result) - $($_.Exception.Message)")
25283
}
26284

27285
$module.ExitJson()

0 commit comments

Comments
 (0)