{"id":19854652,"url":"https://github.com/obytes/terraform-aws-lambda-api","last_synced_at":"2026-05-08T15:16:14.217Z","repository":{"id":77139349,"uuid":"422136034","full_name":"obytes/terraform-aws-lambda-api","owner":"obytes","description":"Terraform module for provisioning AWS Lambda API with CI and APIGW","archived":false,"fork":false,"pushed_at":"2021-11-03T10:44:39.000Z","size":441,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":12,"default_branch":"main","last_synced_at":"2025-07-18T18:28:26.744Z","etag":null,"topics":["api-gateway","aws","aws-lambda","fastapi","flask","lambda","rest-api"],"latest_commit_sha":null,"homepage":"https://www.obytes.com/blog/go-serverless-part-3-deploy-http-api-to-aws-lambda-and-expose-it-via-api-gateway","language":"HCL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/obytes.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-28T09:05:41.000Z","updated_at":"2022-02-14T15:26:36.000Z","dependencies_parsed_at":null,"dependency_job_id":"bdfdc51c-bdf0-4fd9-84ed-79c378a232ae","html_url":"https://github.com/obytes/terraform-aws-lambda-api","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/obytes/terraform-aws-lambda-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obytes%2Fterraform-aws-lambda-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obytes%2Fterraform-aws-lambda-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obytes%2Fterraform-aws-lambda-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obytes%2Fterraform-aws-lambda-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/obytes","download_url":"https://codeload.github.com/obytes/terraform-aws-lambda-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obytes%2Fterraform-aws-lambda-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32785612,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-08T08:22:46.396Z","status":"ssl_error","status_checked_at":"2026-05-08T08:22:45.650Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api-gateway","aws","aws-lambda","fastapi","flask","lambda","rest-api"],"created_at":"2024-11-12T14:10:03.017Z","updated_at":"2026-05-08T15:16:14.193Z","avatar_url":"https://github.com/obytes.png","language":"HCL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Terraform AWS Lambda API\n\nA Terraform reusable module for provisioning AWS Lambda API with its CI/CD and API Gateway\n\nA Functional Lambda API consists of the followings components:\n\n1. AWS Lambda API Code compatible with API Gateway - an API built with any Restfull API framework like Flask API and\n   Fast API, and able to adapt Lambda API Gateway events into HTTP Requests and HTTP Responses into API Gateway Responses.\n   an [AWS Lambda Fast API Starter](https://github.com/obytes/lambda-fast-api) and\n   [AWS Lambda Flask API Starter](https://github.com/obytes/lambda-flask-api) are provided.\n  \n2. [Codeless Lambda Function](https://github.com/obytes/terraform-aws-codeless-lambda) - a reusable Terraform module \n   for provisioning the Lambda resources, the code/dependencies build and deployment should be delegated to an external \n   CI/CD process.\n  \n3. [Lambda Function CI/CD](https://github.com/obytes/terraform-aws-lambda-ci) - a Terraform module for Lambda code and \n   dependencies continuous integration/deployment.\n\n4. [API Gateway HTTP API](https://github.com/obytes/terraform-aws-lambda-apigw) - An API Gateway HTTP API that \n   integrates with an Upstream Lambda Function, authorize and proxy requests.\n\n5. [API Gateway APIs Exposer](https://github.com/obytes/terraform-aws-gato) - API Gateway resources for creating custom \n   domain, mapping the domain with the API Gateway HTTP API and exposing the API through route53 or cloudflare records.\n  \n6. [An Identity as a Service Provider](https://github.com/obytes/terraform-aws-gato) - Any JWT compatible provider that \n   API Gateway can integrate with for authorizing requests based on users JWT access tokens.\n\nThis reusable module, can provision **Codeless Lambda Function(2)**, **Lambda Function CI/CD(3)** and \n**API Gateway HTTP API(4)**.\n\nThe **API Gateway APIs Exposer(5)** is placed in a separate module because it's more generic and it can be used to \nexpose multiple API Gateway HTTP APIs(4) or even API Gateway Websocket APIs.\n\nThe **Lambda API Code compatible with API Gateway(1)** and **Identity as a Service Provider(6)** components are your \nresponsibility to build and configure but a \n[Starter Boilerplate Lambda Flask Application](https://github.com/obytes/lambda-flask-api) is provided to you for \ninspiration and demo.\n\n## Prerequisites\n\n- HTTP API application compatible with Lambda/AWS-APIGW (A starter app is provided)\n- Route53 or Cloudflare zone (That you own of course)\n- ACM certificate for your AWS API Gateway custom domain (For HTTPs)\n- Codestar connection to your Github account.\n- S3 bucket for holding CI/CD artifacts and Lambda Code/Dependencies\n- Firebase project or a project in any other IaaS providers.\n- Slack channel(s) for notifying `success` adn `failure` deployments.\n\n## Usage\n\n- Version Control your Lambda Function API in Github.\n\n- Provision Codeless Lambda Function(2), Lambda Function CI/CD(3) and API Gateway HTTP API(4).\n\n```hcl\nmodule \"aws_lambda_api\" {\n  source      = \"git::https://github.com/obytes/terraform-aws-lambda-api.git//modules/api\"\n  prefix      = \"${local.prefix}-flask\"\n  common_tags = local.common_tags\n\n  # Lambda API\n  description                        = \"Flask Lambda API\"\n  runtime                            = \"python3.7\"\n  handler                            = \"app.runtime.lambda.main.handler\"\n  memory_size                        = 512\n  envs                               = {\n     FIREBASE_APP_API_KEY   = \"AIzaSyAbiq3L6lVT9TyM_Lik6C5rgSLEGCiqJhM\"\n     AWS_API_GW_MAPPING_KEY = \"flask\"\n  }\n  policy_json                        = null\n  logs_retention_in_days             = 3\n  jwt_authorization_groups_attr_name = \"groups\"\n\n  # CI/CD\n  github                          = {\n     owner          = \"obytes\"\n     webhook_secret = \"not-secret\"\n     connection_arn = \"arn:aws:codestar-connections:us-east-1:{ACCOUNT_ID}:connection/{CONNECTION_ID}\"\n  }\n  pre_release                     = true\n  github_repository               = {\n    name   = \"lambda-flask-api\"\n    branch = \"main\"\n  }\n  s3_artifacts                    = {\n     arn    = aws_s3_bucket.artifacts.arn\n     bucket = aws_s3_bucket.artifacts.bucket\n  }\n  app_src_path                    = \"src\"\n  packages_descriptor_path        = \"src/requirements/lambda.txt\"\n  ci_notifications_slack_channels = {\n     info  = \"ci-info\"\n     alert = \"ci-alert\"\n  }\n\n  # API Gateway\n  stage_name                    = \"mvp\"\n  jwt_authorizer                = {\n    issuer   = \"https://securetoken.google.com/flask-lambda\"\n    audience = [ \"flask-lambda\" ]\n  }\n  routes_definitions            = {\n     health_check = {\n        operation_name = \"Service Health Check\"\n        route_key      = \"GET /v1/manage/hc\"\n     }\n     token = {\n        operation_name = \"Get authorization token\"\n        route_key      = \"POST /v1/auth/token\"\n     }\n     whoami = {\n        operation_name = \"Get user claims\"\n        route_key      = \"GET /v1/users/whoami\"\n        # Authorization\n        api_key_required     = false\n        authorization_type   = \"JWT\"\n        authorization_scopes = []\n     }\n     site_map = {\n        operation_name = \"Get endpoints list\"\n        route_key      = \"GET /v1/admin/endpoints\"\n        # Authorization\n        api_key_required     = false\n        authorization_type   = \"JWT\"\n        authorization_scopes = []\n     }\n     swagger_specification = {\n        operation_name = \"Swagger Specification\"\n        route_key      = \"GET /v1/swagger.json\"\n     }\n     swagger_ui = {\n        operation_name = \"Swagger UI\"\n        route_key      = \"GET /v1/docs\"\n     }\n  }\n  access_logs_retention_in_days = 3\n}\n```\n\n- For FastAPI lovers, we've got your back:\n\n```hcl\nmodule \"aws_fast_lambda_api\" {\n  source      = \"git::https://github.com/obytes/terraform-aws-lambda-api.git//modules/api\"\n  prefix      = \"${local.prefix}-fast\"\n  common_tags = local.common_tags\n\n  # Lambda API\n  description                        = \"Fast Lambda API\"\n  runtime                            = \"python3.7\"\n  handler                            = \"app.runtime.lambda.main.handler\"\n  memory_size                        = 512\n  envs                               = {\n    FIREBASE_APP_API_KEY   = \"AIzaSyAbiq3L6lVT9TyM_Lik6C5rgSLEGCiqJhM\"\n    AWS_API_GW_MAPPING_KEY = \"fast\"\n  }\n  policy_json                        = null\n  logs_retention_in_days             = 3\n  jwt_authorization_groups_attr_name = \"groups\"\n\n  # CI/CD\n  github                          = {\n     owner          = \"obytes\"\n     webhook_secret = \"not-secret\"\n     connection_arn = \"arn:aws:codestar-connections:us-east-1:{ACCOUNT_ID}:connection/{CONNECTION_ID}\"\n  }\n  pre_release                     = true\n  github_repository               = {\n    name   = \"lambda-fast-api\"\n    branch = \"main\"\n  }\n  s3_artifacts                    = {\n     arn    = aws_s3_bucket.artifacts.arn\n     bucket = aws_s3_bucket.artifacts.bucket\n  }\n  app_src_path                    = \"src\"\n  packages_descriptor_path        = \"src/requirements/lambda.txt\"\n  ci_notifications_slack_channels = {\n     info  = \"ci-info\"\n     alert = \"ci-alert\"\n  }\n\n  # API Gateway\n  stage_name                    = \"mvp\"\n  jwt_authorizer                = {\n    issuer   = \"https://securetoken.google.com/flask-lambda\"\n    audience = [ \"flask-lambda\" ]\n  }\n  routes_definitions            = {\n    health_check = {\n      operation_name = \"Service Health Check\"\n      route_key      = \"GET /v1/manage/hc\"\n    }\n    token = {\n      operation_name = \"Get authorization token\"\n      route_key      = \"POST /v1/auth/token\"\n    }\n    whoami = {\n      operation_name = \"Get user claims\"\n      route_key      = \"GET /v1/users/whoami\"\n      # Authorization\n      api_key_required     = false\n      authorization_type   = \"JWT\"\n      authorization_scopes = []\n    }\n    site_map = {\n      operation_name = \"Get site map\"\n      route_key      = \"GET /v1/admin/endpoints\"\n      # Authorization\n      api_key_required     = false\n      authorization_type   = \"JWT\"\n      authorization_scopes = []\n    }\n    openapi = {\n      operation_name = \"OpenAPI Specification\"\n      route_key      = \"GET /v1/openapi.json\"\n    }\n    swagger = {\n      operation_name = \"Swagger UI\"\n      route_key      = \"GET /v1/docs\"\n    }\n    redoc = {\n      operation_name = \"ReDoc UI\"\n      route_key      = \"GET /v1/redoc\"\n    }\n  }\n  access_logs_retention_in_days = 3\n}\n```\n\n- Provision The AWS API Gateway APIs Exposer(5)\n\n```hcl\nmodule \"gato\" {\n   source      = \"git::https://github.com/obytes/terraform-aws-gato.git//modules/core-route53\"\n   prefix      = local.prefix\n   common_tags = local.common_tags\n\n   # DNS\n   r53_zone_id = aws_route53_zone.prerequisite.zone_id\n   cert_arn    = aws_acm_certificate.prerequisite.arn\n   domain_name = \"kodhive.com\"\n   sub_domains = {\n      stateless = \"api\"\n      statefull = \"ws\"\n   }\n\n   # Rest APIS\n   http_apis = [\n      {\n         id    = module.aws_flask_lambda_api.http_api_id\n         key   = \"flask\"\n         stage = module.aws_flask_lambda_api.http_api_stage_name\n      },\n      {\n         id    = module.aws_fast_lambda_api.http_api_id\n         key   = \"fast\"\n         stage = module.aws_fast_lambda_api.http_api_stage_name\n      },\n   ]\n   ws_apis = []\n}\n```\n\nWith this configuration, our Lambda API Gateway final base URLs will be https://api.kodhive.com/flask/ for Flask API\nand https://api.kodhive.com/fast/ for Fast API and these endpoints will be exposed:\n\n- FlaskAPI:\n   - GET https://api.kodhive.com/flask/v1/manage/hc [PUBLIC]\n   - POST https://api.kodhive.com/flask/v1/auth/token [AUTH]\n   - GET https://api.kodhive.com/flask/v1/users/whoami [PRIVATE]\n   - GET https://api.kodhive.com/flask/v1/admin/endpoints [ADMIN]\n   - GET https://api.kodhive.com/flask/v1/docs [DOCS]\n\n![Flask Docs](/docs/images/flask-docs.png)\n\n- FastAPI:\n   - GET https://api.kodhive.com/fast/v1/manage/hc [PUBLIC]\n   - POST https://api.kodhive.com/fast/v1/auth/token [AUTH]\n   - GET https://api.kodhive.com/fast/v1/users/whoami [PRIVATE]\n   - GET https://api.kodhive.com/fast/v1/admin/endpoints [ADMIN]\n   - GET https://api.kodhive.com/fast/v1/docs [DOCS]\n\n![Fast Docs](/docs/images/fast-docs.png)\n\n## Demo\n\n- Public Endpoint [ALLOW]\n\n```bash\ncurl -X GET https://api.kodhive.com/flask/v1/manage/hc\n{\n    \"status\": \"I'm sexy and I know It\"\n}\n```\n\n- Auth Endpoint [DENY]\n\n```bash\ncurl -X POST -F 'username=does.not.exist@gmail.com' -F 'password=not-secret' https://api.kodhive.com/flask/v1/auth/token\n{\n    \"error\": {\n        \"code\": \"002401\",\n        \"title\": \"Unauthorized\",\n        \"message\": \"Access unauthorized\",\n        \"reason\": \"EMAIL_NOT_FOUND\"\n    },\n    \"message\": \"EMAIL_NOT_FOUND\"\n}\n```\n\n- Auth Endpoint [ALLOW]\n\n```bash\ncurl -X POST -F 'username=admin@gmail.com' -F 'password=not-secret' https://api.kodhive.com/flask/v1/auth/token\n{\n    \"kind\": \"identitytoolkit#VerifyPasswordResponse\",\n    \"localId\": \"gf30eciYKjVJrA5XMHK0NKDbKeC2\",\n    \"email\": \"admin@gmail.com\",\n    \"displayName\": \"Super Admin\",\n    \"registered\": true,\n    \"profilePicture\": \"https://img2.freepng.fr/20180402/ogw/kisspng-computer-icons-user-profile-clip-art-user-avatar-5ac208105c03d6.9558906215226654883769.jpg\",\n    \"refreshToken\": \"TOO_LONG_TOKEN\",\n    \"expiresIn\": \"3600\",\n    \"token_type\": \"bearer\",\n    \"access_token\": \"TOO_LONG_TOKEN\"\n}\n```\n\n- Private Endpoint [DENY]\n\n```bash\ncurl -X GET https://api.kodhive.com/flask/v1/users/whoami\n{\"message\":\"Unauthorized\"}%\n```\n\n- Private Endpoint [ALLOW]\n\n```bash\ncurl -X GET https://api.kodhive.com/flask/v1/users/whoami -H \"Authorization: Bearer NORMAL_USER_FIREBASE_JWT_TOKEN\"\n{\n    \"claims\": {\n        \"aud\": \"flask-lambda\",\n        \"auth_time\": \"1635015339\",\n        \"email\": \"sanitized@gmail.com\",\n        \"email_verified\": \"true\",\n        \"exp\": \"1635018939\",\n        \"firebase\": \"map[identities:map[email:[sanitized@gmail.com]] sign_in_provider:password]\",\n        \"groups\": \"[USERS ADMINS]\",\n        \"iat\": \"1635015339\",\n        \"iss\": \"https://securetoken.google.com/flask-lambda\",\n        \"name\": \"Hamza Adami\",\n        \"picture\": \"https://siasky.net/_AlWdFnwvbHwXoDeVk-4DrMKcmQajKIJ2z-maOkXsDfYNw\",\n        \"sub\": \"NcpGCnZ9B0cFDqRllYbtTYG8awE2\",\n        \"user_id\": \"NcpGCnZ9B0cFDqRllYbtTYG8awE2\"\n    }\n}\n```\n\n- Admin Endpoint [DENY]\n\n```bash\ncurl -X GET https://api.kodhive.com/flask/v1/admin/endpoints -H \"Authorization: Bearer NORMAL_USER_FIREBASE_JWT_TOKEN\"\n{\n    \"error\": {\n        \"code\": \"002401\",\n        \"title\": \"Unauthorized\",\n        \"message\": \"Access unauthorized\",\n        \"reason\": \"Only ['ADMINS'] can access this endpoint\"\n    },\n    \"message\": \"Only ['ADMINS'] can access this endpoint\"\n}\n```\n\n- Admin Endpoint [ALLOW]\n\n```bash\ncurl -X GET https://api.kodhive.com/flask/v1/admin/endpoints -H \"Authorization: Bearer ADMIN_USER_FIREBASE_JWT_TOKEN\"\n{\n    \"endpoints\": [\n        {\n            \"path\": \"/v1/manage/hc\",\n            \"name\": \"api.manage_health_check\"\n        },\n        {\n            \"path\": \"/v1/admin/endpoints\",\n            \"name\": \"api.admin_list_endpoints\"\n        },\n        {\n            \"path\": \"/v1/users/whoami\",\n            \"name\": \"api.users_who_am_i\"\n        },\n        {\n            \"path\": \"/v1/swagger.json\",\n            \"name\": \"api.specs\"\n        },\n        {\n            \"path\": \"/v1/docs\",\n            \"name\": \"api.doc\"\n        },\n        {\n            \"path\": \"/v1/\",\n            \"name\": \"api.root\"\n        }\n    ]\n}\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobytes%2Fterraform-aws-lambda-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fobytes%2Fterraform-aws-lambda-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobytes%2Fterraform-aws-lambda-api/lists"}