Skip to content

Instantly share code, notes, and snippets.

@markdavidburke
Forked from tbell83/api_gw.py
Created May 27, 2022 07:47
Show Gist options
  • Select an option

  • Save markdavidburke/bfefa2f08bbb73446f37802397de2167 to your computer and use it in GitHub Desktop.

Select an option

Save markdavidburke/bfefa2f08bbb73446f37802397de2167 to your computer and use it in GitHub Desktop.

Revisions

  1. @tbell83 tbell83 created this gist May 26, 2022.
    120 changes: 120 additions & 0 deletions api_gw.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,120 @@
    #!/usr/local/bin/python
    # this script will export the API gateway config as an Open API 3.0 json blob
    # and then create the appropriate terraform resources
    import json
    from subprocess import run as sp_run
    import boto3

    profile_name = 'dev'
    output_file = 'terraform/regional/api_gw_methods.tf'

    client = boto3.Session(profile_name=profile_name, region_name='us-east-1').client('apigateway')

    def get_api_id(api_name):
    response = client.get_rest_apis()
    for apigw in response['items']:
    if apigw['name'] == api_name:
    return apigw['id']
    return False

    response = client.get_export(
    restApiId=get_api_id('userlink'),
    stageName='v1',
    exportType='oas30',
    parameters={
    'extensions': 'integrations'
    },
    accepts = "application/json"
    )

    json_data = json.loads(response['body'].read().decode('utf-8').replace('/v1/', '/'))

    # this logic finds paths not explicitly defined in the api definition but we still need parent terraform resources created for
    all_paths = []
    explicit_paths = [path.replace("/", "", 1) for path in json_data["paths"]]
    for path in json_data["paths"]:
    path_name = path.replace("/", "_").replace("_","",1)
    split_path = path_name.split("_")
    for i in range(len(split_path)):
    current = "/".join(split_path[:i+1])
    if current not in all_paths: all_paths.append(current)
    for path in all_paths:
    if path not in explicit_paths:
    json_data["paths"][f'/{path}'] = {}

    # we do this to get the terraform resources grouped together properly
    json_data = json.dumps(json_data, sort_keys=True)
    json_data = json.loads(json_data)

    output = []
    for path in json_data["paths"]:
    path_name = path.replace("{", "").replace("}", "").replace("/", "_")
    output.append(f'resource "aws_api_gateway_resource" "{path_name}" {{')
    output.append("rest_api_id = aws_api_gateway_rest_api.userlink.id")
    output.append(
    f'parent_id = aws_api_gateway_resource.{"_".join(path_name.split("_")[:-1])}.id'
    if len(path_name.split("_")[:-1]) > 1
    else "parent_id = aws_api_gateway_resource._stage_version.id"
    )
    output.append(f'path_part = "{path.split("/")[-1]}"')
    output.append("}\n")

    for method in json_data["paths"][path]:
    method_type = (
    "ANY" if method == "x-amazon-apigateway-any-method" else method.upper()
    )
    output.append(f'resource "aws_api_gateway_method" "{path_name}__{method_type}" {{')
    output.append("rest_api_id = aws_api_gateway_rest_api.userlink.id")
    output.append(f"resource_id = aws_api_gateway_resource.{path_name}.id")
    output.append(f'http_method = "{method_type}"')
    output.append(
    "authorization = "
    + (
    '"NONE" #tfsec:ignore:aws-api-gateway-no-public-access'
    if not json_data["paths"][path][method].get("security")
    else '"CUSTOM"\n authorizer_id = aws_api_gateway_authorizer.auth.id'
    )
    )
    if json_data["paths"][path][method].get("parameters"):
    output.append("\n request_parameters = {")
    params = []
    for parameters in json_data["paths"][path][method]["parameters"]:
    params.append(
    f'"method.request.{parameters["in"]}.{parameters["name"]}" = {str(parameters["required"]).lower()}'
    )
    for param in sorted(params):
    output.append(param)
    output.append(" }")
    output.append("}\n")

    if json_data["paths"][path][method].get("x-amazon-apigateway-integration"):
    output.append(
    f'resource "aws_api_gateway_integration" "{path_name}__{method_type}_userlink" {{'
    )
    output.append(f"rest_api_id = aws_api_gateway_rest_api.userlink.id")
    output.append(f"resource_id = aws_api_gateway_resource.{path_name}.id")
    output.append(
    f" http_method = aws_api_gateway_method.{path_name}__{method_type}.http_method"
    )
    output.append(f'integration_http_method = "POST"')
    output.append(f'type = "AWS_PROXY"')
    output.append(f"uri = local.lambda_invoke_arn")
    output.append("}\n")

    for response in json_data["paths"][path][method]["responses"]:
    output.append(
    f'resource "aws_api_gateway_method_response" "{path_name}__{method_type}__{response}" {{'
    )
    output.append("rest_api_id = aws_api_gateway_rest_api.userlink.id")
    output.append(f"resource_id = aws_api_gateway_resource.{path_name}.id")
    output.append(
    f"http_method = aws_api_gateway_method.{path_name}__{method_type}.http_method"
    )
    output.append(f"status_code = {response}")
    output.append("}\n")

    with open(output_file, "w") as outfile:
    for line in output:
    outfile.write(f'{line}\n')

    sp_run(["terraform", "fmt", output_file])