2026-08-27 22:03:12 +00:00
resource " aws_apigatewayv2_api " " this " {
name = local . project
protocol_type = " HTTP "
description = " Yealink door unlock and lockdown HTTP API "
}
# Invoke permission is a Lambda resource policy, not AuthorizerCredentialsArn.
# The credentials-role path returned 500 without invoking the authorizer
# (PLAT-102); resource policy matches the route grants.
resource " aws_apigatewayv2_authorizer " " token " {
api_id = aws_apigatewayv2_api . this . id
name = " ${ local . project } -token-authorizer "
authorizer_type = " REQUEST "
authorizer_uri = aws_lambda_function . authorizer . invoke_arn
authorizer_payload_format_version = " 2.0 "
authorizer_result_ttl_in_seconds = 300
enable_simple_responses = true
identity_sources = [ " $ request.querystring.token " ]
}
resource " aws_apigatewayv2_integration " " unlock " {
api_id = aws_apigatewayv2_api . this . id
integration_type = " AWS_PROXY "
integration_method = " POST "
integration_uri = aws_lambda_function . unlock . invoke_arn
payload_format_version = " 2.0 "
timeout_milliseconds = 20000
}
resource " aws_apigatewayv2_integration " " lockdown " {
api_id = aws_apigatewayv2_api . this . id
integration_type = " AWS_PROXY "
integration_method = " POST "
integration_uri = aws_lambda_function . lockdown . invoke_arn
payload_format_version = " 2.0 "
timeout_milliseconds = 15000
}
resource " aws_apigatewayv2_route " " unlock " {
api_id = aws_apigatewayv2_api . this . id
route_key = " GET /unlock "
target = " integrations/ ${ aws_apigatewayv2_integration . unlock . id } "
authorization_type = " CUSTOM "
authorizer_id = aws_apigatewayv2_authorizer . token . id
}
resource " aws_apigatewayv2_route " " lockdown " {
api_id = aws_apigatewayv2_api . this . id
route_key = " GET /lockdown "
target = " integrations/ ${ aws_apigatewayv2_integration . lockdown . id } "
authorization_type = " CUSTOM "
authorizer_id = aws_apigatewayv2_authorizer . token . id
}
resource " aws_apigatewayv2_route " " lockdown_status " {
api_id = aws_apigatewayv2_api . this . id
route_key = " GET /lockdown/status "
target = " integrations/ ${ aws_apigatewayv2_integration . lockdown . id } "
authorization_type = " CUSTOM "
authorizer_id = aws_apigatewayv2_authorizer . token . id
}
resource " aws_apigatewayv2_stage " " default " {
api_id = aws_apigatewayv2_api . this . id
name = " $ default "
auto_deploy = true
access_log_settings {
destination_arn = aws_cloudwatch_log_group . api_access . arn
format = " { \ " requestId \ " : \ " $ context . requestId \ " , \ " ip \ " : \ " $ context . identity . sourceIp \ " , \ " requestTime \ " : \ " $ context . requestTime \ " , \ " method \ " : \ " $ context . httpMethod \ " , \ " routeKey \ " : \ " $ context . routeKey \ " , \ " status \ " : \ " $ context . status \ " , \ " protocol \ " : \ " $ context . protocol \ " , \ " responseLength \ " : \ " $ context . responseLength \ " , \ " integrationError \ " : \ " $ context . integrationErrorMessage \ " } "
}
default_route_settings {
throttling_burst_limit = 5
throttling_rate_limit = 2
}
depends_on = [
aws_apigatewayv2_route . unlock ,
aws_apigatewayv2_route . lockdown ,
aws_apigatewayv2_route . lockdown_status ,
]
}
resource " aws_lambda_permission " " unlock_route " {
statement_id = " AllowApiGatewayInvokeUnlock "
action = " lambda:InvokeFunction "
function_name = aws_lambda_function . unlock . function_name
principal = " apigateway.amazonaws.com "
source_arn = " ${ aws_apigatewayv2_api . this . execution_arn } /*/GET/unlock "
}
resource " aws_lambda_permission " " lockdown_route " {
statement_id = " AllowApiGatewayInvokeLockdown "
action = " lambda:InvokeFunction "
function_name = aws_lambda_function . lockdown . function_name
principal = " apigateway.amazonaws.com "
source_arn = " ${ aws_apigatewayv2_api . this . execution_arn } /*/GET/lockdown "
}
resource " aws_lambda_permission " " lockdown_status_route " {
statement_id = " AllowApiGatewayInvokeLockdownStatus "
action = " lambda:InvokeFunction "
function_name = aws_lambda_function . lockdown . function_name
principal = " apigateway.amazonaws.com "
source_arn = " ${ aws_apigatewayv2_api . this . execution_arn } /*/GET/lockdown/status "
}
resource " aws_lambda_permission " " authorizer " {
statement_id = " AllowApiGatewayInvokeAuthorizer "
action = " lambda:InvokeFunction "
function_name = aws_lambda_function . authorizer . function_name
principal = " apigateway.amazonaws.com "
source_arn = " ${ aws_apigatewayv2_api . this . execution_arn } /authorizers/ ${ aws_apigatewayv2_authorizer . token . id } "
}
resource " aws_apigatewayv2_domain_name " " this " {
2026-08-27 23:06:52 +00:00
count = var . attach_custom_domain ? 1 : 0
2026-08-27 22:03:12 +00:00
domain_name = var . domain_name
domain_name_configuration {
certificate_arn = data . aws_acm_certificate . doorunlock . arn
endpoint_type = " REGIONAL "
security_policy = " TLS_1_2 "
}
}
resource " aws_apigatewayv2_api_mapping " " this " {
2026-08-27 23:06:52 +00:00
count = var . attach_custom_domain ? 1 : 0
2026-08-27 22:03:12 +00:00
api_id = aws_apigatewayv2_api . this . id
2026-08-27 23:06:52 +00:00
domain_name = aws_apigatewayv2_domain_name . this [ 0 ] . id
2026-08-27 22:03:12 +00:00
stage = aws_apigatewayv2_stage . default . id
}