Cross Account Amazon CloudWatch Metric Sharing
There are scenarios where we would like to share Amazon CloudWatch metrics with another AWS account and then retrieve the data programmatically. Read on!
Join the DZone community and get the full member experience.
Join For FreeThere are scenarios where we would like to share Amazon CloudWatch metrics with another AWS account and then retrieve the data programmatically. This article shows how it can be done.
We will use Boto3, which is an Amazon SDK for python, to retrieve the metrics data.
Enable Cross Account Sharing in CloudWatch
We will work with two AWS accounts Account A and Account B. Our requirement are:
- To share CloudWatch metrics data of Account A with Account B
- Retrieve the shared metrics data programmatically
For clarity purposes, we will make a few assumptions.
- Account A's account Id is 987654321987
- Account B's account Id is 123456789321
- Account B has an IAM user with a user name as an account-b-user.
We will provide Account A CloudWatch metrics access to this account-b-user
To share the CloudWatch metrics of Account A with Account B and retrieve it from Account B, the following things have to be done.
- Create a cross-account sharing stack in Account A
The steps to create a cross-account CloudWatch role are mentioned in this link.
When it asks to enter the account Id, enter the account Id of the account with which metrics data need to be shared. In our case, it is Account B's account Id 123456789321.
Continue with the steps until the stack is created. Next, we will make some changes to the IAM role as mentioned below.
2. Update the IAM role in Account A to give access to a specific IAM user in Account B
- Go to IAM console, roles section of Account A
- A new role "CloudWatch-CrossAccountSharingRole" would have been created
- This role needs to be edited to only give access to a specific IAM user in Account B otherwise all users in Account B can access the metrics from Account A
- Choose this role and go to the Trust relationships tab
- Edit trust relationship, and in the Policy Document, update the Principal with IAM user ARN of Account B. The User ARN will be available in IAM details for that user. User ARN for account-b-user is
arn:aws:iam::123456789321:user/account-b-user
.
xxxxxxxxxx
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789321:user/account-b-user"
},
"Action": "sts:AssumeRole"
}
]
}
With this done, account-b-user can access the metrics in Account A. Please copy the role ARN for "CloudWatch-CrossAccountSharingRole". We will need it to access it via the python program.
For our scenario, the role ARN is:
arn:aws:iam::987654321987:role/CloudWatch-
CrossAccountSharingRole
Retrieve the CloudWatch Metrics
Before writing the program to retrieve the metrics, we need to download and install AWS Command Line Interface or AWS CLI. It can be downloaded from here.
AWS CLI has to be configured with account-b-user credentials. User credentials are available for download as CSV file after an IAM user is created.
To configure AWS CLI with this user; open a command prompt or shell or terminal window and type
aws configure
It will ask for:
- AWS Access Key ID — it will be there in the credential file
- AWS Secret Access Key — it will be there in the credential file
- Default region name — provide the region name
- Default output format — Enter "JSON" here
We will use the Boto3 python library to retrieve the metrics. It can be installed via the below command:
pip install boto3
Now, let's write the python program to retrieve the metrics data.
We will get an instance of a "sts" client which stands for Secure Token Service.
We will use this sts client to retrieve temporary credentials to assume the role of "CloudWatch-CrossAccountSharingRole" which was created in Account A. The temporary credentials default validity is one hour.
x
sts_client = boto3.client('sts')
sts_response = sts_client.assume_role(e(
# The below RoleArn will be the ARN value from the other account
# which has this role - CloudWatch-CrossAccountSharingRole
RoleArn='arn:aws:iam::987654321987:role/CloudWatch-CrossAccountSharingRole',
RoleSessionName='cloudwatch-share-acct-session'
)
The sts_response object will contain the access key Id, secret access key, and session token. We need these details to connect to Account A.
Next, we will retrieve the list of EC2 instances in Account A, iterate over this list and get the metrics for each EC2 instance.
x
# Get the access_key_id, secret_access_key, session_token
access_key_id = sts_response["Credentials"]['AccessKeyId']
secret_access_key = sts_response["Credentials"]['SecretAccessKey']
session_token = sts_response["Credentials"].get('SessionToken', '')
if access_key_id != '':
# Get the list of EC2 instances
ec2_client = boto3.client('ec2',
aws_access_key_id=access_key_id,
aws_secret_access_key=secret_access_key,
aws_session_token=session_token
)
ec2_description = ec2_client.describe_instances()
for reservation in ec2_description["Reservations"]:
for instance in reservation["Instances"]:
instance_id = instance['InstanceId']
cloudwatch = boto3.client('cloudwatch',
aws_access_key_id=access_key_id,
aws_secret_access_key=secret_access_key,
aws_session_token=session_token
)
By default, AWS enables a certain set of metrics, and CPU Utilization is one of them. We will retrieve the CPU Utilization metrics in this example.
metrics_response = cloudwatch.get_metric_data(
MetricDataQueries=[
{
"Id": "cpu",
"MetricStat": {
"Metric": {
"Namespace": "AWS/EC2",
"MetricName": "CPUUtilization",
"Dimensions": [
{
"Name": "InstanceId",
"Value": instance_id # instance id of EC2
}
]
},
"Period": 3600, # Hourly metrics
"Stat": "Average", # Average utilization in an hour
"Unit": "Percent"
},
"Label": "CPUUtilizationResponse",
"ReturnData": True
}
],
# Date in format datetime(2020, 6, 16). Generate the date values dynamically
StartTime=datetime(2020, 6, 16),
EndTime=datetime(2020, 6, 17)
)
# Now you can work on this metrics response.
print(json.dumps(metrics_response, indent=2, default=str))
The sample response will look like below. It shows the hourly aggregate of CPU Utilization metrics.
xxxxxxxxxx
{
"MetricDataResults": [
{
"Id": "cpu",
"Label": "CPUUtilizationResponse",
"Timestamps": [
"2020-06-16 12:00:00+00:00",
"2020-06-16 11:00:00+00:00",
"2020-06-16 10:00:00+00:00",
"2020-06-16 09:00:00+00:00",
"2020-06-16 08:00:00+00:00",
"2020-06-16 07:00:00+00:00",
"2020-06-16 06:00:00+00:00",
"2020-06-16 05:00:00+00:00",
"2020-06-16 04:00:00+00:00",
"2020-06-16 03:00:00+00:00",
"2020-06-16 02:00:00+00:00",
"2020-06-16 01:00:00+00:00",
"2020-06-16 00:00:00+00:00"
],
"Values": [
0.1169491525423757,
0.13014571948998135,
0.12728149794696045,
0.12154379302892791,
0.13279769071655734,
0.12501852366398075,
0.13071223488005893,
0.13034639251644017,
0.13048308438167652,
0.130252230557871,
0.13080639683862805,
0.1720130591831061,
0.12214658392763429
],
"StatusCode": "Complete"
}
],
"Messages": [],
"ResponseMetadata": {
"RequestId": "78d5f076-0f6d-4989-9402-5b722bc80bbd",
"HTTPStatusCode": 200,
"HTTPHeaders": {
"x-amzn-requestid": "78d5f076-0f6d-4989-9402-5b722bc80bbd",
"content-type": "text/xml",
"content-length": "4636",
"vary": "accept-encoding",
"date": "Sun, 21 Jun 2020 12:15:25 GMT"
},
"RetryAttempts": 0
}
}
This is how we can share the metrics data across two AWS accounts and retrieve it.
The full code is available here.
Opinions expressed by DZone contributors are their own.
Comments