In today’s world, Amazon Web Services (AWS) is the cloud king. AWS has managed to squeeze out many of its cloud competitors and to convince organizations big and small to migrate workloads to their infrastructure. Even so, cloud competitors remain and vendor lock-in is still a major issue. Enterprises are complex beasts with hundreds or thousands of different applications and services and distributed teams. One team may love the AWS cloud while another may prefer Azure while another still doesn’t trust that “cloud thing”. AWS has noticed this trend, and instead of throwing up their hands and giving up, they decided back in late 2016 they were going to meet consumers half-way in the form of a service called AWS Systems Manager (SSM). Amazon wanted to give customers the ability to manage systems, generate an audit trail, and provide granular access control across any server instance regardless of where it sits. That means managing on-prem or competitor cloud server instances just like they would an EC2 instance. SSM was their answer to that demand.

Prerequisites

SSM can easily manage EC2 instances but what’s the fun in just doing that! We can also manage all of our on-prem servers, too. That sounds much more interesting. Before you get all excited about managing all of your on-prem or Azure server instances with SSM, be sure your servers meet the prerequisites. By browsing over the prerequisites, chances are you’re going to be able to use SSM. They still support Windows Server 2003 and Ubuntu 12.04! Once you determine you’ve met the prerequisites for using SSM, you’ll then need to perform some access control work to ensure the appropriate IAM roles are set up. Also, to follow along with this article, you’ll need to have the AWSPowerShell module installed. If you don’t have it already, it’s available in the PowerShell Gallery and can be downloaded and installed with the Install-Module PowerShell command.

Install-module AWSPowerShell

IAM Service Role Setup

Depending on if you’re going to be managing EC2 instances or on-prem instances depends on the IAM roles that need to be set up. Since we’re going only to be focusing on on-prem instances, we’ll need a service role setup. This service role will be used by all of your on-prem instances to communicate with the SSM service. To create a service role with PowerShell, we’ll first have to create a JSON text file. This JSON file will act as input to the New-IAMRole command to get the role setup. I’ll create a text file that looks like the following as C:\SSMServiceRole.json.

{ "Version": "2012-10-17", "Statement": { "Effect": "Allow", "Principal": {"Service": "ssm.amazonaws.com"}, "Action": "sts:AssumeRole" } }

Once I have the JSON file created, I’ll then run New-IAMRole to assign the policy just created and create a role called SSMServiceRole.

PS> New-IAMRole -RoleName SSMServiceRole -AssumeRolePolicyDocument (Get-Content -raw C:\SSMServiceRole.json) Path RoleName RoleId CreateDate Description ---- -------- ------ ---------- ----------- / SSMServiceRole AROAJYJUOYSDWOTXRRC5C 2/9/2018 9:03:37 PM Once the role is created, we’ll then need to register the IAM role policy giving the SSMServiceRole the ability to create a session token. PS> Register-IAMRolePolicy -RoleName SSMServiceRole -PolicyArn arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM

Managed Instance Activation

Once you’ve got the IAM role setup, we’ll then need to set up a managed instance activation. This will be used to authenticate to the SSM service for your particular server instance. Again, using PowerShell, we’ll use the New-SSMActivation command to make this happen. You can see below that I’m using the us-east-1 region. You can use a number of different regions. Also, be sure to use the IAM service role we created earlier. If the activation is successful, you’ll be returned an activation code and activation ID. We’ll need these two strings later.

PS> New-SSMActivation -DefaultInstanceName N2WSoftwareServers -IamRole SSMServiceRole -RegistrationLimit 10 –Region us-east-1 ActivationCode ActivationId -------------- ------------ XXXXXXXXXXXXXXXXX XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX Once complete, you’ll then be able to see all instance activations using the Get-SSMActivation command. PS> Get-SSMActivation ActivationId : XXXXXXXXXXXX CreatedDate : 2/9/2018 9:42:00 PM DefaultInstanceName : N2WSoftwareServers Description : ExpirationDate : 2/10/2018 9:42:00 PM Expired : False IamRole : SSMServiceRole RegistrationLimit : 10 RegistrationsCount : 1

SSM Agent Installation

Once you’ve got all of the permissions squared away and then your instance activation code and ID, it’s now time to get the SSM agent installed on your on-prem instances. To do that, we’ll first grab a copy of the installer. Since I’m setting up the SSM agent on a Windows Server 2016 instance, I’ll use PowerShell to download it. There are a few lines of PowerShell to do this so I’ll create a script called C:\InstallSSMAgent.ps1 and put the following code inside of it. This script is parameterized to give you the ability to use this script for multiple servers, if necessary.

```PowerShell param( [Parameter(Mandatory)][string]$ActivationCode, [Parameter(Mandatory)][string]$ActivationId, [Parameter()][string]$Region = ‘us-east-1’ )

Download the installer if we need to

$installerFilePath = "$env:Temp.exe" if (-not (Test-Path -Path $installerFilePath)) { $iwrParams = @{ Uri = "https://amazon-ssm-$Region.s3.amazonaws.com/latest/windows_amd64/AmazonSSMAgentSetup.exe" UseBasicParsing = $true OutFile = $installerFilePath } Invoke-WebRequest @iwrParams }

Run the installer

$procParams = @{ FilePath = $installerFilePath ArgumentList = @('/q', '/log', "`"$env:Temp.log`“”, “CODE=$ActivationCode", "ID=$ActivationId”, “REGION=$Region”) Wait = $true NoNewWindow = $true } Write-Host "Installing SSM agent with arguments: [$($procParams.ArgumentList)]" Start-Process @procParams ```

I’ll now invoke this script passing in the activation code and ID I got earlier which will download the SSM agent from my expected region and install it. The install should work, but you can always check by inspecting the installer log that it generates using Get-Content.

PS> C:\InstallSSMAgent.ps1 -ActivationCode 'XXXXXXXXXXX' -ActivationId 'XXXXXXXXXX' PS> Get-Content -Path $env:TEMP\install.log

Once the SSM agent has been installed and linked up to the SSM service, we can now take a look to ensure it’s showing up as a managed instance with the Get-SSMInstanceInformation command.

PS> Get-SSMInstanceInformation ActivationId : XXXXXXXXX AgentVersion : 2.2.160.0 AssociationOverview : AssociationStatus : ComputerName : WEBSRV1.lab.local IamRole : SSMServiceRole InstanceId : mi-09d4ba935f27513ed IPAddress : 10.0.0.5 IsLatestVersion : True LastAssociationExecutionDate : 1/1/0001 12:00:00 AM LastPingDateTime : 2/9/2018 9:46:19 PM LastSuccessfulAssociationExecutionDate : 1/1/0001 12:00:00 AM Name : N2WSoftwareServers PingStatus : Online PlatformName : Microsoft Windows Server 2016 Datacenter PlatformType : Windows PlatformVersion : 10.0.14393 RegistrationDate : 2/9/2018 9:42:28 PM ResourceType : ManagedInstance

Testing out SSM: Running PowerShell Commands

The setup portion is done. At this point, our on-prem server is linked up to the SSM service and ready to go to work. SSM has a multitude of things that you can do to managed instances like patching, inventory, performing wide-scale automation tasks or just running ad-hoc commands. In this article, let’s stick with something simple and see how easy it is to run a PowerShell command on our managed instance from SSM. To run commands on managed instances requires the use of a command document. The command document is a set of instructions that dictate what actions to perform on the managed instance once it gets instructions to do something. In PowerShell, this command document is referenced as a command description. You can create your own command descriptions, but SSM comes with some handy ones by default. We’ll be using the AWS-RunPowerShellScript command description. We can take a look at this by running Get-SSMDocumentDescription.

PS> Get-SSMDocumentDescription -Name "AWS-RunPowerShellScript" CreatedDate : 8/21/2017 8:35:03 PM DefaultVersion : 1 Description : Run a PowerShell script or specify the paths to scripts to run. DocumentFormat : JSON DocumentType : Command DocumentVersion : 1 Hash : 2142e42a19e0955cc09e43600bf2e633df1917b69d2be9693737dfd62e0fdf61 HashType : Sha256 LatestVersion : 1 Name : AWS-RunPowerShellScript Owner : Amazon Parameters : {commands, workingDirectory, executionTimeout} PlatformTypes : {Windows, Linux} SchemaVersion : 1.2 Sha1 : Status : Active Tags : {} TargetType :

We can use this command document by “sending” an SSM command using the Send-SSMCommand. To do this, we’ll need to know the instance ID of the instance we’re running the command against and the PowerShell code to run. In the example below, we’re simply listing the contents of the C:\ on the managed instance we just created.

PS> $ssmCommand = Send-SSMCommand -InstanceId @('mi-09d4ba935f27513ed') -DocumentName AWS-RunPowerShellScript -Comment 'N2W Software Demo' -Parameter @{ 'commands'= @('dir C:\') }

You’ll find that you get nothing back. This is because I’ve assigned the output to a variable. I did this because sometimes commands can take a while and it’s important we’re able to track the progress. We can use the Get-SSMCommand command and pass it the CommandId of the PowerShell command just issued. You can see below that the request was successful!

PS> Get-SSMCommand -CommandId $ssmCommand.CommandId CommandId : a0573372-1f76-46f0-8450-2f176f32ad54 Comment : N2W Software Demo CompletedCount : 1 DocumentName : AWS-RunPowerShellScript ErrorCount : 0 ExpiresAfter : 2/10/2018 12:02:13 AM InstanceIds : {mi-09d4ba935f27513ed} MaxConcurrency : 50 MaxErrors : 0 NotificationConfig : Amazon.SimpleSystemsManagement.Model.NotificationConfig OutputS3BucketName : OutputS3KeyPrefix : OutputS3Region : Parameters : {[commands, Amazon.Runtime.Internal.Util.AlwaysSendList`1[System.String]]} RequestedDateTime : 2/9/2018 10:02:13 PM ServiceRole : Status : Success StatusDetails : Success TargetCount : 1 Targets : {}

Now that we can see the command was successful, we can take a look at the output the PowerShell command generated using the Get-SSMCommandInvocation command. We just need to provide it with the CommandId of the command recently issued, the managed instance ID and to output the details. Also notice below we have to expand the CommandPlugins property that is a part of the object returned from Get-SSMCommandExecution. The CommandPlugins property value is where the output hides.

PS> Get-SSMCommandInvocation -CommandId $ssmCommand.CommandId -Details $true -InstanceId mi-XXXXXXXXX | Select-Object -ExpandProperty CommandPlugins Name : aws:runPowerShellScript Output : Directory: C:\ Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 9/12/2016 11:51 AM Logs d----- 12/27/2017 4:32 PM Packages d----- 7/16/2016 1:18 PM PerfLogs d-r--- 2/9/2018 9:39 PM Program Files d----- 9/12/2016 11:55 AM Program Files (x86) d-r--- 12/27/2017 5:12 PM Users d-r--- 12/27/2017 4:30 PM Windows d----- 2/9/2018 8:36 PM WindowsAzure -a---- 2/9/2018 8:35 PM 32517494 AmazonSSMAgentSetup.exe -a---- 2/9/2018 9:39 PM 902 InstallSSMAgent.ps1 -a---- 2/9/2018 8:58 PM 163 SSMServiceRole.json OutputS3BucketName : OutputS3KeyPrefix : OutputS3Region : us-east-1 ResponseCode : 0 ResponseFinishDateTime : 2/9/2018 10:02:14 PM ResponseStartDateTime : 2/9/2018 10:02:13 PM StandardErrorUrl : StandardOutputUrl : Status : Success StatusDetails : Success

Summary

Think about scale for a second. AWS is giving you a tool for free (as of 02/27/18) that allows you to manage as many of your on-prem instances as you want! All of the items we went over in this article can easily be automated now that we have the PowerShell code to make it happen. Setting up the instance activations and installing the SSM agent could be wrapped up in a single PowerShell script. There’s a lot more we can do here. Using SSM to manage on-prem server instances, we leverage AWS’s infrastructure for orchestrating Windows patching, running PowerShell commands, setting up features and whatever else we need to do.

About the Author Adam Bertram is a 20-year veteran of IT. He’s an automation engineer, blogger, consultant, freelance writer, Pluralsight course author and a content marketing advisor to multiple technology companies. Adam focuses on DevOps, system management, and automation technologies as well as various cloud platforms. You can find him blogging at adamtheautomator.com or connect with him on LinkedIn or Twitter @adbertram.

Try N2WS Backup & Recovery (CPM) for FREE !