hashicorp / terraform-provider-aws

The AWS Provider enables Terraform to manage AWS resources.
https://registry.terraform.io/providers/hashicorp/aws
Mozilla Public License 2.0
9.74k stars 9.1k forks source link

[Bug]: Not able to attach custom authorizer to aws api gateway through openapi spec. #26847

Open mohit-bureau opened 2 years ago

mohit-bureau commented 2 years ago

Terraform Core Version

1.1.9

AWS Provider Version

4.30.0

Affected Resource(s)

aws_api_gateway_rest_api

Expected Behavior

The body parameter accepts open api spec json to merge or overwrite routes in the API gateway. The routes are getting added but the method request authorizer is not enabled to use a custom lambda authorizer. It is being set to NONE even after setting the security key with lambda name in the route.

Actual Behavior

The custom lambda authorizer should be attached with the route method request if the security key is present in the openapi spec json.

Relevant Error/Panic Output Snippet

No response

Terraform Configuration Files

resource "aws_api_gateway_rest_api" "orch-stg" {
  body              = jsonencode(local.openapi_config)
  put_rest_api_mode = "merge"
  name              = "im-api-gateway"
  endpoint_configuration {
    types = ["REGIONAL"]
  }
}

locals {
    openapi_config = {
    openapi = "3.0.1"
    info = {
      title   = "im-dev-api-gateway"
      version = "1.0"
    }
    paths = {
      "/v1/api/go/data" : {
        "post" : {
          "parameters" : [{
            "name" : "proxy",
            "in" : "path",
            "required" : true,
            "schema" : {
              "type" : "string"
            }
          }],
          "responses" : {
            "200" : {
              "description" : "200 response",
              "headers" : {
                "Access-Control-Allow-Origin" : {
                  "schema" : {
                    "type" : "string"
                  }
                }
              },
              "content" : {
                "application/json" : {
                  "schema" : {
                    "$ref" : "#/components/schemas/Empty"
                  }
                }
              }
            }
          },
          "security" : [{
            "im-dev-lambda-authorizer" : []
          }],
          "x-amazon-apigateway-integration" : {
            "httpMethod" : "POST",
            "uri" : "https://$${stageVariables.LoadBalancerURL}/v1/api/go/data",
            "requestParameters" : {
              "integration.request.header.X-Auth-Client-ID" : "context.authorizer.x-auth-client-id",
              "integration.request.path.proxy" : "method.request.path.proxy",
              "integration.request.header.X-Request-ID" : "context.authorizer.x-request-id"
            },
            "passthroughBehavior" : "when_no_match",
            "timeoutInMillis" : 29000,
            "type" : "http_proxy"
          }
        },
        "options" : {
          "responses" : {
            "200" : {
              "description" : "200 response",
              "headers" : {
                "Access-Control-Allow-Origin" : {
                  "schema" : {
                    "type" : "string"
                  }
                },
                "Access-Control-Allow-Methods" : {
                  "schema" : {
                    "type" : "string"
                  }
                },
                "Access-Control-Allow-Headers" : {
                  "schema" : {
                    "type" : "string"
                  }
                }
              },
              "content" : {
                "application/json" : {
                  "schema" : {
                    "$ref" : "#/components/schemas/Empty"
                  }
                }
              }
            }
          },
          "x-amazon-apigateway-integration" : {
            "responses" : {
              "default" : {
                "statusCode" : "200",
                "responseParameters" : {
                  "method.response.header.Access-Control-Allow-Methods" : "'GET,OPTIONS,POST,PUT'",
                  "method.response.header.Access-Control-Allow-Headers" : "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Auth-Client-ID,X-Request-ID'",
                  "method.response.header.Access-Control-Allow-Origin" : "'*'"
                }
              }
            },
            "requestTemplates" : {
              "application/json" : "{\"statusCode\": 200}"
            },
            "passthroughBehavior" : "never",
            "timeoutInMillis" : 29000,
            "type" : "mock"
          }
        }
      },
      "components" : {
        "schemas" : {
          "Empty" : {
            "title" : "Empty Schema",
            "type" : "object"
          }
        },
        "securitySchemes" : {
          "im-dev-lambda-authorizer" : {
            "type" : "apiKey",
            "name" : "Unused",
            "in" : "header",
            "x-amazon-apigateway-authtype" : "custom",
            "x-amazon-apigateway-authorizer" : {
              "authorizerUri" : "arn:aws:apigateway:ap-south-1:lambda:path/2015-03-31/functions/arn:aws:lambda:ap-south-1:999999999:function:im-dev-authorizer/invocations",
              "authorizerCredentials" : "arn:aws:iam::999999999:role/im-dev-api-gateway-auth-invocation",
              "authorizerResultTtlInSeconds" : 0,
              "identitySource" : "context.$context.requestId",
              "type" : "request"
            }
          }
        }
      },
    }
  }
}

Steps to Reproduce

Import the attached openapi spec json to API gateway.

Debug Output

No response

Panic Output

No response

Important Factoids

No response

References

No response

Would you like to implement a fix?

No response

github-actions[bot] commented 2 years ago

Community Note

Voting for Prioritization

Volunteering to Work on This Issue

mridu23 commented 1 year ago

We are facing this issue as well. We tried to work around this by following an iterative approach - creating apigw first, and then open api spec with authorizer as the next step However that does not work either since the cycle detection happens at the plan stage.

For now, we have to fall back to creating methods and integration by creating separate terraform resources for all endpoints, which is extremely messy to manage.

dhanish2k commented 1 year ago

Yes this is a problem for us too, What I ended up doing was to add something like this resource "null_resource" "update-method-authorizer" { provisioner "local-exec" { command = "aws apigateway update-method --rest-api-id ${api.id} --resource-id ${resource.id} --http-method GET --patch-operations op=replace,path=/authorizationType,value=CUSTOM op=replace,path=/authorizerId,value=${authorizer.id}" } }

prawilny commented 1 year ago

I thought I had the same problem, but then I found this example https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-swagger-extensions-authtype.html and using it I managed to get a similar configuration to work (the problem might've been fixed in the meantime, though). Good luck.

guimilleo commented 1 year ago

I'm also facing the same issue. No updates about it?

guimilleo commented 1 year ago

@mohit-bureau, were you able to fix it?

0xW1sKy commented 1 year ago

just got this working in my environment

data "template_file" "swagger_doc" {
  template = file("${path.module}/swagger.yml")
  vars = {
    authorizer_uri         = aws_lambda_function.authorizer.invoke_arn
    authorizer_credentials = aws_iam_role.apigw_execution_role.arn
  }
}

resource "aws_api_gateway_rest_api" "api" {
  name = "ScimAPI"
  body = data.template_file.swagger_doc.rendered
}

resource "aws_api_gateway_deployment" "this" {
  rest_api_id = aws_api_gateway_rest_api.api.id
  stage_name  = "default"
  triggers = {
    redeployment = sha1(jsonencode(aws_api_gateway_rest_api.api.body))
  }
  lifecycle {
    create_before_destroy = true
  }
}

...

it looks like this in my swagger (3.0.1) doc

paths:
  /Groups:
    get:
      security:
        - lambda-authorizer: []
...

components:
  securitySchemes:
    lambda-authorizer:
      type: apiKey
      name: Authorization
      in: header
      x-amazon-apigateway-authorizer:
        type: request
        identitySource: method.request.header.Authorization
        authorizerUri: ${authorizer_uri}
        authorizerCredentials: ${authorizer_credentials}
        authorizerPayloadFormatVersion: '2.0'
        authorizerResultTtlInSeconds: 300
      x-amazon-apigateway-authtype: Custom scheme with corporate claims

This was with AWS Provider version: ~> 4.4