title: AWS CloudWatch Cross-Account Logging with EC2 Instance Profile
body: <p>When I originally setup CloudWatch, I created an EC2 Instance Profile to automatically grant access to write to the account's own CloudWatch service.  Now, I would like to consolidate the logs from several accounts into a central account.    </p>
  
  <p>I'd like to implement a simplified architecture that is based on <a href="https://docs.aws.amazon.com/solutions/latest/centralized-logging/architecture.html" rel="nofollow noreferrer">Centralized Logging on AWS</a>. However, these logs will feed an on-premise ELK stack, so I'm only trying to implement the components outlined in red.  I would like to solve this without the use of Kinesis.</p>
  
  <p><a href="https://i.stack.imgur.com/Qax6N.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/Qax6N.png" alt="simplified central logging on aws"></a></p>
  
  <p>Either the CloudWatch Agent (CWAgent) doesn't support assuming a role or I can't wrap my mind around how to craft the EC2 Instance Profile to allow the CWAgent to assume a role in a different account.  </p>
  
  <p><strong>Logging Target (AWS Account 111111111111)</strong></p>
  
  <p>IAM LogStreamerRole:</p>
  
  <pre><code>{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "AWS": [
            "arn:aws:iam::999999999999:role/EC2CloudWatchLoggerRole"
          ]
        },
        "Action": "sts:AssumeRole",
        "Condition": {}
      }
    ]
  }
  </code></pre>
  
  <p>&nbsp;</p>
  
  <pre><code>{
      "Version": "2012-10-17",
      "Statement": [
          {
              "Sid": "",
              "Effect": "Allow",
              "Action": [
                  "logs:CreateLogGroup",
                  "logs:CreateLogStream",
                  "logs:PutLogEvents"
              ],
              "Resource": [
                  "arn:aws:logs:*:*:*"
              ]
          }
      ]
  }
  </code></pre>
  
  <p><strong>Logging Source (AWS Account 999999999999)</strong></p>
  
  <p>IAM Instance Profile Role:</p>
  
  <pre><code>{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "Service": "ec2.amazonaws.com"
        },
        "Action": "sts:AssumeRole"
      }
    ]
  }
  </code></pre>
  
  <p>&nbsp;</p>
  
  <pre><code>{
      "Version": "2012-10-17",
      "Statement": [
          {
              "Sid": "",
              "Effect": "Allow",
              "Action": "sts:AssumeRole",
              "Resource": "arn:aws:iam::111111111111:role/LogStreamerRole"
          }
      ]
  }
  </code></pre>
  
  <p>The CWAgent is producing the following error:</p>
  
  <pre><code>/opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log:
  2018-02-12T23:27:43Z E! CreateLogStream / CreateLogGroup with log group name Linux/var/log/messages stream name i-123456789abcdef has errors. Will retry the request: AccessDeniedException: User: arn:aws:sts::999999999999:assumed-role/EC2CloudWatchLoggerRole/i-123456789abcdef is not authorized to perform: logs:CreateLogStream on resource: arn:aws:logs:us-west-2:999999999999:log-group:Linux/var/log/messages:log-stream:i-123456789abcdef
      status code: 400, request id: 53271811-1234-11e8-afe1-a3c56071215e
  </code></pre>
  
  <p>It is still trying to write to its own CloudWatch service, instead of to the central CloudWatch service.</p>