Goals
- Set up the tools
- Get familiar with the tools
- Launch some instances
- Launch the full stack from VPC to Windows Based EC2 Instances with a Domain Controller, IIS Web Server, Remote Desktop Gateway
What You Need
- Basic PowerShell knowledge
- Powershell v2 or later / Windows Management Framework
- Powershell ISE
- AWS Tools for Windows PowerShell
- AWS Account and an IAM role with Administrator permissions.
AWS Tools for Powershell
Check your powershell version $psversiontable
If you you do not have a version listed at all, you have v 1.0. You will need to upgrade so go ahead and download the latest version of the Windows Management Framework available for you OS.
Install the AWS Tools for Windows PowerShell.
Setting up Your AWS Profile in Powershell
AWS IAM User
If you don’t have an AWS account, stop here and get one, then set up an IAM user that has Administrator permissions.
Be sure to make note of the AccessKey and SecretKey of that user.
In my case my user is in a group called “Admins” and that group has the following policy attached.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "*", "Resource": "*" } ] }
Setting up Your AWS Profile in PS
In order to interact with AWS we usually have to tell it who we are (authentication credentials) and what region we are looking to work in.
We could certainly provide this info for each command we issue, but we would have to type that info out everytime and potentially expose your credentials. Lets simplify and secure by storing this information in a profile.
The AWS Tools for Windows PowerShell can use either of two credentials stores.
- The AWS SDK store, which encrypts your credentials and stores them in your home folder.
- The credentials file, which is also located in your home folder, but stores credentials as plain text. By default, the credentials file is stored here: C:\Users\username\.aws\credentials.
We will store them in the AWS SDK store so they are encrypted with the following powershell command.
Set-AWSCredential -AccessKey AAAAAAAAAAAAAAAAAAAAAAAAAAAA -SecretKey SSSSSSSSSSSSSSSSSSSSSSSSSSSS -StoreAs YourProfileName
Note that AAAAAAAAAAAAA and SSSSSSSSSSSSSSS represent the AccessKey and Secret key for your IAM user with Administrator permissions.
Verify the profile is properly stored
Get-AWSCredential -ListProfileDetail
You should see that YourProfileName
is securely stored
ProfileNameStoreTypeName ProfileLocation
----------- ------------- ---------------
YourProfileName NetSDKCredentialsFile
Now if we tried to run Get-Ec2Instance
we would get an error because we still haven’t told AWS who we are to what region we want to work in.
Lets do that.
Get-EC2Instance -ProfileName YourProfileName -Region us-east-1
We get now get some info on our EC2 instances.
GroupNames : {}
Groups : {}
Instances : {WebServerKey}
OwnerId : 659152461139
RequesterId :
ReservationId : r-00fa002c52b620dd
But we don’t want to have to specify the Profile Name and Region on every command. It takes too long. Let’s set these as defaults so thay are assumed every time we open up Powershell and issue AWS commands.
Initialize-AWSDefaults -ProfileName YourProfileName -Region us-east-1
Ok that does it for the high-level setup. Lets do some discovery of whats under the covers.
Cmdlets Discovery
PS C:\Users\Brahim> get-module AWSPowerShell ModuleType Version Name ExportedCommands ---------- ------- ---- ---------------- Binary 3.3.245.0 AWSPowerShell {Add-AASScalableTarget, Add-ACMCertificateTag, Add-ADSConf...
In version 3.3.245 of the module there are 4103 commands!
PS C:\Users\Brahim> get-command -Module AWSPowerShell | Measure-Object Count : 4103 Average : Sum : Maximum : Minimum : Property :
Go ahead and see that they are.. I’ll wait…
get-command -Module AWSPowerShell
🙂
Lets see the 278 commands that have EC2 as the noun
get-command -Noun ec2*
Now that we have run a few commands lets get a history of the AWS related commands we have executed.
$AWSHistory Item : Commands : {Get-EC2Instance} LastCommand : Get-EC2Instance LastServiceResponse : Amazon.EC2.Model.DescribeInstancesResponse LastServiceRequest :
In true .net fashion let’s use some dot notation to drill into the object further for a bit more debugging data.
PS C:\Users\Brahim>
$AWSHistory.Commands.LastServiceResponse | Format-List LoggedAt : 3/8/2018 6:10:08 PM NextToken : Reservations : {659152461139, 659152461139, 659152461139, 659152461139} ResponseMetadata : Amazon.Runtime.ResponseMetadata ContentLength : -1 HttpStatusCode : OK
Creating EC2 Instances
Finding an image to use
Let’s get a sense of what Windows AMI images are available
Get-EC2ImageByName WINDOWS_2016_BASE WINDOWS_2016_NANO WINDOWS_2016_CORE WINDOWS_2016_CONTAINER WINDOWS_2016_SQL_SERVER_ENTERPRISE_2016 WINDOWS_2016_SQL_SERVER_STANDARD_2016 WINDOWS_2016_SQL_SERVER_WEB_2016 WINDOWS_2016_SQL_SERVER_EXPRESS_2016 WINDOWS_2012R2_BASE WINDOWS_2012R2_CORE WINDOWS_2012R2_SQL_SERVER_EXPRESS_2016 WINDOWS_2012R2_SQL_SERVER_STANDARD_2016 WINDOWS_2012R2_SQL_SERVER_WEB_2016 WINDOWS_2012R2_SQL_SERVER_EXPRESS_2014 WINDOWS_2012R2_SQL_SERVER_STANDARD_2014 WINDOWS_2012R2_SQL_SERVER_WEB_2014 WINDOWS_2012_BASE WINDOWS_2012_SQL_SERVER_EXPRESS_2014 WINDOWS_2012_SQL_SERVER_STANDARD_2014 WINDOWS_2012_SQL_SERVER_WEB_2014 WINDOWS_2012_SQL_SERVER_EXPRESS_2012 WINDOWS_2012_SQL_SERVER_STANDARD_2012 WINDOWS_2012_SQL_SERVER_WEB_2012 WINDOWS_2012_SQL_SERVER_EXPRESS_2008 WINDOWS_2012_SQL_SERVER_STANDARD_2008 WINDOWS_2012_SQL_SERVER_WEB_2008 WINDOWS_2008R2_BASE WINDOWS_2008R2_SQL_SERVER_EXPRESS_2012 WINDOWS_2008R2_SQL_SERVER_STANDARD_2012 WINDOWS_2008R2_SQL_SERVER_WEB_2012 WINDOWS_2008R2_SQL_SERVER_EXPRESS_2008 WINDOWS_2008R2_SQL_SERVER_STANDARD_2008 WINDOWS_2008R2_SQL_SERVER_WEB_2008 WINDOWS_2008RTM_BASE WINDOWS_2008RTM_SQL_SERVER_EXPRESS_2008 WINDOWS_2008RTM_SQL_SERVER_STANDARD_2008 WINDOWS_2008_BEANSTALK_IIS75 WINDOWS_2012_BEANSTALK_IIS8 VPC_NAT
I noticed that this command only lists the Windows images. What about linux? That’s not nice! I will get back to options for discovering linux AMIs later on.
We can take a look at all of the properties of the object.
Get-EC2ImageByName windows_2016_base | Select-Object Architecture : x86_64 BlockDeviceMappings : {/dev/sda1, xvdca, xvdcb, xvdcc...} CreationDate : 2018-03-06T05:36:15.000Z Description : Microsoft Windows Server 2016 with Desktop Experience Locale English AMI provided by Amazon EnaSupport : True Hypervisor : xen ImageId : ami-cab14db7 ImageLocation : amazon/Windows_Server-2016-English-Full-Base-2018.03.06 ImageOwnerAlias : amazon ImageType : machine KernelId : Name : Windows_Server-2016-English-Full-Base-2018.03.06 OwnerId : 801119661308 Platform : Windows ProductCodes : {} Public : True RamdiskId : RootDeviceName : /dev/sda1 RootDeviceType : ebs SriovNetSupport : simple State : available StateReason : Tags : {} VirtualizationType : hvm
For now let’s inspect the image with a paired down set of properties. ImageId is of interest.
Get-EC2ImageByName windows_2016_base | Select-Object -Property Name,ImageId Name ImageId ---- ------- Windows_Server-2016-English-Full-Base-2018.03.06 ami-cab14db7
So to launch a Windows image I need the proper ImageID. Here, the ImageID is instantiated into a variable $WinImageID that will be used to launch the instances.
$WinImageID = Get-EC2ImageByName windows_2016_base | select -First 1 -expand imageid Echo $WinImageID ami-cab14db7
What about linux images? It is annoying to me that Get-EC2ImageByName
only lists Windows images. If you know why, I’d love to know.
For linux, I had to determine the string pattern on the name and go with that to get a response which shows some nice fresh images.
Get-EC2ImageByName -Names *amzn2-ami-hvm*x86_64* | select -First 1 Architecture : x86_64 BlockDeviceMappings : {/dev/xvda} CreationDate : 2018-01-16T19:06:49.000Z Description : Amazon Linux 2 LTS Candidate AMI 2017.12.0.20180115 x86_64 HVM GP2 EnaSupport : True Hypervisor : xen ImageId : ami-428aa838 ImageLocation : amazon/amzn2-ami-hvm-2017.12.0.20180115-x86_64-gp2 ImageOwnerAlias : amazon ImageType : machine KernelId : Name : amzn2-ami-hvm-2017.12.0.20180115-x86_64-gp2 OwnerId : 137112412989 Platform : ProductCodes : {} Public : True RamdiskId : RootDeviceName : /dev/xvda RootDeviceType : ebs SriovNetSupport : simple State : available StateReason : Tags : {} VirtualizationType : hvm
So to launch a Linux image I need the proper ImageID. Here, the ImageID is instantiated into a variable $LinuxImageID that will be used to launch the instance.
$LinuxImageID = Get-EC2ImageByName -Names *amzn2-ami-hvm*x86_64* | select -First 1 -expand imageid echo $LinuxImageID ami-428aa838
Lets see what instances I have already deployed.
(Get-EC2Instance).Instances InstanceId InstanceType Platform PrivateIpAddress PublicIpAddress SecurityGroups SubnetId VpcId ---------- ------------ -------- ---------------- --------------- -------------- -------- ----- i-0746c6e7a12f92c94 t2.micro 172.31.82.219 {Public - WebServer} subnet-4500e66a vpc-6477a41c i-0b06e2ea62eeb074f t2.micro Windows 172.31.91.213 {Public - WebServer} subnet-4500e66a vpc-6477a41c i-03bf964f8c8aa8b1f t2.micro 172.31.81.118 {Public - WebServer} subnet-4500e66a vpc-6477a41c i-07e4c360067205f61 t2.micro Windows 172.31.36.155 {Public - WebServer} subnet-6ccdd636 vpc-6477a41c
hmm