{{announcement.body}}
{{announcement.title}}

Cross Account Amazon CloudWatch Metric Sharing

DZone 's Guide to

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!

· Cloud Zone ·
Free Resource

There 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.

  1. Account A's account Id is 987654321987
  2. Account B's account Id is 123456789321
  3. 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.

  1. 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

trust relationships

  • 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.
JSON
 




xxxxxxxxxx
1
12


 
1
{
2
  "Version": "2012-10-17",
3
  "Statement": [
4
    {
5
      "Effect": "Allow",
6
      "Principal": {
7
        "AWS": "arn:aws:iam::123456789321:user/account-b-user"
8
      },
9
      "Action": "sts:AssumeRole"
10
    }
11
  ]
12
}



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.

Python
 




x





1
sts_client = boto3.client('sts')
2
sts_response = sts_client.assume_role(e(
3
  # The below RoleArn will be the ARN value from the other account
4
  # which has this role - CloudWatch-CrossAccountSharingRole
5
  RoleArn='arn:aws:iam::987654321987:role/CloudWatch-CrossAccountSharingRole',
6
  RoleSessionName='cloudwatch-share-acct-session'
7
)



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. 

Python
 




x




1
# Get the access_key_id, secret_access_key, session_token
2
access_key_id = sts_response["Credentials"]['AccessKeyId']
3
secret_access_key = sts_response["Credentials"]['SecretAccessKey']
4
session_token = sts_response["Credentials"].get('SessionToken', '')
5
if access_key_id != '':
6
  # Get the list of EC2 instances
7
  ec2_client = boto3.client('ec2',
8
                            aws_access_key_id=access_key_id,
9
                            aws_secret_access_key=secret_access_key,
10
                            aws_session_token=session_token
11
                           )
12
  ec2_description = ec2_client.describe_instances()
13
  for reservation in ec2_description["Reservations"]:
14
    for instance in reservation["Instances"]:
15
      instance_id = instance['InstanceId']
16
 
          
17
      cloudwatch = boto3.client('cloudwatch',
18
                                aws_access_key_id=access_key_id,
19
                                aws_secret_access_key=secret_access_key,
20
                                aws_session_token=session_token
21
                               )



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. 

Python
 




x
30


 
1
metrics_response = cloudwatch.get_metric_data(
2
  MetricDataQueries=[
3
    {
4
      "Id": "cpu",
5
      "MetricStat": {
6
        "Metric": {
7
          "Namespace": "AWS/EC2",
8
          "MetricName": "CPUUtilization",
9
          "Dimensions": [
10
            {
11
              "Name": "InstanceId",
12
              "Value": instance_id # instance id of EC2
13
            }
14
          ]
15
        },
16
        "Period": 3600, # Hourly metrics
17
        "Stat": "Average", # Average utilization in an hour
18
        "Unit": "Percent"
19
      },
20
      "Label": "CPUUtilizationResponse",
21
      "ReturnData": True
22
    }
23
  ],
24
  # Date in format datetime(2020, 6, 16). Generate the date values dynamically
25
  StartTime=datetime(2020, 6, 16), 
26
  EndTime=datetime(2020, 6, 17)
27
)
28
# Now you can work on this metrics response.
29
print(json.dumps(metrics_response, indent=2, default=str))
30
 
          



The sample response will look like below. It shows the hourly aggregate of CPU Utilization metrics.

JSON
 




xxxxxxxxxx
1
52


 
1
{
2
  "MetricDataResults": [
3
    {
4
      "Id": "cpu",
5
      "Label": "CPUUtilizationResponse",
6
      "Timestamps": [
7
        "2020-06-16 12:00:00+00:00",
8
        "2020-06-16 11:00:00+00:00",
9
        "2020-06-16 10:00:00+00:00",
10
        "2020-06-16 09:00:00+00:00",
11
        "2020-06-16 08:00:00+00:00",
12
        "2020-06-16 07:00:00+00:00",
13
        "2020-06-16 06:00:00+00:00",
14
        "2020-06-16 05:00:00+00:00",
15
        "2020-06-16 04:00:00+00:00",
16
        "2020-06-16 03:00:00+00:00",
17
        "2020-06-16 02:00:00+00:00",
18
        "2020-06-16 01:00:00+00:00",
19
        "2020-06-16 00:00:00+00:00"
20
      ],
21
      "Values": [
22
        0.1169491525423757,
23
        0.13014571948998135,
24
        0.12728149794696045,
25
        0.12154379302892791,
26
        0.13279769071655734,
27
        0.12501852366398075,
28
        0.13071223488005893,
29
        0.13034639251644017,
30
        0.13048308438167652,
31
        0.130252230557871,
32
        0.13080639683862805,
33
        0.1720130591831061,
34
        0.12214658392763429
35
      ],
36
      "StatusCode": "Complete"
37
    }
38
  ],
39
  "Messages": [],
40
  "ResponseMetadata": {
41
    "RequestId": "78d5f076-0f6d-4989-9402-5b722bc80bbd",
42
    "HTTPStatusCode": 200,
43
    "HTTPHeaders": {
44
      "x-amzn-requestid": "78d5f076-0f6d-4989-9402-5b722bc80bbd",
45
      "content-type": "text/xml",
46
      "content-length": "4636",
47
      "vary": "accept-encoding",
48
      "date": "Sun, 21 Jun 2020 12:15:25 GMT"
49
    },
50
    "RetryAttempts": 0
51
  }
52
}



This is how we can share the metrics data across two AWS accounts and retrieve it.

The full code is available here.

Topics:
amazon, aws cloudwatch, cloud, iam, tutorial

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}