├── .gitattributes
├── .gitignore
├── Exercise1.md
├── Exercise2.md
├── Exercise2
├── Deploy.ps1
├── Parameters.ps1
└── Templates
│ └── Webserver.template.answer
├── Exercise3.md
├── Exercise3
├── ConfigureWebserver.ps1
├── ConfigureWebserver.ps1.answer
├── DSC_Diagnostics.md
└── PowerShellModules
│ ├── cWinServer
│ ├── DSCResources
│ │ └── WinServerOptions
│ │ │ ├── WinServerOptions.psm1
│ │ │ └── WinServerOptions.schema.mof
│ └── cWinServer.psd1
│ ├── xDscDiagnostics
│ ├── xDscDiagnostics.psd1
│ ├── xDscDiagnostics.psm1
│ └── xDscDiagnosticsFormat.ps1xml
│ ├── xNetworking
│ ├── DSCResources
│ │ ├── MSFT_xDNSServerAddress
│ │ │ ├── MSFT_xDNSServerAddress.psm1
│ │ │ └── MSFT_xDNSServerAddress.schema.mof
│ │ ├── MSFT_xFirewall
│ │ │ ├── MSFT_xFirewall.Schema.mof
│ │ │ └── MSFT_xFirewall.psm1
│ │ └── MSFT_xIPAddress
│ │ │ ├── MSFT_xIPAddress.psm1
│ │ │ └── MSFT_xIPAddress.schema.mof
│ ├── Examples
│ │ ├── Sample_xDnsServerAddress.ps1
│ │ ├── Sample_xFirewall_AddFirewallRule.ps1
│ │ ├── Sample_xFirewall_AddFirewallRuleToExistingGroup.ps1
│ │ ├── Sample_xFirewall_AddFirewallRuleToNewGroup.ps1
│ │ ├── Sample_xFirewall_DisableAccessToApplication.ps1
│ │ ├── Sample_xIPAddress_FixedValue.ps1
│ │ └── Sample_xIPAddress_Parameterized.ps1
│ ├── xNetworking.psd1
│ └── xNetworking_TechNetDocumentation.html
│ ├── xPendingReboot
│ ├── DSCResources
│ │ └── MSFT_xPendingReboot
│ │ │ ├── MSFT_xPendingReboot.psm1
│ │ │ └── MSFT_xPendingReboot.schema.mof
│ ├── xPendingReboot.psd1
│ └── xPendingReboot_Documentation.html
│ └── xWebAdministration
│ ├── DSCResources
│ ├── MSFT_xIisModule
│ │ ├── MSFT_xIisModule.psm1
│ │ ├── MSFT_xIisModule.schema.mof
│ │ └── xIisModuleDesigner.ps1
│ ├── MSFT_xWebAppPool
│ │ ├── MSFT_xWebAppPool.psm1
│ │ └── MSFT_xWebAppPool.schema.mof
│ ├── MSFT_xWebApplication
│ │ ├── MSFT_xWebApplication.psm1
│ │ └── MSFT_xWebApplication.schema.mof
│ ├── MSFT_xWebConfigKeyValue
│ │ ├── MSFT_xWebConfigKeyValue.psm1
│ │ └── MSFT_xWebConfigKeyValue.schema.mof
│ ├── MSFT_xWebVirtualDirectory
│ │ ├── MSFT_xWebVirtualDirectory.psm1
│ │ └── MSFT_xWebVirtualDirectory.schema.mof
│ └── MSFT_xWebsite
│ │ ├── MSFT_xWebsite.psm1
│ │ └── MSFT_xWebsite.schema.mof
│ ├── TechNetDocumentation_xWebAdministration.html
│ └── xWebAdministration.psd1
├── Exercise4.md
├── Exercise4
├── Deploy.ps1
├── Parameters.ps1
├── PowerShellModules
│ ├── cWinServer
│ │ ├── DSCResources
│ │ │ └── WinServerOptions
│ │ │ │ ├── WinServerOptions.psm1
│ │ │ │ └── WinServerOptions.schema.mof
│ │ └── cWinServer.psd1
│ ├── xDscDiagnostics
│ │ ├── xDscDiagnostics.psd1
│ │ ├── xDscDiagnostics.psm1
│ │ └── xDscDiagnosticsFormat.ps1xml
│ ├── xNetworking
│ │ ├── DSCResources
│ │ │ ├── MSFT_xDNSServerAddress
│ │ │ │ ├── MSFT_xDNSServerAddress.psm1
│ │ │ │ └── MSFT_xDNSServerAddress.schema.mof
│ │ │ ├── MSFT_xFirewall
│ │ │ │ ├── MSFT_xFirewall.Schema.mof
│ │ │ │ └── MSFT_xFirewall.psm1
│ │ │ └── MSFT_xIPAddress
│ │ │ │ ├── MSFT_xIPAddress.psm1
│ │ │ │ └── MSFT_xIPAddress.schema.mof
│ │ ├── Examples
│ │ │ ├── Sample_xDnsServerAddress.ps1
│ │ │ ├── Sample_xFirewall_AddFirewallRule.ps1
│ │ │ ├── Sample_xFirewall_AddFirewallRuleToExistingGroup.ps1
│ │ │ ├── Sample_xFirewall_AddFirewallRuleToNewGroup.ps1
│ │ │ ├── Sample_xFirewall_DisableAccessToApplication.ps1
│ │ │ ├── Sample_xIPAddress_FixedValue.ps1
│ │ │ └── Sample_xIPAddress_Parameterized.ps1
│ │ ├── xNetworking.psd1
│ │ └── xNetworking_TechNetDocumentation.html
│ ├── xPendingReboot
│ │ ├── DSCResources
│ │ │ └── MSFT_xPendingReboot
│ │ │ │ ├── MSFT_xPendingReboot.psm1
│ │ │ │ └── MSFT_xPendingReboot.schema.mof
│ │ ├── xPendingReboot.psd1
│ │ └── xPendingReboot_Documentation.html
│ └── xWebAdministration
│ │ ├── DSCResources
│ │ ├── MSFT_xIisModule
│ │ │ ├── MSFT_xIisModule.psm1
│ │ │ ├── MSFT_xIisModule.schema.mof
│ │ │ └── xIisModuleDesigner.ps1
│ │ ├── MSFT_xWebAppPool
│ │ │ ├── MSFT_xWebAppPool.psm1
│ │ │ └── MSFT_xWebAppPool.schema.mof
│ │ ├── MSFT_xWebApplication
│ │ │ ├── MSFT_xWebApplication.psm1
│ │ │ └── MSFT_xWebApplication.schema.mof
│ │ ├── MSFT_xWebConfigKeyValue
│ │ │ ├── MSFT_xWebConfigKeyValue.psm1
│ │ │ └── MSFT_xWebConfigKeyValue.schema.mof
│ │ ├── MSFT_xWebVirtualDirectory
│ │ │ ├── MSFT_xWebVirtualDirectory.psm1
│ │ │ └── MSFT_xWebVirtualDirectory.schema.mof
│ │ └── MSFT_xWebsite
│ │ │ ├── MSFT_xWebsite.psm1
│ │ │ └── MSFT_xWebsite.schema.mof
│ │ ├── TechNetDocumentation_xWebAdministration.html
│ │ └── xWebAdministration.psd1
├── Scripts
│ ├── ConfigureWebserver.ps1
│ └── Teardown.ps1
└── Templates
│ ├── Webserver.template
│ ├── Webserver.template.answer
│ └── Zephyr.template
├── Exercise5.md
├── Exercise5
├── Deploy.ps1
├── Deploy.ps1.answer
├── Parameters.ps1
├── PowerShellModules
│ ├── cOctopus
│ │ ├── DSCResources
│ │ │ └── cTentacleAgent
│ │ │ │ ├── cTentacleAgent.psm1
│ │ │ │ └── cTentacleAgent.schema.mof
│ │ └── cOctopus.psd1
│ ├── cWinServer
│ │ ├── DSCResources
│ │ │ └── WinServerOptions
│ │ │ │ ├── WinServerOptions.psm1
│ │ │ │ └── WinServerOptions.schema.mof
│ │ └── cWinServer.psd1
│ ├── xDscDiagnostics
│ │ ├── xDscDiagnostics.psd1
│ │ ├── xDscDiagnostics.psm1
│ │ └── xDscDiagnosticsFormat.ps1xml
│ ├── xNetworking
│ │ ├── DSCResources
│ │ │ ├── MSFT_xDNSServerAddress
│ │ │ │ ├── MSFT_xDNSServerAddress.psm1
│ │ │ │ └── MSFT_xDNSServerAddress.schema.mof
│ │ │ ├── MSFT_xFirewall
│ │ │ │ ├── MSFT_xFirewall.Schema.mof
│ │ │ │ └── MSFT_xFirewall.psm1
│ │ │ └── MSFT_xIPAddress
│ │ │ │ ├── MSFT_xIPAddress.psm1
│ │ │ │ └── MSFT_xIPAddress.schema.mof
│ │ ├── Examples
│ │ │ ├── Sample_xDnsServerAddress.ps1
│ │ │ ├── Sample_xFirewall_AddFirewallRule.ps1
│ │ │ ├── Sample_xFirewall_AddFirewallRuleToExistingGroup.ps1
│ │ │ ├── Sample_xFirewall_AddFirewallRuleToNewGroup.ps1
│ │ │ ├── Sample_xFirewall_DisableAccessToApplication.ps1
│ │ │ ├── Sample_xIPAddress_FixedValue.ps1
│ │ │ └── Sample_xIPAddress_Parameterized.ps1
│ │ ├── xNetworking.psd1
│ │ └── xNetworking_TechNetDocumentation.html
│ ├── xPendingReboot
│ │ ├── DSCResources
│ │ │ └── MSFT_xPendingReboot
│ │ │ │ ├── MSFT_xPendingReboot.psm1
│ │ │ │ └── MSFT_xPendingReboot.schema.mof
│ │ ├── xPendingReboot.psd1
│ │ └── xPendingReboot_Documentation.html
│ └── xWebAdministration
│ │ ├── DSCResources
│ │ ├── MSFT_xIisModule
│ │ │ ├── MSFT_xIisModule.psm1
│ │ │ ├── MSFT_xIisModule.schema.mof
│ │ │ └── xIisModuleDesigner.ps1
│ │ ├── MSFT_xWebAppPool
│ │ │ ├── MSFT_xWebAppPool.psm1
│ │ │ └── MSFT_xWebAppPool.schema.mof
│ │ ├── MSFT_xWebApplication
│ │ │ ├── MSFT_xWebApplication.psm1
│ │ │ └── MSFT_xWebApplication.schema.mof
│ │ ├── MSFT_xWebConfigKeyValue
│ │ │ ├── MSFT_xWebConfigKeyValue.psm1
│ │ │ └── MSFT_xWebConfigKeyValue.schema.mof
│ │ ├── MSFT_xWebVirtualDirectory
│ │ │ ├── MSFT_xWebVirtualDirectory.psm1
│ │ │ └── MSFT_xWebVirtualDirectory.schema.mof
│ │ └── MSFT_xWebsite
│ │ │ ├── MSFT_xWebsite.psm1
│ │ │ └── MSFT_xWebsite.schema.mof
│ │ ├── TechNetDocumentation_xWebAdministration.html
│ │ └── xWebAdministration.psd1
├── Scripts
│ ├── ConfigureWebserver.ps1
│ ├── ConfigureWebserver.ps1.answer
│ └── Teardown.ps1
└── Templates
│ ├── Webserver.template
│ └── Zephyr.template
├── README.md
└── ResetCredentials.bat
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studo 2015 cache/options directory
26 | .vs/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | # NUNIT
33 | *.VisualState.xml
34 | TestResult.xml
35 |
36 | # Build Results of an ATL Project
37 | [Dd]ebugPS/
38 | [Rr]eleasePS/
39 | dlldata.c
40 |
41 | *_i.c
42 | *_p.c
43 | *_i.h
44 | *.ilk
45 | *.meta
46 | *.obj
47 | *.pch
48 | *.pdb
49 | *.pgc
50 | *.pgd
51 | *.rsp
52 | *.sbr
53 | *.tlb
54 | *.tli
55 | *.tlh
56 | *.tmp
57 | *.tmp_proj
58 | *.log
59 | *.vspscc
60 | *.vssscc
61 | .builds
62 | *.pidb
63 | *.svclog
64 | *.scc
65 |
66 | # Chutzpah Test files
67 | _Chutzpah*
68 |
69 | # Visual C++ cache files
70 | ipch/
71 | *.aps
72 | *.ncb
73 | *.opensdf
74 | *.sdf
75 | *.cachefile
76 |
77 | # Visual Studio profiler
78 | *.psess
79 | *.vsp
80 | *.vspx
81 |
82 | # TFS 2012 Local Workspace
83 | $tf/
84 |
85 | # Guidance Automation Toolkit
86 | *.gpState
87 |
88 | # ReSharper is a .NET coding add-in
89 | _ReSharper*/
90 | *.[Rr]e[Ss]harper
91 | *.DotSettings.user
92 |
93 | # JustCode is a .NET coding addin-in
94 | .JustCode
95 |
96 | # TeamCity is a build add-in
97 | _TeamCity*
98 |
99 | # DotCover is a Code Coverage Tool
100 | *.dotCover
101 |
102 | # NCrunch
103 | _NCrunch_*
104 | .*crunch*.local.xml
105 |
106 | # MightyMoose
107 | *.mm.*
108 | AutoTest.Net/
109 |
110 | # Web workbench (sass)
111 | .sass-cache/
112 |
113 | # Installshield output folder
114 | [Ee]xpress/
115 |
116 | # DocProject is a documentation generator add-in
117 | DocProject/buildhelp/
118 | DocProject/Help/*.HxT
119 | DocProject/Help/*.HxC
120 | DocProject/Help/*.hhc
121 | DocProject/Help/*.hhk
122 | DocProject/Help/*.hhp
123 | DocProject/Help/Html2
124 | DocProject/Help/html
125 |
126 | # Click-Once directory
127 | publish/
128 |
129 | # Publish Web Output
130 | *.[Pp]ublish.xml
131 | *.azurePubxml
132 | # TODO: Comment the next line if you want to checkin your web deploy settings
133 | # but database connection strings (with potential passwords) will be unencrypted
134 | *.pubxml
135 | *.publishproj
136 |
137 | # NuGet Packages
138 | *.nupkg
139 | # The packages folder can be ignored because of Package Restore
140 | **/packages/*
141 | # except build/, which is used as an MSBuild target.
142 | !**/packages/build/
143 | # Uncomment if necessary however generally it will be regenerated when needed
144 | #!**/packages/repositories.config
145 |
146 | # Windows Azure Build Output
147 | csx/
148 | *.build.csdef
149 |
150 | # Windows Store app package directory
151 | AppPackages/
152 |
153 | # Others
154 | *.[Cc]ache
155 | ClientBin/
156 | [Ss]tyle[Cc]op.*
157 | ~$*
158 | *~
159 | *.dbmdl
160 | *.dbproj.schemaview
161 | *.pfx
162 | *.publishsettings
163 | node_modules/
164 | bower_components/
165 |
166 | # RIA/Silverlight projects
167 | Generated_Code/
168 |
169 | # Backup & report files from converting an old project file
170 | # to a newer Visual Studio version. Backup files are not needed,
171 | # because we have git ;-)
172 | _UpgradeReport_Files/
173 | Backup*/
174 | UpgradeLog*.XML
175 | UpgradeLog*.htm
176 |
177 | # SQL Server files
178 | *.mdf
179 | *.ldf
180 |
181 | # Business Intelligence projects
182 | *.rdl.data
183 | *.bim.layout
184 | *.bim_*.settings
185 |
186 | # Microsoft Fakes
187 | FakesAssemblies/
188 |
189 | # Node.js Tools for Visual Studio
190 | .ntvs_analysis.dat
191 |
192 | # Visual Studio 6 build log
193 | *.plg
194 |
195 | # Visual Studio 6 workspace options file
196 | *.opt
197 | Private/*
198 | **/Private/*
199 |
--------------------------------------------------------------------------------
/Exercise1.md:
--------------------------------------------------------------------------------
1 | # Exercise 1
2 |
3 | ## Manually provisioning
4 |
5 | In this exercise we will be provisioning an EC2 instance by hand to build some familiarity with the web console, and to develop an appreciation for the level of effort involved to launch and configure an instance by hand.
6 |
7 | ## Goals
8 |
9 | * Build familiarity with the AWS Web console
10 | * Develop a healthy appreciation for manual provisioning effort
11 | * Provision a functional web-server by hand, and deploy to it with Octopus
12 |
13 | ## Instructions
14 |
15 | 1. Open the EC2 console within the AWS web console
16 | 2. Launch a "Microsoft Windows Server 2016 Base" image-based EC2 instance
17 | 3. Make it a t2.medium
18 | 4. Ensure it is on the *CloudFormawesome* VPC, in the *DMZ B* subnet
19 | 5. Ensure it is assigned a public IP address
20 | 6. Provision a 50 gigabyte *General Purpose* SSD to be used
21 | 7. Tag the instance with a key of "Name", and value of "{yourinitials}-WebServer-Manual"
22 | 8. Create a new security group named {yourinitials}-WebServer-Manual-SecurityGroup
23 | 9. Given we are going to be using the instance to host a web site, need to remote to it to configure a tentacle, and Octopus needs to talk to it, assign inbound access rules for all IP addresses to ports 80 and 3389, and for the VPC IP range to 10933
24 | 10. GO GO GO! (Review, then click Launch)
25 | 11. You will be prompted for a key pair that will be used to generate the instance's administrator password. Select the AwsDayKeyPair
26 | 12. Once launched, remote onto your instance via it's public IP address - to retrieve the password for your instance, select it in the console and click 'Connect', locate the .pem file for the AwsDayKeyPair and click 'Decrypt Password'
27 | 13. Give that this is a base windows image, we will need to add the *Web Server (IIS)* role to it in Server Management, and ensure under that that we have selected *Application Development > ASP.NET 4.6*
28 | 14. Finally, connect to Octopus (address and credentials are be provided), install a tentacle onto your machine, add your machine to the Production environment and trigger a deployment. _Use the manual tentacle registration if discovery fails in Octopus._
29 | 15. On your webserver hit http://localhost - great success!
30 |
--------------------------------------------------------------------------------
/Exercise2.md:
--------------------------------------------------------------------------------
1 | # Exercise 2
2 |
3 | ## Cloud Formation templating
4 |
5 | In this exercise we will build a cloud formation template to provision the security group and EC2 instance pair that we manually created in [Exercise 1](https://github.com/andrewabest/AWS-Workshop/blob/master/Exercise1.md)
6 |
7 | ## Goals
8 |
9 | * Gain exposure to AWS powershell API
10 | * Get hands dirty building a CloudFormation template
11 | * Launch a security group and EC2 instance via powershell - Infrastructure as code!
12 |
13 | ## Prior to starting
14 |
15 | To complete this exercise you'll need to add an appropriate set of credentials to your [SDK Credential Store](http://docs.aws.amazon.com/powershell/latest/userguide/specifying-your-aws-credentials.html) - run ResetCredentials.bat from the repository root with appropriate parameters to do this
16 |
17 | ## Instructions
18 |
19 | 1. Navigate to .\Exercise2 and open Deploy.ps1 in Powershell ISE
20 | 2. Spend a some time getting familiar with what it is doing
21 | * How does the template get from our local machine to AWS?
22 | * How do we supply parameters that our CloudFormation template requires?
23 | 3. Open .\Exercise2\Parameters.ps1. Update the ResourcePrefix parameter to your initials, and take note of the other parameters provided
24 | 4. Create an empty file named Webserver.template in .\Exercise2\Templates
25 | 5. Build your template's [Skeleton Structure](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/template-anatomy.html)
26 | 6. Define your [Security Group Template](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html)
27 | * Refer to the [samples available](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/sample-templates-services-us-west-2.html#d0e111750) if you need a more complete sample to work from
28 | 7. Define your [EC2 Instance Template](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-instance.html)
29 | 8. Kick off .\Deploy.ps1 by F5-ing it in ISE, and open the CloudFormation section of the AWS console
30 | 9. Monitor your stack's creation by opening the 'Events' tab for a running summary of progress
31 | 10. If something fails, analyse the error. What went wrong? Double check your template, and the template documentation. Feel free to grab someone to rubber duck!
32 | 11. If it is all green, jump into the EC2 console and try to remote into your instance
33 | 12. Great success!
34 |
35 | Note: If you installed the [Visual Studio Tooling](http://blog.kloud.com.au/2015/05/18/create-aws-cloudformation-templates-with-visual-studio/) you can use an "AWS CloudFormation project" to work with your template, which will give you some intellisense out of the box.
36 |
--------------------------------------------------------------------------------
/Exercise2/Deploy.ps1:
--------------------------------------------------------------------------------
1 | cls
2 |
3 | Import-Module AWSPowerShell
4 |
5 | ############################################################################################################################
6 | #
7 | # 00 - Helper Functions
8 | #
9 | ############################################################################################################################
10 |
11 | function GenerateConfigFileS3Key($environment, $release, $filename)
12 | {
13 | $key = $environment + "/" + $release + "/" + $filename
14 | return $key
15 | }
16 |
17 | ############################################################################################################################
18 | #
19 | # 01 - Wrangling Octopus Variables
20 | #
21 | ############################################################################################################################
22 |
23 | # Create a new variable scope so that we can run this script multiple times
24 | # in a single script console instance without polluting the global scope with
25 | # fake variables.
26 | & {
27 | $scriptPath = [System.IO.Path]::GetDirectoryName($myInvocation.PSCommandPath)
28 |
29 | . .\Parameters.ps1
30 |
31 | # Lower case variables sensitive to casing
32 | $Parameters['CloudFormationStackName'] = $Parameters['CloudFormationStackName'].ToLowerInvariant()
33 | $Parameters['S3BucketName'] = $Parameters['S3BucketName'].ToLowerInvariant()
34 |
35 | Write-Output $Parameters
36 | Write-Output ""
37 |
38 | ############################################################################################################################
39 | #
40 | # 02 - Push templates to clouds
41 | #
42 | ############################################################################################################################
43 |
44 | # Create an S3 bucket to upload our templates and scripts to.
45 | if (-Not (Get-S3Bucket -BucketName $Parameters['S3BucketName'] -Region $Parameters['AWSRegion'] -ProfileName "AWSWorkshop"))
46 | {
47 | Write-Output "Creating S3 bucket..."
48 | New-S3Bucket -BucketName $Parameters['S3BucketName'] -Region $Parameters['AWSRegion'] -ProfileName "AWSWorkshop"
49 | }
50 |
51 | # CloudFormation templates
52 | Write-Output "Uploading CloudFormation templates..."
53 | $webserverTemplateS3BucketKey = GenerateConfigFileS3Key -environment $Parameters['Environment'] -release $Parameters['Version'] -filename "Webserver.template"
54 | Write-S3Object -BucketName: $Parameters['S3BucketName'] -Key $webserverTemplateS3BucketKey -File $scriptPath\Templates\Webserver.template -Region $Parameters['AWSRegion'] -ProfileName "AWSWorkshop"
55 |
56 | ############################################################################################################################
57 | #
58 | # 03 - GO GO GO (Create the stack)
59 | #
60 | ############################################################################################################################
61 |
62 | $webserverTemplateUrl = "https://" + $Parameters['S3BucketName'] + ".s3.amazonaws.com/$webserverTemplateS3BucketKey"
63 | $timestamp = Get-Date -Format u
64 |
65 | $stack = $null
66 | try
67 | {
68 | $stack = Get-CFNStack -StackName $Parameters['CloudFormationStackName'] -Region $Parameters['AWSRegion'] -ProfileName "AWSWorkshop"
69 | }
70 | catch
71 | {
72 | }
73 |
74 | $stackParameters = `
75 | @(`
76 | @{ParameterKey="VpcId"; ParameterValue=$Parameters['VpcId']},`
77 | @{ParameterKey="Version"; ParameterValue=$Parameters['Version']},`
78 | @{ParameterKey="Environment"; ParameterValue=$Parameters['Environment']},`
79 | @{ParameterKey="KeyPairName"; ParameterValue=$Parameters['KeyPairName']},`
80 | @{ParameterKey="WebserverImageId"; ParameterValue=$Parameters['WebserverImageId']},`
81 | @{ParameterKey="WebserverInstanceType"; ParameterValue=$Parameters['WebserverInstanceType']},`
82 | @{ParameterKey="WebserverSubnetId"; ParameterValue=$Parameters['WebserverSubnetId']},`
83 | @{ParameterKey="ResourcePrefix"; ParameterValue=$Parameters['ResourcePrefix']})
84 |
85 | $stackName = $Parameters['CloudFormationStackName']
86 | if ($stack -eq $null)
87 | {
88 | Write-Output "Creating new CFN stack $stackName"
89 |
90 | New-CFNStack -Capability "CAPABILITY_IAM" -StackName $stackName -TemplateURL $webserverTemplateUrl -Parameters $stackParameters -Region $Parameters['AWSRegion'] -ProfileName "AWSWorkshop"
91 | }
92 | else
93 | {
94 | Write-Output "Updating existing CFN stack $stackName"
95 |
96 | Update-CFNStack -Capability "CAPABILITY_IAM" -StackName $stackName -TemplateURL $webserverTemplateUrl -Parameters $stackParameters -Region $Parameters['AWSRegion'] -ProfileName "AWSWorkshop"
97 | }
98 |
99 | while($true)
100 | {
101 | $stack = Get-CFNStack -StackName $stackName -Region $Parameters['AWSRegion'] -ProfileName "AWSWorkshop"
102 |
103 | if ($stack.StackStatus -eq [Amazon.CloudFormation.StackStatus]::CREATE_COMPLETE -or $stack.StackStatus -eq [Amazon.CloudFormation.StackStatus]::UPDATE_COMPLETE)
104 | {
105 | Write-Output "Cloud formation succeeded with the following outputs..."
106 | $stack.Outputs | Format-Table | Write-Output
107 |
108 | # Note: In here, wire up external DNS etc based on stack output parameters
109 |
110 | break;
111 | }
112 |
113 | if ($stack.StackStatus -eq [Amazon.CloudFormation.StackStatus]::CREATE_FAILED -or $stack.StackStatus -eq [Amazon.CloudFormation.StackStatus]::ROLLBACK_COMPLETE -or $stack.StackStatus -eq [Amazon.CloudFormation.StackStatus]::ROLLBACK_FAILED)
114 | {
115 | Write-Output "Cloud formation failed, abandoning..."
116 |
117 | break;
118 | }
119 |
120 | Write-Output "Waiting for cloud formation $stackName to finish creation..."
121 |
122 | Start-Sleep -s 10
123 | }
124 |
125 | Write-Output "fin"
126 | }
--------------------------------------------------------------------------------
/Exercise2/Parameters.ps1:
--------------------------------------------------------------------------------
1 | $Parameters = @{}
2 |
3 | # Octopus parameters
4 | $Parameters['ResourcePrefix'] = "aab";
5 | $Parameters['Environment'] = "Production";
6 | $Parameters['Version'] = "1.0.0-ryan0001";
7 |
8 | # CloudFormation parameters
9 | $Parameters['AWSRegion'] = "ap-southeast-2";
10 | $Parameters['CloudFormationStackName'] = "{0}-simple-sandbox-{1}" -f @($Parameters['ResourcePrefix'], $Parameters['Environment']);
11 | $Parameters['S3BucketName'] = "{0}-simple-sandbox-infrastructure" -f $Parameters['ResourcePrefix'];
12 | $Parameters['VpcId'] = "vpc-7ecaee1b";
13 |
14 | # AWS parameters
15 | $Parameters['KeyPairName'] = "AwsDayKeyPair";
16 | $Parameters['WebserverImageId'] = "ami-bf8895dc"; #WINDOWS_2016_BASE
17 | $Parameters['WebserverInstanceType'] = "t2.medium";
18 | $Parameters['WebserverSubnetId'] = "subnet-99477cee"; # DMZ B
--------------------------------------------------------------------------------
/Exercise2/Templates/Webserver.template.answer:
--------------------------------------------------------------------------------
1 | {
2 | "AWSTemplateFormatVersion": "2010-09-09",
3 |
4 | "Description": "A template to deploy a simple web server to a single subnet.",
5 |
6 | "Parameters": {
7 | "VpcId": {
8 | "Description": "The Vpc to deploy the Webserver infrastructure into.",
9 | "Type": "String"
10 | },
11 | "Version": {
12 | "Description": "The package version that contains this CloudFormation template.",
13 | "Type": "String"
14 | },
15 | "Environment": {
16 | "Type": "String",
17 | "Default": "Development"
18 | },
19 | "KeyPairName": {
20 | "Description": "The EC2 key pair used to launch web instances",
21 | "Type": "AWS::EC2::KeyPair::KeyName"
22 | },
23 | "WebserverImageId": {
24 | "Description": "The EC2 AmiId to use for web",
25 | "Type": "String"
26 | },
27 | "WebserverInstanceType": {
28 | "Description": "The EC2 instance type to use for web",
29 | "Type": "String"
30 | },
31 | "WebserverSubnetId": {
32 | "Description": "The PUBLIC subnet belonging to availability zone one into which the instance will be launched",
33 | "Type": "String"
34 | },
35 | "ResourcePrefix" : {
36 | "Description": "Used to prefix a unique name to resources where applicable",
37 | "Type": "String"
38 | }
39 | },
40 |
41 | "Resources": {
42 | "WebSecurityGroup": {
43 | "Type": "AWS::EC2::SecurityGroup",
44 | "Properties": {
45 | "GroupDescription": "Inbound Octopus, RDP and HTTP (web and healthcheck)",
46 | "VpcId": { "Ref": "VpcId" },
47 | "SecurityGroupIngress": [
48 | {
49 | "IpProtocol": "tcp",
50 | "FromPort": "10933",
51 | "ToPort": "10933",
52 | "CidrIp": "172.26.0.0/0"
53 | },
54 | {
55 | "IpProtocol": "tcp",
56 | "FromPort": "80",
57 | "ToPort": "80",
58 | "CidrIp": "0.0.0.0/0"
59 | },
60 | {
61 | "IpProtocol": "tcp",
62 | "FromPort": "3389",
63 | "ToPort": "3389",
64 | "CidrIp": "0.0.0.0/0"
65 | }
66 | ]
67 | }
68 | },
69 | "WebServer": {
70 | "Type": "AWS::EC2::Instance",
71 | "Properties": {
72 | "ImageId": { "Ref": "WebserverImageId" },
73 | "InstanceType": { "Ref": "WebserverInstanceType" },
74 | "KeyName": { "Ref": "KeyPairName" },
75 | "BlockDeviceMappings": [
76 | {
77 | "DeviceName": "/dev/sda1",
78 | "Ebs": {
79 | "VolumeSize": "50",
80 | "VolumeType": "gp2"
81 | }
82 | }
83 | ],
84 | "NetworkInterfaces": [ {
85 | "AssociatePublicIpAddress": "true",
86 | "DeviceIndex": "0",
87 | "GroupSet": [ { "Fn::GetAtt": [ "WebSecurityGroup", "GroupId" ] } ],
88 | "SubnetId": { "Ref" : "WebserverSubnetId" }
89 | } ],
90 | "Tags": [
91 | {
92 | "Key": "Name",
93 | "Value": {
94 | "Fn::Join": [
95 | "",
96 | [
97 | {
98 | "Ref": "ResourcePrefix"
99 | },
100 | "-",
101 | {
102 | "Ref": "Environment"
103 | },
104 | "-WebServer"
105 | ]
106 | ]
107 | }
108 | },
109 | {
110 | "Key": "Version",
111 | "Value": { "Ref": "Version" }
112 | },
113 | {
114 | "Key": "Environment",
115 | "Value": { "Ref": "Environment" }
116 | }
117 | ]
118 | }
119 | }
120 | }
121 | }
--------------------------------------------------------------------------------
/Exercise3.md:
--------------------------------------------------------------------------------
1 | # Exercise 3
2 |
3 | ## PowerShell DSC authoring
4 |
5 | In this exercise we will build out a sample DSC template and apply it to our CloudFormation-created web servers that we created in [Exercise 2](https://github.com/andrewabest/AWS-Workshop/blob/master/Exercise2.md).
6 |
7 | We are going to configure a website to act as a basic load balancer endpoint that our server's IIS can serve up when requested over port 81 - a static index.html file will suffice.
8 |
9 | ## Goals
10 |
11 | * Use DSC resources to add a load balancer endpoint and firewall exceptions to the supplied DSC template
12 | * See what happens when a configuration fails to compile, and know how to 'fail fast'
13 | * See the output of the Local Configuration Manager when it applies a configuration
14 | * Discover how to diagnose errors that occur when applying DSC configurations
15 | * Configure a Windows server with DSC
16 |
17 | ## Instructions
18 |
19 | 1. Remote into your EC2 instance that you created with CloudFormation in [Exercise 2](https://github.com/andrewabest/AWS-Workshop/blob/master/Exercise2.md).
20 | 2. Copy the contents of .\Exercise3 onto the instance
21 | 3. Jump into PowerShell ISE on your instance and allow us to utilize our unsigned DSC resources by executing the following
22 |
23 | > Set-ExecutionPolicy Bypass
24 |
25 | 4. Open .\Exercise3\PowerShellModules, and copy all of the folders therein over to
26 |
27 | > C:\Program Files\WindowsPowerShell\Modules
28 |
29 | > NOTE: since Powershell 5, we can install these modules like so:
30 | > install-module xdscdiagnostics -Repository 'PSGallery'
31 |
32 | 5. Open .\Exercise3\DSC_Diagnostics.md and read it. Enable low level logging on your instance, and have a play with the Get and Trace cmdlets mentioned
33 | 6. Open .\Exercise3\ConfigureWebserver.ps1 - this is our DSC configuration. Take a look at its structure. Look at what it is already doing
34 | 7. Complete the [File](https://msdn.microsoft.com/en-us/PowerShell/DSC/fileResource) resource TODO
35 | 8. Complete the [xWebsite](https://github.com/PowerShell/xWebAdministration#xwebsite) resource TODO
36 | 9. Complete the [xFirewall](https://github.com/PowerShell/xNetworking#xfirewall) resource TODO
37 | 10. F5 your configuration. The machine will need to reboot a couple of times - you can see where by looking for the **xPendingReboot** resource usage
38 | 11. Monitor the EC2 console in AWS for your machine to come back online - once it is, remote back into it
39 | 12. Open the DSC_Diagnostics.md guide again and use the instructions to see what operations were executed, if they were successful or not, and what diagnostic information you are provided with
40 | 13. If there were errors, troubleshoot what they were. Pair up, rubber duck, whatever works! Once you think you have fixed the errors in your configuration again, F5 it again!
41 | 14. Rinse and repeat until you have succesfully configured your server
42 |
43 | ### Gotchas
44 |
45 | If you want to run the configuration multiple times, you will need to remove the previously generated MOF before regenerating a new one, or you will get a reasonably undecipherable error
46 |
--------------------------------------------------------------------------------
/Exercise3/ConfigureWebserver.ps1:
--------------------------------------------------------------------------------
1 | Configuration ConfigureWebserver
2 | {
3 | Import-DscResource -ModuleName cWinServer
4 | Import-DscResource -ModuleName xWebAdministration
5 | Import-DscResource -ModuleName xPendingReboot
6 | Import-DscResource -ModuleName xNetworking
7 |
8 | # Localhost targets the node this script is run on
9 | Node 'localhost'
10 | {
11 | LocalConfigurationManager
12 | {
13 | RebootNodeIfNeeded = $True
14 | }
15 |
16 | WinServerOptions ServerOptions
17 | {
18 | Ensure = "Present"
19 | Name = "Set timezone and culture"
20 | Culture = "en-AU"
21 | TimeZone = "AUS Eastern Standard Time"
22 | }
23 |
24 | xPendingReboot AfterServerOptions
25 | {
26 | Name = "AfterServerOptions"
27 | DependsOn = '[WinServerOptions]ServerOptions'
28 | }
29 |
30 | $windowsFeatures = @(
31 | "Web-App-Dev",
32 | "Web-Common-Http",
33 | "Web-Health",
34 | "Web-Performance",
35 | "Web-Security",
36 | "Web-Scripting-Tools",
37 | "Web-Mgmt-Service",
38 | "Web-Mgmt-Console"
39 | )
40 |
41 | $windowsFeatureDependOn = @();
42 |
43 | foreach ($windowsFeature in $windowsFeatures)
44 | {
45 | WindowsFeature "IIS_$windowsFeature"
46 | {
47 | Ensure = "Present"
48 | Name = $windowsFeature
49 | IncludeAllSubFeature = $true
50 | DependsOn = "[xPendingReboot]AfterServerOptions"
51 | }
52 |
53 | $windowsFeatureDependOn += "[WindowsFeature]IIS_$windowsFeature"
54 | }
55 |
56 | <#
57 | NOTE: For new players, if you want to discover whether a reboot will be required after a given piece of DSC, search for "$global:DSCMachineStatus = 1" in the resources you have used.
58 | #>
59 |
60 | xPendingReboot AfterWindowsFeatures
61 | {
62 | Name = 'AfterWindowsFeatures'
63 | DependsOn = $windowsFeatureDependOn
64 | }
65 |
66 | # Stop & Remove the default website
67 | xWebsite DefaultSite
68 | {
69 | Ensure = "Absent"
70 | Name = "Default Web Site"
71 | State = "Stopped"
72 | PhysicalPath = "C:\inetpub\wwwroot"
73 | DependsOn = $windowsFeatureDependOn
74 | }
75 |
76 | # Remove all default Application Pools EXCEPT DEFAULT (will use this for the load balancer health check)
77 | foreach ($appPool in @("Classic .NET AppPool", ".NET v2.0",
78 | ".NET v2.0 Classic", ".NET v4.5", ".NET v4.5 Classic"))
79 | {
80 | xWebAppPool $appPool
81 | {
82 | Ensure = "Absent"
83 | Name = $appPool
84 | DependsOn = ($windowsFeatureDependOn + @("[xWebsite]DefaultSite"))
85 | }
86 | }
87 |
88 | # TODO: Use File Resource to add a load-balancer endpoint index.html
89 |
90 | # TODO: Use xWebsite Resource to set up an IIS website at the root of the load-balancer endpoint
91 |
92 | # TODO: Use xFirewall Resource to allow inbound http access on ports 80 and 81
93 | }
94 | }
95 |
96 | ConfigureWebserver
97 |
98 | Set-DscLocalConfigurationManager -Path .\ConfigureWebserver -Verbose
99 | Start-DscConfiguration -Path .\ConfigureWebserver -Verbose -Wait -Force
100 |
--------------------------------------------------------------------------------
/Exercise3/ConfigureWebserver.ps1.answer:
--------------------------------------------------------------------------------
1 | Configuration ConfigureWebserver
2 | {
3 | Import-DscResource -ModuleName cWinServer
4 | Import-DscResource -ModuleName xWebAdministration
5 | Import-DscResource -ModuleName xPendingReboot
6 | Import-DscResource -ModuleName xNetworking
7 |
8 | # Localhost targets the node this script is run on
9 | Node 'localhost'
10 | {
11 | LocalConfigurationManager
12 | {
13 | RebootNodeIfNeeded = $True
14 | }
15 |
16 | WinServerOptions ServerOptions
17 | {
18 | Ensure = "Present"
19 | Name = "Set timezone and culture"
20 | Culture = "en-AU"
21 | TimeZone = "AUS Eastern Standard Time"
22 | }
23 |
24 | xPendingReboot AfterServerOptions
25 | {
26 | Name = "AfterServerOptions"
27 | DependsOn = '[WinServerOptions]ServerOptions'
28 | }
29 |
30 | $windowsFeatures = @(
31 | "Web-App-Dev",
32 | "Web-Common-Http",
33 | "Web-Health",
34 | "Web-Performance",
35 | "Web-Security",
36 | "Web-Scripting-Tools",
37 | "Web-Mgmt-Service",
38 | "Web-Mgmt-Console"
39 | )
40 |
41 | $windowsFeatureDependOn = @();
42 |
43 | foreach ($windowsFeature in $windowsFeatures)
44 | {
45 | WindowsFeature "IIS_$windowsFeature"
46 | {
47 | Ensure = "Present"
48 | Name = $windowsFeature
49 | IncludeAllSubFeature = $true
50 | DependsOn = "[xPendingReboot]AfterServerOptions"
51 | }
52 |
53 | $windowsFeatureDependOn += "[WindowsFeature]IIS_$windowsFeature"
54 | }
55 |
56 | <#
57 | NOTE: For new players, if you want to discover whether a reboot will be required after a given piece of DSC, search for "$global:DSCMachineStatus = 1" in the resources you have used.
58 | #>
59 |
60 | xPendingReboot AfterWindowsFeatures
61 | {
62 | Name = 'AfterWindowsFeatures'
63 | DependsOn = $windowsFeatureDependOn
64 | }
65 |
66 | # Stop & Remove the default website
67 | xWebsite DefaultSite
68 | {
69 | Ensure = "Absent"
70 | Name = "Default Web Site"
71 | State = "Stopped"
72 | PhysicalPath = "C:\inetpub\wwwroot"
73 | DependsOn = $windowsFeatureDependOn
74 | }
75 |
76 | # Remove all default Application Pools EXCEPT DEFAULT (will use this for the load balancer health check)
77 | foreach ($appPool in @("Classic .NET AppPool", ".NET v2.0",
78 | ".NET v2.0 Classic", ".NET v4.5", ".NET v4.5 Classic"))
79 | {
80 | xWebAppPool $appPool
81 | {
82 | Ensure = "Absent"
83 | Name = $appPool
84 | DependsOn = ($windowsFeatureDependOn + @("[xWebsite]DefaultSite"))
85 | }
86 | }
87 |
88 | File LoadBalancerHealthCheckEndpointContent
89 | {
90 | Ensure = "Present"
91 | DestinationPath = "C:\inetpub\wwwroot\index.html"
92 | Contents = "Hello, is it me you're looking for?"
93 | Type = "File"
94 | }
95 |
96 | xWebsite LoadBalancerHealthCheckEndpoint
97 | {
98 | Ensure = "Present"
99 | Name = "LoadBalancerHealthCheck"
100 | State = "Started"
101 | PhysicalPath = "C:\inetpub\wwwroot"
102 | BindingInfo = MSFT_xWebBindingInformation
103 | {
104 | Protocol = "HTTP"
105 | Port = 81
106 | }
107 | DependsOn = "[File]LoadBalancerHealthCheckEndpointContent"
108 | }
109 |
110 | xFirewall Firewall
111 | {
112 | Name = "Web"
113 | DisplayName = "Inbound access for web requests"
114 | Ensure = "Present"
115 | Access = "Allow"
116 | State = "Enabled"
117 | Profile = ("Domain", "Private", "Public")
118 | Direction = "InBound"
119 | RemotePort = ("Any")
120 | LocalPort = ("80", "81", "443")
121 | Protocol = "TCP"
122 | Description = "Inbound access for web requests"
123 | }
124 | }
125 | }
126 |
127 | ConfigureWebserver
128 |
129 | Set-DscLocalConfigurationManager -Path .\ConfigureWebserver -Verbose
130 | Start-DscConfiguration -Path .\ConfigureWebserver -Verbose -Wait -Force
131 |
--------------------------------------------------------------------------------
/Exercise3/DSC_Diagnostics.md:
--------------------------------------------------------------------------------
1 | # DSC Diagnostics
2 |
3 | PowerShell logs all DSC related events to *[Applications and Services Logs/Microsoft/Windows/Desired State Configuration]* in the Windows Event Log.
4 |
5 | By default, **analytic** and **debug** level logging are off by default. To turn them on, we can use the [xDscDiagnostics](http://blogs.msdn.com/b/powershell/archive/2014/02/11/dsc-diagnostics-module-analyze-dsc-logs-instantly-now.aspx) module and run the following commands
6 |
7 | Update-xDscEventLogStatus -Channel Analytic -Status Enabled
8 | Update-xDscEventLogStatus -Channel Debug -Status Enabled
9 |
10 | Once we have enabled our low-level logging, we can query to see what DSC operations have been executed thus far by executing
11 |
12 | Get-xDscOperation
13 |
14 | To get detailed information on an operation, we can then go further and use
15 |
16 | Trace-xDscOperation -SequenceID 1 | Format-Table
17 |
18 | If you are particularly sadistic, and the xDscDiagnostics tools are not returning the information you want to see, you can query the event log directly using the approaches outlined [here](https://technet.microsoft.com/en-au/library/dn249926.aspx). Disclaimer: it is a horrible way to work.
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/cWinServer/DSCResources/WinServerOptions/WinServerOptions.psm1:
--------------------------------------------------------------------------------
1 | function Get-TargetResource
2 | {
3 | [CmdletBinding()]
4 | [OutputType([System.Collections.Hashtable])]
5 | param
6 | (
7 | [parameter(Mandatory = $true)]
8 | [System.String]
9 | $Name,
10 |
11 | [System.String]
12 | $Culture,
13 |
14 | [System.String]
15 | $TimeZone
16 | )
17 |
18 | $returnValue = @{
19 | Ensure = $Ensure
20 | Name = $Name
21 | Culture = $Culture
22 | Timezone = $Timezone
23 | }
24 |
25 | return $returnValue;
26 | }
27 |
28 | function Set-TargetResource
29 | {
30 | [CmdletBinding()]
31 | param
32 | (
33 | [ValidateSet("Present","Absent")]
34 | [System.String]
35 | $Ensure,
36 |
37 | [parameter(Mandatory = $true)]
38 | [System.String]
39 | $Name,
40 |
41 | [System.String]
42 | $Culture,
43 |
44 | [System.String]
45 | $TimeZone
46 | )
47 |
48 | if ($Ensure -eq "Present")
49 | {
50 | if ($Culture)
51 | {
52 | if ((Get-WinSystemLocale).Name -ne $Culture)
53 | {
54 | Write-Verbose "Setting System Locale to $Culture. Will Require reboot to take effect."
55 | Set-WinSystemLocale -SystemLocale $Culture
56 |
57 | $global:DSCMachineStatus = 1;
58 | }
59 | }
60 |
61 | if (([System.TimeZone]::CurrentTimeZone).StandardName -ne $TimeZone)
62 | {
63 | Write-Verbose "Setting System TimeZone to [$TimeZone]"
64 | & tzutil.exe /s "$TimeZone"
65 | }
66 | }
67 | }
68 |
69 | function Test-TargetResource
70 | {
71 | [CmdletBinding()]
72 | [OutputType([System.Boolean])]
73 | param
74 | (
75 | [ValidateSet("Present","Absent")]
76 | [System.String]
77 | $Ensure,
78 |
79 | [parameter(Mandatory = $true)]
80 | [System.String]
81 | $Name,
82 |
83 | [System.String]
84 | $Culture,
85 |
86 | [System.String]
87 | $TimeZone
88 | )
89 |
90 | if ($Ensure -eq "Present")
91 | {
92 | if ($Culture)
93 | {
94 | if ((Get-WinSystemLocale).Name -ne $Culture)
95 | {
96 | Write-Verbose "System Locale is currently $((Get-WinSystemLocale).Name) and should be $Culture"
97 | return $false;
98 | }
99 |
100 | Write-Verbose "System Locale and Culture are correct."
101 | }
102 |
103 | if ($TimeZone)
104 | {
105 | if (([System.TimeZone]::CurrentTimeZone).StandardName -ne $TimeZone)
106 | {
107 | Write-Verbose "System TimeZone is current:[$(([System.TimeZone]::CurrentTimeZone).StandardName)] and should be:[$TimeZone]"
108 | return $false;
109 | }
110 |
111 | Write-Verbose "System TimeZone is correct."
112 | }
113 | }
114 | else
115 | {
116 | Write-Verbose "Ignoring checks"
117 | }
118 |
119 | return $true;
120 | }
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/cWinServer/DSCResources/WinServerOptions/WinServerOptions.schema.mof:
--------------------------------------------------------------------------------
1 | [ClassVersion("1.0.0.0"), FriendlyName("WinServerOptions")]
2 | class WinServerOptions : OMI_BaseResource
3 | {
4 | [Write, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure;
5 | [Key, Description("The name for the setup. Can just be the server name")] String Name;
6 | [Write, Description("The Windows Server culture")] String Culture;
7 | [Write, Description("The Windows Server Timezone")] String TimeZone;
8 | };
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/cWinServer/cWinServer.psd1:
--------------------------------------------------------------------------------
1 | #
2 | # Module manifest for module 'cWinServer'
3 | #
4 | # Generated by: andrewb
5 | #
6 | # Generated on: 9/06/2015
7 | @{
8 | ModuleVersion = '1.0'
9 | GUID = '90798d5f-9f2e-4af4-b9fd-79b4f67899fb'
10 | Author = 'andrewb'
11 | CompanyName = 'Unknown'
12 | Copyright = '(c) 2015 andrewb. All rights reserved.'
13 | Description = ''
14 | PowerShellVersion = '4.0'
15 | FunctionsToExport = @('Get-TargetResource','Set-TargetResource','Test-TargetResource')
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xDscDiagnostics/xDscDiagnostics.psd1:
--------------------------------------------------------------------------------
1 |
2 |
3 | @{
4 |
5 |
6 | ModuleVersion = '2.0'
7 | GUID = 'ef098cb4-f7e9-4763-b636-0cd9799e1c9a'
8 |
9 | Author = 'Microsoft Corporation'
10 | CompanyName = 'Microsoft Corporation'
11 | Copyright = '(c) 2013 Microsoft Corporation. All rights reserved.'
12 |
13 | Description = 'Module to help in reading details from DSC events'
14 |
15 | PowerShellVersion = '4.0'
16 |
17 | CLRVersion = '4.0'
18 |
19 | FunctionsToExport = @("*")
20 |
21 | NestedModules = @('xDscDiagnostics.psm1')
22 | }
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xDscDiagnostics/xDscDiagnosticsFormat.ps1xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Microsoft.PowerShell.xDscDiagnostics.GroupedEvents
7 |
8 | Microsoft.PowerShell.xDscDiagnostics.GroupedEvents
9 |
10 |
11 |
12 |
13 |
14 | 14
15 |
16 |
17 |
18 | 10
19 |
20 |
21 |
22 | 21
23 |
24 |
25 |
26 | 8
27 |
28 |
29 |
30 | 37
31 |
32 |
33 |
34 | 21
35 |
36 |
37 |
38 |
39 |
40 |
41 | ComputerName
42 |
43 |
44 | SequenceId
45 |
46 |
47 | TimeCreated
48 |
49 |
50 | Result
51 |
52 |
53 | JobID
54 |
55 |
56 | AllEvents
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | Microsoft.PowerShell.xDscDiagnostics.TraceOutput
65 |
66 | Microsoft.PowerShell.xDscDiagnostics.TraceOutput
67 |
68 |
69 |
70 |
71 |
72 | 14
73 |
74 |
75 |
76 | 12
77 |
78 |
79 |
80 | 21
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | ComputerName
91 |
92 |
93 | EventType
94 |
95 |
96 | TimeCreated
97 |
98 |
99 | Message
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xNetworking/DSCResources/MSFT_xDNSServerAddress/MSFT_xDNSServerAddress.psm1:
--------------------------------------------------------------------------------
1 | <#######################################################################################
2 | # xDNSServerAddress : DSC Resource that will set/test/get the current DNS Server
3 | # Address, by accepting values among those given in xDNSServerAddress.schema.mof
4 | #######################################################################################>
5 |
6 |
7 |
8 | ######################################################################################
9 | # The Get-TargetResource cmdlet.
10 | # This function will get the present list of DNS ServerAddress DSC Resource schema variables on the system
11 | ######################################################################################
12 | function Get-TargetResource
13 | {
14 | param
15 | (
16 | [Parameter(Mandatory)]
17 | [ValidateNotNullOrEmpty()]
18 | [String[]]$Address,
19 |
20 | [Parameter(Mandatory)]
21 | [ValidateNotNullOrEmpty()]
22 | [String]$InterfaceAlias,
23 |
24 | [ValidateSet("IPv4", "IPv6")]
25 | [String]$AddressFamily = "IPv4"
26 | )
27 |
28 |
29 | $returnValue = @{
30 | Address = (Get-DnsClientServerAddress -InterfaceAlias $InterfaceAlias -AddressFamily $AddressFamily).ServerAddresses
31 | AddressFamily = $AddressFamily
32 | InterfaceAlias = $InterfaceAlias
33 | }
34 |
35 | $returnValue
36 | }
37 |
38 | ######################################################################################
39 | # The Set-TargetResource cmdlet.
40 | # This function will set a new Server Address in the current node
41 | ######################################################################################
42 | function Set-TargetResource
43 | {
44 | param
45 | (
46 | #IP Address that has to be set
47 | [Parameter(Mandatory)]
48 | [ValidateNotNullOrEmpty()]
49 | [String[]]$Address,
50 |
51 | [Parameter(Mandatory)]
52 | [ValidateNotNullOrEmpty()]
53 | [String]$InterfaceAlias,
54 |
55 | [ValidateSet("IPv4", "IPv6")]
56 | [String]$AddressFamily = "IPv4"
57 | )
58 |
59 | ValidateProperties @PSBoundParameters -Apply
60 | }
61 |
62 | ######################################################################################
63 | # The Test-TargetResource cmdlet.
64 | # This will test if the given Server Address is among the current node's Server Address collection
65 | ######################################################################################
66 | function Test-TargetResource
67 | {
68 | param
69 | (
70 | [Parameter(Mandatory)]
71 | [ValidateNotNullOrEmpty()]
72 | [String[]]$Address,
73 |
74 | [Parameter(Mandatory)]
75 | [ValidateNotNullOrEmpty()]
76 | [String]$InterfaceAlias,
77 |
78 | [ValidateSet("IPv4", "IPv6")]
79 | [String]$AddressFamily = "IPv4"
80 | )
81 |
82 | ValidateProperties @PSBoundParameters
83 | }
84 |
85 |
86 | #######################################################################################
87 | # Helper function that validates the Server Address properties. If the switch parameter
88 | # "Apply" is set, then it will set the properties after a test
89 | #######################################################################################
90 | function ValidateProperties
91 | {
92 | param
93 | (
94 | [Parameter(Mandatory)]
95 | [ValidateNotNullOrEmpty()]
96 | [String[]]$Address,
97 |
98 | [Parameter(Mandatory)]
99 | [ValidateNotNullOrEmpty()]
100 | [String]$InterfaceAlias,
101 |
102 | [ValidateSet("IPv4", "IPv6")]
103 | [String]$AddressFamily,
104 |
105 | [Switch]$Apply
106 | )
107 | $sa =$Address
108 | $sa | %{
109 | if(!([System.Net.Ipaddress]::TryParse($_, [ref]0)))
110 | {
111 | throw "Server Address *$_* is not in the correct format. Please correct the Address in the configuration and try again"
112 | }
113 | if (([System.Net.IPAddress]$_).AddressFamily.ToString() -eq [System.Net.Sockets.AddressFamily]::InterNetwork.ToString())
114 | {
115 | if ($AddressFamily -ne "IPv4")
116 | {
117 | throw "Server address $Address is in IPv4 format, which does not match server address family $AddressFamily. Please correct either of them in the configuration and try again"
118 | }
119 | }
120 | else
121 | {
122 | if ($AddressFamily -ne "IPv6")
123 | {
124 | throw "Server address $Address is in IPv6 format, which does not match server address family $AddressFamily. Please correct either of them in the configuration and try again"
125 | }
126 | }
127 | }
128 | try
129 | {
130 | Write-Verbose -Message "Checking the DNS Server Address ..."
131 | #Get the current IP Address based on the parameters given.
132 | $currentAddress = (Get-DnsClientServerAddress -InterfaceAlias $InterfaceAlias -AddressFamily $AddressFamily -ErrorAction Stop).ServerAddresses
133 |
134 | #Check if the Server addresses are the same as the desired addresses.
135 | if(@(Compare-Object -ReferenceObject $currentAddress -DifferenceObject $Address -SyncWindow 0).Length -gt 0)
136 | {
137 | Write-Verbose -Message "DNS Servers are not correct. Expected $Address, actual $currentAddress"
138 | if($Apply)
139 | {
140 | # Set the DNS settings as well
141 | Set-DnsClientServerAddress -InterfaceAlias $InterfaceAlias -ServerAddresses $Address
142 | Write-Verbose -Message "DNS Servers have been set correctly."
143 | }
144 | else
145 | {
146 | return $false
147 | }
148 | }
149 | else
150 | {
151 | #Test will return true in this case
152 | Write-Verbose -Message "DNS Servers are set correctly."
153 | return $true
154 | }
155 | }
156 | catch
157 | {
158 | Write-Verbose -Message $_
159 | throw "Can not set or find valid DNS Server addresses using InterfaceAlias $InterfaceAlias and AddressFamily $AddressFamily"
160 | }
161 | }
162 |
163 |
164 |
165 | # FUNCTIONS TO BE EXPORTED
166 | Export-ModuleMember -function Get-TargetResource, Set-TargetResource, Test-TargetResource
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xNetworking/DSCResources/MSFT_xDNSServerAddress/MSFT_xDNSServerAddress.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xNetworking/DSCResources/MSFT_xDNSServerAddress/MSFT_xDNSServerAddress.schema.mof
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xNetworking/DSCResources/MSFT_xFirewall/MSFT_xFirewall.Schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xNetworking/DSCResources/MSFT_xFirewall/MSFT_xFirewall.Schema.mof
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xNetworking/DSCResources/MSFT_xIPAddress/MSFT_xIPAddress.psm1:
--------------------------------------------------------------------------------
1 | <#######################################################################################
2 | # MSDSCPack_IPAddress : DSC Resource that will set/test/get the current IP
3 | # Address, by accepting values among those given in MSDSCPack_IPAddress.schema.mof
4 | #######################################################################################>
5 |
6 |
7 |
8 | ######################################################################################
9 | # The Get-TargetResource cmdlet.
10 | # This function will get the present list of IP Address DSC Resource schema variables on the system
11 | ######################################################################################
12 | function Get-TargetResource
13 | {
14 | param
15 | (
16 | [Parameter(Mandatory)]
17 | [ValidateNotNullOrEmpty()]
18 | [String]$IPAddress,
19 |
20 | [Parameter(Mandatory)]
21 | [ValidateNotNullOrEmpty()]
22 | [String]$InterfaceAlias,
23 |
24 | [Int]$SubnetMask = 16,
25 |
26 | [ValidateNotNullOrEmpty()]
27 | [String]$DefaultGateway,
28 |
29 | [ValidateSet("IPv4", "IPv6")]
30 | [String]$AddressFamily = "IPv4"
31 | )
32 |
33 |
34 | $returnValue = @{
35 | IPAddress = [System.String]::Join(", ",(Get-NetIPAddress -InterfaceAlias $InterfaceAlias -AddressFamily $AddressFamily).IPAddress)
36 | SubnetMask = $SubnetMask
37 | DefaultGateway = $DefaultGateway
38 | AddressFamily = $AddressFamily
39 | InterfaceAlias=$InterfaceAlias
40 | }
41 |
42 | $returnValue
43 | }
44 |
45 | ######################################################################################
46 | # The Set-TargetResource cmdlet.
47 | # This function will set a new IP Address in the current node
48 | ######################################################################################
49 | function Set-TargetResource
50 | {
51 | param
52 | (
53 | #IP Address that has to be set
54 | [Parameter(Mandatory)]
55 | [ValidateNotNullOrEmpty()]
56 | [String]$IPAddress,
57 |
58 | [Parameter(Mandatory)]
59 | [ValidateNotNullOrEmpty()]
60 | [String]$InterfaceAlias,
61 |
62 | [Int]$SubnetMask,
63 |
64 | [ValidateNotNullOrEmpty()]
65 | [String]$DefaultGateway,
66 |
67 | [ValidateSet("IPv4", "IPv6")]
68 | [String]$AddressFamily = "IPv4"
69 | )
70 |
71 |
72 | ValidateProperties @PSBoundParameters -Apply
73 | }
74 |
75 | ######################################################################################
76 | # The Test-TargetResource cmdlet.
77 | # This will test if the given IP Address is among the current node's IP Address collection
78 | ######################################################################################
79 | function Test-TargetResource
80 | {
81 | param
82 | (
83 | [Parameter(Mandatory)]
84 | [ValidateNotNullOrEmpty()]
85 | [String]$IPAddress,
86 |
87 | [Parameter(Mandatory)]
88 | [ValidateNotNullOrEmpty()]
89 | [String]$InterfaceAlias,
90 |
91 | [Int]$SubnetMask,
92 |
93 | [ValidateNotNullOrEmpty()]
94 | [String]$DefaultGateway,
95 |
96 | [ValidateSet("IPv4", "IPv6")]
97 | [String]$AddressFamily = "IPv4"
98 | )
99 |
100 | ValidateProperties @PSBoundParameters
101 | }
102 |
103 |
104 | #######################################################################################
105 | # Helper function that validates the IP Address properties. If the switch parameter
106 | # "Apply" is set, then it will set the properties after a test
107 | #######################################################################################
108 | function ValidateProperties
109 | {
110 | param
111 | (
112 | [Parameter(Mandatory)]
113 | [ValidateNotNullOrEmpty()]
114 | [String]$IPAddress,
115 |
116 | [Parameter(Mandatory)]
117 | [ValidateNotNullOrEmpty()]
118 | [String]$InterfaceAlias,
119 |
120 | [ValidateNotNullOrEmpty()]
121 | [String]$DefaultGateway,
122 |
123 | [Int]$SubnetMask = 16,
124 |
125 | [ValidateSet("IPv4", "IPv6")]
126 | [String]$AddressFamily = "IPv4",
127 |
128 | [Switch]$Apply
129 | )
130 | $ip=$IPAddress
131 | if(!([System.Net.Ipaddress]::TryParse($ip, [ref]0)))
132 | {
133 | throw "IP Address *$IPAddress* is not in the correct format. Please correct the ipaddress in the configuration and try again"
134 | }
135 | try
136 | {
137 | Write-Verbose -Message "Checking the IPAddress ..."
138 | #Get the current IP Address based on the parameters given.
139 | $currentIP = Get-NetIPAddress -InterfaceAlias $InterfaceAlias -AddressFamily $AddressFamily -ErrorAction Stop
140 |
141 | #Test if the IP Address passed is equal to the current ip address
142 | if(!$currentIP.IPAddress.Contains($IPAddress))
143 | {
144 | Write-Verbose -Message "IPAddress not correct. Expected $IPAddress, actual $($currentIP.IPAddress)"
145 | $Parameters = @{}
146 |
147 | #Apply is true in the case of set - target resource - in which case, it will set the new IP Address
148 | if($Apply)
149 | {
150 | Write-Verbose -Message "Setting IPAddress ..."
151 | $Parameters["IPAddress"] = $IPAddress
152 | $Parameters["PrefixLength"] = $SubnetMask
153 | $Parameters["InterfaceAlias"] = $currentIP[0].InterfaceAlias
154 |
155 | if($DefaultGateway){ $Parameters["DefaultGateWay"] = $DefaultGateway }
156 | $null = New-NetIPAddress @Parameters -ErrorAction Stop
157 |
158 | # Make the connection profile private
159 | Get-NetConnectionProfile -InterfaceAlias $InterfaceAlias | Set-NetConnectionProfile -NetworkCategory Private -ErrorAction SilentlyContinue
160 | Write-Verbose -Message "IPAddress is set to $IPAddress."
161 | }
162 | else {return $false}
163 | }
164 | else
165 | {
166 | Write-Verbose -Message "IPAddress is correct."
167 | return $true
168 | }
169 | }
170 | catch
171 | {
172 | Write-Verbose -Message $_
173 | throw "Can not set or find valid IPAddress using InterfaceAlias $InterfaceAlias and AddressFamily $AddressFamily"
174 | }
175 | }
176 |
177 |
178 |
179 | # FUNCTIONS TO BE EXPORTED
180 | Export-ModuleMember -function Get-TargetResource, Set-TargetResource, Test-TargetResource
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xNetworking/DSCResources/MSFT_xIPAddress/MSFT_xIPAddress.schema.mof:
--------------------------------------------------------------------------------
1 | [ClassVersion("1.0.0"), FriendlyName("xIPAddress")]
2 | class MSFT_xIPAddress : OMI_BaseResource
3 | {
4 | [Key] string IPAddress;
5 | [Key] string InterfaceAlias;
6 | [write] string DefaultGateway;
7 | [Write] uint32 SubnetMask;
8 | [Write,ValueMap{"IPv4", "IPv6"},Values{"IPv4", "IPv6"}] string AddressFamily;
9 | };
10 |
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xNetworking/Examples/Sample_xDnsServerAddress.ps1:
--------------------------------------------------------------------------------
1 | configuration Sample_xDnsServerAddress
2 | {
3 | param
4 | (
5 | [string[]]$NodeName = 'localhost',
6 |
7 | [Parameter(Mandatory)]
8 | [string]$DnsServerAddress,
9 |
10 | [Parameter(Mandatory)]
11 | [string]$InterfaceAlias,
12 |
13 | [ValidateSet("IPv4","IPv6")]
14 | [string]$AddressFamily = 'IPv4'
15 | )
16 |
17 | Import-DscResource -Module xNetworking
18 |
19 | Node $NodeName
20 | {
21 | xDnsServerAddress DnsServerAddress
22 | {
23 | Address = $DnsServerAddress
24 | InterfaceAlias = $InterfaceAlias
25 | AddressFamily = $AddressFamily
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xNetworking/Examples/Sample_xFirewall_AddFirewallRule.ps1:
--------------------------------------------------------------------------------
1 | # DSC configuration for Firewall
2 |
3 | configuration Sample_xFirewall_AddFirewallRule
4 | {
5 | param
6 | (
7 | [string[]]$NodeName = 'localhost'
8 | )
9 |
10 | Import-DSCResource -ModuleName xNetworking
11 |
12 | Node $NodeName
13 | {
14 | xFirewall Firewall
15 | {
16 | Name = "NotePadFirewallRule"
17 | DisplayName = "Firewall Rule for Notepad.exe"
18 | DisplayGroup = "NotePad Firewall Rule Group"
19 | Ensure = "Present"
20 | Access = "Allow"
21 | State = "Enabled"
22 | Profile = ("Domain", "Private")
23 | Direction = "OutBound"
24 | RemotePort = ("8080", "8081")
25 | LocalPort = ("9080", "9081")
26 | Protocol = "TCP"
27 | Description = "Firewall Rule for Notepad.exe"
28 | ApplicationPath = "c:\windows\system32\notepad.exe"
29 | Service = "WinRM"
30 | }
31 | }
32 | }
33 |
34 | Sample_xFirewall_AddFirewallRule
35 | Start-DscConfiguration -Path Sample_xFirewall_AddFirewallRule -Wait -Verbose -Force
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xNetworking/Examples/Sample_xFirewall_AddFirewallRuleToExistingGroup.ps1:
--------------------------------------------------------------------------------
1 | # DSC configuration for Firewall
2 | #
3 |
4 | configuration Sample_xFirewall_AddFirewallRuleToExistingGroup
5 | {
6 | param
7 | (
8 | [string[]]$NodeName = 'localhost'
9 | )
10 |
11 | Import-DSCResource -ModuleName xNetworking
12 |
13 | Node $NodeName
14 | {
15 | xFirewall Firewall
16 | {
17 | Name = "MyFirewallRule"
18 | DisplayName = "My Firewall Rule"
19 | DisplayGroup = "My Firewall Rule Group"
20 | Access = "Allow"
21 | }
22 |
23 | xFirewall Firewall1
24 | {
25 | Name = "MyFirewallRule1"
26 | DisplayName = "My Firewall Rule"
27 | DisplayGroup = "My Firewall Rule Group"
28 | Ensure = "Present"
29 | Access = "Allow"
30 | State = "Enabled"
31 | Profile = ("Domain", "Private")
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xNetworking/Examples/Sample_xFirewall_AddFirewallRuleToNewGroup.ps1:
--------------------------------------------------------------------------------
1 | # DSC configuration for Firewall
2 |
3 | configuration Sample_xFirewall_AddFirewallRuleToNewGroup
4 | {
5 | param
6 | (
7 | [string[]]$NodeName = 'localhost'
8 | )
9 |
10 | Import-DSCResource -ModuleName xNetworking
11 |
12 | Node $NodeName
13 | {
14 | xFirewall Firewall
15 | {
16 | Name = "MyAppFirewallRule"
17 | ApplicationPath = "c:\windows\system32\MyApp.exe"
18 | Access = "Allow"
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xNetworking/Examples/Sample_xFirewall_DisableAccessToApplication.ps1:
--------------------------------------------------------------------------------
1 | # DSC configuration for Firewall
2 | #
3 |
4 | configuration Sample_xFirewall_AddFirewallRuleToNewGroup
5 | {
6 | param
7 | (
8 | [string[]]$NodeName = 'localhost'
9 | )
10 |
11 | Import-DSCResource -ModuleName xNetworking
12 |
13 | Node $NodeName
14 | {
15 | xFirewall Firewall
16 | {
17 | Name = "NotePadFirewallRule"
18 | DisplayName = "Firewall Rule for Notepad.exe"
19 | DisplayGroup = "NotePad Firewall Rule Group"
20 | Ensure = "Present"
21 | Access = "Block"
22 | Description = "Firewall Rule for Notepad.exe"
23 | ApplicationPath = "c:\windows\system32\notepad.exe"
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xNetworking/Examples/Sample_xIPAddress_FixedValue.ps1:
--------------------------------------------------------------------------------
1 | configuration Sample_xIPAddress_FixedValue
2 | {
3 | param
4 | (
5 | [string[]]$NodeName = 'localhost'
6 | )
7 |
8 | Import-DscResource -Module xNetworking
9 |
10 | Node $NodeName
11 | {
12 | xIPAddress NewIPAddress
13 | {
14 | IPAddress = "2001:4898:200:7:6c71:a102:ebd8:f482"
15 | InterfaceAlias = "Ethernet"
16 | SubnetMask = 24
17 | AddressFamily = "IPV6"
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xNetworking/Examples/Sample_xIPAddress_Parameterized.ps1:
--------------------------------------------------------------------------------
1 | configuration Sample_xIPAddress_Parameterized
2 | {
3 | param
4 | (
5 |
6 | [string[]]$NodeName = 'localhost',
7 |
8 | [Parameter(Mandatory)]
9 | [string]$IPAddress,
10 |
11 | [Parameter(Mandatory)]
12 | [string]$InterfaceAlias,
13 |
14 | [Parameter(Mandatory)]
15 | [string]$DefaultGateway,
16 |
17 | [int]$SubnetMask = 16,
18 |
19 | [ValidateSet("IPv4","IPv6")]
20 | [string]$AddressFamily = 'IPv4'
21 | )
22 |
23 | Import-DscResource -Module xNetworking
24 |
25 | Node $NodeName
26 | {
27 | xIPAddress NewIPAddress
28 | {
29 | IPAddress = $IPAddress
30 | InterfaceAlias = $InterfaceAlias
31 | DefaultGateway = $DefaultGateway
32 | SubnetMask = $SubnetMask
33 | AddressFamily = $AddressFamily
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xNetworking/xNetworking.psd1:
--------------------------------------------------------------------------------
1 | @{
2 | # Version number of this module.
3 | ModuleVersion = '2.1.1'
4 |
5 | # ID used to uniquely identify this module
6 | GUID = 'e6647cc3-ce9c-4c86-9eb8-2ee8919bf358'
7 |
8 | # Author of this module
9 | Author = 'Microsoft Corporation'
10 |
11 | # Company or vendor of this module
12 | CompanyName = 'Microsoft Corporation'
13 |
14 | # Copyright statement for this module
15 | Copyright = '(c) 2013 Microsoft Corporation. All rights reserved.'
16 |
17 | # Description of the functionality provided by this module
18 | Description = 'Module with DSC Resources for Networking area'
19 |
20 | # Minimum version of the Windows PowerShell engine required by this module
21 | PowerShellVersion = '4.0'
22 |
23 | # Minimum version of the common language runtime (CLR) required by this module
24 | CLRVersion = '4.0'
25 |
26 | # Functions to export from this module
27 | FunctionsToExport = '*'
28 |
29 | # Cmdlets to export from this module
30 | CmdletsToExport = '*'
31 | }
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xPendingReboot/DSCResources/MSFT_xPendingReboot/MSFT_xPendingReboot.psm1:
--------------------------------------------------------------------------------
1 | Function Get-TargetResource
2 | {
3 | [CmdletBinding()]
4 | param
5 | (
6 | [Parameter(Mandatory=$true)]
7 | [string]$Name
8 | )
9 |
10 | <## Remove:
11 | $ComponentBasedServicing = (Get-ItemProperty 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\').RebootPending -ne $null
12 | Remove - $WindowsUpdate = (Get-ItemProperty 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\').RebootRequired -ne $null
13 | Remove - $PendingFileRename = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\').PendingFileRenameOperations -ne $null
14 | #>
15 |
16 | ## Brian's additions:--------------------------------------------------
17 | $ComponentBasedServicing = (Get-ChildItem 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\').Name.Split("\") -contains "RebootPending"
18 | $WindowsUpdate = (Get-ChildItem 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\').Name.Split("\") -contains "RebootRequired"
19 | $PendingFileRename = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\').PendingFileRenameOperations.Length -gt 0
20 | $ActiveComputerName = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName').ComputerName
21 | $PendingComputerName = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName').ComputerName
22 | $PendingComputerRename = $ActiveComputerName -ne $PendingComputerName
23 |
24 | $CCMSplat = @{
25 | NameSpace='ROOT\ccm\ClientSDK'
26 | Class='CCM_ClientUtilities'
27 | Name='DetermineIfRebootPending'
28 | ErrorAction='Stop'
29 | }
30 |
31 | Try {
32 | $CCMClientSDK = Invoke-WmiMethod @CCMSplat
33 | } Catch {
34 | Write-Warning "Unable to query CCM_ClientUtilities: $_"
35 | }
36 |
37 | $SCCMSDK = ($CCMClientSDK.ReturnValue -eq 0) -and ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending)
38 | ## End Brian's additions------------------------------------------------
39 |
40 | return @{
41 | Name = $Name
42 | ComponentBasedServicing = $ComponentBasedServicing
43 | WindowsUpdate = $WindowsUpdate
44 | PendingFileRename = $PendingFileRename
45 | PendingComputerRename = $PendingComputerRename
46 | CcmClientSDK = $SCCMSDK
47 | }
48 | }
49 |
50 | Function Set-TargetResource
51 | {
52 | [CmdletBinding()]
53 | param
54 | (
55 | [Parameter(Mandatory=$true)]
56 | [string]$Name
57 | )
58 |
59 | $global:DSCMachineStatus = 1
60 | }
61 |
62 | Function Test-TargetResource
63 | {
64 | [CmdletBinding()]
65 | param
66 | (
67 | [Parameter(Mandatory=$true)]
68 | [string]$Name
69 | )
70 |
71 | <## Remove
72 | $regRebootLocations += @{'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\'='RebootPending'}
73 | $regRebootLocations += @{'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\'='RebootRequired'}
74 | $regRebootLocations += @{'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\'='PendingFileRenameOperations'}
75 |
76 | foreach ($reg in $regRebootLocations.keys) {
77 | if ((Get-ItemProperty $reg).($regRebootLocations[$reg]) -ne $Null) {
78 | Write-Verbose "A pending reboot was found at $reg."
79 | Write-Verbose 'Setting the DSCMachineStatus global variable to 1.'
80 | return $false}
81 | }
82 | #>
83 |
84 | ## Brian's additions:--------------------------------------------------
85 | $ScriptBlocks += @{ComponentBasedServicing = {(Get-ChildItem 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\').Name.Split("\") -contains "RebootPending"}}
86 | $ScriptBlocks += @{WindowsUpdate = {(Get-ChildItem 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\').Name.Split("\") -contains "RebootRequired"}}
87 | $ScriptBlocks += @{PendingFileRename = {(Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\').PendingFileRenameOperations.Length -gt 0}}
88 | $ScriptBlocks += @{PendingComputerRename = {
89 | $ActiveComputerName = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName').ComputerName
90 | $PendingComputerName = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName').ComputerName
91 | $ActiveComputerName -ne $PendingComputerName
92 | }
93 | }
94 | $ScriptBlocks += @{CcmClientSDK = {
95 | $CCMSplat = @{
96 | NameSpace='ROOT\ccm\ClientSDK'
97 | Class='CCM_ClientUtilities'
98 | Name='DetermineIfRebootPending'
99 | ErrorAction='Stop'
100 | }
101 | Try {
102 | $CCMClientSDK = Invoke-WmiMethod @CCMSplat
103 | ($CCMClientSDK.ReturnValue -eq 0) -and ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending)
104 | } Catch {
105 | Write-Warning "Unable to query CCM_ClientUtilities: $_"
106 | }
107 | }
108 | }
109 | Foreach ($Script in $ScriptBlocks.Keys) {
110 | If (Invoke-Command $ScriptBlocks[$Script]) {
111 | Write-Verbose "A pending reboot was found for $Script."
112 | Write-Verbose 'Setting the DSCMachineStatus global variable to 1.'
113 | return $false
114 | }
115 | }
116 | ## End Brian's additions------------------------------------------------
117 |
118 | Write-Verbose 'No pending reboots found.'
119 | return $true
120 | }
121 |
122 | Export-ModuleMember -Function *-TargetResource
123 |
124 | $regRebootLocations = $null
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xPendingReboot/DSCResources/MSFT_xPendingReboot/MSFT_xPendingReboot.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xPendingReboot/DSCResources/MSFT_xPendingReboot/MSFT_xPendingReboot.schema.mof
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xPendingReboot/xPendingReboot.psd1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xPendingReboot/xPendingReboot.psd1
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/MSFT_xIisModule.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/MSFT_xIisModule.psm1
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/MSFT_xIisModule.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/MSFT_xIisModule.schema.mof
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/xIisModuleDesigner.ps1:
--------------------------------------------------------------------------------
1 | $diff = join-Path ${env:ProgramFiles(x86)} "Beyond compare 2\bc2.exe"
2 | $friendlyName = "xIisModule"
3 | $resourceName = "MSFT_$friendlyName"
4 | $classVersion = "1.0.0"
5 |
6 | $scriptRoot = Split-Path $MyInvocation.MyCommand.Path
7 | $originalModuleRoot = join-Path $scriptroot "..\.."
8 | $originalModuleRootPath = Resolve-Path $originalModuleRoot
9 | $moduleRoot = Join-Path $env:temp "$($originalModuleRootPath.path | split-path -Leaf)Temp"
10 |
11 | $resources = @()
12 | $schemaPath = (join-path $scriptRoot "$resourceName.schema.mof")
13 |
14 | #Key properties
15 | $resources += New-xDscResourceProperty -Name Path -Type String -Attribute Key -Description "The path to the module, usually a dll, to be added to IIS."
16 |
17 |
18 | #Required Properites
19 | $resources += New-xDscResourceProperty -Name Name -Type String -Attribute Required -Description "The logical name of the module to add to IIS."
20 | $resources += New-xDscResourceProperty -Name RequestPath -Type String -Attribute Required -Description "The allowed request Path example: *.php"
21 | $resources += New-xDscResourceProperty -Name Verb -Type String[] -Attribute Required -Description "The supported verbs for the module."
22 |
23 | #Write Properties
24 | $resources += New-xDscResourceProperty -Name SiteName -Type String -Attribute Write -Description "The IIS Site to register the module."
25 | $resources += New-xDscResourceProperty -Name Ensure -Type String -Attribute Write -Description "Should the module be present or absent." -ValidateSet @("Present","Absent")
26 | $resources += New-xDscResourceProperty -Name ModuleType -Type String -Attribute Write -Description "The type of the module." -ValidateSet @("FastCgiModule")
27 |
28 | #Read Properties
29 | $resources += New-xDscResourceProperty -Name EndPointSetup -Type Boolean -Attribute Read -Description "The End Point is setup. Such as a Fast Cgi endpoint."
30 |
31 |
32 |
33 | Write-Host updating...
34 |
35 | # Create a New template resource to a temporary folder
36 | New-xDscResource -Property $resources -ClassVersion $classVersion -Name $resourceName -Path $moduleRoot -FriendlyName $friendlyName
37 |
38 |
39 | # Use your favorite diff program to compare and merge the current resource and the existing resource
40 |
41 | if((test-Path $diff))
42 | {
43 | &$diff $originalModuleRoot $moduleRoot
44 | }
45 | else
46 | {
47 | Write-Warning "Diff propgram not found!`r`nUse your favorite diff program to compare and merge:`r`n `t$($originalModuleRootPath.path)`r`n and:`r`n `t$moduleRoot"
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.psm1
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.schema.mof
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.psm1
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.schema.mof
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.psm1
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.schema.mof
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.psm1
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.schema.mof
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof
--------------------------------------------------------------------------------
/Exercise3/PowerShellModules/xWebAdministration/xWebAdministration.psd1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise3/PowerShellModules/xWebAdministration/xWebAdministration.psd1
--------------------------------------------------------------------------------
/Exercise4.md:
--------------------------------------------------------------------------------
1 | # Exercise 4
2 |
3 | ## Bootstrapping CloudFormation created instances with PowerShell DSC
4 |
5 | In this exercise we will take a fleshed out web server CloudFormation template, and wire it up so that it bootstraps our PowerShell DSC configuration script on the EC2 instances it creates for us
6 |
7 | ## Goals
8 |
9 | * Discover some of the functionality CloudFormation offers to configure provisioned instances with
10 | * Bootstrap Powershell DSC configuration on created EC2 instances by leveraging cfn-init
11 |
12 | ## Instructions
13 |
14 | 1. Read through this example of [Bootstrapping Windows Instances](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-windows-stacks-bootstrapping.html)
15 | 2. Read the documentation on the [CloudFormation::Init template](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html)
16 | 3. Open .\Exercise4\Templates\Webserver.template
17 | 4. Locate the the WebServerAzOne resource definition within the webserver template
18 | 5. Follow the [Bootstrapping Windows Instances](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-windows-stacks-bootstrapping.html) example and fill out the UserData section of the template to kickstart cfn-init
19 | 6. Complete the **sources** section of the [CloudFormation::Init template](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html) within WebServerAzOne to pull down
20 | * Our powershell modules from the PowerShellModulesBundleUrl template parameter to C:\Program Files\WindowsPowerShell\Modules
21 | * Our scripts from the BootstrapperScriptBundleUrl template parameter to c:\cfn\Zephyr\Scripts
22 | 7. Complete the **commands** section of the [CloudFormation::Init template](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-init.html) within WebServerAzOne to
23 | * Set the powershell execution policy to unrestricted
24 | * Invoke our ConfigureWebserver DSC configuration
25 | 8. Duplicate 5-7 on WebServerAzTwo
26 | 9. Open .\Exercise4\Parameters.ps1. Update the ResourcePrefix parameter to your initials, and take note of the other parameters provided
27 | 10. Open Deploy.ps1 locally in Powershell ISE.
28 | 11. F5!!!
29 | 12. Open the CloudFormation console in AWS and monitor your stack's creation
30 | 13. If it fails, troubleshooting time! Pick your troubleshooting buddy and get it sorted
31 | 14. If it succeeds, open up the EC2 console and remote into one of your instances
32 | 15. Open c:\cfn\log\cfn-init.log
33 | 16. Can you see your DSC output inside it? Are there any errors, or does everything look good?
34 |
35 | ### Gotcha
36 |
37 | cfn-init will consider its job done when at the point when all of its commands have succesfully completed - this is going to be at the first reboot of your DSC. This means that if subsequent parts of your DSC fail, the cloud formation init logs are not going to tell you - so you need to monitor your DSC logs to ensure it is happily configured.
38 |
39 | 17. Revisit your recently acquired DSC log analyzing skills. Has everything gone swimmingly?
40 | 18. Profit!
41 |
--------------------------------------------------------------------------------
/Exercise4/Deploy.ps1:
--------------------------------------------------------------------------------
1 | cls
2 |
3 | Add-Type -Assembly "System.IO.Compression.FileSystem";
4 | Import-Module AWSPowerShell
5 |
6 | ############################################################################################################################
7 | #
8 | # 00 - Helper Functions
9 | #
10 | ############################################################################################################################
11 |
12 | function GenerateConfigFileS3Key($environment, $release, $filename)
13 | {
14 | $key = $environment + "/" + $release + "/" + $filename
15 | return $key
16 | }
17 |
18 | function CompressDirectoryToArchive($directoryPath, $filePath)
19 | {
20 | if (Test-Path $filePath)
21 | {
22 | Remove-Item $filePath -Force
23 | }
24 |
25 | [System.IO.Compression.ZipFile]::CreateFromDirectory($directoryPath, $filePath);
26 | }
27 |
28 | function EnsureDirectoryExists($directoryPath)
29 | {
30 | if (-Not (Test-Path $directoryPath))
31 | {
32 | New-Item $directoryPath -ItemType Directory
33 | }
34 | }
35 |
36 | ############################################################################################################################
37 | #
38 | # 01 - Wrangling Octopus Variables
39 | #
40 | ############################################################################################################################
41 |
42 | # Create a new variable scope so that we can run this script multiple times
43 | # in a single script console instance without polluting the global scope with
44 | # fake Octopus variables.
45 | & {
46 | $scriptPath = [System.IO.Path]::GetDirectoryName($myInvocation.PSCommandPath)
47 | $scriptsPath = "$scriptPath\Scripts"
48 | EnsureDirectoryExists($scriptsPath)
49 |
50 | if ($OctopusParameters -eq $null)
51 | {
52 | Write-Output "Doesn't look like we have any Octopus variables. Using development defaults."
53 |
54 | . .\Parameters.ps1
55 | }
56 | else
57 | {
58 | Write-Output "Using Octopus-provided variables..."
59 | }
60 |
61 | # Lower case variables sensitive to casing
62 | $OctopusParameters['CloudFormationStackName'] = $OctopusParameters['CloudFormationStackName'].ToLowerInvariant()
63 | $OctopusParameters['S3BucketName'] = $OctopusParameters['S3BucketName'].ToLowerInvariant()
64 |
65 | Write-Output $OctopusParameters
66 | Write-Output ""
67 |
68 | ############################################################################################################################
69 | #
70 | # 02 - Creating cleanup scripts
71 | #
72 | ############################################################################################################################
73 |
74 | $cleanupScript = @"
75 | `
76 | `# TODO: Remove machines from octopus
77 | `
78 | `# Tear down infrastructure
79 | `Remove-CFNStack -StackName "$($OctopusParameters['CloudFormationStackName'])" -Force -ProfileName "AWSWorkshop" -Region us-west-2
80 | "@
81 |
82 | $cleanupScript | Out-File -FilePath "$scriptPath\Scripts\Cleanup.ps1" -Encoding ASCII -Force
83 |
84 | ############################################################################################################################
85 | #
86 | # 03 - Push scripts and templates to clouds
87 | #
88 | ############################################################################################################################
89 |
90 | # Create a directory to store our zipped powershell modules and bootstrapper scripts.
91 | $tempPath = "$scriptPath\Temp"
92 | EnsureDirectoryExists($tempPath)
93 |
94 | # Create an S3 bucket to upload our templates and scripts to.
95 | if (-Not (Get-S3Bucket -BucketName $OctopusParameters['S3BucketName'] -ProfileName "AWSWorkshop" -Region $OctopusParameters['AWSRegion']))
96 | {
97 | Write-Output "Creating S3 bucket..."
98 | New-S3Bucket -BucketName $OctopusParameters['S3BucketName'] -ProfileName "AWSWorkshop" -Region $OctopusParameters['AWSRegion']
99 | }
100 |
101 | # Cleanup scripts
102 | Write-Output "Uploading cleanup script..."
103 | $cleanupScriptFullPath = "$scriptPath\Scripts\Cleanup.ps1"
104 | $cleanupScriptsS3BucketKey = GenerateConfigFileS3Key -environment $OctopusParameters['Environment'] -release $OctopusParameters['Version'] -filename "Cleanup.ps1"
105 | Write-S3Object -BucketName: $OctopusParameters['S3BucketName'] -Key $cleanupScriptsS3BucketKey -File $cleanupScriptFullPath -ProfileName "AWSWorkshop" -Region $OctopusParameters['AWSRegion']
106 |
107 | # Powershell modules
108 | $powerShellModulesFullPath = "$scriptPath\Temp\PowerShellModules.zip"
109 | CompressDirectoryToArchive -directoryPath "$scriptPath\PowerShellModules" -filePath $powerShellModulesFullPath
110 | $powerShellModulesS3BucketKey = GenerateConfigFileS3Key -environment $OctopusParameters['Environment'] -release $OctopusParameters['Version'] -filename "PowerShellModules.zip"
111 | Write-Output "Uploading powershell modules..."
112 | Write-S3Object -BucketName: $OctopusParameters['S3BucketName'] -Key $powerShellModulesS3BucketKey -File $powerShellModulesFullPath -ProfileName "AWSWorkshop" -Region $OctopusParameters['AWSRegion']
113 |
114 | # Bootstrapper scripts
115 | $scriptsFullPath = "$scriptPath\Temp\Scripts.zip"
116 | CompressDirectoryToArchive -directoryPath "$scriptPath\Scripts" -filePath $scriptsFullPath
117 | $scriptsS3BucketKey = GenerateConfigFileS3Key -environment $OctopusParameters['Environment'] -release $OctopusParameters['Version'] -filename "Scripts.zip"
118 | Write-Output "Uploading bootstrapper scripts..."
119 | Write-S3Object -BucketName: $OctopusParameters['S3BucketName'] -Key $scriptsS3BucketKey -File $scriptsFullPath -ProfileName "AWSWorkshop" -Region $OctopusParameters['AWSRegion']
120 |
121 | # CloudFormation templates
122 | Write-Output "Uploading CloudFormation templates..."
123 | $webserverTemplateS3BucketKey = GenerateConfigFileS3Key -environment $OctopusParameters['Environment'] -release $OctopusParameters['Version'] -filename "Webserver.template"
124 | Write-S3Object -BucketName: $OctopusParameters['S3BucketName'] -Key $webserverTemplateS3BucketKey -File $scriptPath\Templates\Webserver.template -ProfileName "AWSWorkshop" -Region $OctopusParameters['AWSRegion']
125 | $mainTemplateS3BucketKey = GenerateConfigFileS3Key -environment $OctopusParameters['Environment'] -release $OctopusParameters['Version'] -filename "Zephyr.template"
126 | Write-S3Object -BucketName: $OctopusParameters['S3BucketName'] -Key $mainTemplateS3BucketKey -File $scriptPath\Templates\Zephyr.template -ProfileName "AWSWorkshop" -Region $OctopusParameters['AWSRegion']
127 |
128 | # Cleanup generated scripts
129 | Remove-Item "$scriptPath\Scripts\Cleanup.ps1" -Force
130 |
131 | ############################################################################################################################
132 | #
133 | # 04 - GO GO GO (Create the stack)
134 | #
135 | ############################################################################################################################
136 |
137 | $powerShellModulesBundleUrl = "https://" + $OctopusParameters['S3BucketName'] + ".s3.amazonaws.com/$powerShellModulesS3BucketKey"
138 | $bootstrapperScriptBundleUrl = "https://" + $OctopusParameters['S3BucketName'] + ".s3.amazonaws.com/$scriptsS3BucketKey"
139 | $webserverTemplateUrl = "https://" + $OctopusParameters['S3BucketName'] + ".s3.amazonaws.com/$webserverTemplateS3BucketKey"
140 | $mainStackTemplateUrl = "https://" + $OctopusParameters['S3BucketName'] + ".s3.amazonaws.com/$mainTemplateS3BucketKey"
141 | $timestamp = Get-Date -Format u
142 |
143 | $stack = $null
144 | try
145 | {
146 | $stack = Get-CFNStack -StackName $OctopusParameters['CloudFormationStackName'] -ProfileName "AWSWorkshop" -Region $OctopusParameters['AWSRegion']
147 | }
148 | catch
149 | {
150 | }
151 |
152 | $stackParameters = `
153 | @(`
154 | @{ParameterKey="S3BucketName"; ParameterValue=$OctopusParameters['S3BucketName']},`
155 | @{ParameterKey="VpcId"; ParameterValue=$OctopusParameters['VpcId']},`
156 | @{ParameterKey="PowerShellModulesBundleUrl"; ParameterValue="$powerShellModulesBundleUrl"},`
157 | @{ParameterKey="BootstrapperScriptBundleUrl"; ParameterValue="$bootstrapperScriptBundleUrl"},`
158 | @{ParameterKey="WebserverTemplateUrl"; ParameterValue="$webserverTemplateUrl"},`
159 | @{ParameterKey="Timestamp"; ParameterValue=$timestamp},`
160 | @{ParameterKey="Version"; ParameterValue=$OctopusParameters['Version']},`
161 | @{ParameterKey="Environment"; ParameterValue=$OctopusParameters['Environment']},`
162 | @{ParameterKey="KeyPairName"; ParameterValue=$OctopusParameters['KeyPairName']},`
163 | @{ParameterKey="WebserverImageId"; ParameterValue=$OctopusParameters['WebserverImageId']},`
164 | @{ParameterKey="WebserverInstanceType"; ParameterValue=$OctopusParameters['WebserverInstanceType']},`
165 | @{ParameterKey="WebserverSubnetIdAzOne"; ParameterValue=$OctopusParameters['WebserverSubnetIdAzOne']},`
166 | @{ParameterKey="WebserverSubnetIdAzTwo"; ParameterValue=$OctopusParameters['WebserverSubnetIdAzTwo']},`
167 | @{ParameterKey="LoadBalancerSubnetIdAzOne"; ParameterValue=$OctopusParameters['LoadBalancerSubnetIdAzOne']},`
168 | @{ParameterKey="LoadBalancerSubnetIdAzTwo"; ParameterValue=$OctopusParameters['LoadBalancerSubnetIdAzTwo']},`
169 | @{ParameterKey="ResourcePrefix"; ParameterValue=$OctopusParameters['ResourcePrefix']})
170 |
171 | $stackName = $OctopusParameters['CloudFormationStackName']
172 | if ($stack -eq $null)
173 | {
174 | Write-Output "Creating new CFN stack $stackName"
175 |
176 | New-CFNStack -Capability "CAPABILITY_IAM" -StackName $stackName -TemplateURL $mainStackTemplateUrl -Parameters $stackParameters -ProfileName "AWSWorkshop" -Region $OctopusParameters['AWSRegion']
177 | }
178 | else
179 | {
180 | Write-Output "Updating existing CFN stack $stackName"
181 |
182 | Update-CFNStack -Capability "CAPABILITY_IAM" -StackName $stackName -TemplateURL $mainStackTemplateUrl -Parameters $stackParameters -ProfileName "AWSWorkshop" -Region $OctopusParameters['AWSRegion']
183 | }
184 |
185 | while($true)
186 | {
187 | $stack = Get-CFNStack -StackName $stackName -ProfileName "AWSWorkshop" -Region $OctopusParameters['AWSRegion']
188 |
189 | if ($stack.StackStatus -eq [Amazon.CloudFormation.StackStatus]::CREATE_COMPLETE -or $stack.StackStatus -eq [Amazon.CloudFormation.StackStatus]::UPDATE_COMPLETE)
190 | {
191 | Write-Output "Cloud formation succeeded with the following outputs..."
192 | $stack.Outputs | Format-Table | Write-Output
193 |
194 | # Note: In here, wire up external DNS etc based on stack output parameters
195 |
196 | break;
197 | }
198 |
199 | if ($stack.StackStatus -eq [Amazon.CloudFormation.StackStatus]::CREATE_FAILED -or $stack.StackStatus -eq [Amazon.CloudFormation.StackStatus]::ROLLBACK_COMPLETE -or $stack.StackStatus -eq [Amazon.CloudFormation.StackStatus]::ROLLBACK_FAILED)
200 | {
201 | Write-Output "Cloud formation failed, abandoning..."
202 |
203 | break;
204 | }
205 |
206 | Write-Output "Waiting for cloud formation $stackName to finish creation..."
207 |
208 | Start-Sleep -s 10
209 | }
210 |
211 | Write-Output "fin"
212 | }
--------------------------------------------------------------------------------
/Exercise4/Parameters.ps1:
--------------------------------------------------------------------------------
1 | $OctopusParameters = @{}
2 |
3 | # Octopus parameters
4 | $OctopusParameters['ResourcePrefix'] = 'aab';
5 | $OctopusParameters['Environment'] = "Production";
6 | $OctopusParameters['Version'] = "1.0.0-ryan0001";
7 |
8 | # CloudFormation parameters
9 | $OctopusParameters['AWSRegion'] = "ap-southeast-2";
10 | $OctopusParameters['CloudFormationStackName'] = "{0}-sandbox-{1}" -f @($OctopusParameters['ResourcePrefix'], $OctopusParameters['Environment']);
11 | $OctopusParameters['S3BucketName'] = "{0}-sandbox-infrastructure" -f $OctopusParameters['ResourcePrefix'];
12 | $OctopusParameters['VpcId'] = "vpc-7ecaee1b";
13 |
14 | # AWS parameters
15 | $OctopusParameters['KeyPairName'] = "AwsDayKeyPair";
16 | $OctopusParameters['WebserverImageId'] = "ami-bf8895dc"; #WINDOWS_2016_BASE
17 | $OctopusParameters['WebserverInstanceType'] = "t2.medium";
18 | $OctopusParameters['WebserverSubnetIdAzOne'] = "subnet-b1afb5d4"; # Web A
19 | $OctopusParameters['WebserverSubnetIdAzTwo'] = "subnet-14787e63"; # Web B
20 | $OctopusParameters['LoadBalancerSubnetIdAzOne'] = "subnet-973728f2"; # DMZ A
21 | $OctopusParameters['LoadBalancerSubnetIdAzTwo'] = "subnet-99477cee"; # DMZ B
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/cWinServer/DSCResources/WinServerOptions/WinServerOptions.psm1:
--------------------------------------------------------------------------------
1 | function Get-TargetResource
2 | {
3 | [CmdletBinding()]
4 | [OutputType([System.Collections.Hashtable])]
5 | param
6 | (
7 | [parameter(Mandatory = $true)]
8 | [System.String]
9 | $Name,
10 |
11 | [System.String]
12 | $Culture,
13 |
14 | [System.String]
15 | $TimeZone
16 | )
17 |
18 | $returnValue = @{
19 | Ensure = $Ensure
20 | Name = $Name
21 | Culture = $Culture
22 | Timezone = $Timezone
23 | }
24 |
25 | return $returnValue;
26 | }
27 |
28 | function Set-TargetResource
29 | {
30 | [CmdletBinding()]
31 | param
32 | (
33 | [ValidateSet("Present","Absent")]
34 | [System.String]
35 | $Ensure,
36 |
37 | [parameter(Mandatory = $true)]
38 | [System.String]
39 | $Name,
40 |
41 | [System.String]
42 | $Culture,
43 |
44 | [System.String]
45 | $TimeZone
46 | )
47 |
48 | if ($Ensure -eq "Present")
49 | {
50 | if ($Culture)
51 | {
52 | if ((Get-WinSystemLocale).Name -ne $Culture)
53 | {
54 | Write-Verbose "Setting System Locale to $Culture. Will Require reboot to take effect."
55 | Set-WinSystemLocale -SystemLocale $Culture
56 |
57 | $global:DSCMachineStatus = 1;
58 | }
59 | }
60 |
61 | if (([System.TimeZone]::CurrentTimeZone).StandardName -ne $TimeZone)
62 | {
63 | Write-Verbose "Setting System TimeZone to [$TimeZone]"
64 | & tzutil.exe /s "$TimeZone"
65 | }
66 | }
67 | }
68 |
69 | function Test-TargetResource
70 | {
71 | [CmdletBinding()]
72 | [OutputType([System.Boolean])]
73 | param
74 | (
75 | [ValidateSet("Present","Absent")]
76 | [System.String]
77 | $Ensure,
78 |
79 | [parameter(Mandatory = $true)]
80 | [System.String]
81 | $Name,
82 |
83 | [System.String]
84 | $Culture,
85 |
86 | [System.String]
87 | $TimeZone
88 | )
89 |
90 | if ($Ensure -eq "Present")
91 | {
92 | if ($Culture)
93 | {
94 | if ((Get-WinSystemLocale).Name -ne $Culture)
95 | {
96 | Write-Verbose "System Locale is currently $((Get-WinSystemLocale).Name) and should be $Culture"
97 | return $false;
98 | }
99 |
100 | Write-Verbose "System Locale and Culture are correct."
101 | }
102 |
103 | if ($TimeZone)
104 | {
105 | if (([System.TimeZone]::CurrentTimeZone).StandardName -ne $TimeZone)
106 | {
107 | Write-Verbose "System TimeZone is current:[$(([System.TimeZone]::CurrentTimeZone).StandardName)] and should be:[$TimeZone]"
108 | return $false;
109 | }
110 |
111 | Write-Verbose "System TimeZone is correct."
112 | }
113 | }
114 | else
115 | {
116 | Write-Verbose "Ignoring checks"
117 | }
118 |
119 | return $true;
120 | }
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/cWinServer/DSCResources/WinServerOptions/WinServerOptions.schema.mof:
--------------------------------------------------------------------------------
1 | [ClassVersion("1.0.0.0"), FriendlyName("WinServerOptions")]
2 | class WinServerOptions : OMI_BaseResource
3 | {
4 | [Write, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure;
5 | [Key, Description("The name for the setup. Can just be the server name")] String Name;
6 | [Write, Description("The Windows Server culture")] String Culture;
7 | [Write, Description("The Windows Server Timezone")] String TimeZone;
8 | };
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/cWinServer/cWinServer.psd1:
--------------------------------------------------------------------------------
1 | #
2 | # Module manifest for module 'cWinServer'
3 | #
4 | # Generated by: andrewb
5 | #
6 | # Generated on: 9/06/2015
7 | @{
8 | ModuleVersion = '1.0'
9 | GUID = '90798d5f-9f2e-4af4-b9fd-79b4f67899fb'
10 | Author = 'andrewb'
11 | CompanyName = 'Unknown'
12 | Copyright = '(c) 2015 andrewb. All rights reserved.'
13 | Description = ''
14 | PowerShellVersion = '4.0'
15 | FunctionsToExport = @('Get-TargetResource','Set-TargetResource','Test-TargetResource')
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xDscDiagnostics/xDscDiagnostics.psd1:
--------------------------------------------------------------------------------
1 |
2 |
3 | @{
4 |
5 |
6 | ModuleVersion = '2.0'
7 | GUID = 'ef098cb4-f7e9-4763-b636-0cd9799e1c9a'
8 |
9 | Author = 'Microsoft Corporation'
10 | CompanyName = 'Microsoft Corporation'
11 | Copyright = '(c) 2013 Microsoft Corporation. All rights reserved.'
12 |
13 | Description = 'Module to help in reading details from DSC events'
14 |
15 | PowerShellVersion = '4.0'
16 |
17 | CLRVersion = '4.0'
18 |
19 | FunctionsToExport = @("*")
20 |
21 | NestedModules = @('xDscDiagnostics.psm1')
22 | }
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xDscDiagnostics/xDscDiagnosticsFormat.ps1xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Microsoft.PowerShell.xDscDiagnostics.GroupedEvents
7 |
8 | Microsoft.PowerShell.xDscDiagnostics.GroupedEvents
9 |
10 |
11 |
12 |
13 |
14 | 14
15 |
16 |
17 |
18 | 10
19 |
20 |
21 |
22 | 21
23 |
24 |
25 |
26 | 8
27 |
28 |
29 |
30 | 37
31 |
32 |
33 |
34 | 21
35 |
36 |
37 |
38 |
39 |
40 |
41 | ComputerName
42 |
43 |
44 | SequenceId
45 |
46 |
47 | TimeCreated
48 |
49 |
50 | Result
51 |
52 |
53 | JobID
54 |
55 |
56 | AllEvents
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | Microsoft.PowerShell.xDscDiagnostics.TraceOutput
65 |
66 | Microsoft.PowerShell.xDscDiagnostics.TraceOutput
67 |
68 |
69 |
70 |
71 |
72 | 14
73 |
74 |
75 |
76 | 12
77 |
78 |
79 |
80 | 21
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | ComputerName
91 |
92 |
93 | EventType
94 |
95 |
96 | TimeCreated
97 |
98 |
99 | Message
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xNetworking/DSCResources/MSFT_xDNSServerAddress/MSFT_xDNSServerAddress.psm1:
--------------------------------------------------------------------------------
1 | <#######################################################################################
2 | # xDNSServerAddress : DSC Resource that will set/test/get the current DNS Server
3 | # Address, by accepting values among those given in xDNSServerAddress.schema.mof
4 | #######################################################################################>
5 |
6 |
7 |
8 | ######################################################################################
9 | # The Get-TargetResource cmdlet.
10 | # This function will get the present list of DNS ServerAddress DSC Resource schema variables on the system
11 | ######################################################################################
12 | function Get-TargetResource
13 | {
14 | param
15 | (
16 | [Parameter(Mandatory)]
17 | [ValidateNotNullOrEmpty()]
18 | [String[]]$Address,
19 |
20 | [Parameter(Mandatory)]
21 | [ValidateNotNullOrEmpty()]
22 | [String]$InterfaceAlias,
23 |
24 | [ValidateSet("IPv4", "IPv6")]
25 | [String]$AddressFamily = "IPv4"
26 | )
27 |
28 |
29 | $returnValue = @{
30 | Address = (Get-DnsClientServerAddress -InterfaceAlias $InterfaceAlias -AddressFamily $AddressFamily).ServerAddresses
31 | AddressFamily = $AddressFamily
32 | InterfaceAlias = $InterfaceAlias
33 | }
34 |
35 | $returnValue
36 | }
37 |
38 | ######################################################################################
39 | # The Set-TargetResource cmdlet.
40 | # This function will set a new Server Address in the current node
41 | ######################################################################################
42 | function Set-TargetResource
43 | {
44 | param
45 | (
46 | #IP Address that has to be set
47 | [Parameter(Mandatory)]
48 | [ValidateNotNullOrEmpty()]
49 | [String[]]$Address,
50 |
51 | [Parameter(Mandatory)]
52 | [ValidateNotNullOrEmpty()]
53 | [String]$InterfaceAlias,
54 |
55 | [ValidateSet("IPv4", "IPv6")]
56 | [String]$AddressFamily = "IPv4"
57 | )
58 |
59 | ValidateProperties @PSBoundParameters -Apply
60 | }
61 |
62 | ######################################################################################
63 | # The Test-TargetResource cmdlet.
64 | # This will test if the given Server Address is among the current node's Server Address collection
65 | ######################################################################################
66 | function Test-TargetResource
67 | {
68 | param
69 | (
70 | [Parameter(Mandatory)]
71 | [ValidateNotNullOrEmpty()]
72 | [String[]]$Address,
73 |
74 | [Parameter(Mandatory)]
75 | [ValidateNotNullOrEmpty()]
76 | [String]$InterfaceAlias,
77 |
78 | [ValidateSet("IPv4", "IPv6")]
79 | [String]$AddressFamily = "IPv4"
80 | )
81 |
82 | ValidateProperties @PSBoundParameters
83 | }
84 |
85 |
86 | #######################################################################################
87 | # Helper function that validates the Server Address properties. If the switch parameter
88 | # "Apply" is set, then it will set the properties after a test
89 | #######################################################################################
90 | function ValidateProperties
91 | {
92 | param
93 | (
94 | [Parameter(Mandatory)]
95 | [ValidateNotNullOrEmpty()]
96 | [String[]]$Address,
97 |
98 | [Parameter(Mandatory)]
99 | [ValidateNotNullOrEmpty()]
100 | [String]$InterfaceAlias,
101 |
102 | [ValidateSet("IPv4", "IPv6")]
103 | [String]$AddressFamily,
104 |
105 | [Switch]$Apply
106 | )
107 | $sa =$Address
108 | $sa | %{
109 | if(!([System.Net.Ipaddress]::TryParse($_, [ref]0)))
110 | {
111 | throw "Server Address *$_* is not in the correct format. Please correct the Address in the configuration and try again"
112 | }
113 | if (([System.Net.IPAddress]$_).AddressFamily.ToString() -eq [System.Net.Sockets.AddressFamily]::InterNetwork.ToString())
114 | {
115 | if ($AddressFamily -ne "IPv4")
116 | {
117 | throw "Server address $Address is in IPv4 format, which does not match server address family $AddressFamily. Please correct either of them in the configuration and try again"
118 | }
119 | }
120 | else
121 | {
122 | if ($AddressFamily -ne "IPv6")
123 | {
124 | throw "Server address $Address is in IPv6 format, which does not match server address family $AddressFamily. Please correct either of them in the configuration and try again"
125 | }
126 | }
127 | }
128 | try
129 | {
130 | Write-Verbose -Message "Checking the DNS Server Address ..."
131 | #Get the current IP Address based on the parameters given.
132 | $currentAddress = (Get-DnsClientServerAddress -InterfaceAlias $InterfaceAlias -AddressFamily $AddressFamily -ErrorAction Stop).ServerAddresses
133 |
134 | #Check if the Server addresses are the same as the desired addresses.
135 | if(@(Compare-Object -ReferenceObject $currentAddress -DifferenceObject $Address -SyncWindow 0).Length -gt 0)
136 | {
137 | Write-Verbose -Message "DNS Servers are not correct. Expected $Address, actual $currentAddress"
138 | if($Apply)
139 | {
140 | # Set the DNS settings as well
141 | Set-DnsClientServerAddress -InterfaceAlias $InterfaceAlias -ServerAddresses $Address
142 | Write-Verbose -Message "DNS Servers have been set correctly."
143 | }
144 | else
145 | {
146 | return $false
147 | }
148 | }
149 | else
150 | {
151 | #Test will return true in this case
152 | Write-Verbose -Message "DNS Servers are set correctly."
153 | return $true
154 | }
155 | }
156 | catch
157 | {
158 | Write-Verbose -Message $_
159 | throw "Can not set or find valid DNS Server addresses using InterfaceAlias $InterfaceAlias and AddressFamily $AddressFamily"
160 | }
161 | }
162 |
163 |
164 |
165 | # FUNCTIONS TO BE EXPORTED
166 | Export-ModuleMember -function Get-TargetResource, Set-TargetResource, Test-TargetResource
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xNetworking/DSCResources/MSFT_xDNSServerAddress/MSFT_xDNSServerAddress.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xNetworking/DSCResources/MSFT_xDNSServerAddress/MSFT_xDNSServerAddress.schema.mof
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xNetworking/DSCResources/MSFT_xFirewall/MSFT_xFirewall.Schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xNetworking/DSCResources/MSFT_xFirewall/MSFT_xFirewall.Schema.mof
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xNetworking/DSCResources/MSFT_xIPAddress/MSFT_xIPAddress.psm1:
--------------------------------------------------------------------------------
1 | <#######################################################################################
2 | # MSDSCPack_IPAddress : DSC Resource that will set/test/get the current IP
3 | # Address, by accepting values among those given in MSDSCPack_IPAddress.schema.mof
4 | #######################################################################################>
5 |
6 |
7 |
8 | ######################################################################################
9 | # The Get-TargetResource cmdlet.
10 | # This function will get the present list of IP Address DSC Resource schema variables on the system
11 | ######################################################################################
12 | function Get-TargetResource
13 | {
14 | param
15 | (
16 | [Parameter(Mandatory)]
17 | [ValidateNotNullOrEmpty()]
18 | [String]$IPAddress,
19 |
20 | [Parameter(Mandatory)]
21 | [ValidateNotNullOrEmpty()]
22 | [String]$InterfaceAlias,
23 |
24 | [Int]$SubnetMask = 16,
25 |
26 | [ValidateNotNullOrEmpty()]
27 | [String]$DefaultGateway,
28 |
29 | [ValidateSet("IPv4", "IPv6")]
30 | [String]$AddressFamily = "IPv4"
31 | )
32 |
33 |
34 | $returnValue = @{
35 | IPAddress = [System.String]::Join(", ",(Get-NetIPAddress -InterfaceAlias $InterfaceAlias -AddressFamily $AddressFamily).IPAddress)
36 | SubnetMask = $SubnetMask
37 | DefaultGateway = $DefaultGateway
38 | AddressFamily = $AddressFamily
39 | InterfaceAlias=$InterfaceAlias
40 | }
41 |
42 | $returnValue
43 | }
44 |
45 | ######################################################################################
46 | # The Set-TargetResource cmdlet.
47 | # This function will set a new IP Address in the current node
48 | ######################################################################################
49 | function Set-TargetResource
50 | {
51 | param
52 | (
53 | #IP Address that has to be set
54 | [Parameter(Mandatory)]
55 | [ValidateNotNullOrEmpty()]
56 | [String]$IPAddress,
57 |
58 | [Parameter(Mandatory)]
59 | [ValidateNotNullOrEmpty()]
60 | [String]$InterfaceAlias,
61 |
62 | [Int]$SubnetMask,
63 |
64 | [ValidateNotNullOrEmpty()]
65 | [String]$DefaultGateway,
66 |
67 | [ValidateSet("IPv4", "IPv6")]
68 | [String]$AddressFamily = "IPv4"
69 | )
70 |
71 |
72 | ValidateProperties @PSBoundParameters -Apply
73 | }
74 |
75 | ######################################################################################
76 | # The Test-TargetResource cmdlet.
77 | # This will test if the given IP Address is among the current node's IP Address collection
78 | ######################################################################################
79 | function Test-TargetResource
80 | {
81 | param
82 | (
83 | [Parameter(Mandatory)]
84 | [ValidateNotNullOrEmpty()]
85 | [String]$IPAddress,
86 |
87 | [Parameter(Mandatory)]
88 | [ValidateNotNullOrEmpty()]
89 | [String]$InterfaceAlias,
90 |
91 | [Int]$SubnetMask,
92 |
93 | [ValidateNotNullOrEmpty()]
94 | [String]$DefaultGateway,
95 |
96 | [ValidateSet("IPv4", "IPv6")]
97 | [String]$AddressFamily = "IPv4"
98 | )
99 |
100 | ValidateProperties @PSBoundParameters
101 | }
102 |
103 |
104 | #######################################################################################
105 | # Helper function that validates the IP Address properties. If the switch parameter
106 | # "Apply" is set, then it will set the properties after a test
107 | #######################################################################################
108 | function ValidateProperties
109 | {
110 | param
111 | (
112 | [Parameter(Mandatory)]
113 | [ValidateNotNullOrEmpty()]
114 | [String]$IPAddress,
115 |
116 | [Parameter(Mandatory)]
117 | [ValidateNotNullOrEmpty()]
118 | [String]$InterfaceAlias,
119 |
120 | [ValidateNotNullOrEmpty()]
121 | [String]$DefaultGateway,
122 |
123 | [Int]$SubnetMask = 16,
124 |
125 | [ValidateSet("IPv4", "IPv6")]
126 | [String]$AddressFamily = "IPv4",
127 |
128 | [Switch]$Apply
129 | )
130 | $ip=$IPAddress
131 | if(!([System.Net.Ipaddress]::TryParse($ip, [ref]0)))
132 | {
133 | throw "IP Address *$IPAddress* is not in the correct format. Please correct the ipaddress in the configuration and try again"
134 | }
135 | try
136 | {
137 | Write-Verbose -Message "Checking the IPAddress ..."
138 | #Get the current IP Address based on the parameters given.
139 | $currentIP = Get-NetIPAddress -InterfaceAlias $InterfaceAlias -AddressFamily $AddressFamily -ErrorAction Stop
140 |
141 | #Test if the IP Address passed is equal to the current ip address
142 | if(!$currentIP.IPAddress.Contains($IPAddress))
143 | {
144 | Write-Verbose -Message "IPAddress not correct. Expected $IPAddress, actual $($currentIP.IPAddress)"
145 | $Parameters = @{}
146 |
147 | #Apply is true in the case of set - target resource - in which case, it will set the new IP Address
148 | if($Apply)
149 | {
150 | Write-Verbose -Message "Setting IPAddress ..."
151 | $Parameters["IPAddress"] = $IPAddress
152 | $Parameters["PrefixLength"] = $SubnetMask
153 | $Parameters["InterfaceAlias"] = $currentIP[0].InterfaceAlias
154 |
155 | if($DefaultGateway){ $Parameters["DefaultGateWay"] = $DefaultGateway }
156 | $null = New-NetIPAddress @Parameters -ErrorAction Stop
157 |
158 | # Make the connection profile private
159 | Get-NetConnectionProfile -InterfaceAlias $InterfaceAlias | Set-NetConnectionProfile -NetworkCategory Private -ErrorAction SilentlyContinue
160 | Write-Verbose -Message "IPAddress is set to $IPAddress."
161 | }
162 | else {return $false}
163 | }
164 | else
165 | {
166 | Write-Verbose -Message "IPAddress is correct."
167 | return $true
168 | }
169 | }
170 | catch
171 | {
172 | Write-Verbose -Message $_
173 | throw "Can not set or find valid IPAddress using InterfaceAlias $InterfaceAlias and AddressFamily $AddressFamily"
174 | }
175 | }
176 |
177 |
178 |
179 | # FUNCTIONS TO BE EXPORTED
180 | Export-ModuleMember -function Get-TargetResource, Set-TargetResource, Test-TargetResource
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xNetworking/DSCResources/MSFT_xIPAddress/MSFT_xIPAddress.schema.mof:
--------------------------------------------------------------------------------
1 | [ClassVersion("1.0.0"), FriendlyName("xIPAddress")]
2 | class MSFT_xIPAddress : OMI_BaseResource
3 | {
4 | [Key] string IPAddress;
5 | [Key] string InterfaceAlias;
6 | [write] string DefaultGateway;
7 | [Write] uint32 SubnetMask;
8 | [Write,ValueMap{"IPv4", "IPv6"},Values{"IPv4", "IPv6"}] string AddressFamily;
9 | };
10 |
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xNetworking/Examples/Sample_xDnsServerAddress.ps1:
--------------------------------------------------------------------------------
1 | configuration Sample_xDnsServerAddress
2 | {
3 | param
4 | (
5 | [string[]]$NodeName = 'localhost',
6 |
7 | [Parameter(Mandatory)]
8 | [string]$DnsServerAddress,
9 |
10 | [Parameter(Mandatory)]
11 | [string]$InterfaceAlias,
12 |
13 | [ValidateSet("IPv4","IPv6")]
14 | [string]$AddressFamily = 'IPv4'
15 | )
16 |
17 | Import-DscResource -Module xNetworking
18 |
19 | Node $NodeName
20 | {
21 | xDnsServerAddress DnsServerAddress
22 | {
23 | Address = $DnsServerAddress
24 | InterfaceAlias = $InterfaceAlias
25 | AddressFamily = $AddressFamily
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xNetworking/Examples/Sample_xFirewall_AddFirewallRule.ps1:
--------------------------------------------------------------------------------
1 | # DSC configuration for Firewall
2 |
3 | configuration Sample_xFirewall_AddFirewallRule
4 | {
5 | param
6 | (
7 | [string[]]$NodeName = 'localhost'
8 | )
9 |
10 | Import-DSCResource -ModuleName xNetworking
11 |
12 | Node $NodeName
13 | {
14 | xFirewall Firewall
15 | {
16 | Name = "NotePadFirewallRule"
17 | DisplayName = "Firewall Rule for Notepad.exe"
18 | DisplayGroup = "NotePad Firewall Rule Group"
19 | Ensure = "Present"
20 | Access = "Allow"
21 | State = "Enabled"
22 | Profile = ("Domain", "Private")
23 | Direction = "OutBound"
24 | RemotePort = ("8080", "8081")
25 | LocalPort = ("9080", "9081")
26 | Protocol = "TCP"
27 | Description = "Firewall Rule for Notepad.exe"
28 | ApplicationPath = "c:\windows\system32\notepad.exe"
29 | Service = "WinRM"
30 | }
31 | }
32 | }
33 |
34 | Sample_xFirewall_AddFirewallRule
35 | Start-DscConfiguration -Path Sample_xFirewall_AddFirewallRule -Wait -Verbose -Force
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xNetworking/Examples/Sample_xFirewall_AddFirewallRuleToExistingGroup.ps1:
--------------------------------------------------------------------------------
1 | # DSC configuration for Firewall
2 | #
3 |
4 | configuration Sample_xFirewall_AddFirewallRuleToExistingGroup
5 | {
6 | param
7 | (
8 | [string[]]$NodeName = 'localhost'
9 | )
10 |
11 | Import-DSCResource -ModuleName xNetworking
12 |
13 | Node $NodeName
14 | {
15 | xFirewall Firewall
16 | {
17 | Name = "MyFirewallRule"
18 | DisplayName = "My Firewall Rule"
19 | DisplayGroup = "My Firewall Rule Group"
20 | Access = "Allow"
21 | }
22 |
23 | xFirewall Firewall1
24 | {
25 | Name = "MyFirewallRule1"
26 | DisplayName = "My Firewall Rule"
27 | DisplayGroup = "My Firewall Rule Group"
28 | Ensure = "Present"
29 | Access = "Allow"
30 | State = "Enabled"
31 | Profile = ("Domain", "Private")
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xNetworking/Examples/Sample_xFirewall_AddFirewallRuleToNewGroup.ps1:
--------------------------------------------------------------------------------
1 | # DSC configuration for Firewall
2 |
3 | configuration Sample_xFirewall_AddFirewallRuleToNewGroup
4 | {
5 | param
6 | (
7 | [string[]]$NodeName = 'localhost'
8 | )
9 |
10 | Import-DSCResource -ModuleName xNetworking
11 |
12 | Node $NodeName
13 | {
14 | xFirewall Firewall
15 | {
16 | Name = "MyAppFirewallRule"
17 | ApplicationPath = "c:\windows\system32\MyApp.exe"
18 | Access = "Allow"
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xNetworking/Examples/Sample_xFirewall_DisableAccessToApplication.ps1:
--------------------------------------------------------------------------------
1 | # DSC configuration for Firewall
2 | #
3 |
4 | configuration Sample_xFirewall_AddFirewallRuleToNewGroup
5 | {
6 | param
7 | (
8 | [string[]]$NodeName = 'localhost'
9 | )
10 |
11 | Import-DSCResource -ModuleName xNetworking
12 |
13 | Node $NodeName
14 | {
15 | xFirewall Firewall
16 | {
17 | Name = "NotePadFirewallRule"
18 | DisplayName = "Firewall Rule for Notepad.exe"
19 | DisplayGroup = "NotePad Firewall Rule Group"
20 | Ensure = "Present"
21 | Access = "Block"
22 | Description = "Firewall Rule for Notepad.exe"
23 | ApplicationPath = "c:\windows\system32\notepad.exe"
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xNetworking/Examples/Sample_xIPAddress_FixedValue.ps1:
--------------------------------------------------------------------------------
1 | configuration Sample_xIPAddress_FixedValue
2 | {
3 | param
4 | (
5 | [string[]]$NodeName = 'localhost'
6 | )
7 |
8 | Import-DscResource -Module xNetworking
9 |
10 | Node $NodeName
11 | {
12 | xIPAddress NewIPAddress
13 | {
14 | IPAddress = "2001:4898:200:7:6c71:a102:ebd8:f482"
15 | InterfaceAlias = "Ethernet"
16 | SubnetMask = 24
17 | AddressFamily = "IPV6"
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xNetworking/Examples/Sample_xIPAddress_Parameterized.ps1:
--------------------------------------------------------------------------------
1 | configuration Sample_xIPAddress_Parameterized
2 | {
3 | param
4 | (
5 |
6 | [string[]]$NodeName = 'localhost',
7 |
8 | [Parameter(Mandatory)]
9 | [string]$IPAddress,
10 |
11 | [Parameter(Mandatory)]
12 | [string]$InterfaceAlias,
13 |
14 | [Parameter(Mandatory)]
15 | [string]$DefaultGateway,
16 |
17 | [int]$SubnetMask = 16,
18 |
19 | [ValidateSet("IPv4","IPv6")]
20 | [string]$AddressFamily = 'IPv4'
21 | )
22 |
23 | Import-DscResource -Module xNetworking
24 |
25 | Node $NodeName
26 | {
27 | xIPAddress NewIPAddress
28 | {
29 | IPAddress = $IPAddress
30 | InterfaceAlias = $InterfaceAlias
31 | DefaultGateway = $DefaultGateway
32 | SubnetMask = $SubnetMask
33 | AddressFamily = $AddressFamily
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xNetworking/xNetworking.psd1:
--------------------------------------------------------------------------------
1 | @{
2 | # Version number of this module.
3 | ModuleVersion = '2.1.1'
4 |
5 | # ID used to uniquely identify this module
6 | GUID = 'e6647cc3-ce9c-4c86-9eb8-2ee8919bf358'
7 |
8 | # Author of this module
9 | Author = 'Microsoft Corporation'
10 |
11 | # Company or vendor of this module
12 | CompanyName = 'Microsoft Corporation'
13 |
14 | # Copyright statement for this module
15 | Copyright = '(c) 2013 Microsoft Corporation. All rights reserved.'
16 |
17 | # Description of the functionality provided by this module
18 | Description = 'Module with DSC Resources for Networking area'
19 |
20 | # Minimum version of the Windows PowerShell engine required by this module
21 | PowerShellVersion = '4.0'
22 |
23 | # Minimum version of the common language runtime (CLR) required by this module
24 | CLRVersion = '4.0'
25 |
26 | # Functions to export from this module
27 | FunctionsToExport = '*'
28 |
29 | # Cmdlets to export from this module
30 | CmdletsToExport = '*'
31 | }
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xPendingReboot/DSCResources/MSFT_xPendingReboot/MSFT_xPendingReboot.psm1:
--------------------------------------------------------------------------------
1 | Function Get-TargetResource
2 | {
3 | [CmdletBinding()]
4 | param
5 | (
6 | [Parameter(Mandatory=$true)]
7 | [string]$Name
8 | )
9 |
10 | <## Remove:
11 | $ComponentBasedServicing = (Get-ItemProperty 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\').RebootPending -ne $null
12 | Remove - $WindowsUpdate = (Get-ItemProperty 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\').RebootRequired -ne $null
13 | Remove - $PendingFileRename = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\').PendingFileRenameOperations -ne $null
14 | #>
15 |
16 | ## Brian's additions:--------------------------------------------------
17 | $ComponentBasedServicing = (Get-ChildItem 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\').Name.Split("\") -contains "RebootPending"
18 | $WindowsUpdate = (Get-ChildItem 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\').Name.Split("\") -contains "RebootRequired"
19 | $PendingFileRename = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\').PendingFileRenameOperations.Length -gt 0
20 | $ActiveComputerName = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName').ComputerName
21 | $PendingComputerName = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName').ComputerName
22 | $PendingComputerRename = $ActiveComputerName -ne $PendingComputerName
23 |
24 | $CCMSplat = @{
25 | NameSpace='ROOT\ccm\ClientSDK'
26 | Class='CCM_ClientUtilities'
27 | Name='DetermineIfRebootPending'
28 | ErrorAction='Stop'
29 | }
30 |
31 | Try {
32 | $CCMClientSDK = Invoke-WmiMethod @CCMSplat
33 | } Catch {
34 | Write-Warning "Unable to query CCM_ClientUtilities: $_"
35 | }
36 |
37 | $SCCMSDK = ($CCMClientSDK.ReturnValue -eq 0) -and ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending)
38 | ## End Brian's additions------------------------------------------------
39 |
40 | return @{
41 | Name = $Name
42 | ComponentBasedServicing = $ComponentBasedServicing
43 | WindowsUpdate = $WindowsUpdate
44 | PendingFileRename = $PendingFileRename
45 | PendingComputerRename = $PendingComputerRename
46 | CcmClientSDK = $SCCMSDK
47 | }
48 | }
49 |
50 | Function Set-TargetResource
51 | {
52 | [CmdletBinding()]
53 | param
54 | (
55 | [Parameter(Mandatory=$true)]
56 | [string]$Name
57 | )
58 |
59 | $global:DSCMachineStatus = 1
60 | }
61 |
62 | Function Test-TargetResource
63 | {
64 | [CmdletBinding()]
65 | param
66 | (
67 | [Parameter(Mandatory=$true)]
68 | [string]$Name
69 | )
70 |
71 | <## Remove
72 | $regRebootLocations += @{'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\'='RebootPending'}
73 | $regRebootLocations += @{'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\'='RebootRequired'}
74 | $regRebootLocations += @{'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\'='PendingFileRenameOperations'}
75 |
76 | foreach ($reg in $regRebootLocations.keys) {
77 | if ((Get-ItemProperty $reg).($regRebootLocations[$reg]) -ne $Null) {
78 | Write-Verbose "A pending reboot was found at $reg."
79 | Write-Verbose 'Setting the DSCMachineStatus global variable to 1.'
80 | return $false}
81 | }
82 | #>
83 |
84 | ## Brian's additions:--------------------------------------------------
85 | $ScriptBlocks += @{ComponentBasedServicing = {(Get-ChildItem 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\').Name.Split("\") -contains "RebootPending"}}
86 | $ScriptBlocks += @{WindowsUpdate = {(Get-ChildItem 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\').Name.Split("\") -contains "RebootRequired"}}
87 | $ScriptBlocks += @{PendingFileRename = {(Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\').PendingFileRenameOperations.Length -gt 0}}
88 | $ScriptBlocks += @{PendingComputerRename = {
89 | $ActiveComputerName = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName').ComputerName
90 | $PendingComputerName = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName').ComputerName
91 | $ActiveComputerName -ne $PendingComputerName
92 | }
93 | }
94 | $ScriptBlocks += @{CcmClientSDK = {
95 | $CCMSplat = @{
96 | NameSpace='ROOT\ccm\ClientSDK'
97 | Class='CCM_ClientUtilities'
98 | Name='DetermineIfRebootPending'
99 | ErrorAction='Stop'
100 | }
101 | Try {
102 | $CCMClientSDK = Invoke-WmiMethod @CCMSplat
103 | ($CCMClientSDK.ReturnValue -eq 0) -and ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending)
104 | } Catch {
105 | Write-Warning "Unable to query CCM_ClientUtilities: $_"
106 | }
107 | }
108 | }
109 | Foreach ($Script in $ScriptBlocks.Keys) {
110 | If (Invoke-Command $ScriptBlocks[$Script]) {
111 | Write-Verbose "A pending reboot was found for $Script."
112 | Write-Verbose 'Setting the DSCMachineStatus global variable to 1.'
113 | return $false
114 | }
115 | }
116 | ## End Brian's additions------------------------------------------------
117 |
118 | Write-Verbose 'No pending reboots found.'
119 | return $true
120 | }
121 |
122 | Export-ModuleMember -Function *-TargetResource
123 |
124 | $regRebootLocations = $null
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xPendingReboot/DSCResources/MSFT_xPendingReboot/MSFT_xPendingReboot.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xPendingReboot/DSCResources/MSFT_xPendingReboot/MSFT_xPendingReboot.schema.mof
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xPendingReboot/xPendingReboot.psd1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xPendingReboot/xPendingReboot.psd1
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/MSFT_xIisModule.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/MSFT_xIisModule.psm1
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/MSFT_xIisModule.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/MSFT_xIisModule.schema.mof
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/xIisModuleDesigner.ps1:
--------------------------------------------------------------------------------
1 | $diff = join-Path ${env:ProgramFiles(x86)} "Beyond compare 2\bc2.exe"
2 | $friendlyName = "xIisModule"
3 | $resourceName = "MSFT_$friendlyName"
4 | $classVersion = "1.0.0"
5 |
6 | $scriptRoot = Split-Path $MyInvocation.MyCommand.Path
7 | $originalModuleRoot = join-Path $scriptroot "..\.."
8 | $originalModuleRootPath = Resolve-Path $originalModuleRoot
9 | $moduleRoot = Join-Path $env:temp "$($originalModuleRootPath.path | split-path -Leaf)Temp"
10 |
11 | $resources = @()
12 | $schemaPath = (join-path $scriptRoot "$resourceName.schema.mof")
13 |
14 | #Key properties
15 | $resources += New-xDscResourceProperty -Name Path -Type String -Attribute Key -Description "The path to the module, usually a dll, to be added to IIS."
16 |
17 |
18 | #Required Properites
19 | $resources += New-xDscResourceProperty -Name Name -Type String -Attribute Required -Description "The logical name of the module to add to IIS."
20 | $resources += New-xDscResourceProperty -Name RequestPath -Type String -Attribute Required -Description "The allowed request Path example: *.php"
21 | $resources += New-xDscResourceProperty -Name Verb -Type String[] -Attribute Required -Description "The supported verbs for the module."
22 |
23 | #Write Properties
24 | $resources += New-xDscResourceProperty -Name SiteName -Type String -Attribute Write -Description "The IIS Site to register the module."
25 | $resources += New-xDscResourceProperty -Name Ensure -Type String -Attribute Write -Description "Should the module be present or absent." -ValidateSet @("Present","Absent")
26 | $resources += New-xDscResourceProperty -Name ModuleType -Type String -Attribute Write -Description "The type of the module." -ValidateSet @("FastCgiModule")
27 |
28 | #Read Properties
29 | $resources += New-xDscResourceProperty -Name EndPointSetup -Type Boolean -Attribute Read -Description "The End Point is setup. Such as a Fast Cgi endpoint."
30 |
31 |
32 |
33 | Write-Host updating...
34 |
35 | # Create a New template resource to a temporary folder
36 | New-xDscResource -Property $resources -ClassVersion $classVersion -Name $resourceName -Path $moduleRoot -FriendlyName $friendlyName
37 |
38 |
39 | # Use your favorite diff program to compare and merge the current resource and the existing resource
40 |
41 | if((test-Path $diff))
42 | {
43 | &$diff $originalModuleRoot $moduleRoot
44 | }
45 | else
46 | {
47 | Write-Warning "Diff propgram not found!`r`nUse your favorite diff program to compare and merge:`r`n `t$($originalModuleRootPath.path)`r`n and:`r`n `t$moduleRoot"
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.psm1
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.schema.mof
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.psm1
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.schema.mof
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.psm1
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.schema.mof
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.psm1
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.schema.mof
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof
--------------------------------------------------------------------------------
/Exercise4/PowerShellModules/xWebAdministration/xWebAdministration.psd1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise4/PowerShellModules/xWebAdministration/xWebAdministration.psd1
--------------------------------------------------------------------------------
/Exercise4/Scripts/ConfigureWebserver.ps1:
--------------------------------------------------------------------------------
1 | Configuration ConfigureWebserver
2 | {
3 | Import-DscResource -ModuleName cWinServer
4 | Import-DscResource -ModuleName xWebAdministration
5 | Import-DscResource -ModuleName xPendingReboot
6 | Import-DscResource -ModuleName xNetworking
7 |
8 | # Localhost targets the node this script is run on
9 | Node 'localhost'
10 | {
11 | LocalConfigurationManager
12 | {
13 | RebootNodeIfNeeded = $True
14 | }
15 |
16 | WinServerOptions ServerOptions
17 | {
18 | Ensure = "Present"
19 | Name = "Set timezone and culture"
20 | Culture = "en-AU"
21 | TimeZone = "AUS Eastern Standard Time"
22 | }
23 |
24 | xPendingReboot AfterServerOptions
25 | {
26 | Name = "AfterServerOptions"
27 | DependsOn = '[WinServerOptions]ServerOptions'
28 | }
29 |
30 | $windowsFeatures = @(
31 | "Web-App-Dev",
32 | "Web-Common-Http",
33 | "Web-Health",
34 | "Web-Performance",
35 | "Web-Security",
36 | "Web-Scripting-Tools",
37 | "Web-Mgmt-Service",
38 | "Web-Mgmt-Console"
39 | )
40 |
41 | $windowsFeatureDependOn = @();
42 |
43 | foreach ($windowsFeature in $windowsFeatures)
44 | {
45 | WindowsFeature "IIS_$windowsFeature"
46 | {
47 | Ensure = "Present"
48 | Name = $windowsFeature
49 | IncludeAllSubFeature = $true
50 | DependsOn = "[xPendingReboot]AfterServerOptions"
51 | }
52 |
53 | $windowsFeatureDependOn += "[WindowsFeature]IIS_$windowsFeature"
54 | }
55 |
56 | <#
57 | NOTE: For new players, if you want to discover whether a reboot will be required after a given piece of DSC, search for "$global:DSCMachineStatus = 1" in the resources you have used.
58 | #>
59 |
60 | xPendingReboot RebootAfterWindowsFeatures
61 | {
62 | Name = 'AfterWindowsFeatures'
63 | DependsOn = $windowsFeatureDependOn
64 | }
65 |
66 | # Stop & Remove the default website
67 | xWebsite DefaultSite
68 | {
69 | Ensure = "Absent"
70 | Name = "Default Web Site"
71 | State = "Stopped"
72 | PhysicalPath = "C:\inetpub\wwwroot"
73 | DependsOn = $windowsFeatureDependOn
74 | }
75 |
76 | # Remove all default Application Pools EXCEPT DEFAULT (will use this for the load balancer health check)
77 | foreach ($appPool in @("Classic .NET AppPool", ".NET v2.0",
78 | ".NET v2.0 Classic", ".NET v4.5", ".NET v4.5 Classic"))
79 | {
80 | xWebAppPool $appPool
81 | {
82 | Ensure = "Absent"
83 | Name = $appPool
84 | DependsOn = ($windowsFeatureDependOn + @("[xWebsite]DefaultSite"))
85 | }
86 | }
87 |
88 | File LoadBalancerHealthCheckEndpointContent
89 | {
90 | Ensure = "Present"
91 | DestinationPath = "C:\inetpub\wwwroot\index.html"
92 | Contents = "Hello, is it me you're looking for?"
93 | Type = "File"
94 | }
95 |
96 | xWebsite LoadBalancerHealthCheckEndpoint
97 | {
98 | Ensure = "Present"
99 | Name = "LoadBalancerHealthCheck"
100 | State = "Started"
101 | PhysicalPath = "C:\inetpub\wwwroot"
102 | BindingInfo = MSFT_xWebBindingInformation
103 | {
104 | Protocol = "HTTP"
105 | Port = 81
106 | }
107 | DependsOn = "[File]LoadBalancerHealthCheckEndpointContent"
108 | }
109 |
110 | xFirewall Firewall
111 | {
112 | Name = "Web"
113 | DisplayName = "Inbound access for web requests"
114 | Ensure = "Present"
115 | Access = "Allow"
116 | State = "Enabled"
117 | Profile = ("Domain", "Private", "Public")
118 | Direction = "InBound"
119 | RemotePort = ("Any")
120 | LocalPort = ("80", "81", "443")
121 | Protocol = "TCP"
122 | Description = "Inbound access for web requests"
123 | }
124 | }
125 | }
126 |
127 | ConfigureWebserver
128 |
129 | Set-DscLocalConfigurationManager -Path .\ConfigureWebserver -Verbose
130 | Start-DscConfiguration -Path .\ConfigureWebserver -Verbose -Wait -Force
131 |
--------------------------------------------------------------------------------
/Exercise4/Scripts/Teardown.ps1:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Exercise4/Templates/Zephyr.template:
--------------------------------------------------------------------------------
1 | {
2 | "AWSTemplateFormatVersion": "2010-09-09",
3 |
4 | "Description": "A template to deploy a simple fault tolerant load balanced web hosting infrastructure.",
5 |
6 | "Parameters": {
7 | "S3BucketName": {
8 | "Description": "The S3 Bucket Name used in URL's to specify authentication against.",
9 | "Type": "String"
10 | },
11 | "VpcId": {
12 | "Description": "The Vpc to deploy the infrastructure into.",
13 | "Type": "String"
14 | },
15 | "PowerShellModulesBundleUrl": {
16 | "Description": "The URL to a ZIP file containing any PowerShell modules required by this CloudFormation template.",
17 | "Type": "String"
18 | },
19 | "BootstrapperScriptBundleUrl": {
20 | "Description": "The URL to a ZIP file containing the PowerShell script package to bootstrap EC2 instances in this CloudFormation template.",
21 | "Type": "String"
22 | },
23 | "WebserverTemplateUrl": {
24 | "Description": "The URL to the CloudFormation stack template for web servers.",
25 | "Type": "String"
26 | },
27 | "Timestamp": {
28 | "Description": "When this CloudFormation stack was last updated.",
29 | "Type": "String"
30 | },
31 | "Version": {
32 | "Description": "The package version that contains this CloudFormation template.",
33 | "Type": "String"
34 | },
35 | "Environment": {
36 | "Type": "String",
37 | "Default": "Development"
38 | },
39 | "KeyPairName": {
40 | "Description": "The EC2 key pair used to launch web instances",
41 | "Type": "AWS::EC2::KeyPair::KeyName"
42 | },
43 | "WebserverImageId": {
44 | "Description": "The EC2 AmiId to use for web",
45 | "Type": "String",
46 | "Default": "ami-f9760dc3"
47 | },
48 | "WebserverInstanceType": {
49 | "Description": "The EC2 instance type to use for web",
50 | "Type": "String",
51 | "Default": "t2.small"
52 | },
53 | "WebserverSubnetIdAzOne": {
54 | "Description": "The PUBLIC subnet belonging to availability zone one into which the instance will be launched",
55 | "Type": "String"
56 | },
57 | "WebserverSubnetIdAzTwo": {
58 | "Description": "The PUBLIC subnet belonging to availability zone two into which the instance will be launched",
59 | "Type": "String"
60 | },
61 | "LoadBalancerSubnetIdAzOne": {
62 | "Description": "The PUBLIC IG-connected subnet belonging to availability zone one that the load balancer will belong to",
63 | "Type": "String"
64 | },
65 | "LoadBalancerSubnetIdAzTwo": {
66 | "Description": "The PUBLIC IG-connected subnet belonging to availability zone two that the load balancer will belong to",
67 | "Type": "String"
68 | },
69 | "ResourcePrefix" : {
70 | "Description": "Used to prefix a unique name to resources where applicable",
71 | "Type": "String"
72 | }
73 | },
74 |
75 | "Resources": {
76 | "BootstrapRole": {
77 | "Type": "AWS::IAM::Role",
78 | "Properties": {
79 | "AssumeRolePolicyDocument": {
80 | "Version": "2012-10-17",
81 | "Statement": [
82 | {
83 | "Effect": "Allow",
84 | "Principal": {
85 | "Service": [ "ec2.amazonaws.com" ]
86 | },
87 | "Action": [ "sts:AssumeRole" ]
88 | }
89 | ]
90 | },
91 | "Path": "/"
92 | }
93 | },
94 | "BootstrapRolePolicies": {
95 | "Type": "AWS::IAM::Policy",
96 | "Properties": {
97 | "PolicyName": "bootstrap",
98 | "PolicyDocument": {
99 | "Version": "2012-10-17",
100 | "Statement": [
101 | {
102 | "Effect": "Allow",
103 | "Action": "s3:*",
104 | "Resource": [
105 | { "Fn::Join": [ "", [ "arn:aws:s3:::", { "Ref": "S3BucketName" } ] ] },
106 | { "Fn::Join": [ "", [ "arn:aws:s3:::", { "Ref": "S3BucketName" }, "/*" ] ] }
107 | ]
108 | }
109 | ]
110 | },
111 | "Roles": [
112 | {
113 | "Ref": "BootstrapRole"
114 | }
115 | ]
116 | }
117 | },
118 | "BootstrapInstanceProfile": {
119 | "Type": "AWS::IAM::InstanceProfile",
120 | "Properties": {
121 | "Path": "/",
122 | "Roles": [
123 | {
124 | "Ref": "BootstrapRole"
125 | }
126 | ]
127 | }
128 | },
129 | "WebStack": {
130 | "Type": "AWS::CloudFormation::Stack",
131 | "Properties": {
132 | "Parameters": {
133 | "S3BucketName": { "Ref": "S3BucketName" },
134 | "VpcId": { "Ref": "VpcId" },
135 | "PowerShellModulesBundleUrl": { "Ref": "PowerShellModulesBundleUrl" },
136 | "BootstrapperScriptBundleUrl": { "Ref": "BootstrapperScriptBundleUrl" },
137 | "Timestamp": { "Ref": "Timestamp" },
138 | "Version": { "Ref": "Version" },
139 | "Environment": { "Ref": "Environment" },
140 | "InstanceProfile": { "Ref": "BootstrapInstanceProfile" },
141 | "BootstrapperRole": { "Ref": "BootstrapRole" },
142 | "KeyPairName": { "Ref": "KeyPairName" },
143 | "WebserverImageId": { "Ref": "WebserverImageId" },
144 | "WebserverInstanceType": { "Ref": "WebserverInstanceType" },
145 | "WebserverSubnetIdAzOne": { "Ref": "WebserverSubnetIdAzOne" },
146 | "WebserverSubnetIdAzTwo": { "Ref": "WebserverSubnetIdAzTwo" },
147 | "LoadBalancerSubnetIdAzOne": { "Ref": "LoadBalancerSubnetIdAzOne" },
148 | "LoadBalancerSubnetIdAzTwo": { "Ref": "LoadBalancerSubnetIdAzTwo" },
149 | "ResourcePrefix": { "Ref": "ResourcePrefix" }
150 | },
151 | "TemplateURL": { "Ref": "WebserverTemplateUrl" },
152 | "TimeoutInMinutes": 10
153 | }
154 | }
155 | },
156 |
157 | "Outputs": {
158 | "LoadBalancerUri": {
159 | "Value": { "Fn::GetAtt": [ "WebStack", "Outputs.LoadBalancerUri" ] }
160 | }
161 | }
162 | }
--------------------------------------------------------------------------------
/Exercise5.md:
--------------------------------------------------------------------------------
1 | # Exercise 5
2 |
3 | ## Deployment Magic
4 |
5 | In the final exercise, we are going to use some DSC + Octopus magic to [Automatically Deploy](https://octopus.com/docs/guides/elastic-and-transient-environments/immutable-infrastructure) to our transient infrastructure.
6 |
7 | ## Goals
8 |
9 | * Learn how we can automatically deploy our software along with our infrastructure
10 |
11 | ## Instructions
12 |
13 | 1. Open .\Exercise5\Parameters.ps1. Update the ResourcePrefix parameter to your initials, and take note of the other parameters provided
14 | 2. Open up .\Exercise5\Deploy.ps1
15 | 3. With PowerShell, write a file to scriptPath\Scripts\Variables.ps1 containing a HashTable named $BootstrapParameters that contains the values of the following parameters
16 | * OctopusServerUrl
17 | * OctopusApiKey
18 | * OctopusRole
19 | * Octopus.Environment.Name as 'Environment'
20 | 4. The astute observer would notice that this file will be scooped up into our scripts zip that we then download onto our instances during cfn-init
21 | 5. Navigate to .\Exercise5\PowerShellModules\cOctopus\DSCResources\cTentacleAgent\cTentacleAgent.psm1 and open it up in PowerShell ISE
22 | 6. Follow through **Set-TargetResource** and see how it does its thing
23 | 7. Go to Octopus, open the *CloudFormawesome* project, and navigate to its _Triggers_. Take a look at the trigger that will deploy our software when our transient infrastructure enters our environment.
24 | 8. Open up .\Exercise5\Scripts\ConfigureWebserver.ps1
25 | 9. At the top of the file, determine the execution location using
26 |
27 | [System.IO.Path]::GetDirectoryName($PSScriptRoot)
28 | 10. This will give us the root execution location - c:\cfn. Now we can dot-source our variables.ps1 file that will be downloaded onto the machine
29 | 11. Now that we have our $BootstrapParameters collection in scope, we can use the values in it to add a [cTentacleAgent resource](https://github.com/OctopusDeploy/OctopusDSC) to the end of our DSC configuration
30 | 12. Return to .\Exercise5\Deploy.ps1 and F5!
31 | 13. Monitor your stack's creation, and once your instances are available, remote in and take a look in the cfn-init log along with the DSC logs and ensure the operation was successful
32 | 14. If all went well, your machines should pop up in Octopus, and have a deployment triggered for themselves (one deployment per machine)
33 | 15. Hit your load balancer URL returned by the script! Wow! Such automated. Much website
34 |
35 |
--------------------------------------------------------------------------------
/Exercise5/Parameters.ps1:
--------------------------------------------------------------------------------
1 | $OctopusParameters = @{}
2 |
3 | # Octopus parameters
4 | $OctopusParameters['ResourcePrefix'] = 'aab';
5 | $OctopusParameters['OctopusServerUrl'] = "http://octopus.cfa.aws";
6 | $OctopusParameters['OctopusRole'] = "web";
7 | $OctopusParameters['OctopusApiKey'] = "";
8 | $OctopusParameters['Octopus.Environment.Name'] = "Production";
9 | $OctopusParameters['Octopus.Release.Number'] = "1.0.0-ryan0001";
10 |
11 | # CloudFormation parameters
12 | $OctopusParameters['AWSRegion'] = "ap-southeast-2";
13 | $OctopusParameters['CloudFormationStackName'] = "{0}-sandbox-{1}" -f @($OctopusParameters['ResourcePrefix'], $OctopusParameters['Octopus.Environment.Name']);
14 | $OctopusParameters['S3BucketName'] = "{0}-sandbox-infrastructure" -f $OctopusParameters['ResourcePrefix'];
15 | $OctopusParameters['VpcId'] = "vpc-7ecaee1b";
16 |
17 | # AWS parameters
18 | $OctopusParameters['KeyPairName'] = "AwsDayKeyPair";
19 | $OctopusParameters['WebserverImageId'] = "ami-bf8895dc"; #WINDOWS_2016_BASE
20 | $OctopusParameters['WebserverInstanceType'] = "t2.medium";
21 | $OctopusParameters['WebserverSubnetIdAzOne'] = "subnet-b1afb5d4"; # Web A
22 | $OctopusParameters['WebserverSubnetIdAzTwo'] = "subnet-14787e63"; # Web B
23 | $OctopusParameters['LoadBalancerSubnetIdAzOne'] = "subnet-973728f2"; # DMZ A
24 | $OctopusParameters['LoadBalancerSubnetIdAzTwo'] = "subnet-99477cee"; # DMZ B
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/cOctopus/DSCResources/cTentacleAgent/cTentacleAgent.schema.mof:
--------------------------------------------------------------------------------
1 | [ClassVersion("1.0.0"), FriendlyName("cTentacleAgent")]
2 | class cTentacleAgent : OMI_BaseResource
3 | {
4 | [Key] string Name;
5 | [Write, ValueMap{"Present", "Absent"}, Values{"Present", "Absent"}] string Ensure;
6 | [Write, ValueMap{"Started", "Stopped"}, Values{"Started", "Stopped"}] string State;
7 |
8 | [Write, ValueMap{"Listen", "Poll"}, Values{"Listen", "Poll"}] string CommunicationMode;
9 | [Write] string ApiKey;
10 | [Write] string OctopusServerUrl;
11 | [Write] string DisplayName;
12 | [Write] string Policy;
13 | [Write] string Environments[];
14 | [Write] string Roles[];
15 | [Write] string Tenants[];
16 | [Write] string TenantTags[];
17 | [Write] UInt32 ListenPort;
18 | [Write] UInt32 ServerPort;
19 | [Write] string DefaultApplicationDirectory;
20 | [Write] string TentacleDownloadUrl;
21 | [Write] string TentacleDownloadUrl64;
22 | [Write, ValueMap{"PublicIp", "FQDN", "ComputerName", "Custom"}, Values{"PublicIp", "FQDN", "ComputerName", "Custom"}] string PublicHostNameConfiguration;
23 | [Write] string CustomPublicHostName;
24 | [Write] string TentacleHomeDirectory;
25 | [Write] Boolean RegisterWithServer;
26 | [Write] String OctopusServerThumbprint;
27 | };
28 |
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/cOctopus/cOctopus.psd1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/cOctopus/cOctopus.psd1
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/cWinServer/DSCResources/WinServerOptions/WinServerOptions.psm1:
--------------------------------------------------------------------------------
1 | function Get-TargetResource
2 | {
3 | [CmdletBinding()]
4 | [OutputType([System.Collections.Hashtable])]
5 | param
6 | (
7 | [parameter(Mandatory = $true)]
8 | [System.String]
9 | $Name,
10 |
11 | [System.String]
12 | $Culture,
13 |
14 | [System.String]
15 | $TimeZone
16 | )
17 |
18 | $returnValue = @{
19 | Ensure = $Ensure
20 | Name = $Name
21 | Culture = $Culture
22 | Timezone = $Timezone
23 | }
24 |
25 | return $returnValue;
26 | }
27 |
28 | function Set-TargetResource
29 | {
30 | [CmdletBinding()]
31 | param
32 | (
33 | [ValidateSet("Present","Absent")]
34 | [System.String]
35 | $Ensure,
36 |
37 | [parameter(Mandatory = $true)]
38 | [System.String]
39 | $Name,
40 |
41 | [System.String]
42 | $Culture,
43 |
44 | [System.String]
45 | $TimeZone
46 | )
47 |
48 | if ($Ensure -eq "Present")
49 | {
50 | if ($Culture)
51 | {
52 | if ((Get-WinSystemLocale).Name -ne $Culture)
53 | {
54 | Write-Verbose "Setting System Locale to $Culture. Will Require reboot to take effect."
55 | Set-WinSystemLocale -SystemLocale $Culture
56 |
57 | $global:DSCMachineStatus = 1;
58 | }
59 | }
60 |
61 | if (([System.TimeZone]::CurrentTimeZone).StandardName -ne $TimeZone)
62 | {
63 | Write-Verbose "Setting System TimeZone to [$TimeZone]"
64 | & tzutil.exe /s "$TimeZone"
65 | }
66 | }
67 | }
68 |
69 | function Test-TargetResource
70 | {
71 | [CmdletBinding()]
72 | [OutputType([System.Boolean])]
73 | param
74 | (
75 | [ValidateSet("Present","Absent")]
76 | [System.String]
77 | $Ensure,
78 |
79 | [parameter(Mandatory = $true)]
80 | [System.String]
81 | $Name,
82 |
83 | [System.String]
84 | $Culture,
85 |
86 | [System.String]
87 | $TimeZone
88 | )
89 |
90 | if ($Ensure -eq "Present")
91 | {
92 | if ($Culture)
93 | {
94 | if ((Get-WinSystemLocale).Name -ne $Culture)
95 | {
96 | Write-Verbose "System Locale is currently $((Get-WinSystemLocale).Name) and should be $Culture"
97 | return $false;
98 | }
99 |
100 | Write-Verbose "System Locale and Culture are correct."
101 | }
102 |
103 | if ($TimeZone)
104 | {
105 | if (([System.TimeZone]::CurrentTimeZone).StandardName -ne $TimeZone)
106 | {
107 | Write-Verbose "System TimeZone is current:[$(([System.TimeZone]::CurrentTimeZone).StandardName)] and should be:[$TimeZone]"
108 | return $false;
109 | }
110 |
111 | Write-Verbose "System TimeZone is correct."
112 | }
113 | }
114 | else
115 | {
116 | Write-Verbose "Ignoring checks"
117 | }
118 |
119 | return $true;
120 | }
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/cWinServer/DSCResources/WinServerOptions/WinServerOptions.schema.mof:
--------------------------------------------------------------------------------
1 | [ClassVersion("1.0.0.0"), FriendlyName("WinServerOptions")]
2 | class WinServerOptions : OMI_BaseResource
3 | {
4 | [Write, ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure;
5 | [Key, Description("The name for the setup. Can just be the server name")] String Name;
6 | [Write, Description("The Windows Server culture")] String Culture;
7 | [Write, Description("The Windows Server Timezone")] String TimeZone;
8 | };
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/cWinServer/cWinServer.psd1:
--------------------------------------------------------------------------------
1 | #
2 | # Module manifest for module 'cWinServer'
3 | #
4 | # Generated by: andrewb
5 | #
6 | # Generated on: 9/06/2015
7 | @{
8 | ModuleVersion = '1.0'
9 | GUID = '90798d5f-9f2e-4af4-b9fd-79b4f67899fb'
10 | Author = 'andrewb'
11 | CompanyName = 'Unknown'
12 | Copyright = '(c) 2015 andrewb. All rights reserved.'
13 | Description = ''
14 | PowerShellVersion = '4.0'
15 | FunctionsToExport = @('Get-TargetResource','Set-TargetResource','Test-TargetResource')
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xDscDiagnostics/xDscDiagnostics.psd1:
--------------------------------------------------------------------------------
1 |
2 |
3 | @{
4 |
5 |
6 | ModuleVersion = '2.0'
7 | GUID = 'ef098cb4-f7e9-4763-b636-0cd9799e1c9a'
8 |
9 | Author = 'Microsoft Corporation'
10 | CompanyName = 'Microsoft Corporation'
11 | Copyright = '(c) 2013 Microsoft Corporation. All rights reserved.'
12 |
13 | Description = 'Module to help in reading details from DSC events'
14 |
15 | PowerShellVersion = '4.0'
16 |
17 | CLRVersion = '4.0'
18 |
19 | FunctionsToExport = @("*")
20 |
21 | NestedModules = @('xDscDiagnostics.psm1')
22 | }
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xDscDiagnostics/xDscDiagnosticsFormat.ps1xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Microsoft.PowerShell.xDscDiagnostics.GroupedEvents
7 |
8 | Microsoft.PowerShell.xDscDiagnostics.GroupedEvents
9 |
10 |
11 |
12 |
13 |
14 | 14
15 |
16 |
17 |
18 | 10
19 |
20 |
21 |
22 | 21
23 |
24 |
25 |
26 | 8
27 |
28 |
29 |
30 | 37
31 |
32 |
33 |
34 | 21
35 |
36 |
37 |
38 |
39 |
40 |
41 | ComputerName
42 |
43 |
44 | SequenceId
45 |
46 |
47 | TimeCreated
48 |
49 |
50 | Result
51 |
52 |
53 | JobID
54 |
55 |
56 | AllEvents
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | Microsoft.PowerShell.xDscDiagnostics.TraceOutput
65 |
66 | Microsoft.PowerShell.xDscDiagnostics.TraceOutput
67 |
68 |
69 |
70 |
71 |
72 | 14
73 |
74 |
75 |
76 | 12
77 |
78 |
79 |
80 | 21
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 | ComputerName
91 |
92 |
93 | EventType
94 |
95 |
96 | TimeCreated
97 |
98 |
99 | Message
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xNetworking/DSCResources/MSFT_xDNSServerAddress/MSFT_xDNSServerAddress.psm1:
--------------------------------------------------------------------------------
1 | <#######################################################################################
2 | # xDNSServerAddress : DSC Resource that will set/test/get the current DNS Server
3 | # Address, by accepting values among those given in xDNSServerAddress.schema.mof
4 | #######################################################################################>
5 |
6 |
7 |
8 | ######################################################################################
9 | # The Get-TargetResource cmdlet.
10 | # This function will get the present list of DNS ServerAddress DSC Resource schema variables on the system
11 | ######################################################################################
12 | function Get-TargetResource
13 | {
14 | param
15 | (
16 | [Parameter(Mandatory)]
17 | [ValidateNotNullOrEmpty()]
18 | [String[]]$Address,
19 |
20 | [Parameter(Mandatory)]
21 | [ValidateNotNullOrEmpty()]
22 | [String]$InterfaceAlias,
23 |
24 | [ValidateSet("IPv4", "IPv6")]
25 | [String]$AddressFamily = "IPv4"
26 | )
27 |
28 |
29 | $returnValue = @{
30 | Address = (Get-DnsClientServerAddress -InterfaceAlias $InterfaceAlias -AddressFamily $AddressFamily).ServerAddresses
31 | AddressFamily = $AddressFamily
32 | InterfaceAlias = $InterfaceAlias
33 | }
34 |
35 | $returnValue
36 | }
37 |
38 | ######################################################################################
39 | # The Set-TargetResource cmdlet.
40 | # This function will set a new Server Address in the current node
41 | ######################################################################################
42 | function Set-TargetResource
43 | {
44 | param
45 | (
46 | #IP Address that has to be set
47 | [Parameter(Mandatory)]
48 | [ValidateNotNullOrEmpty()]
49 | [String[]]$Address,
50 |
51 | [Parameter(Mandatory)]
52 | [ValidateNotNullOrEmpty()]
53 | [String]$InterfaceAlias,
54 |
55 | [ValidateSet("IPv4", "IPv6")]
56 | [String]$AddressFamily = "IPv4"
57 | )
58 |
59 | ValidateProperties @PSBoundParameters -Apply
60 | }
61 |
62 | ######################################################################################
63 | # The Test-TargetResource cmdlet.
64 | # This will test if the given Server Address is among the current node's Server Address collection
65 | ######################################################################################
66 | function Test-TargetResource
67 | {
68 | param
69 | (
70 | [Parameter(Mandatory)]
71 | [ValidateNotNullOrEmpty()]
72 | [String[]]$Address,
73 |
74 | [Parameter(Mandatory)]
75 | [ValidateNotNullOrEmpty()]
76 | [String]$InterfaceAlias,
77 |
78 | [ValidateSet("IPv4", "IPv6")]
79 | [String]$AddressFamily = "IPv4"
80 | )
81 |
82 | ValidateProperties @PSBoundParameters
83 | }
84 |
85 |
86 | #######################################################################################
87 | # Helper function that validates the Server Address properties. If the switch parameter
88 | # "Apply" is set, then it will set the properties after a test
89 | #######################################################################################
90 | function ValidateProperties
91 | {
92 | param
93 | (
94 | [Parameter(Mandatory)]
95 | [ValidateNotNullOrEmpty()]
96 | [String[]]$Address,
97 |
98 | [Parameter(Mandatory)]
99 | [ValidateNotNullOrEmpty()]
100 | [String]$InterfaceAlias,
101 |
102 | [ValidateSet("IPv4", "IPv6")]
103 | [String]$AddressFamily,
104 |
105 | [Switch]$Apply
106 | )
107 | $sa =$Address
108 | $sa | %{
109 | if(!([System.Net.Ipaddress]::TryParse($_, [ref]0)))
110 | {
111 | throw "Server Address *$_* is not in the correct format. Please correct the Address in the configuration and try again"
112 | }
113 | if (([System.Net.IPAddress]$_).AddressFamily.ToString() -eq [System.Net.Sockets.AddressFamily]::InterNetwork.ToString())
114 | {
115 | if ($AddressFamily -ne "IPv4")
116 | {
117 | throw "Server address $Address is in IPv4 format, which does not match server address family $AddressFamily. Please correct either of them in the configuration and try again"
118 | }
119 | }
120 | else
121 | {
122 | if ($AddressFamily -ne "IPv6")
123 | {
124 | throw "Server address $Address is in IPv6 format, which does not match server address family $AddressFamily. Please correct either of them in the configuration and try again"
125 | }
126 | }
127 | }
128 | try
129 | {
130 | Write-Verbose -Message "Checking the DNS Server Address ..."
131 | #Get the current IP Address based on the parameters given.
132 | $currentAddress = (Get-DnsClientServerAddress -InterfaceAlias $InterfaceAlias -AddressFamily $AddressFamily -ErrorAction Stop).ServerAddresses
133 |
134 | #Check if the Server addresses are the same as the desired addresses.
135 | if(@(Compare-Object -ReferenceObject $currentAddress -DifferenceObject $Address -SyncWindow 0).Length -gt 0)
136 | {
137 | Write-Verbose -Message "DNS Servers are not correct. Expected $Address, actual $currentAddress"
138 | if($Apply)
139 | {
140 | # Set the DNS settings as well
141 | Set-DnsClientServerAddress -InterfaceAlias $InterfaceAlias -ServerAddresses $Address
142 | Write-Verbose -Message "DNS Servers have been set correctly."
143 | }
144 | else
145 | {
146 | return $false
147 | }
148 | }
149 | else
150 | {
151 | #Test will return true in this case
152 | Write-Verbose -Message "DNS Servers are set correctly."
153 | return $true
154 | }
155 | }
156 | catch
157 | {
158 | Write-Verbose -Message $_
159 | throw "Can not set or find valid DNS Server addresses using InterfaceAlias $InterfaceAlias and AddressFamily $AddressFamily"
160 | }
161 | }
162 |
163 |
164 |
165 | # FUNCTIONS TO BE EXPORTED
166 | Export-ModuleMember -function Get-TargetResource, Set-TargetResource, Test-TargetResource
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xNetworking/DSCResources/MSFT_xDNSServerAddress/MSFT_xDNSServerAddress.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xNetworking/DSCResources/MSFT_xDNSServerAddress/MSFT_xDNSServerAddress.schema.mof
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xNetworking/DSCResources/MSFT_xFirewall/MSFT_xFirewall.Schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xNetworking/DSCResources/MSFT_xFirewall/MSFT_xFirewall.Schema.mof
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xNetworking/DSCResources/MSFT_xIPAddress/MSFT_xIPAddress.psm1:
--------------------------------------------------------------------------------
1 | <#######################################################################################
2 | # MSDSCPack_IPAddress : DSC Resource that will set/test/get the current IP
3 | # Address, by accepting values among those given in MSDSCPack_IPAddress.schema.mof
4 | #######################################################################################>
5 |
6 |
7 |
8 | ######################################################################################
9 | # The Get-TargetResource cmdlet.
10 | # This function will get the present list of IP Address DSC Resource schema variables on the system
11 | ######################################################################################
12 | function Get-TargetResource
13 | {
14 | param
15 | (
16 | [Parameter(Mandatory)]
17 | [ValidateNotNullOrEmpty()]
18 | [String]$IPAddress,
19 |
20 | [Parameter(Mandatory)]
21 | [ValidateNotNullOrEmpty()]
22 | [String]$InterfaceAlias,
23 |
24 | [Int]$SubnetMask = 16,
25 |
26 | [ValidateNotNullOrEmpty()]
27 | [String]$DefaultGateway,
28 |
29 | [ValidateSet("IPv4", "IPv6")]
30 | [String]$AddressFamily = "IPv4"
31 | )
32 |
33 |
34 | $returnValue = @{
35 | IPAddress = [System.String]::Join(", ",(Get-NetIPAddress -InterfaceAlias $InterfaceAlias -AddressFamily $AddressFamily).IPAddress)
36 | SubnetMask = $SubnetMask
37 | DefaultGateway = $DefaultGateway
38 | AddressFamily = $AddressFamily
39 | InterfaceAlias=$InterfaceAlias
40 | }
41 |
42 | $returnValue
43 | }
44 |
45 | ######################################################################################
46 | # The Set-TargetResource cmdlet.
47 | # This function will set a new IP Address in the current node
48 | ######################################################################################
49 | function Set-TargetResource
50 | {
51 | param
52 | (
53 | #IP Address that has to be set
54 | [Parameter(Mandatory)]
55 | [ValidateNotNullOrEmpty()]
56 | [String]$IPAddress,
57 |
58 | [Parameter(Mandatory)]
59 | [ValidateNotNullOrEmpty()]
60 | [String]$InterfaceAlias,
61 |
62 | [Int]$SubnetMask,
63 |
64 | [ValidateNotNullOrEmpty()]
65 | [String]$DefaultGateway,
66 |
67 | [ValidateSet("IPv4", "IPv6")]
68 | [String]$AddressFamily = "IPv4"
69 | )
70 |
71 |
72 | ValidateProperties @PSBoundParameters -Apply
73 | }
74 |
75 | ######################################################################################
76 | # The Test-TargetResource cmdlet.
77 | # This will test if the given IP Address is among the current node's IP Address collection
78 | ######################################################################################
79 | function Test-TargetResource
80 | {
81 | param
82 | (
83 | [Parameter(Mandatory)]
84 | [ValidateNotNullOrEmpty()]
85 | [String]$IPAddress,
86 |
87 | [Parameter(Mandatory)]
88 | [ValidateNotNullOrEmpty()]
89 | [String]$InterfaceAlias,
90 |
91 | [Int]$SubnetMask,
92 |
93 | [ValidateNotNullOrEmpty()]
94 | [String]$DefaultGateway,
95 |
96 | [ValidateSet("IPv4", "IPv6")]
97 | [String]$AddressFamily = "IPv4"
98 | )
99 |
100 | ValidateProperties @PSBoundParameters
101 | }
102 |
103 |
104 | #######################################################################################
105 | # Helper function that validates the IP Address properties. If the switch parameter
106 | # "Apply" is set, then it will set the properties after a test
107 | #######################################################################################
108 | function ValidateProperties
109 | {
110 | param
111 | (
112 | [Parameter(Mandatory)]
113 | [ValidateNotNullOrEmpty()]
114 | [String]$IPAddress,
115 |
116 | [Parameter(Mandatory)]
117 | [ValidateNotNullOrEmpty()]
118 | [String]$InterfaceAlias,
119 |
120 | [ValidateNotNullOrEmpty()]
121 | [String]$DefaultGateway,
122 |
123 | [Int]$SubnetMask = 16,
124 |
125 | [ValidateSet("IPv4", "IPv6")]
126 | [String]$AddressFamily = "IPv4",
127 |
128 | [Switch]$Apply
129 | )
130 | $ip=$IPAddress
131 | if(!([System.Net.Ipaddress]::TryParse($ip, [ref]0)))
132 | {
133 | throw "IP Address *$IPAddress* is not in the correct format. Please correct the ipaddress in the configuration and try again"
134 | }
135 | try
136 | {
137 | Write-Verbose -Message "Checking the IPAddress ..."
138 | #Get the current IP Address based on the parameters given.
139 | $currentIP = Get-NetIPAddress -InterfaceAlias $InterfaceAlias -AddressFamily $AddressFamily -ErrorAction Stop
140 |
141 | #Test if the IP Address passed is equal to the current ip address
142 | if(!$currentIP.IPAddress.Contains($IPAddress))
143 | {
144 | Write-Verbose -Message "IPAddress not correct. Expected $IPAddress, actual $($currentIP.IPAddress)"
145 | $Parameters = @{}
146 |
147 | #Apply is true in the case of set - target resource - in which case, it will set the new IP Address
148 | if($Apply)
149 | {
150 | Write-Verbose -Message "Setting IPAddress ..."
151 | $Parameters["IPAddress"] = $IPAddress
152 | $Parameters["PrefixLength"] = $SubnetMask
153 | $Parameters["InterfaceAlias"] = $currentIP[0].InterfaceAlias
154 |
155 | if($DefaultGateway){ $Parameters["DefaultGateWay"] = $DefaultGateway }
156 | $null = New-NetIPAddress @Parameters -ErrorAction Stop
157 |
158 | # Make the connection profile private
159 | Get-NetConnectionProfile -InterfaceAlias $InterfaceAlias | Set-NetConnectionProfile -NetworkCategory Private -ErrorAction SilentlyContinue
160 | Write-Verbose -Message "IPAddress is set to $IPAddress."
161 | }
162 | else {return $false}
163 | }
164 | else
165 | {
166 | Write-Verbose -Message "IPAddress is correct."
167 | return $true
168 | }
169 | }
170 | catch
171 | {
172 | Write-Verbose -Message $_
173 | throw "Can not set or find valid IPAddress using InterfaceAlias $InterfaceAlias and AddressFamily $AddressFamily"
174 | }
175 | }
176 |
177 |
178 |
179 | # FUNCTIONS TO BE EXPORTED
180 | Export-ModuleMember -function Get-TargetResource, Set-TargetResource, Test-TargetResource
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xNetworking/DSCResources/MSFT_xIPAddress/MSFT_xIPAddress.schema.mof:
--------------------------------------------------------------------------------
1 | [ClassVersion("1.0.0"), FriendlyName("xIPAddress")]
2 | class MSFT_xIPAddress : OMI_BaseResource
3 | {
4 | [Key] string IPAddress;
5 | [Key] string InterfaceAlias;
6 | [write] string DefaultGateway;
7 | [Write] uint32 SubnetMask;
8 | [Write,ValueMap{"IPv4", "IPv6"},Values{"IPv4", "IPv6"}] string AddressFamily;
9 | };
10 |
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xNetworking/Examples/Sample_xDnsServerAddress.ps1:
--------------------------------------------------------------------------------
1 | configuration Sample_xDnsServerAddress
2 | {
3 | param
4 | (
5 | [string[]]$NodeName = 'localhost',
6 |
7 | [Parameter(Mandatory)]
8 | [string]$DnsServerAddress,
9 |
10 | [Parameter(Mandatory)]
11 | [string]$InterfaceAlias,
12 |
13 | [ValidateSet("IPv4","IPv6")]
14 | [string]$AddressFamily = 'IPv4'
15 | )
16 |
17 | Import-DscResource -Module xNetworking
18 |
19 | Node $NodeName
20 | {
21 | xDnsServerAddress DnsServerAddress
22 | {
23 | Address = $DnsServerAddress
24 | InterfaceAlias = $InterfaceAlias
25 | AddressFamily = $AddressFamily
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xNetworking/Examples/Sample_xFirewall_AddFirewallRule.ps1:
--------------------------------------------------------------------------------
1 | # DSC configuration for Firewall
2 |
3 | configuration Sample_xFirewall_AddFirewallRule
4 | {
5 | param
6 | (
7 | [string[]]$NodeName = 'localhost'
8 | )
9 |
10 | Import-DSCResource -ModuleName xNetworking
11 |
12 | Node $NodeName
13 | {
14 | xFirewall Firewall
15 | {
16 | Name = "NotePadFirewallRule"
17 | DisplayName = "Firewall Rule for Notepad.exe"
18 | DisplayGroup = "NotePad Firewall Rule Group"
19 | Ensure = "Present"
20 | Access = "Allow"
21 | State = "Enabled"
22 | Profile = ("Domain", "Private")
23 | Direction = "OutBound"
24 | RemotePort = ("8080", "8081")
25 | LocalPort = ("9080", "9081")
26 | Protocol = "TCP"
27 | Description = "Firewall Rule for Notepad.exe"
28 | ApplicationPath = "c:\windows\system32\notepad.exe"
29 | Service = "WinRM"
30 | }
31 | }
32 | }
33 |
34 | Sample_xFirewall_AddFirewallRule
35 | Start-DscConfiguration -Path Sample_xFirewall_AddFirewallRule -Wait -Verbose -Force
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xNetworking/Examples/Sample_xFirewall_AddFirewallRuleToExistingGroup.ps1:
--------------------------------------------------------------------------------
1 | # DSC configuration for Firewall
2 | #
3 |
4 | configuration Sample_xFirewall_AddFirewallRuleToExistingGroup
5 | {
6 | param
7 | (
8 | [string[]]$NodeName = 'localhost'
9 | )
10 |
11 | Import-DSCResource -ModuleName xNetworking
12 |
13 | Node $NodeName
14 | {
15 | xFirewall Firewall
16 | {
17 | Name = "MyFirewallRule"
18 | DisplayName = "My Firewall Rule"
19 | DisplayGroup = "My Firewall Rule Group"
20 | Access = "Allow"
21 | }
22 |
23 | xFirewall Firewall1
24 | {
25 | Name = "MyFirewallRule1"
26 | DisplayName = "My Firewall Rule"
27 | DisplayGroup = "My Firewall Rule Group"
28 | Ensure = "Present"
29 | Access = "Allow"
30 | State = "Enabled"
31 | Profile = ("Domain", "Private")
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xNetworking/Examples/Sample_xFirewall_AddFirewallRuleToNewGroup.ps1:
--------------------------------------------------------------------------------
1 | # DSC configuration for Firewall
2 |
3 | configuration Sample_xFirewall_AddFirewallRuleToNewGroup
4 | {
5 | param
6 | (
7 | [string[]]$NodeName = 'localhost'
8 | )
9 |
10 | Import-DSCResource -ModuleName xNetworking
11 |
12 | Node $NodeName
13 | {
14 | xFirewall Firewall
15 | {
16 | Name = "MyAppFirewallRule"
17 | ApplicationPath = "c:\windows\system32\MyApp.exe"
18 | Access = "Allow"
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xNetworking/Examples/Sample_xFirewall_DisableAccessToApplication.ps1:
--------------------------------------------------------------------------------
1 | # DSC configuration for Firewall
2 | #
3 |
4 | configuration Sample_xFirewall_AddFirewallRuleToNewGroup
5 | {
6 | param
7 | (
8 | [string[]]$NodeName = 'localhost'
9 | )
10 |
11 | Import-DSCResource -ModuleName xNetworking
12 |
13 | Node $NodeName
14 | {
15 | xFirewall Firewall
16 | {
17 | Name = "NotePadFirewallRule"
18 | DisplayName = "Firewall Rule for Notepad.exe"
19 | DisplayGroup = "NotePad Firewall Rule Group"
20 | Ensure = "Present"
21 | Access = "Block"
22 | Description = "Firewall Rule for Notepad.exe"
23 | ApplicationPath = "c:\windows\system32\notepad.exe"
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xNetworking/Examples/Sample_xIPAddress_FixedValue.ps1:
--------------------------------------------------------------------------------
1 | configuration Sample_xIPAddress_FixedValue
2 | {
3 | param
4 | (
5 | [string[]]$NodeName = 'localhost'
6 | )
7 |
8 | Import-DscResource -Module xNetworking
9 |
10 | Node $NodeName
11 | {
12 | xIPAddress NewIPAddress
13 | {
14 | IPAddress = "2001:4898:200:7:6c71:a102:ebd8:f482"
15 | InterfaceAlias = "Ethernet"
16 | SubnetMask = 24
17 | AddressFamily = "IPV6"
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xNetworking/Examples/Sample_xIPAddress_Parameterized.ps1:
--------------------------------------------------------------------------------
1 | configuration Sample_xIPAddress_Parameterized
2 | {
3 | param
4 | (
5 |
6 | [string[]]$NodeName = 'localhost',
7 |
8 | [Parameter(Mandatory)]
9 | [string]$IPAddress,
10 |
11 | [Parameter(Mandatory)]
12 | [string]$InterfaceAlias,
13 |
14 | [Parameter(Mandatory)]
15 | [string]$DefaultGateway,
16 |
17 | [int]$SubnetMask = 16,
18 |
19 | [ValidateSet("IPv4","IPv6")]
20 | [string]$AddressFamily = 'IPv4'
21 | )
22 |
23 | Import-DscResource -Module xNetworking
24 |
25 | Node $NodeName
26 | {
27 | xIPAddress NewIPAddress
28 | {
29 | IPAddress = $IPAddress
30 | InterfaceAlias = $InterfaceAlias
31 | DefaultGateway = $DefaultGateway
32 | SubnetMask = $SubnetMask
33 | AddressFamily = $AddressFamily
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xNetworking/xNetworking.psd1:
--------------------------------------------------------------------------------
1 | @{
2 | # Version number of this module.
3 | ModuleVersion = '2.1.1'
4 |
5 | # ID used to uniquely identify this module
6 | GUID = 'e6647cc3-ce9c-4c86-9eb8-2ee8919bf358'
7 |
8 | # Author of this module
9 | Author = 'Microsoft Corporation'
10 |
11 | # Company or vendor of this module
12 | CompanyName = 'Microsoft Corporation'
13 |
14 | # Copyright statement for this module
15 | Copyright = '(c) 2013 Microsoft Corporation. All rights reserved.'
16 |
17 | # Description of the functionality provided by this module
18 | Description = 'Module with DSC Resources for Networking area'
19 |
20 | # Minimum version of the Windows PowerShell engine required by this module
21 | PowerShellVersion = '4.0'
22 |
23 | # Minimum version of the common language runtime (CLR) required by this module
24 | CLRVersion = '4.0'
25 |
26 | # Functions to export from this module
27 | FunctionsToExport = '*'
28 |
29 | # Cmdlets to export from this module
30 | CmdletsToExport = '*'
31 | }
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xPendingReboot/DSCResources/MSFT_xPendingReboot/MSFT_xPendingReboot.psm1:
--------------------------------------------------------------------------------
1 | Function Get-TargetResource
2 | {
3 | [CmdletBinding()]
4 | param
5 | (
6 | [Parameter(Mandatory=$true)]
7 | [string]$Name
8 | )
9 |
10 | <## Remove:
11 | $ComponentBasedServicing = (Get-ItemProperty 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\').RebootPending -ne $null
12 | Remove - $WindowsUpdate = (Get-ItemProperty 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\').RebootRequired -ne $null
13 | Remove - $PendingFileRename = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\').PendingFileRenameOperations -ne $null
14 | #>
15 |
16 | ## Brian's additions:--------------------------------------------------
17 | $ComponentBasedServicing = (Get-ChildItem 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\').Name.Split("\") -contains "RebootPending"
18 | $WindowsUpdate = (Get-ChildItem 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\').Name.Split("\") -contains "RebootRequired"
19 | $PendingFileRename = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\').PendingFileRenameOperations.Length -gt 0
20 | $ActiveComputerName = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName').ComputerName
21 | $PendingComputerName = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName').ComputerName
22 | $PendingComputerRename = $ActiveComputerName -ne $PendingComputerName
23 |
24 | $CCMSplat = @{
25 | NameSpace='ROOT\ccm\ClientSDK'
26 | Class='CCM_ClientUtilities'
27 | Name='DetermineIfRebootPending'
28 | ErrorAction='Stop'
29 | }
30 |
31 | Try {
32 | $CCMClientSDK = Invoke-WmiMethod @CCMSplat
33 | } Catch {
34 | Write-Warning "Unable to query CCM_ClientUtilities: $_"
35 | }
36 |
37 | $SCCMSDK = ($CCMClientSDK.ReturnValue -eq 0) -and ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending)
38 | ## End Brian's additions------------------------------------------------
39 |
40 | return @{
41 | Name = $Name
42 | ComponentBasedServicing = $ComponentBasedServicing
43 | WindowsUpdate = $WindowsUpdate
44 | PendingFileRename = $PendingFileRename
45 | PendingComputerRename = $PendingComputerRename
46 | CcmClientSDK = $SCCMSDK
47 | }
48 | }
49 |
50 | Function Set-TargetResource
51 | {
52 | [CmdletBinding()]
53 | param
54 | (
55 | [Parameter(Mandatory=$true)]
56 | [string]$Name
57 | )
58 |
59 | $global:DSCMachineStatus = 1
60 | }
61 |
62 | Function Test-TargetResource
63 | {
64 | [CmdletBinding()]
65 | param
66 | (
67 | [Parameter(Mandatory=$true)]
68 | [string]$Name
69 | )
70 |
71 | <## Remove
72 | $regRebootLocations += @{'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\'='RebootPending'}
73 | $regRebootLocations += @{'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\'='RebootRequired'}
74 | $regRebootLocations += @{'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\'='PendingFileRenameOperations'}
75 |
76 | foreach ($reg in $regRebootLocations.keys) {
77 | if ((Get-ItemProperty $reg).($regRebootLocations[$reg]) -ne $Null) {
78 | Write-Verbose "A pending reboot was found at $reg."
79 | Write-Verbose 'Setting the DSCMachineStatus global variable to 1.'
80 | return $false}
81 | }
82 | #>
83 |
84 | ## Brian's additions:--------------------------------------------------
85 | $ScriptBlocks += @{ComponentBasedServicing = {(Get-ChildItem 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\').Name.Split("\") -contains "RebootPending"}}
86 | $ScriptBlocks += @{WindowsUpdate = {(Get-ChildItem 'hklm:SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\').Name.Split("\") -contains "RebootRequired"}}
87 | $ScriptBlocks += @{PendingFileRename = {(Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\Session Manager\').PendingFileRenameOperations.Length -gt 0}}
88 | $ScriptBlocks += @{PendingComputerRename = {
89 | $ActiveComputerName = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName').ComputerName
90 | $PendingComputerName = (Get-ItemProperty 'hklm:\SYSTEM\CurrentControlSet\Control\ComputerName\ComputerName').ComputerName
91 | $ActiveComputerName -ne $PendingComputerName
92 | }
93 | }
94 | $ScriptBlocks += @{CcmClientSDK = {
95 | $CCMSplat = @{
96 | NameSpace='ROOT\ccm\ClientSDK'
97 | Class='CCM_ClientUtilities'
98 | Name='DetermineIfRebootPending'
99 | ErrorAction='Stop'
100 | }
101 | Try {
102 | $CCMClientSDK = Invoke-WmiMethod @CCMSplat
103 | ($CCMClientSDK.ReturnValue -eq 0) -and ($CCMClientSDK.IsHardRebootPending -or $CCMClientSDK.RebootPending)
104 | } Catch {
105 | Write-Warning "Unable to query CCM_ClientUtilities: $_"
106 | }
107 | }
108 | }
109 | Foreach ($Script in $ScriptBlocks.Keys) {
110 | If (Invoke-Command $ScriptBlocks[$Script]) {
111 | Write-Verbose "A pending reboot was found for $Script."
112 | Write-Verbose 'Setting the DSCMachineStatus global variable to 1.'
113 | return $false
114 | }
115 | }
116 | ## End Brian's additions------------------------------------------------
117 |
118 | Write-Verbose 'No pending reboots found.'
119 | return $true
120 | }
121 |
122 | Export-ModuleMember -Function *-TargetResource
123 |
124 | $regRebootLocations = $null
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xPendingReboot/DSCResources/MSFT_xPendingReboot/MSFT_xPendingReboot.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xPendingReboot/DSCResources/MSFT_xPendingReboot/MSFT_xPendingReboot.schema.mof
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xPendingReboot/xPendingReboot.psd1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xPendingReboot/xPendingReboot.psd1
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/MSFT_xIisModule.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/MSFT_xIisModule.psm1
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/MSFT_xIisModule.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/MSFT_xIisModule.schema.mof
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xIisModule/xIisModuleDesigner.ps1:
--------------------------------------------------------------------------------
1 | $diff = join-Path ${env:ProgramFiles(x86)} "Beyond compare 2\bc2.exe"
2 | $friendlyName = "xIisModule"
3 | $resourceName = "MSFT_$friendlyName"
4 | $classVersion = "1.0.0"
5 |
6 | $scriptRoot = Split-Path $MyInvocation.MyCommand.Path
7 | $originalModuleRoot = join-Path $scriptroot "..\.."
8 | $originalModuleRootPath = Resolve-Path $originalModuleRoot
9 | $moduleRoot = Join-Path $env:temp "$($originalModuleRootPath.path | split-path -Leaf)Temp"
10 |
11 | $resources = @()
12 | $schemaPath = (join-path $scriptRoot "$resourceName.schema.mof")
13 |
14 | #Key properties
15 | $resources += New-xDscResourceProperty -Name Path -Type String -Attribute Key -Description "The path to the module, usually a dll, to be added to IIS."
16 |
17 |
18 | #Required Properites
19 | $resources += New-xDscResourceProperty -Name Name -Type String -Attribute Required -Description "The logical name of the module to add to IIS."
20 | $resources += New-xDscResourceProperty -Name RequestPath -Type String -Attribute Required -Description "The allowed request Path example: *.php"
21 | $resources += New-xDscResourceProperty -Name Verb -Type String[] -Attribute Required -Description "The supported verbs for the module."
22 |
23 | #Write Properties
24 | $resources += New-xDscResourceProperty -Name SiteName -Type String -Attribute Write -Description "The IIS Site to register the module."
25 | $resources += New-xDscResourceProperty -Name Ensure -Type String -Attribute Write -Description "Should the module be present or absent." -ValidateSet @("Present","Absent")
26 | $resources += New-xDscResourceProperty -Name ModuleType -Type String -Attribute Write -Description "The type of the module." -ValidateSet @("FastCgiModule")
27 |
28 | #Read Properties
29 | $resources += New-xDscResourceProperty -Name EndPointSetup -Type Boolean -Attribute Read -Description "The End Point is setup. Such as a Fast Cgi endpoint."
30 |
31 |
32 |
33 | Write-Host updating...
34 |
35 | # Create a New template resource to a temporary folder
36 | New-xDscResource -Property $resources -ClassVersion $classVersion -Name $resourceName -Path $moduleRoot -FriendlyName $friendlyName
37 |
38 |
39 | # Use your favorite diff program to compare and merge the current resource and the existing resource
40 |
41 | if((test-Path $diff))
42 | {
43 | &$diff $originalModuleRoot $moduleRoot
44 | }
45 | else
46 | {
47 | Write-Warning "Diff propgram not found!`r`nUse your favorite diff program to compare and merge:`r`n `t$($originalModuleRootPath.path)`r`n and:`r`n `t$moduleRoot"
48 | }
49 |
50 |
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.psm1
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebAppPool/MSFT_xWebAppPool.schema.mof
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.psm1
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebApplication/MSFT_xWebApplication.schema.mof
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.psm1
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebConfigKeyValue/MSFT_xWebConfigKeyValue.schema.mof
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.psm1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.psm1
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebVirtualDirectory/MSFT_xWebVirtualDirectory.schema.mof
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xWebAdministration/DSCResources/MSFT_xWebsite/MSFT_xWebsite.schema.mof
--------------------------------------------------------------------------------
/Exercise5/PowerShellModules/xWebAdministration/xWebAdministration.psd1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andrewabest/AWS-Workshop/071e4b7912e2704a366be0a6294d4d3d1da95a4d/Exercise5/PowerShellModules/xWebAdministration/xWebAdministration.psd1
--------------------------------------------------------------------------------
/Exercise5/Scripts/ConfigureWebserver.ps1:
--------------------------------------------------------------------------------
1 | # TODO: Dot-source our variables.ps1
2 |
3 | Configuration ConfigureWebserver
4 | {
5 | Import-DscResource -ModuleName cWinServer
6 | Import-DscResource -ModuleName xWebAdministration
7 | Import-DscResource -ModuleName xPendingReboot
8 | Import-DscResource -ModuleName xNetworking
9 |
10 | # Localhost targets the node this script is run on
11 | Node 'localhost'
12 | {
13 | LocalConfigurationManager
14 | {
15 | RebootNodeIfNeeded = $True
16 | }
17 |
18 | WinServerOptions ServerOptions
19 | {
20 | Ensure = "Present"
21 | Name = "Set timezone and culture"
22 | Culture = "en-AU"
23 | TimeZone = "AUS Eastern Standard Time"
24 | }
25 |
26 | xPendingReboot AfterServerOptions
27 | {
28 | Name = "AfterServerOptions"
29 | DependsOn = '[WinServerOptions]ServerOptions'
30 | }
31 |
32 | $windowsFeatures = @(
33 | "Web-App-Dev",
34 | "Web-Common-Http",
35 | "Web-Health",
36 | "Web-Performance",
37 | "Web-Security",
38 | "Web-Scripting-Tools",
39 | "Web-Mgmt-Service",
40 | "Web-Mgmt-Console"
41 | )
42 |
43 | $windowsFeatureDependOn = @();
44 |
45 | foreach ($windowsFeature in $windowsFeatures)
46 | {
47 | WindowsFeature "IIS_$windowsFeature"
48 | {
49 | Ensure = "Present"
50 | Name = $windowsFeature
51 | IncludeAllSubFeature = $true
52 | DependsOn = "[xPendingReboot]AfterServerOptions"
53 | }
54 |
55 | $windowsFeatureDependOn += "[WindowsFeature]IIS_$windowsFeature"
56 | }
57 |
58 | <#
59 | NOTE: For new players, if you want to discover whether a reboot will be required after a given piece of DSC, search for "$global:DSCMachineStatus = 1" in the resources you have used.
60 | #>
61 |
62 | xPendingReboot RebootAfterWindowsFeatures
63 | {
64 | Name = 'AfterWindowsFeatures'
65 | DependsOn = $windowsFeatureDependOn
66 | }
67 |
68 | # Stop & Remove the default website
69 | xWebsite DefaultSite
70 | {
71 | Ensure = "Absent"
72 | Name = "Default Web Site"
73 | State = "Stopped"
74 | PhysicalPath = "C:\inetpub\wwwroot"
75 | DependsOn = $windowsFeatureDependOn
76 | }
77 |
78 | # Remove all default Application Pools EXCEPT DEFAULT (will use this for the load balancer health check)
79 | foreach ($appPool in @("Classic .NET AppPool", ".NET v2.0",
80 | ".NET v2.0 Classic", ".NET v4.5", ".NET v4.5 Classic"))
81 | {
82 | xWebAppPool $appPool
83 | {
84 | Ensure = "Absent"
85 | Name = $appPool
86 | DependsOn = ($windowsFeatureDependOn + @("[xWebsite]DefaultSite"))
87 | }
88 | }
89 |
90 | File LoadBalancerHealthCheckEndpointContent
91 | {
92 | Ensure = "Present"
93 | DestinationPath = "C:\inetpub\wwwroot\index.html"
94 | Contents = "Hello, is it me you're looking for?"
95 | Type = "File"
96 | }
97 |
98 | xWebsite LoadBalancerHealthCheckEndpoint
99 | {
100 | Ensure = "Present"
101 | Name = "LoadBalancerHealthCheck"
102 | State = "Started"
103 | PhysicalPath = "C:\inetpub\wwwroot"
104 | BindingInfo = MSFT_xWebBindingInformation
105 | {
106 | Protocol = "HTTP"
107 | Port = 81
108 | }
109 | DependsOn = "[File]LoadBalancerHealthCheckEndpointContent"
110 | }
111 |
112 | xFirewall Firewall
113 | {
114 | Name = "Web"
115 | DisplayName = "Inbound access for web requests"
116 | Ensure = "Present"
117 | Access = "Allow"
118 | State = "Enabled"
119 | Profile = ("Domain", "Private", "Public")
120 | Direction = "InBound"
121 | RemotePort = ("Any")
122 | LocalPort = ("80", "81", "443")
123 | Protocol = "TCP"
124 | Description = "Inbound access for web requests"
125 | }
126 |
127 | # TODO: Add cTentacleAgent resource
128 | }
129 | }
130 |
131 | ConfigureWebserver
132 |
133 | Set-DscLocalConfigurationManager -Path .\ConfigureWebserver -Verbose
134 | Start-DscConfiguration -Path .\ConfigureWebserver -Verbose -Wait -Force
135 |
--------------------------------------------------------------------------------
/Exercise5/Scripts/ConfigureWebserver.ps1.answer:
--------------------------------------------------------------------------------
1 | # We don't get executed from our own directory so we need to find out where our scripts have
2 | # been dropped and execute everything from there.
3 | $scriptPath = [System.IO.Path]::GetDirectoryName($PSScriptRoot)
4 | Write-Host "Executing scripts from $scriptPath"
5 |
6 | . $scriptPath\Scripts\Variables.ps1
7 |
8 | Configuration ConfigureWebserver
9 | {
10 | Import-DscResource -ModuleName cWinServer
11 | Import-DscResource -ModuleName cOctopus
12 | Import-DscResource -ModuleName xWebAdministration
13 | Import-DscResource -ModuleName xPendingReboot
14 | Import-DscResource -ModuleName xNetworking
15 |
16 | # Localhost targets the node this script is run on
17 | Node 'localhost'
18 | {
19 | LocalConfigurationManager
20 | {
21 | RebootNodeIfNeeded = $True
22 | }
23 |
24 | WinServerOptions ServerOptions
25 | {
26 | Ensure = "Present"
27 | Name = "Set timezone and culture"
28 | Culture = "en-AU"
29 | TimeZone = "AUS Eastern Standard Time"
30 | }
31 |
32 | xPendingReboot AfterServerOptions
33 | {
34 | Name = "AfterServerOptions"
35 | DependsOn = '[WinServerOptions]ServerOptions'
36 | }
37 |
38 | $windowsFeatures = @(
39 | "Web-App-Dev",
40 | "Web-Common-Http",
41 | "Web-Health",
42 | "Web-Performance",
43 | "Web-Security",
44 | "Web-Scripting-Tools",
45 | "Web-Mgmt-Service",
46 | "Web-Mgmt-Console"
47 | )
48 |
49 | $windowsFeatureDependOn = @();
50 |
51 | foreach ($windowsFeature in $windowsFeatures)
52 | {
53 | WindowsFeature "IIS_$windowsFeature"
54 | {
55 | Ensure = "Present"
56 | Name = $windowsFeature
57 | IncludeAllSubFeature = $true
58 | DependsOn = "[xPendingReboot]AfterServerOptions"
59 | }
60 |
61 | $windowsFeatureDependOn += "[WindowsFeature]IIS_$windowsFeature"
62 | }
63 |
64 | <#
65 | NOTE: For new players, if you want to discover whether a reboot will be required after a given piece of DSC, search for "$global:DSCMachineStatus = 1" in the resources you have used.
66 | #>
67 |
68 | xPendingReboot RebootAfterWindowsFeatures
69 | {
70 | Name = 'AfterWindowsFeatures'
71 | DependsOn = $windowsFeatureDependOn
72 | }
73 |
74 | # Stop & Remove the default website
75 | xWebsite DefaultSite
76 | {
77 | Ensure = "Absent"
78 | Name = "Default Web Site"
79 | State = "Stopped"
80 | PhysicalPath = "C:\inetpub\wwwroot"
81 | DependsOn = $windowsFeatureDependOn
82 | }
83 |
84 | # Remove all default Application Pools EXCEPT DEFAULT (will use this for the load balancer health check)
85 | foreach ($appPool in @("Classic .NET AppPool", ".NET v2.0",
86 | ".NET v2.0 Classic", ".NET v4.5", ".NET v4.5 Classic"))
87 | {
88 | xWebAppPool $appPool
89 | {
90 | Ensure = "Absent"
91 | Name = $appPool
92 | DependsOn = ($windowsFeatureDependOn + @("[xWebsite]DefaultSite"))
93 | }
94 | }
95 |
96 | File LoadBalancerHealthCheckEndpointContent
97 | {
98 | Ensure = "Present"
99 | DestinationPath = "C:\inetpub\wwwroot\index.html"
100 | Contents = "Hello, is it me you're looking for?"
101 | Type = "File"
102 | }
103 |
104 | xWebsite LoadBalancerHealthCheckEndpoint
105 | {
106 | Ensure = "Present"
107 | Name = "LoadBalancerHealthCheck"
108 | State = "Started"
109 | PhysicalPath = "C:\inetpub\wwwroot"
110 | BindingInfo = MSFT_xWebBindingInformation
111 | {
112 | Protocol = "HTTP"
113 | Port = 81
114 | }
115 | DependsOn = "[File]LoadBalancerHealthCheckEndpointContent"
116 | }
117 |
118 | xFirewall Firewall
119 | {
120 | Name = "Web"
121 | DisplayName = "Inbound access for web requests"
122 | Ensure = "Present"
123 | Access = "Allow"
124 | State = "Enabled"
125 | Profile = ("Domain", "Private", "Public")
126 | Direction = "InBound"
127 | RemotePort = ("Any")
128 | LocalPort = ("80", "81", "443")
129 | Protocol = "TCP"
130 | Description = "Inbound access for web requests"
131 | }
132 |
133 | cTentacleAgent OctopusTentacle
134 | {
135 | Ensure = "Present"
136 | State = "Started"
137 | Name = "Tentacle"
138 |
139 | # Registration - all parameters required
140 | ApiKey = $BootstrapParameters['OctopusApiKey']
141 | OctopusServerUrl = $BootstrapParameters['OctopusServerUrl']
142 | Environments = $BootstrapParameters['Environment']
143 | Roles = $BootstrapParameters['OctopusRole']
144 |
145 | # Optional settings
146 | ListenPort = 10933;
147 | DefaultApplicationDirectory = "C:\Octopus\Applications"
148 | DependsOn = "[xWebsite]LoadBalancerHealthCheckEndpoint"
149 | }
150 | }
151 | }
152 |
153 | ConfigureWebserver
154 |
155 | Set-DscLocalConfigurationManager -Path .\ConfigureWebserver -Verbose
156 | Start-DscConfiguration -Path .\ConfigureWebserver -Verbose -Wait -Force
157 |
--------------------------------------------------------------------------------
/Exercise5/Scripts/Teardown.ps1:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/Exercise5/Templates/Zephyr.template:
--------------------------------------------------------------------------------
1 | {
2 | "AWSTemplateFormatVersion": "2010-09-09",
3 |
4 | "Description": "A template to deploy a simple fault tolerant load balanced web hosting infrastructure.",
5 |
6 | "Parameters": {
7 | "S3BucketName": {
8 | "Description": "The S3 Bucket Name used in URL's to specify authentication against.",
9 | "Type": "String"
10 | },
11 | "VpcId": {
12 | "Description": "The Vpc to deploy the infrastructure into.",
13 | "Type": "String"
14 | },
15 | "PowerShellModulesBundleUrl": {
16 | "Description": "The URL to a ZIP file containing any PowerShell modules required by this CloudFormation template.",
17 | "Type": "String"
18 | },
19 | "BootstrapperScriptBundleUrl": {
20 | "Description": "The URL to a ZIP file containing the PowerShell script package to bootstrap EC2 instances in this CloudFormation template.",
21 | "Type": "String"
22 | },
23 | "WebserverTemplateUrl": {
24 | "Description": "The URL to the CloudFormation stack template for web servers.",
25 | "Type": "String"
26 | },
27 | "Timestamp": {
28 | "Description": "When this CloudFormation stack was last updated.",
29 | "Type": "String"
30 | },
31 | "Version": {
32 | "Description": "The package version that contains this CloudFormation template.",
33 | "Type": "String"
34 | },
35 | "Environment": {
36 | "Type": "String",
37 | "Default": "Development"
38 | },
39 | "KeyPairName": {
40 | "Description": "The EC2 key pair used to launch web instances",
41 | "Type": "AWS::EC2::KeyPair::KeyName"
42 | },
43 | "WebserverImageId": {
44 | "Description": "The EC2 AmiId to use for web",
45 | "Type": "String",
46 | "Default": "ami-f9760dc3"
47 | },
48 | "WebserverInstanceType": {
49 | "Description": "The EC2 instance type to use for web",
50 | "Type": "String",
51 | "Default": "t2.small"
52 | },
53 | "WebserverSubnetIdAzOne": {
54 | "Description": "The PUBLIC subnet belonging to availability zone one into which the instance will be launched",
55 | "Type": "String"
56 | },
57 | "WebserverSubnetIdAzTwo": {
58 | "Description": "The PUBLIC subnet belonging to availability zone two into which the instance will be launched",
59 | "Type": "String"
60 | },
61 | "LoadBalancerSubnetIdAzOne": {
62 | "Description": "The PUBLIC IG-connected subnet belonging to availability zone one that the load balancer will belong to",
63 | "Type": "String"
64 | },
65 | "LoadBalancerSubnetIdAzTwo": {
66 | "Description": "The PUBLIC IG-connected subnet belonging to availability zone two that the load balancer will belong to",
67 | "Type": "String"
68 | },
69 | "ResourcePrefix" : {
70 | "Description": "Used to prefix a unique name to resources where applicable",
71 | "Type": "String"
72 | }
73 | },
74 |
75 | "Resources": {
76 | "BootstrapRole": {
77 | "Type": "AWS::IAM::Role",
78 | "Properties": {
79 | "AssumeRolePolicyDocument": {
80 | "Version": "2012-10-17",
81 | "Statement": [
82 | {
83 | "Effect": "Allow",
84 | "Principal": {
85 | "Service": [ "ec2.amazonaws.com" ]
86 | },
87 | "Action": [ "sts:AssumeRole" ]
88 | }
89 | ]
90 | },
91 | "Path": "/"
92 | }
93 | },
94 | "BootstrapRolePolicies": {
95 | "Type": "AWS::IAM::Policy",
96 | "Properties": {
97 | "PolicyName": "bootstrap",
98 | "PolicyDocument": {
99 | "Version": "2012-10-17",
100 | "Statement": [
101 | {
102 | "Effect": "Allow",
103 | "Action": "s3:*",
104 | "Resource": [
105 | { "Fn::Join": [ "", [ "arn:aws:s3:::", { "Ref": "S3BucketName" } ] ] },
106 | { "Fn::Join": [ "", [ "arn:aws:s3:::", { "Ref": "S3BucketName" }, "/*" ] ] }
107 | ]
108 | }
109 | ]
110 | },
111 | "Roles": [
112 | {
113 | "Ref": "BootstrapRole"
114 | }
115 | ]
116 | }
117 | },
118 | "BootstrapInstanceProfile": {
119 | "Type": "AWS::IAM::InstanceProfile",
120 | "Properties": {
121 | "Path": "/",
122 | "Roles": [
123 | {
124 | "Ref": "BootstrapRole"
125 | }
126 | ]
127 | }
128 | },
129 | "WebStack": {
130 | "Type": "AWS::CloudFormation::Stack",
131 | "Properties": {
132 | "Parameters": {
133 | "S3BucketName": { "Ref": "S3BucketName" },
134 | "VpcId": { "Ref": "VpcId" },
135 | "PowerShellModulesBundleUrl": { "Ref": "PowerShellModulesBundleUrl" },
136 | "BootstrapperScriptBundleUrl": { "Ref": "BootstrapperScriptBundleUrl" },
137 | "Timestamp": { "Ref": "Timestamp" },
138 | "Version": { "Ref": "Version" },
139 | "Environment": { "Ref": "Environment" },
140 | "InstanceProfile": { "Ref": "BootstrapInstanceProfile" },
141 | "BootstrapperRole": { "Ref": "BootstrapRole" },
142 | "KeyPairName": { "Ref": "KeyPairName" },
143 | "WebserverImageId": { "Ref": "WebserverImageId" },
144 | "WebserverInstanceType": { "Ref": "WebserverInstanceType" },
145 | "WebserverSubnetIdAzOne": { "Ref": "WebserverSubnetIdAzOne" },
146 | "WebserverSubnetIdAzTwo": { "Ref": "WebserverSubnetIdAzTwo" },
147 | "LoadBalancerSubnetIdAzOne": { "Ref": "LoadBalancerSubnetIdAzOne" },
148 | "LoadBalancerSubnetIdAzTwo": { "Ref": "LoadBalancerSubnetIdAzTwo" },
149 | "ResourcePrefix": { "Ref": "ResourcePrefix" }
150 | },
151 | "TemplateURL": { "Ref": "WebserverTemplateUrl" },
152 | "TimeoutInMinutes": 10
153 | }
154 | }
155 | },
156 |
157 | "Outputs": {
158 | "LoadBalancerUri": {
159 | "Value": { "Fn::GetAtt": [ "WebStack", "Outputs.LoadBalancerUri" ] }
160 | }
161 | }
162 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # AWS-Workshop
2 | Workshop content for automated delivery in AWS for .NET
3 |
4 | ## Prerequisites
5 |
6 | You will need to have installed [The AWS.NET SDK](https://aws.amazon.com/sdk-for-net/). You could optionally install The [AWS VS Tooling](http://aws.amazon.com/visualstudio/) instead which includes the SDK, and also gives you intellisense for CloudFormation templates.
7 |
8 | The samples within assume you are using the [AWS SDK Credential Store](http://docs.aws.amazon.com/powershell/latest/userguide/specifying-your-aws-credentials.html). You will need to store an appropriate set of credentials under the "AWSWorkshop" profile to execute the samples. *ResetCredentials.bat* will help accomplish this.
9 |
10 | ## Itinerary
11 |
12 | * Working securely in AWS
13 | * [AWS a-b-c's](https://speakerdeck.com/andrewabest/aws-a-b-cs)
14 | * [Exercise One - DIY](https://github.com/andrewabest/AWS-Workshop/blob/master/Exercise1.md)
15 | * CloudFormation Introduction ([supplementary information](http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-whatis-howdoesitwork.html))
16 | * [Exercise Two - CloudFormation](https://github.com/andrewabest/AWS-Workshop/blob/master/Exercise2.md)
17 | * Question Time
18 | * [DSC a-b-c's](https://speakerdeck.com/andrewabest/dsc-a-b-cs)
19 | * [Exercise Three - DSC DIY](https://github.com/andrewabest/AWS-Workshop/blob/master/Exercise3.md)
20 | * Question Time
21 | * [Exercise Four - CloudFormation + DSC](https://github.com/andrewabest/AWS-Workshop/blob/master/Exercise4.md)
22 | * [Exercise Five - CloudFormation + DSC + Octopus (Form like Voltron)](https://github.com/andrewabest/AWS-Workshop/blob/master/Exercise5.md)
23 | * Discussion time - Automating infrastructure
24 |
25 | ### Disclaimer
26 |
27 | What is presented here is 101 level infrastructure automation, and is not intended as a production solution. Most production rollouts in AWS will involve a significantly more complex setup to enforce appropriate security and scalability - for a reference architecture, see [Amazon's examples](http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Scenario3.html).
28 |
--------------------------------------------------------------------------------
/ResetCredentials.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | IF '%~1' == '' ECHO "Missing 'AccessKey' arg"
4 | IF '%~1' == '' GOTO ERROR
5 |
6 | IF '%~2' == '' ECHO "Missing 'SecretKey' arg"
7 | IF '%~2' == '' GOTO ERROR
8 |
9 | powershell.exe -ExecutionPolicy Bypass -Command "Set-AWSCredentials -AccessKey %~1 -SecretKey %~2 -StoreAs AWSWorkshop"
10 |
11 | exit /b 0
12 |
13 | goto end
14 |
15 | :error
16 |
17 | echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
18 | echo !!! Stopping due to error !!!
19 | echo !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
20 |
21 | exit /b 1
22 |
23 | goto end
24 |
25 | :end
26 | exit /b
--------------------------------------------------------------------------------