0
votes

I have a CloudWatch rule set up to trigger a Lambda function whenever a new AWS account is created. I am using API Calls from CloudTrail with the EventName CreateAccountResult. Within the CloudTrail log, it basically gives me these details:

"serviceEventDetails": {
   "createAccountStatus": {
       "id": "string",
       "state": "SUCCEEDED",
       "accountName": "****",

       "accountId": " *accountID* ",

       "requestedTimestamp": "date/time",
       "completedTimestamp": "date/time"

The lambda function that gets triggered is written in Python 3.7 and uses this account ID to create an AWS connector to a program called Trend Micro Deep Security. Currently, I manually take this account ID, swap it out with the variable, and run the script:

import http.client
import mimetypes

def lambda_handler(event,context):
  account = ' *accountID* '
  conn = http.client.HTTPSConnection("app.deepsecurity.trendmicro.com", 443)
  payload = "{\n    \"crossAccountRoleArn\": \"arn:aws:iam::" + account + ":role/*role*\",\n    \"workspacesEnabled\": true\n}"
  headers = {
    'api-version': 'v1',
    'Content-Type': 'application/json',
    'api-secret-key': 'string'
  }
  conn.request("POST", "/api/awsconnectors", payload, headers)
  res = conn.getresponse()
  data = res.read()
  print(data.decode("utf-8"))

What I would like to be able to do, is write some code into the lambda function that pulls the account ID from the CloudTrail event that triggered the Lambda function and use that to replace variable string to complete this script, essentially automating the process.

Is anyone aware of a way to accomplish this?

Thank you in advance!

EDIT: I need to be able to test this before implementing, but I am not able to create accounts freely for trial and error. If you could also provide a means to pull the account ID from an existing CloudTrail log so that I can test its function, that would be greatly appreciated.

I have been testing using EC2 instances to pull the instance ID, but AWS account creation and EC2 instance creation seem too far different to accurately test this.

2

2 Answers

0
votes
  1. If your event rule is as below then you can modify lambda code fetch details from same event.

     {
       "source": [
         "aws.cloudtrail"
       ],
       "detail-type": [
         "AWS API Call via CloudTrail"
       ],
       "detail": {
         "eventSource": [
           "cloudtrail.amazonaws.com"
         ],
         "eventName": [
           "CreateAccountResult"
         ]
       }
     }
    
  2. I have modified the lambda code to use same event rule invocation to get account ID details and execute.

     import http.client
     import mimetypes
    
     def lambda_handler(event,context):
         if (event and event['detail-type'] == 'AWS API Call via CloudTrail'):
             event_state = event['createAccountStatus']['state']
             event_accountId = event['createAccountStatus']['accountId']
             if event_state == 'SUCCEEDED':
                 account = event_accountId
                 conn = http.client.HTTPSConnection("app.deepsecurity.trendmicro.com", 443)
                 payload = "{\n    \"crossAccountRoleArn\": \"arn:aws:iam::" + account + ":role/*role*\",\n   \"workspacesEnabled\": true\n}"
                 headers = {
                   'api-version': 'v1',
                   'Content-Type': 'application/json',
                   'api-secret-key': 'string'
                 }
                 conn.request("POST", "/api/awsconnectors", payload, headers)
                 res = conn.getresponse()
                 data = res.read()
                 print(data.decode("utf-8"))
             else:
                 logger.info(event)
         else:
             logger.warning(f"Unhandeled event: {event}")
    

Lambda will only execute when state is SUCCEEDED

Note: I need full event response to get accurate details for these two lines

event_state = event['createAccountStatus']['state']
event_accountId = event['createAccountStatus']['accountId']
0
votes

Thanks Guys!

Been tinkering with this answer to come to a conclusion. Looks like our trigger is slightly different...

{
  "detail": {
    "eventSource": [
      "organizations.amazonaws.com"
    ],
    "eventName": [
      "CreateAccountResult"
    ]
  }
}

Though, we haven't verified this completely, just basing it off of tests with EC2 instances modified to accept created accounts. Looks like the CloudTrail log spits out a bit differently, but looks like the keys are generally the same:

{
    "eventVersion": "1.05",
    "userIdentity": {
        "accountId": "###",
        "invokedBy": "AWS Internal"
    },
    "eventTime": "date/time",
    "eventSource": "organizations.amazonaws.com",
    "eventName": "CreateAccountResult",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "AWS Internal",
    "userAgent": "AWS Internal",
    "requestParameters": null,
    "responseElements": null,
    "eventID": "###",
    "readOnly": false,
    "eventType": "AwsServiceEvent",
    "recipientAccountId": "###",
    "serviceEventDetails": {
        "createAccountStatus": {
            "id": " car-#### ",
            "state": "SUCCEEDED",
            "accountName": "****",
            "accountId": " *accountID* ",
            "requestedTimestamp": "date/time",
            "completedTimestamp": "date/time"
        }
    }
}