Skip to content

Setting Up an API Gateway with a Lambda Integration

This guide explains how to expose a Lambda function via API Gateway (HTTP API) using the terraform-byks-module.

Step 1: Define your Lambda function

See the Lambda documentation for further details

Add an entry to lambda_functions. The map key (kattehotell-api) becomes the Lambda's logical ID inside the module.

module "application" {
  ...
  lambda_functions = {
    kattehotell-api = {
      package_type     = "Image"
      ecr_uri          = local.ecr["kattehotell-api]          # or 336385411112.dkr.ecr.eu-west-1.amazonaws.com/kattehotell-api-shared
      image_tag        = var.environment                      # usually dev,test,prod

      environment_variables = {
        LOG_LEVEL = "info"
      }
    }
  }
}
  ...

Step 2: Define the API Gateway

Set api_gateway and point an integration at the Lambda you defined above. The integration key (kattehotell-api-integration) is a name you choose, and is only used internally to link to a route.

module "application" {
  ...
  api_gateway = {
    description = "Public API for my application"

    integrations = {
      lambda_functions = {
        # Key = integration name, referenced by routes below
        kattehotell-api-integration = {
          lambda_function_id     = "kattehotell-api"          # Must match a key in lambda_functions
          description            = "kattehotell-api handler"
          integration_method     = "POST"                     # Lambda proxy always uses POST internally
          timeout_milliseconds   = 30000
          payload_format_version = "2.0"                      # 2.0 is recommended for HTTP API
        }
      }
    }

    routes = {
      # Key format: "METHOD /path"
      "GET /cats" = {
        target_integration = "kattehotell-api-integration"    # Must match an integration key above
        authorizer         = "onelogin" # Check step 3 for setting up an authorizer, 'NONE' is also valid input, but not recommended
      }

      "POST /cats" = {
        target_integration = "kattehotell-api-integration"
        authorizer         = "onelogin" # Check step 3 for setting up an authorizer, 'NONE' is also valid input, but not recommended
      }
    }
  }
  ...
}

The resulting public URL is:

  • https://kattehotell-api.dev.bymoslo.net/cats (DEV)

  • https://kattehotell-api.test.bymoslo.net/cats (TEST)

  • https://kattehotell-api.bymoslo.no/cats (PROD)


Step 3: (optional) Protect routes with a JWT authorizer

Add an authorizer block and reference it by name in any route that should require authentication.

module "application" {
  ...
  api_gateway = {
    authorizers = {
      onelogin = {
        identity_sources = ["$request.header.Authorization"]
        jwt_configuration = {
          issuer   = <onelogin_issuer> # Issuer URL depends on environment, usually https://oslo.onelogin.com/oidc/2 (PROD) or https://sandbox-oslo.onelogin.com/oidc/2 (TEST/DEV)
          audience = ["<my-app-client-id>"]
        }
      }
    }

    integrations = {
      lambda_functions = {
        kattehotell-api-integration = {
          lambda_function_id = "kattehotell-api"
        }
      }
    }

    routes = {
      "GET /cats" = {
        target_integration   = "kattehotell-api-integration"
        authorizer           = "onelogin"                     # Name of the authorizer above
        authorization_scopes = ["openid", "profile"]          # Only applicable for JWT authorizers
      }
    }
  }
  ...
}

Step 4: (optional) Enable CORS

CORS Configuration

Exact configuration of CORS (origins, methods, headers) varies depending on what is required by the backend API

module "application" {
  ...
  api_gateway = {
    cors_configuration = {
      allow_origins = ["https://kattehotell-frontend.dev.bymoslo.net", "https://localhost:3000", "http://localhost:3000"] # Eksempel-URL, localhost
      allow_methods = ["*"]
      allow_headers = ["*"]
      max_age       = 300
    }

    # ... integrations and routes as above
  }
}
  ...

Complete minimal example

locals.tf
locals {
  ecr = { for k, v in data.terraform_remote_state.shared_kattehotell_ecr.outputs.ecr: k => v.ecr_url }
}
main.tf
module "application" {
  source = "git@github.com:BYM-IKT/terraform-byks-module.git?ref=v12"
  account_id       = var.account_id
  region           = var.region
  application_name = "kattehotell-api"
  environment      = var.environment
  team             = var.team

  lambda_functions = {
    kattehotell-api = {
      ecr_uri   = "336385411112.dkr.ecr.eu-west-1.amazonaws.com/kattehotell-api-shared"
      image_tag = var.environment
    }
  }

  api_gateway = {
    description = "API gateway for kattehotell-løsningen"

    integrations = {
      lambda_functions = {
        kattehotell-api-integration = {
          lambda_function_id = "kattehotell-api"
        }
      }
    }

    authorizers = {
      onelogin = {
        identity_sources = ["$request.header.Authorization"]
        jwt_configuration = {
          issuer   = "https://sandbox-oslo.onelogin.com/oidc/2" # Issuer URL depends on environment, usually https://oslo.onelogin.com/oidc/2 (PROD) or https://sandbox-oslo.onelogin.com/oidc/2 (TEST/DEV)
          audience = ["kattehotell-client-id"]
        }
      }
    }

    routes = {
      "GET /cats" = {
        target_integration = "kattehotell-api-integration"
        authorizer         = "onelogin"
      }
    }
  }

  providers = {
    aws.route53   = aws.route53
    aws.us-east-1 = aws.us-east-1
    aws.ses       = aws.ses
  }
}