Skip to content

Repository files navigation

SBN Live Site Checker

This repository contains an AWS Lambda function that checks live sites on a schedule and via API Gateway. It validates TLS certificates (for final HTTPS destinations), confirms the sites return 2xx responses after redirects, emails alerts via SES, and writes the latest results to S3.

Quick Overview

This code builds an AWS Lambda function. It runs on a cron schedule that is configured in .env. It can also be triggered via the script _ping_endpoint. When it runs, it looks though the contents of .json files at urls specified within .env. It reads the content of that json file, which tells the function which sites to ping with http(s) requests and, if there is any problem, which emails to notify.

If you want to add an email to receive notifications then you need to go to the group's AWS Console, navigate to SES, and 'validate' that email address.

Tofu Version

This template was built and tested with:

OpenTofu v1.10.6
on darwin_arm64
+ provider registry.opentofu.org/hashicorp/aws v6.18.0

If you upgrade tofu/terraform in the future and try to use the state files from this template, you may run into issues. In that case, re-initialize the project with tofu init -upgrade after ensuring your version is compatible.

Workflow

After cp .env-template .env and editing .env to your liking, and running tofu init, the essential workflow is:

./_docker
./_tf plan
./_tf apply

Triggers

  • API Gateway: GET /check
  • CloudWatch schedule: controlled by TF_VAR_CRON_EXPR

Manual API Gateway invocations require the shared secret from TF_VAR_API_TRIGGER_SECRET in the x-sbn-check-secret request header. The scheduled CloudWatch trigger does not need this header.

Template Essentials

When creating a new project based on this template, ALL such repos MUST have the following:

  • docker/Dockerfile
  • docker/build.sh
  • .env-template
  • tf_main.tf
  • tf_variables.tf
  • tf_outputs.tf
  • src/index.ts
  • package.json
  • tsconfig.json
  • _docker
  • _tf
  • AGENTS.md

All other scripts and files are on a per-project basis.

Features

  • Lambda function written in TypeScript and packaged in an AWS Docker container
  • API Gateway endpoint for on-demand checks
  • CloudWatch schedule for periodic checks
  • SES email alerts for failures
  • S3 bucket for storing latest-results.json and private per-run history snapshots
  • CloudFront distribution in front of latest-results.json

Email Behavior

  • The primary sender receives a single summary email with all down sites.
  • Each email listed in a site list source receives one digest email containing the down sites it is associated with.

Rationale / Design Decisions

  • We only use terraform/tofu with AWS.
  • We use a docker container so that npm modules are installed/built on the target linux platform.
  • Wrapper scripts are intentionally thin; _docker prints the commands it executes, and _tf sources .env before running tofu commands.
  • _tf prints a guide of commands that I use often.

Terraform/Tofu Config and State Files

Everything related to state is kept in the root directory; placing files elsewhere complicates terminal commands and makes the user dependent on wrapper scripts. See _tf for details.

Environment Variables

These are supplied via .env (use TF_VAR_ prefixes where noted).

  • AWS_ACCESS_KEY_ID: AWS access key for terraform and tooling.
  • AWS_SECRET_ACCESS_KEY: AWS secret key for terraform and tooling.
  • DOCKER_IMAGE_NAME: Docker image name for the build container.
  • DOCKER_IMAGE_TAG: Docker image tag for the build container.
  • TF_VAR_PROJECT_PREFIX: Prefix applied to resource names.
  • TF_VAR_LAMBDA_FUNCTION_NAME: Lambda function name suffix.
  • TF_VAR_S3_BUCKET_NAME: Bucket for latest-results.json and private run history snapshots.
  • TF_VAR_LAMBDA_RUNTIME: Lambda runtime identifier.
  • TF_VAR_AWS_REGION: AWS region for resources.
  • TF_VAR_LAMBDA_FUNCTION_DESC: Lambda description string.
  • TF_VAR_LAMBDA_ARCHITECTURE: Lambda architecture (e.g., x86_64).
  • TF_VAR_LAMBDA_MAX_RUNTIME_SECONDS: Lambda timeout in seconds.
  • TF_VAR_LAMBDA_DEPLOYMENT: Deployment label (also API Gateway stage).
  • TF_VAR_LAMBDA_LOGS_TO_CLOUDWATCH: Whether to create a CloudWatch log group.
  • TF_VAR_LAMBDA_LOGS_RETENTION_DAYS: Log retention in days.
  • TF_VAR_API_GATEWAY_DATA_TRACE_ENABLED: Whether API Gateway should log full request/response bodies. Keep false unless debugging.
  • TF_VAR_S3_PUBLIC_READ: Toggle public read for latest-results.json only.
  • TF_VAR_S3_FILE_PREFIX: Currently unused by the Lambda (reserved).
  • TF_VAR_S3_RUN_HISTORY_RETENTION_DAYS: Number of days to retain private per-run snapshots under runs/.
  • TF_VAR_CLOUDFRONT_PRICE_CLASS: CloudFront price class.
  • TF_VAR_CLOUDFRONT_DESCRIPTION: CloudFront distribution description.
  • TF_VAR_CRON_EXPR: CloudWatch schedule expression.
  • TF_VAR_STATIC_PRIMARY_SENDER_EMAIL: Primary sender email for alerts (SES-verified).
  • TF_VAR_API_TRIGGER_SECRET: Shared secret required for manual GET /check calls.
  • TF_VAR_CHECK_CONCURRENCY_LIMIT: Maximum number of site checks to run concurrently.
  • TF_VAR_EMAIL_CONCURRENCY_LIMIT: Maximum number of alert emails to send concurrently.
  • TF_VAR_SITE_LIST_SOURCES: JSON array of URLs pointing to JSON site lists.
  • TF_VAR_EXTRA_SITES: JSON array of strings or { "url": "...", "emails": ["..."] } (emails are ignored; only the primary sender is notified).
  • TF_VAR_GITHUB_ACCESS_TOKEN: Optional token for private GitHub raw content access.

Output

The Lambda writes the current result to latest-results.json and also writes a private per-run snapshot under runs/YYYY/MM/DD/<timestamp>.json. Terraform configures an S3 lifecycle rule that expires objects under runs/ after TF_VAR_S3_RUN_HISTORY_RETENTION_DAYS days. The lifecycle rule does not expire latest-results.json.

The result object shape is:

{
  "time": "2025-01-01T00:00:00.000Z",
  "results": [ ... ]
}

Each site result includes failure metadata when relevant, including failureKind values such as dns, timeout, tls, http_status, network, invalid_url, or unknown.

The Lambda response includes both s3LatestObjectKey and s3RunHistoryObjectKey so each invocation can be matched to its private S3 snapshot.

Testing

Run the local TypeScript build and focused unit tests with:

npm test

Run only the compiler with:

npm run build:local

Node Version

  • This repo is set for Node 22. If/when AWS Lambda supports Node 24, update .env-template and docker/Dockerfile.

About

Lambda function that writes to S3

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages