- Deploying an AWS EC2 Windows VM via PowerShell - Mon, Dec 16 2019
- Creating an AWS VPC with PowerShell - Fri, Nov 15 2019
- Configuring Azure Private DNS - Mon, Nov 11 2019
Prerequisites
For this deployment to work, the following prerequisites must be met:
- AWS PowerShell module installed
- AWS VPC and Subnets created
- See previous article in this series about VPC creation
- Get the VpcId for the VPC into which you want to deploy the EC2
- Get the Subnet ID for the private subnet in your VPC
Once you have these in place, we can get started.
Deploying an EC2 into a private subnet
We will be deploying this new VM into a private subnet, which means the VM will not have a public IP. As a best practice, VMs should be deployed into a private subnet without a public IP attached to its network interface card (ENI [Elastic Network Interface]). The resources we are going to deploy will all support the EC2 instance and secure access to it.
- EC2 key pair
- Required to decrypt the encrypted Windows administrator password
- https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-key-pairs.html
- Elastic IP (public IP address)
- EC2 instance
- Security group (virtual firewall rule)
Creating an AWS EC2 Key Pair
AWS EC2 key pairs are required to access EC2 instances. AWS users either use an EC2 key pair to connect to Linux instances via SSH or to decrypt the automatically generated Windows administrator password. On instantiation of a Windows EC2 instance, the operating system creates a randomly generated password for the local administrator user, encrypts it, and reports it to the AWS console.
To create the key pair, run the following:
$keyPair = New-EC2KeyPair -KeyName ec2keypair # Write the Key Pair to a local file $keyPair.KeyMaterial | Set-Content -Path ./ec2-keypair.pem -Force
Creating an AWS Security Group
Every EC2 must also be attached to an AWS security group. Think of a security group as a virtual firewall rule attached directly to the instance. This is in addition to the operating system's firewall. A security group functions externally to the operating system. Security groups filter traffic based on source or destination IP and port.
$vpcId = Read-Host -Prompt "Enter Vpc Id" $securityGroup = New-EC2SecurityGroup -GroupName "allow RDP inbound" -VpcId $vpcId -Description "This Security Group allows traffic inbound to port 3389."
We also need to create rules that allow ingress/egress communication and attach the rules to that security group. Remember, only allowing communication through the OS's firewall is not enough.
$ingress = @{ IpProtocol="tcp"; FromPort="3389"; ToPort="3389"; IpRanges="10.0.2.0/24" } Grant-EC2SecurityGroupIngress -GroupId $securityGroup -IpPermission @( $ingress )
If you followed the VPC deployment article mentioned above, then this rule will allow all resources in your VPC's private subnet to communicate with this EC2 resource on port 3389 (RDP).
Note: The EC2 we are deploying will be in the private subnet. This means even if you added an IP range of 0.0.0.0/0 to the security group, communication would not work since the EC2 is not routable from outside the VPC.
If you want to enable communication to EC2 resources in private subnets, read up on topics such as “Bastion Hosts” and “AWS Systems Manager Port Forwarding.”
Creating an AWS EC2 Instance
The EC2 will be deployed in the VPC and subnet mentioned in the prerequisites. This has a few sub-steps that we need to execute.
$amiId = (Get-EC2ImageByName -Name WINDOWS_2016_BASE | Sort-Object CreationDate -Descending | Select-Object -First 1).ImageId
This will get us the AMI ID of the latest Windows Server 2016 base AMI available in the AWS marketplace for our region. AMI IDs are region-specific, so if you are deploying resources into multiple regions, you will need to get an AMI ID in each region.
$subnetId = Read-Host -Prompt "Enter subnet Id" $instance = New-EC2Instance -ImageId $amiId -InstanceType t3a.medium -SubnetId $subnetId -KeyName ec2keypair -AssociatePublicIp $false -SecurityGroupId $securityGroup
A Windows deployment typically takes a couple of minutes to complete. You can either watch the progress in the AWS console or use PowerShell to poll the status from the AWS API.
Get-EC2Instance -InstanceId $instance.Instances.InstanceId
Once the status changes to Running, the instance is ready to accept connections. To connect to the instance, we require the password for the automatically created Administrator user. As mentioned before, we can decrypt the password using the EC2 key pair.
Subscribe to 4sysops newsletter!
$password = Get-EC2PasswordData -InstanceId $instance.Instances.InstanceId -Decrypt -PemFile ./ec2-keypair.pem
With this password and if we had network connectivity to the instance, we would be able to RDP into our new Windows instance.