AWS Device Groups

Last updated on 24 February, 2021

You can use LogicMonitor’s REST API to manage AWS groups.  AWS groups are just LogicMonitor device groups with a few key differences.  This document covers the differences, as well as how to add & update AWS Groups.

AWS Group Differentiators

  1. AWS Specific groupType: AWS groups have a special groupType value.  Specifically, normal and dynamic groups will have a groupType value of Normal, while AWS device groups will have a value of AWS/SERVICE, where SERVICE is the AWS service the group was created for (e.g. EC2, RDS, S3, etc.).  The AWS account level group will have a groupType value of AWS/AwsRoot.
  2. AWS specific fields: The awsRegionsInfo, awsTestResult and awsTestResultCode are all read-only fields specific to AWS groups. More importantly, AWS group specific information, such as AWS account credentials & AWS service/region configurations, are included in the ‘extra’ object in the device group JSON.  Specifically the extra object includes the following information:
Property Description Type Example
default The default service settings configured for the AWS group. This should include selectAll (can be used to select all regions for monitoring), monitoringRegions (can be used to select specific regions for monitoring), deadOperation (MANUALLY | KEEP_7_DAYS | KEEP_14_DAYS | KEEP_30_DAYS | IMMEDIATELY), useDefault (not applicable to default object), nameFilter (not applicable to default object), tags (used to specify tag filters) JSON Array “default”:{“selectAll”:true,”monitoringRegions”:[“US_EAST_1″,”US_EAST_2″,”US_WEST_1″,”US_WEST_2″,”EU_WEST_1″,”EU_CENTRAL_1″,”AP_SOUTH_1″,”AP_SOUTHEAST_1″,”AP_SOUTHEAST_2″,”AP_NORTHEAST_1″,”AP_NORTHEAST_2″,”SA_EAST_1″],”deadOperation”:”MANUALLY”,”useDefault”:false,”nameFilter”:[ ],”tags”:[{“name” : “system.aws.tag.Name”,”value”:”ecs”},{“name”:”system.aws.tag.Name”,”value”:”linux*”}]}
services The service settings for the AWS Group. This should include selectAll (can be used to select all regions for monitoring), monitoringRegions (can be used to select specific regions for monitoring), deadOperation (MANUALLY | KEEP_7_DAYS | KEEP_14_DAYS | KEEP_30_DAYS | IMMEDIATELY), useDefault (whether or not default settings should be applied), nameFilter (only applicable as a filter for DynamoDB, SQS, SNS, ECS, APIGateway and SWF), tags (used to specify tag filters) JSON Array “services”:{“selectAll”:false,”monitoringRegions”:[“US_EAST_1″,”US_EAST_2″],”deadOperation”:”KEEP_7_DAYS”,”useDefault”:false,”nameFilter”:[ ],”tags”:[{“name” : “system.aws.tag.Name”,”value”:”ecs”}]}
account The account level information for the AWS Group. This should include assumedRoleArn (required), externalId (required), accountId (optional), schedule (optional -discovery frequency in cron syntax), billingBucketName (only required if you want to enable Billing monitoring), billingBucketPrefix (only required if you want to enable billing monitoring) and collectorId (optional) JSON Array “account”:{“accountId”:”000678212345″,”schedule”:”0 * * * *”,”assumedRoleArn”:”arn:aws:iam::000678212345:role/crossAccountRoleProd”,”externalId”:”d0ee51f3-o9r2-4c94-h9ew-345t72dbff04″,”collectorId”:200,”type”:”cross-account”,”billingBucketName”:”prodBillingS3″,”billingBucketPrefix”:”billing/prod”}

Adding an AWS Group

LogicMonitor requires a designated AWS IAM Cross Account Role to authenticate CloudWatch data collection requests.  When you add your AWS account into LogicMonitor you’ll need to provide such a role. As such, to add an AWS Group you’ll need to:

  1. Make a GET request to /aws/externalId resource (i.e. GET “https://ACCOUNT.logicmonitor.com/santaba/rest/aws/externalId”) to get an external Id. Note that this external Id is only valid for one hour, and must be requested by the same user that will perform step 2 (which enables LM to verify the external Id for step 2).
  2. Create an AWS cross account role with the external Id from step 1 for LogicMonitor’s Account Id (282028653949).  You can do this programmatically via AWS development tools (e.g. CLI, SDK).
  3. Make a POST request to the /device/groups resource to add your AWS account into LogicMonitor.

Examples

1. Get External ID

The following Python script requests an external Id for account api.logicmonitor.com:

#!/bin/env python
import requests
import json
import hashlib
import base64
import time
import hmac

#Account Info
AccessId ='48v2wRzfK94y53sq5EuF'
AccessKey ='H_D9i(f5~B^U36^K6i42=^nS~e75gy382Bf6{)P+'
Company = 'api'

#Request Info
httpVerb ='GET'
resourcePath = '/aws/externalId'
queryParams =''
data= ''

#Construct URL 
url = 'https://'+ Company +'.logicmonitor.com/santaba/rest' + resourcePath +queryParams

#Get current time in milliseconds
epoch = str(int(time.time() * 1000))

#Concatenate Request details
requestVars = httpVerb + epoch + data + resourcePath

#Construct signature
hmac1 = hmac.new(AccessKey.encode(),msg=requestVars.encode(),digestmod=hashlib.sha256).hexdigest()
signature = base64.b64encode(hmac1.encode())

#Construct headers
auth = 'LMv1 ' + AccessId + ':' + signature.decode() + ':' + epoch
headers = {'Content-Type':'application/json','Authorization':auth}

#Make request
response = requests.get(url, data=data, headers=headers)

#Print status and body of response
print('Response Status:',response.status_code)
print('Response Body:',response.content)
Python 3

2. POST new AWS group

The following Python script request adds an AWS Group named ‘LM AWS’.  The default service settings section only has three regions selected: us-east-1, us-west-1 and us-west-2, and resources are not set to be automatically deleted.  The EC2 service is selected for monitoring, where EC2 has two tag filters applied, nine regions selected, and resources are set to be automatically deleted after 7 days.  The auto discovery frequency for the account is not set, and will default to every hour, and a billing bucket named ‘ProdS3Billing’ is provided with prefix ‘billing/prod’.  Additionally, a property ‘customer’ is added to the group and set to the value ‘customerA’.

#!/bin/env python

import requests
import json
import hashlib
import base64
import time
import hmac

#Account Info
AccessId ='48v2wRzfK94y53sq5EuF'
AccessKey ='H_D9i(f5~B^U36^K6i42=^nS~e75gy382Bf6{)P+'
Company = 'api'

#Request Info
httpVerb ='POST'
resourcePath = '/device/groups'
queryParams =''
data = '{"groupType":"AWS/AwsRoot", "name": "LM AWS", "description": "device description", "disableAlerting": false, "customProperties": [{"name": "customer", "value":"customerA"}], "parentId": 1, "extra":{"default": {"selectAll": false, "monitoringRegions": ["US_EAST_1", "US_WEST_1", "US_WEST_2"],"deadOperation": "MANUALLY","tags":[]},"services": {"EC2": {"selectAll": true, "tags": [{"name": "system.aws.tag.Name", "value": "ecs"},{"name": "system.aws.tag.Name", "value": "linux*"}],"monitoringRegions": ["US_EAST_1", "US_WEST_1", "US_WEST_2", "EU_WEST_1", "EU_CENTRAL_1", "AP_SOUTHEAST_1", "AP_SOUTHEAST_2","AP_NORTHEAST_1","SA_EAST_1"],"useDefault":false, "deadOperation": "KEEP_7_DAYS"}},"account": {"externalId":"df77ccda-a965-4ed6-af33-4f07568eedaa","assumedRoleArn":"arn:aws:iam::000123456789:role/crossAccountRoleProd","billingBucketName":"ProdS3Billing","billingBucketPrefix":"billing/prod"}}}'

#Construct URL 
url = 'https://'+ Company +'.logicmonitor.com/santaba/rest' + resourcePath + queryParams

#Get current time in milliseconds
epoch = str(int(time.time() * 1000))

#Concatenate Request details
requestVars = httpVerb + epoch + data + resourcePath

#Construct signature
hmac1 = hmac.new(AccessKey.encode(),msg=requestVars.encode(),digestmod=hashlib.sha256).hexdigest()
signature = base64.b64encode(hmac1.encode())

#Construct headers
auth = 'LMv1 ' + AccessId + ':' + signature.decode() + ':' + epoch
headers = {'Content-Type':'application/json','Authorization':auth}

#Make request
response = requests.post(url, data=data, headers=headers)

#Print status and body of response
print('Response Status:',response.status_code)
print('Response Body:',response.content)
Python 3

Updating an AWS Group

If you’re updating an AWS Group, we recommend first making a GET request to get the group JSON, parsing the output, replacing the desired values, and then using PUT to update the resource.

Example

The following Python script makes a GET request to get device group 39 (which happens to be the AWS root group), parses out the response, replaces the assigned Collector, adds the configuration object, and then makes a PUT request to update the group 39:

#!/bin/env python

import requests
import json
import hashlib
import base64
import time
import hmac

#Account Info
AccessId ='48v2wRzfK94y53sq5EuF'
AccessKey ='H_D9i(f5~B^U36^K6i42=^nS~e75gy382Bf6{)P+'
Company = 'api'

#Request Info
httpVerb ='GET'
resourcePath = '/device/groups/39'

#Construct URL 
url = 'https://'+ Company +'.logicmonitor.com/santaba/rest' + resourcePath 

#Get current time in milliseconds
epoch = str(int(time.time() * 1000))

#Concatenate Request details
requestVars = httpVerb + epoch + resourcePath

#Construct signature
hmac1 = hmac.new(AccessKey.encode(),msg=requestVars.encode(),digestmod=hashlib.sha256).hexdigest()
signature = base64.b64encode(hmac1.encode())

#Construct headers
auth = 'LMv1 ' + AccessId + ':' + signature.decode() + ':' + epoch
headers = {'Content-Type':'application/json','Authorization':auth}

#Make request
response = requests.get(url, headers=headers)

#Parse response
jsonResponse = json.loads(response.content)

#Change Collector Id and add configuration object
group = jsonResponse['data']
group['extra']['account']['collectorId'] = 218

#PUT Request Info
httpVerb ='PUT'
resourcePath = '/device/groups/39'
queryParams =''
data = str(json.dumps(group))

#Construct URL 
url = 'https://'+ Company +'.logicmonitor.com/santaba/rest' + resourcePath +queryParams

#Get current time in milliseconds
epoch = str(int(time.time() * 1000))

#Concatenate Request details
requestVars = httpVerb + epoch + data + resourcePath

#Construct signature
hmac1 = hmac.new(AccessKey.encode(),msg=requestVars.encode(),digestmod=hashlib.sha256).hexdigest()
signature = base64.b64encode(hmac1.encode())

#Construct headers
auth = 'LMv1 ' + AccessId + ':' + signature.decode() + ':' + epoch
headers = {'Content-Type':'application/json','Authorization':auth}

#Make request
putResponse = requests.put(url, data=data, headers=headers)

#Print status and body of response
print('Response Status:',response.status_code)
print('Response Body:',response.content)
Python 3
In This Article