Incident Ingest

AWS CloudWatch + Alert24 Integration: Create Incidents from Alarms

Automatically create Alert24 incidents when AWS CloudWatch alarms fire using SNS and a Lambda function. Includes Python handler, deployment steps, and auto-resolution.

AWS CloudWatch alarms can notify an SNS topic. By subscribing a small Lambda function to that topic, you get a fully serverless pipeline that creates Alert24 incidents whenever an alarm enters the ALARM state.

Before you start

You'll need:

  • An Alert24 API key with write or incidents scope (Settings → API Keys), stored in AWS Secrets Manager or SSM Parameter Store
  • An existing SNS topic (or create one: aws sns create-topic --name alert24-incidents)
  • Lambda deployment permissions

Lambda function

import json
import os
import urllib.request

API_KEY = os.environ['ALERT24_API_KEY']

SEVERITY_MAP = {
    'ALARM': 'critical',
    'INSUFFICIENT_DATA': 'medium',
}

def lambda_handler(event, context):
    for record in event.get('Records', []):
        message = json.loads(record['Sns']['Message'])

        state = message.get('NewStateValue', 'ALARM')
        if state == 'OK':
            continue  # auto-resolution not handled here; extend if needed

        alarm_name = message.get('AlarmName', 'Unknown alarm')
        description = message.get('NewStateReason', '')
        region = message.get('Region', '')

        payload = json.dumps({
            'title': f'AWS: {alarm_name}',
            'description': description,
            'severity': SEVERITY_MAP.get(state, 'medium'),
            'alias': f'cloudwatch-{alarm_name.replace(" ", "-")}',
            'source': 'cloudwatch',
            'tags': ['aws', 'cloudwatch', region],
        }).encode()

        req = urllib.request.Request(
            'https://app.alert24.net/api/v1/incidents',
            data=payload,
            headers={
                'Authorization': f'Bearer {API_KEY}',
                'Content-Type': 'application/json',
            },
            method='POST'
        )
        with urllib.request.urlopen(req) as resp:
            print(resp.read().decode())

    return {'statusCode': 200}

Deploy via AWS CLI

# Package and deploy
zip function.zip lambda_function.py

aws lambda create-function \
  --function-name alert24-cloudwatch-incidents \
  --runtime python3.12 \
  --handler lambda_function.lambda_handler \
  --zip-file fileb://function.zip \
  --role arn:aws:iam::YOUR_ACCOUNT:role/lambda-basic-execution \
  --environment Variables={ALERT24_API_KEY=ak_live_YOUR_KEY}

# Subscribe to SNS
aws sns subscribe \
  --topic-arn arn:aws:sns:us-east-1:YOUR_ACCOUNT:alert24-incidents \
  --protocol lambda \
  --notification-endpoint arn:aws:lambda:us-east-1:YOUR_ACCOUNT:function:alert24-cloudwatch-incidents

# Grant SNS permission to invoke Lambda
aws lambda add-permission \
  --function-name alert24-cloudwatch-incidents \
  --statement-id sns-invoke \
  --action lambda:InvokeFunction \
  --principal sns.amazonaws.com \
  --source-arn arn:aws:sns:us-east-1:YOUR_ACCOUNT:alert24-incidents

Wire a CloudWatch alarm to the SNS topic

aws cloudwatch put-metric-alarm \
  --alarm-name "HighCPU-prod" \
  --alarm-actions arn:aws:sns:us-east-1:YOUR_ACCOUNT:alert24-incidents \
  --metric-name CPUUtilization \
  --namespace AWS/EC2 \
  --statistic Average \
  --period 300 \
  --threshold 80 \
  --comparison-operator GreaterThanThreshold \
  --evaluation-periods 2

Or add the SNS action to existing alarms in the CloudWatch console under Actions → In alarm → Add notification.

Tips

  • Secrets Manager: Store the API key in Secrets Manager and retrieve it at Lambda cold start rather than using an environment variable for better security.
  • Multiple alarms: All CloudWatch alarms can publish to the same SNS topic. One Lambda handles all of them.
  • Auto-resolution: To resolve Alert24 incidents when the alarm returns to OK, handle the state == 'OK' case by calling GET /api/v1/incidents?alias=cloudwatch-{alarm_name} then PUT /api/v1/incidents/{id} with status: resolved.
  • Composite alarms: CloudWatch composite alarms send the same SNS message format — this Lambda handles them identically.