CloudWatch Rule Events

Important: These docs are for the outdated Jets 5 versions and below. For the latest Jets docs: docs.rubyonjets.com

Jets supports CloudWatch Event Rules. This allows you to have a Lambda function run when there’s a change to AWS resources. Here’s an extensive list of supported Event Types.

Example

Generate code.

jets generate job security --type rule --name detect_security_group_changes

It looks something like this.

An example might be getting notified when an unwanted security group port gets opened.

app/jobs/security_job.rb

class SecurityJob < ApplicationJob
  rule_event(
    description: "Checks for security group changes",
    detail_type: ["AWS API Call via CloudTrail"],
    detail: {
      event_source: ["ec2.amazonaws.com"],
      event_name: [
        "AuthorizeSecurityGroupIngress",
        "AuthorizeSecurityGroupEgress",
        "RevokeSecurityGroupIngress",
        "RevokeSecurityGroupEgress",
        "CreateSecurityGroup",
        "DeleteSecurityGroup"
      ]
    }
  )
  def detect_security_group_changes
    puts "event: #{JSON.dump(event)}" # event is available
    # your logic
  end
end

The rule_event declaration creates an AWS::Events::Rule and sets the event_pattern attributes. The description property is treated specially and is added as a property to the AWS::Events::Rule structure appropriately.

Note, events for security group changes come from CloudTrail and currently take about 15 minutes to be delivered. Here’s what the event rule looks like in the CloudWatch console:

Here’s an example from the CloudWatch log when the Lambda function runs:

Complete Form

If you need more control, and you can also set any properties of the AWS::Events::Rule by passing a hash. Here’s another example that detects when an instance goes into stopping state.

class SecurityJob < ApplicationJob
  rule_event(
    description: "Detects when instance stops",
    event_pattern: {
      source: ["aws.ec2"],
      detail_type: ["EC2 Instance State-change Notification"],
      detail: {
        state: ["stopping"],
      }
    }
  )
  def instance_stopping
    puts "event #{JSON.dump(event)}" # event is available
    # logic goes here
  end
end

This pattern of watching CloudWatch events can be used for things like automatically closing security group ports that get unintentionally opened. CloudWatch Events opens up a world of possibilities.

Tailing Logs

It helps to tail the logs and watch the event as it comes through.

jets logs -f -n security_job-instance_stopping

Multiple Events Support

Registering multiple events to the same Lambda function is supported. Add multiple rule_event declarations above the method definition. Example:

class SecurityJob < ApplicationJob
  rule_event(
    source: ["aws.ec2"],
    detail_type: ["EC2 Instance State-change Notification"],
    detail: {
      state: ["stopping"],
    }
  )
  rule_event(
    detail_type: ["AWS API Call via CloudTrail"],
    detail: {
      userIdentity: {
        type: ["Root"]
      }
    }
  )
  rate "10 hours"
  def perform_some_logic
    puts "event: #{JSON.dump(event)}" # event is available
    # logic goes here
  end
end

Notice in the above example that you can even mix in the rate declaration with the Lambda function. Underneath the hood rate delegates to the rule_event method.