Windows Server 2022 on AWS User Guide
Overview
This image is Microsoft Windows Server 2022 Datacenter, one software version of the cloudimg Hardened AMIs for Microsoft Windows Server 2019, 2022 & 2025 listing on AWS Marketplace. Every release in the listing is described at /guides/windows-server-windows-aws/.
The Windows Firewall allows inbound Remote Desktop (3389) only: open any other port in both the security group and the Windows Firewall. Opening a port in the security group alone is not enough.
What cloudimg does to the image:
- Configured with the Microsoft Security Baseline for Windows Server 2022, Member Server profile. The build downloads the Windows Server 2022 Security Baseline and LGPO.exe from Microsoft's Security Compliance Toolkit (pinned by SHA-256) and applies the same Group Policy set Microsoft's own install script applies to a member server: Member Server, Domain Security (password and lockout policy), Microsoft Defender Antivirus and Internet Explorer 11. The Credential Guard policy is not applied (see the waived rules).
- Measured with HardeningKitty. On a fresh instance from this image, HardeningKitty v.0.9.4 audits Microsoft's own finding list for Windows Server 2022 Member Server (328 rules): 320 of 320 scored rules pass (100%), with 8 rules waived for EC2. The build fails below 98%. The HTML and CSV reports, the summary and the waivers ship in the image under
C:\ProgramData\cloudimg\baseline\. This is a measurement made by open-source tooling against Microsoft's published baseline, not a certification or accreditation by Microsoft or any other body. - 8 rules waived, each with its reason (listed below and in
C:\ProgramData\cloudimg\baseline\waivers.txt): two would stop the Administrator signing in over Remote Desktop, and six belong to the Credential Guard policy, which cannot run on this image. - Fully patched at build time with every update Windows Update offered (the October 2026 cumulative update, build 20348.5761); the build fails if any update is still pending or a reboot is owed.
- A unique Administrator password on every instance. The image is generalised with Sysprep through EC2Launch v2, so each instance gets its own random Administrator password (retrieved with your key pair), machine SID, computer name and Remote Desktop certificate. There is no default or shared password.
- Remote Desktop with Network Level Authentication, and the baseline's NTLMv2-only, 128-bit session security and CredSSP "Force Updated Clients" settings.
- Windows Firewall on for every profile, inbound blocked by default, with only Remote Desktop (3389) and core networking (ICMP, DHCP) allowed in. WinRM, Cast to Device, DIAL, mDNS, AllJoyn, Delivery Optimization, Teredo and Remote Desktop shadowing are closed. SMBv1 is off.
- IMDSv2 only. The AMI is marked IMDSv2-only, so instance metadata requires a session token.
- No build residue. Build tools, downloaded installers, the build's logs, PowerShell history and the build's Remote Desktop certificate are removed before capture, and the page file is cleared at shutdown so no build memory ships.
Connecting to your instance
Connect with Remote Desktop as the Administrator:
| Operating system variant | Remote Desktop login user |
|---|---|
| Windows Server 2022 Datacenter | Administrator |
Launch from AWS Marketplace
- Open the listing on AWS Marketplace and choose View purchase options, then Subscribe. One subscription covers every version in the listing.
- Once the subscription is active, choose Launch your software.
- Choose Windows Server 2022 Datacenter as the software version, your Region and an instance type.
m5.large(2 vCPU, 8 GiB) is the recommended starting size. - Choose a key pair. You need its private key to get the Administrator password; without a key pair there is no way to read it.
- Use a security group that allows RDP (TCP 3389) from your own address only, never
0.0.0.0/0if you can avoid it. The listing's default security group opens 3389 to the internet so the instance is reachable straight away; tighten it to your address range. - Launch, then wait about four minutes after the instance is running: Windows finishes its first boot and EC2Launch sets the Administrator password.
Get the Administrator password
In the EC2 console select the instance, choose Actions, Security, Get Windows password, upload the private key of the key pair you launched with and choose Decrypt password. Or with the AWS CLI on your workstation:
aws ec2 get-password-data --region <region> --instance-id <instance-id> \
--priv-launch-key ~/.ssh/my-key-pair.pem --query PasswordData --output text
An empty result means Windows has not finished setting the password yet; try again a minute later. Every instance has a different password.
Connect over Remote Desktop
Connect to the instance's public DNS name or IP address on port 3389 with any Remote Desktop client that supports Network Level Authentication (Microsoft Remote Desktop on Windows and macOS, FreeRDP on Linux), as user Administrator with the password from the previous step.
On first connection your client shows the instance's self-signed Remote Desktop certificate. Each instance generates its own certificate on first boot, so the fingerprint is unique to your instance. To check it before you trust it, read the thumbprint from the instance (for example over AWS Systems Manager Session Manager) and compare it with what your client shows:
Get-ChildItem 'Cert:\LocalMachine\Remote Desktop' | Select-Object Subject, Thumbprint, NotAfter
Change the Administrator password after your first sign-in if you will share the decrypted password with anyone: press Ctrl+Alt+End in the Remote Desktop session and choose Change a password. The baseline requires at least 14 characters with complexity and remembers the last 24 passwords.
View the baseline report
Everything the build measured ships in C:\ProgramData\cloudimg\baseline\:
| File | What it is |
|---|---|
baseline-report.html |
Every rule audited, its result and the recommended value; waived rules marked |
hardeningkitty-report.csv |
The raw HardeningKitty audit |
baseline-summary.json |
Rules audited, waived, scored and passed, the pass rate and threshold |
waivers.txt / waivers.json |
The waived rules and why |
tool-versions.json |
The baseline, LGPO and HardeningKitty versions and SHA-256 values used |
Show the summary in PowerShell:
Get-Content C:\ProgramData\cloudimg\baseline\baseline-summary.json | ConvertFrom-Json |
Select-Object profile, audited, waived, scored, pass, fail, ratePct, thresholdPct, evaluatedAt
Open baseline-report.html in a browser on the instance, or copy it to your workstation.
Re-run the audit yourself
HardeningKitty v.0.9.4 stays in the image so you can measure the instance again at any time, for example after you install software or join a domain. Run it in an elevated PowerShell (Run as administrator); it only reads settings (Audit mode) and takes a minute or two:
$hk = 'C:\ProgramData\cloudimg\tools\HardeningKitty-0.9.4'
Import-Module "$hk\HardeningKitty.psm1" -Force
$list = "$hk\lists\finding_list_msft_security_baseline_windows_server_2022_21h2_member_machine.csv"
$csv = Join-Path $env:TEMP 'hardeningkitty-now.csv'
Remove-Item $csv -ErrorAction SilentlyContinue
$null = Invoke-HardeningKitty -Mode Audit -FileFindingList $list -Report -ReportFile $csv -SkipMachineInformation *>&1
$waived = (Get-Content -Raw C:\ProgramData\cloudimg\baseline\waivers.json | ConvertFrom-Json).waivers.id
$scored = @(Import-Csv $csv | Where-Object { $waived -notcontains $_.ID })
$pass = @($scored | Where-Object { $_.Severity -eq 'Passed' }).Count
"{0} of {1} scored rules pass ({2:N1}%)" -f $pass, $scored.Count, (100 * $pass / $scored.Count)
$scored | Where-Object { $_.Severity -ne 'Passed' } | Select-Object ID, Name, Result, Recommended
Waived rules
These rules from Microsoft's finding list are set differently on purpose. Each one is in waivers.txt with its reason:
| ID | Rule | Set to | Why |
|---|---|---|---|
| 10311 | Deny access to this computer from the network | Guests | The baseline denies network logon to local administrators. Remote Desktop with Network Level Authentication checks the Administrator's password with a network logon first, so the EC2 Administrator could not sign in. |
| 10312 | Deny log on through Remote Desktop Services | Guests | The baseline denies Remote Desktop to every local account. On a stand-alone EC2 instance the local Administrator is the only way in. |
| 10672-10677 | Device Guard: Virtualization Based Security and Credential Guard (6 rules) | Not configured | Credential Guard needs UEFI Secure Boot. This image boots in legacy BIOS mode on EC2, so the policy could not run and a "pass" would be misleading. |
If you join the instance to an Active Directory domain, Microsoft's domain-joined guidance applies: you can deny local accounts network and Remote Desktop logon again once you sign in with domain accounts.
Windows Firewall
Every firewall profile (Domain, Private, Public) is on with inbound traffic blocked unless a rule allows it. The only inbound rules enabled are Remote Desktop (3389, TCP and UDP) and core networking (ICMP, DHCP). List them:
Get-NetFirewallRule -Direction Inbound -Enabled True -Action Allow |
Select-Object DisplayGroup, DisplayName, Profile | Sort-Object DisplayGroup, DisplayName
Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultInboundAction
To serve something else, for example HTTPS for IIS, open the port in the Windows Firewall and in the instance's security group:
New-NetFirewallRule -DisplayName 'HTTPS (TCP-In)' -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
Windows Remote Management (WinRM, 5985) is closed by default. If you need PowerShell remoting, prefer AWS Systems Manager Session Manager, which needs no inbound port.
IMDSv2
The AMI is marked IMDSv2-only. A metadata request without a token is refused (HTTP 401); request a token first:
try { Invoke-WebRequest -UseBasicParsing http://169.254.169.254/latest/meta-data/instance-id | Out-Null; 'tokenless call answered' }
catch { 'tokenless call refused: HTTP ' + [int]$_.Exception.Response.StatusCode }
$token = Invoke-RestMethod -Method Put -Uri http://169.254.169.254/latest/api/token -Headers @{ 'X-aws-ec2-metadata-token-ttl-seconds' = '300' }
Invoke-RestMethod -Uri http://169.254.169.254/latest/meta-data/instance-id -Headers @{ 'X-aws-ec2-metadata-token' = $token }
The AWS tools and SDKs, EC2Launch v2 and the SSM agent in the image all use IMDSv2.
Per-instance identity
Sysprep runs at the end of the build, so nothing that identifies a machine is shared between instances: the Administrator password, the machine SID, the computer name (EC2AMAZ-...) and the Remote Desktop certificate are all created on each instance's first boot. Check them:
$env:COMPUTERNAME
(Get-LocalUser -Name Administrator).SID.Value
Get-ChildItem 'Cert:\LocalMachine\Remote Desktop' | Select-Object -ExpandProperty Thumbprint
Services
Nothing beyond Windows Server itself is installed. The services that matter on EC2 are running: Remote Desktop Services (TermService), the AWS Systems Manager agent (AmazonSSMAgent), EC2Launch v2 (Amazon EC2Launch), Microsoft Defender Antivirus (WinDefend) and the Windows Firewall (mpssvc):
Get-Service TermService, AmazonSSMAgent, 'Amazon EC2Launch', WinDefend, mpssvc | Select-Object Name, Status, StartType
Patching
The image is fully patched when it is built; the build does not change Windows Update's own settings. To check for updates yourself:
$searcher = (New-Object -ComObject Microsoft.Update.Session).CreateUpdateSearcher()
$searcher.Search("IsInstalled=0 and IsHidden=0 and Type='Software'").Updates | Select-Object Title
Then install them from Settings, Windows Update, or with sconfig option 6, and restart when Windows asks.
The page file is cleared at every shutdown (ClearPageFileAtShutdown), which keeps memory contents off the disk but makes shutdowns slower on large-memory instances. To turn it off:
Set-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management' -Name ClearPageFileAtShutdown -Value 0
Emergency access
If you lose the Administrator password, connect with AWS Systems Manager Session Manager (the instance needs an instance profile with the AmazonSSMManagedInstanceCore policy) and set a new one, or follow the AWS guide "Reset the Windows administrator password for an Amazon EC2 instance" (EC2Launch v2 or EC2Rescue). The EC2 serial console and the instance screenshot in the EC2 console help when the instance does not answer on 3389.
Support
cloudimg provides 24/7 technical support for this image by email and live chat: support@cloudimg.co.uk. Windows Server licensing is included in the AWS instance charge; licensing questions go to AWS and Microsoft.
Microsoft and Windows Server are trademarks of the Microsoft group of companies. cloudimg is not affiliated with or endorsed by Microsoft.