Or: Yet another encounter with undocumented nuance on AWS

Recently, I needed to setup an SSM Automation doc via Terraform. This was to support a workflow of gracefully shutting down an instance upon a termination event. The basic flow went like this:

  1. instance terminates
  2. ASG lifecycle hook executes
  3. Cloudwatch event rule is triggered
  4. SSM Automation starts
  5. Python script on instance executes
  6. SSM Automation notifies lifecycle hook of success
  7. lifecycle hook continues instance termination.

So from this flow, you can ascertain that the following resources need to be created via Terraform:

  • ASG lifecycle hook
  • SSM Automation doc
  • Cloudwatch Event Rule
  • IAM stuff everywhere

Most of those resources are straightforward (I mean, as straightforward as IAM can be while still being a constant PITA), but one sharp edge I found was pointing the Cloudwatch Event Rule at the SSM Automation doc.

One of the tricky things with the SSM automation is filling in the arn parameter on the aws_cloudwatch_event_target resource. Typically, you would just be able to take the arn output of whatever other resource you created. However, for some reason, when you get the output from the SSM document (i.e. aws_ssm_document.this.arn) the ARN it outputs doesn’t match the scheme that Cloudwatch is expecting.

For example, the standard ARN for SSM documents looks like this:

arn:${Partition}:ssm:${Region}:${Account}:document/${DocumentName}

However, when using the document as an automation definition, AWS expects it to have an ARN matching this pattern:

arn:${Partition}:ssm:${Region}:${Account}:automation-definition/${AutomationDefinitionName:VersionId}

Even though one should be using DocumentName and another should be using AutomationDefinitionName, for our purposes, they’re the same. And for some reason, omitting the :VersionId part doesn’t matter, either. So, all you have to do is in your Cloudwatch Event resource, put a simple string replace on the output ARN, to change the document/ path to automation-definition/:

resource "aws_cloudwatch_event_target" "graceful_shutdown" {
  arn      = "${replace("${aws_ssm_document.graceful_shutdown.arn}", "document/", "automation-definition/")}"
  rule     = "${aws_cloudwatch_event_rule.graceful_shutdown.name}"
  role_arn = "${aws_iam_role.graceful_shutdown_events.arn}"
}

Once again, a very simple solution to a very obtuse problem on AWS.

Thanks to @pvanbuijtene on this Github issue who actually solved this problem.