4

I have defined the creation of a StepFunction state machine in Terraform, now I want to set a timer to trigger the state machine everyday, I think probably using cloudwatch event rules is a good choice, I know how to set event rule to trigger a Lambda:

resource "aws_cloudwatch_event_rule" "lambda_event_rule" {
  name                = xxx
  schedule_expression = xxx
  description         = xxx
}

resource "aws_cloudwatch_event_target" "lambda_event_target" {
  target_id = xxx
  rule      = aws_cloudwatch_event_rule.lambda_event_rule.name
  arn       = xxx
}

#I must setup the right permissions using 'aws_lambda_permission' 
#see: https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_event_target

resource "aws_lambda_permission" "lambda_event_permission" {
  statement_id  = xxx
  action        = "lambda:InvokeFunction"
  function_name = xxx
  principal     = "events.amazonaws.com"
  source_arn    = aws_cloudwatch_event_rule.lambda_event_rule.name
}

but how can I setup the permission part for triggerring a state machine? I couldn't find any examples about it, am I missing anything? Is it because we don't need a permission config for state machine? Can someone help please?

Below is what I got to use cloudwatch event rules to trigger state machine so far:

resource "aws_cloudwatch_event_rule" "step_function_event_rule" {
  name                = xxx
  schedule_expression = xxx
  description         = xxx
}

resource "aws_cloudwatch_event_target" "step_function_event_target" {
  target_id = xxx
  rule      = aws_cloudwatch_event_rule.step_function_event_rule.name
  arn       = xxx
}


?????What else should I add here?

PS: I found someone else was asking about a similar question here, but no answers yet.

wawawa
  • 2,835
  • 6
  • 44
  • 105

2 Answers2

4

The

    resource "aws_lambda_permission" "lambda_event_permission" {
     statement_id  = xxx
     action        = "lambda:InvokeFunction"
     function_name = xxx
     principal     = "events.amazonaws.com"
     source_arn    = aws_cloudwatch_event_rule.lambda_event_rule.name
    }

part is not needed at all in your case, only needed as stated "In order to be able to have your AWS Lambda function or SNS topic invoked by an EventBridge rule".

As blr stated in his answer, you need to add the role_arn in the aws_cloudwatch_event_target, set up a role with assume_role_policy which grants access to states.amazonaws.com and events.amazonaws.com, and attach to this role an extra policy as follows:

    data "aws_iam_policy_document" "CW2SF_allowexec" {
      statement {
        actions = [
          "sts:AssumeRole"
        ]

        principals {
          type = "Service"
          identifiers = [
            "states.amazonaws.com",
            "events.amazonaws.com"
          ]
        }
      }
    }

    resource "aws_iam_role" "CW2SF_allowexec" {
      name               = "AWS_Events_Invoke-StepFunc"
      assume_role_policy = data.aws_iam_policy_document.CW2SF_allowexec.json
    }

    resource "aws_iam_role_policy" "state-execution" {
      name        = "CW2SF_allowexec"
      role   = aws_iam_role.CW2SF_allowexec.id

      policy = <<EOF
    {
      "Version": "2012-10-17",
      "Statement": [
          {
              "Effect": "Allow",
              "Action": [
                  "states:StartExecution"
              ],
              "Resource": [          
"arn:aws:states:${var.region}:${data.aws_caller_identity.current.account_id}:stateMachine:data-pipeline-incremental"
          ]
      }
  ]
}
EOF
} 

You need to establish the trust between CloudWatch and StepFunctions with the AssumeRole, and then attach an inline or managed policy to the role that specifically allows this role to StartExecution of the state machine.

Mar0cR3am
  • 81
  • 4
3

I'm not well versed with terraform but it seems to follow a similar pattern to the official documentation. For targets; https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutTargets.html >> See section "Adds a Step Functions state machine as a target"

{
    "Rule": "testrule", 
    "Targets": [
           {
        "RoleArn": "arn:aws:iam::123456789012:role/MyRoleToAccessStepFunctions"
        "Arn":"arn:aws:states:us-east-1:123456789012:stateMachine:HelloWorld"
      }
    ]
}

This tells me that you need to pass the role and arn. So taking your example, here's the thing you probably need to fill

resource "aws_cloudwatch_event_rule" "step_function_event_rule" {
  name                = <something unique>
  schedule_expression = <syntax described in https://docs.aws.amazon.com/eventbridge/latest/userguide/scheduled-events.html>
  description         = <something descriptive>
}

resource "aws_cloudwatch_event_target" "step_function_event_target" {
  target_id = <something unique>
  rule      = aws_cloudwatch_event_rule.step_function_event_rule.name
  arn       = <step function arn>
  role_arn  = <role that allows eventbridge to start execution on your behalf>
}
blr
  • 908
  • 4
  • 8
  • is this `target_id = ` a required field? – wawawa Jan 05 '21 at 15:34
  • I just checked the doc, it's optinal, I included it anyway, thanks – wawawa Jan 05 '21 at 15:37
  • Based on https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_Target.html, seems to be required. Perhaps terraform creates one for you if you don't set it. – blr Jan 05 '21 at 15:37
  • when I try 'terraform plan', it shows an extra field for the event rule ` + event_bus_name = "default"`, I assume this is better be included in the script otherwise it'll be set to default. – wawawa Jan 05 '21 at 16:25
  • 1
    Yes. It'll be set to default. – blr Jan 13 '21 at 18:52