AWS - Configure Lambda API Gateway Integration

Octopus.AwsRunScript exported 2022-10-04 by twerthi belongs to ‘AWS’ category.

Configures an API v2 Gateway to connect to and invoke a Lambda Function. That includes:

  • Integration on the API Gateway
  • Route on the API Gateway
  • Permission Policy on AWS Lambda (Aliases are supported)

Please Note: Your AWS Lambda function MUST exist prior to running this step.

This step uses the following AWS CLI commands to create the integration and route. You will be required to install the AWS CLI on your server/worker for this to work. The AWS CLI is pre-installed on the dynamic workers in Octopus Cloud as well as the provided docker containers for Execution Containers.

APIGatewayV2 CLI Methods

Lambda CLI Methods

Output Variables

This step template sets the following output variables:

  • ApiGatewayEndPoint: The endpoint of the API Gateway
  • ApiGatewayId: The id of the API Gateway
  • ApiGatewayArn: The ARN of the API Gateway

Parameters

When steps based on the template are included in a project’s deployment process, the parameters below can be set.

API Gateway Name

AWS.Api.Gateway.Name =

Required.

The name of the API gateway to create the integration and route.

AWS Account

AWS.Api.Gateway.Account =

Required.

The account used to update the API Gateway.

AWS Region

AWS.Api.Gateway.Region =

Required.

The region where the API gateway is in.

VPC Connection

AWS.Api.Gateway.Integration.Connection =

Optional.

The VPC connection you wish to use with this link. Supports:

  • VPC Link Name - The name of the VPC link specified when it was created.
  • VPC Link Id - The 6-character alphanumeric key assigned by AWS to the VPC Link.

Please note: Sending a value in will change the connection type from INTERNET to VPC_LINK.

Route Key

AWS.Api.Gateway.Route.Key = $default

Required.

The route key for the route. Examples:

  • $default
  • /signup

HTTP Method

AWS.Api.Gateway.Integration.HttpMethod = ANY

Required.

The HTTP method of the route and integration you wish to create.

Lambda ARN

AWS.Api.Gateway.Lambda.Arn =

Required.

The ARN of the AWS Lambda to connect to.

Lambda Alias

AWS.Api.Gateway.Lambda.Alias =

Required.

The alias in the lambda function to use when the API Gateway invokes the function.

Payload Format Version

AWS.Api.Gateway.Integration.PayloadFormatVersion = 2.0

Required.

The payload format version specifies the format of the data that API Gateway sends to a Lambda integration, and how API Gateway interprets the response from Lambda.

Script body

Steps based on this template will execute the following PowerShell script.

$ApiGatewayName = $OctopusParameters["AWS.Api.Gateway.Name"]
$ApiRouteKey = $OctopusParameters["AWS.Api.Gateway.Route.Key"]
$ApiLambdaUri = $OctopusParameters["AWS.Api.Gateway.Lambda.Arn"]
$ApiPayloadFormatVersion = $OctopusParameters["AWS.Api.Gateway.Integration.PayloadFormatVersion"]
$ApiConnection = $OctopusParameters["AWS.Api.Gateway.Integration.Connection"]
$ApiIntegrationMethod = $OctopusParameters["AWS.Api.Gateway.Integration.HttpMethod"]
$ApiLambdaAlias = $OctopusParameters["AWS.Api.Gateway.Lambda.Alias"]
$ApiRegion = $OctopusParameters["AWS.Api.Gateway.Region"]

$stepName = $OctopusParameters["Octopus.Step.Name"]

if ([string]::IsNullOrWhiteSpace($ApiGatewayName))
{
	Write-Error "The parameter Gateway Name is required."
    Exit 1
}

if ([string]::IsNullOrWhiteSpace($ApiRouteKey))
{
	Write-Error "The parameter Route Key is required."
    Exit 1
}

if ([string]::IsNullOrWhiteSpace($ApiLambdaUri))
{
	Write-Error "The parameter Lambda ARN is required."
    Exit 1
}

if ([string]::IsNullOrWhiteSpace($ApiPayloadFormatVersion))
{
	Write-Error "The parameter Payload Format Version is required."
    Exit 1
}

if ([string]::IsNullOrWhiteSpace($ApiIntegrationMethod))
{
	Write-Error "The parameter Http Method is required."
    Exit 1
}

Write-Host "Gateway Name: $ApiGatewayName"
Write-Host "Route Key: $ApiRouteKey"
Write-Host "Lambda ARN: $ApiLambdaUri"
Write-Host "Lambda Alias: $ApiLambdaAlias"
Write-Host "Payload Format Version: $ApiPayloadFormatVersion"
Write-Host "VPC Connection: $ApiConnection"
Write-host "API Region: $apiRegion"

if ([string]::IsNullOrWhiteSpace($apiLambdaAlias) -eq $false)
{
	Write-Host "Alias specified, adding it to the Lambda ARN"
	$apiLambdaIntegrationArn = "$($apiLambdaUri):$($apiLambdaAlias)"
}
else
{
	Write-Host "No alias specified, going directly to the lambda function"
	$apiLambdaIntegrationArn = $apiLambdaUri
}

$apiQueryOutput = aws apigatewayv2 get-apis --no-paginate
$apiQueryOutput = ($apiQueryOutput | ConvertFrom-JSON)

$apiList = @($apiQueryOutput.Items)
$apiGatewayToUpdate = $null
foreach ($api in $apiList)
{
	if ($api.Name.ToLower().Trim() -eq $apiGatewayName.ToLower().Trim())
    {
    	Write-Highlight "Found the gateway $apiGatewayName"
    	$apiGatewayToUpdate = $api
        break
    }
}

if ($null -eq $apiGatewayToUpdate)
{
	Write-Error "Unable to find the gateway with the name $apiGatewayName"
    exit 1
}

Write-Host $apiGatewayToUpdate

$apiId = $apiGatewayToUpdate.ApiId
Write-Host "The id of the api gateway is $apiId"

$apiConnectionType = "INTERNET"
if ([string]::IsNullOrWhiteSpace($ApiConnection) -eq $false)
{
	$apiConnectionType = "VPC_LINK"
    $existingVPCLinks = aws apigatewayv2 get-vpc-links --no-paginate
    $existingVPCLinks = ($existingVPCLinks | ConvertFrom-JSON)
    
    $existingVPCLinkList = @($existingVPCLinks.Items)
    foreach ($vpc in $existingVPCLinkList)
    {
    	if ($vpc.Name.ToLower().Trim() -eq $ApiConnection.ToLower().Trim())
        {
        	Write-Host "The name $($vpc.Name) matches $apiConnection"
        	$apiConnectionId = $vpc.VpcLinkId
            break
        }
        elseif ($vpc.VpcLinkId.ToLower().Trim() -eq $apiConnection.ToLower().Trim())
        {
        	Write-Host "The vpc link id $($vpc.VpcLinkId) matches $apiConnection"
        	$apiConnectionId = $vpc.VpcLinkId
            break
        }
    }
    
    if ([string]::IsNullOrWhiteSpace($apiConnectionId) -eq $true)
    {
    	Write-Error "The VPC Connection $apiConnection could not be found.  Please check the name or ID and try again.  Please note: names can be updated, if you are matching by name double check nothing has changed."
        exit 1
    }    
}

$apiIntegrations = aws apigatewayv2 get-integrations --api-id "$apiId" --no-paginate
$apiIntegrations = ($apiIntegrations | ConvertFrom-JSON)

$integrationList = @($apiIntegrations.Items)
$integrationToUpdate = $null
foreach ($integration in $integrationList)
{
	if ($integration.IntegrationUri -eq $apiLambdaIntegrationArn -and $integration.ConnectionType -eq $apiConnectionType -and $integration.IntegrationType -eq "AWS_PROXY" -and $integration.PayloadFormatVersion -eq $ApiPayloadFormatVersion)
    {
    	Write-Highlight "Found the existing integration $($integration.Id)"
    	$integrationToUpdate = $integration
        break
    }
}

if ($null -ne $integrationToUpdate)
{
	Write-Highlight "Updating existing integration"
}
else
{
	Write-Highlight "Creating new integration"
    if ($apiConnectionType -eq "INTERNET")
    {
    	Write-Host "Command line: aws apigatewayv2 create-integration --api-id ""$apiId"" --connection-type ""$apiConnectionType"" --integration-method ""$ApiIntegrationMethod"" --integration-type ""AWS_PROXY"" --integration-uri ""$apiLambdaIntegrationArn"" --payload-format-version ""$ApiPayloadFormatVersion"" "
    	$integrationToUpdate = aws apigatewayv2 create-integration --api-id "$apiId" --connection-type "$apiConnectionType" --integration-method "$ApiIntegrationMethod" --integration-type "AWS_PROXY" --integration-uri "$apiLambdaIntegrationArn" --payload-format-version "$ApiPayloadFormatVersion"
    }
    else
    {
    	Write-Host "Command line: aws apigatewayv2 create-integration --api-id ""$apiId"" --connection-type ""$apiConnectionType"" --connection-id ""$ApiConnectionId"" --integration-method ""$ApiIntegrationMethod"" --integration-type ""AWS_PROXY"" --integration-uri ""$apiLambdaIntegrationArn"" --payload-format-version ""$ApiPayloadFormatVersion"" "
    	$integrationToUpdate = aws apigatewayv2 create-integration --api-id "$apiId" --connection-type "$apiConnectionType" --connection-id "$ApiConnectionId" --integration-method "$ApiIntegrationMethod" --integration-type "AWS_PROXY" --integration-uri "$apiLambdaIntegrationArn" --payload-format-version "$ApiPayloadFormatVersion"    
    }
    
    $integrationToUpdate = ($integrationToUpdate | ConvertFrom-JSON)
}

If ($null -eq $integrationToUpdate)
{
	Write-Error "There was an error finding or creating the integration."
    Exit 1
}

Write-Host "$integrationToUpdate"

Write-Host "Command line: aws apigatewayv2 update-integration --api-id ""$apiId"" --integration-id ""$($integrationToUpdate.IntegrationId)"" --integration-method ""$ApiIntegrationMethod"" "
$updateResult = aws apigatewayv2 update-integration --api-id "$apiId" --integration-id "$($integrationToUpdate.IntegrationId)" --integration-method "$ApiIntegrationMethod"

Write-Host "Command line: aws apigatewayv2 get-routes --api-id ""$apiId"" --no-paginate"
$apiRoutes = aws apigatewayv2 get-routes --api-id "$apiId" --no-paginate
$apiRoutes = ($apiRoutes | ConvertFrom-JSON)

$routeList = @($apiRoutes.Items)
$routeToUpdate = $null
$routePath = "$ApiIntegrationMethod $ApiRouteKey"
$routeTarget = "integrations/$($integrationToUpdate.IntegrationId)"
foreach ($route in $routeList)
{
	Write-Host "Comparing $($route.RouteKey) with $routePath and $($route.Target) with $routeTarget"
	if ($route.RouteKey -eq $routePath -and $route.Target -eq $routeTarget)
    {
    	Write-Highlight "Found the existing path $($route.RouteId)"
    	$routeToUpdate = $route
        break
    }
}

if ($null -eq $routeToUpdate)
{
	Write-Highlight "The route with the path $routePath pointing to integration $($integrationToUpdate.IntegrationId) does not exist.  Creating that one now."
    $routeResult = aws apigatewayv2 create-route --api-id "$apiId" --route-key "$routePath" --target "$routeTarget"
}
else
{
	Write-Highlight "The route with the path $routePath pointing to integration $($integrationToUpdate.IntegrationId) already exists.  Leaving that alone."   
}

$accountInfo = aws sts get-caller-identity
$accountInfo = ($accountInfo | ConvertFrom-JSON)

if ($apiRoute -notcontains "*default")
{
	$routeKeyToUse = $apiRouteKey
    $statementIdToUse = "$($ApiGatewayName)$($apiRouteKey.Replace("/", "-"))"
}
else
{
	$routeKeyToUse = ""
    $statementIdToUse = "$ApiGatewayName"
}
$sourceArn = "arn:aws:execute-api:$($apiRegion):$($accountInfo.Account):$($apiId)/*/*$routeKeyToUse"

Write-Host "Source ARN: $sourceArn"
$hasExistingPolicy = $false
$deleteExistingPolicy = $false

try
{
	Write-Host "Getting existing policies"
	$existingPolicy = aws lambda get-policy --function-name "$apiLambdaIntegrationArn" 2> $null
    
    if ($LASTEXITCODE -eq 255 -or $LASTEXITCODE -eq 254)
    {
    	Write-Host "Last exit code was $LASTEXITCODE the policy does not exist"
    	$hasExistingPolicy = $false
    }
    else
    {
    	Write-Host "The policy exists"
    	$hasExistingPolicy = $true
    }
    
    $existingPolicy = ($existingPolicy | ConvertFrom-JSON)
    Write-Host $existingPolicy
    
    $policyObject = ($existingPolicy.Policy | ConvertFrom-JSON)
    
	$statementList = @($policyObject.Statement)
    Write-Host "Statement List $statementList"
    
    foreach ($existingStatement in $statementList)
    {
    	Write-Host $existingStatement
    	Write-Host "Comparing $($existingStatement.Sid) with $statementIdToUse and $($existingStatement.Condition.ArnLike.'AWS:SourceArn') with $sourceArn"
    	if ($existingStatement.Sid -eq "$statementIdToUse" -and $existingStatement.Condition.ArnLike.'AWS:SourceArn' -ne "$sourceArn")
        {
        	Write-Host "The policy exists but it is not pointing to the write source arn, recreating it."
        	$deleteExistingPolicy = $true
        }
    }
}
catch
{
	Write-Host "Error pulling back the policies, this typically means the policy does not exist"
	$hasExistingPolicy = $false
}

if ($hasExistingPolicy -eq $true -and $deleteExistingPolicy -eq $true)
{
	Write-Highlight "Removing the existing policy $statementIdToUse"
    aws lambda remove-permission --function-name "$apiLambdaIntegrationArn" --statement-id "$statementIdToUse"
}

if ($hasExistingPolicy -eq $false -or $deleteExistingPolicy -eq $true)
{
	Write-Highlight "Adding the policy $statementIdToUse"
	aws lambda add-permission --function-name "$apiLambdaIntegrationArn" --statement-id "$statementIdToUse" --action "lambda:InvokeFunction" --principal "apigateway.amazonaws.com" --qualifier "$ApiLambdaAlias" --source-arn "$sourceArn"
}

Write-Highlight "Setting the output variable 'Octopus.Action[$($stepName)].Output.ApiGatewayEndPoint' to $($apiGatewayToUpdate.ApiEndpoint)"
Set-OctopusVariable -name "ApiGatewayEndPoint" -value "$($apiGatewayToUpdate.ApiEndpoint)"

Write-Highlight "Setting the output variable 'Octopus.Action[$($stepName)].Output.ApiGatewayId' to $apiId"
Set-OctopusVariable -name "ApiGatewayId" -value "$apiId"

Write-Highlight "Setting the output variable 'Octopus.Action[$($stepName)].Output.ApiGatewayArn' to $sourceArn"
Set-OctopusVariable -name "ApiGatewayArn" -value "$sourceArn"

Provided under the Apache License version 2.0.

Report an issue

To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.

{
  "Id": "7e818c42-8c59-4a14-b612-2b9cb69fcf4a",
  "Name": "AWS - Configure Lambda API Gateway Integration",
  "Description": "Configures an API v2 Gateway to connect to and invoke a Lambda Function.  That includes:\n\n- Integration on the API Gateway\n- Route on the API Gateway\n- Permission Policy on AWS Lambda (Aliases are supported)\n\n**Please Note:** Your AWS Lambda function **MUST** exist prior to running this step.\n\nThis step uses the following AWS CLI commands to create the integration and route.  You will be required to install the AWS CLI on your server/worker for this to work.  The AWS CLI is pre-installed on the [dynamic workers](https://octopus.com/docs/infrastructure/workers/dynamic-worker-pools) in Octopus Cloud as well as the provided docker containers for [Execution Containers](https://octopus.com/docs/deployment-process/execution-containers-for-workers).\n\nAPIGatewayV2 CLI Methods\n- [create-integration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigatewayv2/create-integration.html)\n- [create-route](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigatewayv2/create-route.html)\n- [get-apis](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigatewayv2/get-apis.html)\n- [get-integrations](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigatewayv2/get-integrations.html)\n- [get-routes](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigatewayv2/get-routes.html)\n- [get-vpc-links](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigatewayv2/get-vpc-links.html)\n- [update-integration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apigatewayv2/update-integration.html)\n\nLambda CLI Methods\n- [add-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/add-permission.html)\n- [get-policy](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/get-policy.html)\n- [remove-permission](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/remove-permission.html)\n\n\n## Output Variables\n\nThis step template sets the following output variables:\n\n- `ApiGatewayEndPoint`: The endpoint of the API Gateway\n- `ApiGatewayId`: The id of the API Gateway\n- `ApiGatewayArn`: The ARN of the API Gateway",
  "Version": 2,
  "ExportedAt": "2022-10-04T18:34:13.219Z",
  "ActionType": "Octopus.AwsRunScript",
  "Author": "twerthi",
  "Packages": [],
  "Parameters": [
    {
      "Id": "6a63ef8c-5f0b-4501-beca-fc3839f7f5c9",
      "Name": "AWS.Api.Gateway.Name",
      "Label": "API Gateway Name",
      "HelpText": "Required.\n\nThe name of the API gateway to create the integration and route.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "0fb1f1fa-35f6-46b3-bf4a-527ddd98fb80",
      "Name": "AWS.Api.Gateway.Account",
      "Label": "AWS Account",
      "HelpText": "Required.\n\nThe account used to update the API Gateway.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "AmazonWebServicesAccount"
      }
    },
    {
      "Id": "a42498df-fadd-45d1-9271-78e80edb9623",
      "Name": "AWS.Api.Gateway.Region",
      "Label": "AWS Region",
      "HelpText": "Required.\n\nThe region where the API gateway is in.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Select",
        "Octopus.SelectOptions": "us-east-2|US East (Ohio)\nus-east-1|US East (N. Virginia)\nus-west-1|US West (N. California)\nus-west-2|US West (Oregon)\naf-south-1|Africa (Cape Town)\nap-east-1|Asia Pacific (Hong Kong)\nap-south-1|Asia Pacific (Mumbai)\nap-northeast-3|Asia Pacific (Osaka-Local)\nap-northeast-2|Asia Pacific (Seoul)\nap-southeast-1|Asia Pacific (Singapore)\nap-southeast-2|Asia Pacific (Sydney)\nap-northeast-1|Asia Pacific (Tokyo)\nca-central-1|Canada (Central)\neu-central-1|Europe (Frankfurt)\neu-west-1|Europe (Ireland)\neu-west-2|Europe (London)\neu-south-1|Europe (Milan)\neu-west-3|Europe (Paris)\neu-north-1|Europe (Stockholm)\nme-south-1|Middle East (Bahrain)\nsa-east-1|South America (São Paulo)"
      }
    },
    {
      "Id": "bd681a63-f62c-4dcb-a401-ae43428075ed",
      "Name": "AWS.Api.Gateway.Integration.Connection",
      "Label": "VPC Connection",
      "HelpText": "Optional.\n\nThe VPC connection you wish to use with this link.  Supports:\n\n- VPC Link Name - The name of the VPC link specified when it was created.\n- VPC Link Id - The 6-character alphanumeric key assigned by AWS to the VPC Link.\n\n**Please note**: Sending a value in will change the connection type from `INTERNET` to `VPC_LINK`.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "607e787d-d0bd-47b9-984e-2195d58278ed",
      "Name": "AWS.Api.Gateway.Route.Key",
      "Label": "Route Key",
      "HelpText": "Required.\n\nThe route key for the route.  Examples:\n\n- `$default`\n- `/signup`",
      "DefaultValue": "$default",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "f255a0c5-f2e6-4739-af59-a0329c6ddb14",
      "Name": "AWS.Api.Gateway.Integration.HttpMethod",
      "Label": "HTTP Method",
      "HelpText": "Required.\n\nThe HTTP method of the route and integration you wish to create.",
      "DefaultValue": "ANY",
      "DisplaySettings": {
        "Octopus.ControlType": "Select",
        "Octopus.SelectOptions": "ANY|ANY\nPOST|POST\nPUT|PUT\nGET|GET\nDELETE|DELETE"
      }
    },
    {
      "Id": "6552c873-6576-4272-a724-a3b257b1b13e",
      "Name": "AWS.Api.Gateway.Lambda.Arn",
      "Label": "Lambda ARN",
      "HelpText": "Required.\n\nThe ARN of the AWS Lambda to connect to.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "261a89c2-dc9b-4608-8f76-fcb07385725c",
      "Name": "AWS.Api.Gateway.Lambda.Alias",
      "Label": "Lambda Alias",
      "HelpText": "Required.\n\nThe alias in the lambda function to use when the API Gateway invokes the function.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "4c281de7-1922-4d78-b16d-9c60cd2d2477",
      "Name": "AWS.Api.Gateway.Integration.PayloadFormatVersion",
      "Label": "Payload Format Version",
      "HelpText": "Required.\n\nThe payload format version specifies the format of the data that API Gateway sends to a Lambda integration, and how API Gateway interprets the response from Lambda.",
      "DefaultValue": "2.0",
      "DisplaySettings": {
        "Octopus.ControlType": "Select",
        "Octopus.SelectOptions": "1.0|1.0\n2.0|2.0"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Aws.AssumeRole": "False",
    "Octopus.Action.AwsAccount.UseInstanceRole": "False",
    "Octopus.Action.AwsAccount.Variable": "#{AWS.Api.Gateway.Account}",
    "Octopus.Action.Aws.Region": "#{AWS.Api.Gateway.Region}",
    "Octopus.Action.Script.ScriptBody": "$ApiGatewayName = $OctopusParameters[\"AWS.Api.Gateway.Name\"]\n$ApiRouteKey = $OctopusParameters[\"AWS.Api.Gateway.Route.Key\"]\n$ApiLambdaUri = $OctopusParameters[\"AWS.Api.Gateway.Lambda.Arn\"]\n$ApiPayloadFormatVersion = $OctopusParameters[\"AWS.Api.Gateway.Integration.PayloadFormatVersion\"]\n$ApiConnection = $OctopusParameters[\"AWS.Api.Gateway.Integration.Connection\"]\n$ApiIntegrationMethod = $OctopusParameters[\"AWS.Api.Gateway.Integration.HttpMethod\"]\n$ApiLambdaAlias = $OctopusParameters[\"AWS.Api.Gateway.Lambda.Alias\"]\n$ApiRegion = $OctopusParameters[\"AWS.Api.Gateway.Region\"]\n\n$stepName = $OctopusParameters[\"Octopus.Step.Name\"]\n\nif ([string]::IsNullOrWhiteSpace($ApiGatewayName))\n{\n\tWrite-Error \"The parameter Gateway Name is required.\"\n    Exit 1\n}\n\nif ([string]::IsNullOrWhiteSpace($ApiRouteKey))\n{\n\tWrite-Error \"The parameter Route Key is required.\"\n    Exit 1\n}\n\nif ([string]::IsNullOrWhiteSpace($ApiLambdaUri))\n{\n\tWrite-Error \"The parameter Lambda ARN is required.\"\n    Exit 1\n}\n\nif ([string]::IsNullOrWhiteSpace($ApiPayloadFormatVersion))\n{\n\tWrite-Error \"The parameter Payload Format Version is required.\"\n    Exit 1\n}\n\nif ([string]::IsNullOrWhiteSpace($ApiIntegrationMethod))\n{\n\tWrite-Error \"The parameter Http Method is required.\"\n    Exit 1\n}\n\nWrite-Host \"Gateway Name: $ApiGatewayName\"\nWrite-Host \"Route Key: $ApiRouteKey\"\nWrite-Host \"Lambda ARN: $ApiLambdaUri\"\nWrite-Host \"Lambda Alias: $ApiLambdaAlias\"\nWrite-Host \"Payload Format Version: $ApiPayloadFormatVersion\"\nWrite-Host \"VPC Connection: $ApiConnection\"\nWrite-host \"API Region: $apiRegion\"\n\nif ([string]::IsNullOrWhiteSpace($apiLambdaAlias) -eq $false)\n{\n\tWrite-Host \"Alias specified, adding it to the Lambda ARN\"\n\t$apiLambdaIntegrationArn = \"$($apiLambdaUri):$($apiLambdaAlias)\"\n}\nelse\n{\n\tWrite-Host \"No alias specified, going directly to the lambda function\"\n\t$apiLambdaIntegrationArn = $apiLambdaUri\n}\n\n$apiQueryOutput = aws apigatewayv2 get-apis --no-paginate\n$apiQueryOutput = ($apiQueryOutput | ConvertFrom-JSON)\n\n$apiList = @($apiQueryOutput.Items)\n$apiGatewayToUpdate = $null\nforeach ($api in $apiList)\n{\n\tif ($api.Name.ToLower().Trim() -eq $apiGatewayName.ToLower().Trim())\n    {\n    \tWrite-Highlight \"Found the gateway $apiGatewayName\"\n    \t$apiGatewayToUpdate = $api\n        break\n    }\n}\n\nif ($null -eq $apiGatewayToUpdate)\n{\n\tWrite-Error \"Unable to find the gateway with the name $apiGatewayName\"\n    exit 1\n}\n\nWrite-Host $apiGatewayToUpdate\n\n$apiId = $apiGatewayToUpdate.ApiId\nWrite-Host \"The id of the api gateway is $apiId\"\n\n$apiConnectionType = \"INTERNET\"\nif ([string]::IsNullOrWhiteSpace($ApiConnection) -eq $false)\n{\n\t$apiConnectionType = \"VPC_LINK\"\n    $existingVPCLinks = aws apigatewayv2 get-vpc-links --no-paginate\n    $existingVPCLinks = ($existingVPCLinks | ConvertFrom-JSON)\n    \n    $existingVPCLinkList = @($existingVPCLinks.Items)\n    foreach ($vpc in $existingVPCLinkList)\n    {\n    \tif ($vpc.Name.ToLower().Trim() -eq $ApiConnection.ToLower().Trim())\n        {\n        \tWrite-Host \"The name $($vpc.Name) matches $apiConnection\"\n        \t$apiConnectionId = $vpc.VpcLinkId\n            break\n        }\n        elseif ($vpc.VpcLinkId.ToLower().Trim() -eq $apiConnection.ToLower().Trim())\n        {\n        \tWrite-Host \"The vpc link id $($vpc.VpcLinkId) matches $apiConnection\"\n        \t$apiConnectionId = $vpc.VpcLinkId\n            break\n        }\n    }\n    \n    if ([string]::IsNullOrWhiteSpace($apiConnectionId) -eq $true)\n    {\n    \tWrite-Error \"The VPC Connection $apiConnection could not be found.  Please check the name or ID and try again.  Please note: names can be updated, if you are matching by name double check nothing has changed.\"\n        exit 1\n    }    \n}\n\n$apiIntegrations = aws apigatewayv2 get-integrations --api-id \"$apiId\" --no-paginate\n$apiIntegrations = ($apiIntegrations | ConvertFrom-JSON)\n\n$integrationList = @($apiIntegrations.Items)\n$integrationToUpdate = $null\nforeach ($integration in $integrationList)\n{\n\tif ($integration.IntegrationUri -eq $apiLambdaIntegrationArn -and $integration.ConnectionType -eq $apiConnectionType -and $integration.IntegrationType -eq \"AWS_PROXY\" -and $integration.PayloadFormatVersion -eq $ApiPayloadFormatVersion)\n    {\n    \tWrite-Highlight \"Found the existing integration $($integration.Id)\"\n    \t$integrationToUpdate = $integration\n        break\n    }\n}\n\nif ($null -ne $integrationToUpdate)\n{\n\tWrite-Highlight \"Updating existing integration\"\n}\nelse\n{\n\tWrite-Highlight \"Creating new integration\"\n    if ($apiConnectionType -eq \"INTERNET\")\n    {\n    \tWrite-Host \"Command line: aws apigatewayv2 create-integration --api-id \"\"$apiId\"\" --connection-type \"\"$apiConnectionType\"\" --integration-method \"\"$ApiIntegrationMethod\"\" --integration-type \"\"AWS_PROXY\"\" --integration-uri \"\"$apiLambdaIntegrationArn\"\" --payload-format-version \"\"$ApiPayloadFormatVersion\"\" \"\n    \t$integrationToUpdate = aws apigatewayv2 create-integration --api-id \"$apiId\" --connection-type \"$apiConnectionType\" --integration-method \"$ApiIntegrationMethod\" --integration-type \"AWS_PROXY\" --integration-uri \"$apiLambdaIntegrationArn\" --payload-format-version \"$ApiPayloadFormatVersion\"\n    }\n    else\n    {\n    \tWrite-Host \"Command line: aws apigatewayv2 create-integration --api-id \"\"$apiId\"\" --connection-type \"\"$apiConnectionType\"\" --connection-id \"\"$ApiConnectionId\"\" --integration-method \"\"$ApiIntegrationMethod\"\" --integration-type \"\"AWS_PROXY\"\" --integration-uri \"\"$apiLambdaIntegrationArn\"\" --payload-format-version \"\"$ApiPayloadFormatVersion\"\" \"\n    \t$integrationToUpdate = aws apigatewayv2 create-integration --api-id \"$apiId\" --connection-type \"$apiConnectionType\" --connection-id \"$ApiConnectionId\" --integration-method \"$ApiIntegrationMethod\" --integration-type \"AWS_PROXY\" --integration-uri \"$apiLambdaIntegrationArn\" --payload-format-version \"$ApiPayloadFormatVersion\"    \n    }\n    \n    $integrationToUpdate = ($integrationToUpdate | ConvertFrom-JSON)\n}\n\nIf ($null -eq $integrationToUpdate)\n{\n\tWrite-Error \"There was an error finding or creating the integration.\"\n    Exit 1\n}\n\nWrite-Host \"$integrationToUpdate\"\n\nWrite-Host \"Command line: aws apigatewayv2 update-integration --api-id \"\"$apiId\"\" --integration-id \"\"$($integrationToUpdate.IntegrationId)\"\" --integration-method \"\"$ApiIntegrationMethod\"\" \"\n$updateResult = aws apigatewayv2 update-integration --api-id \"$apiId\" --integration-id \"$($integrationToUpdate.IntegrationId)\" --integration-method \"$ApiIntegrationMethod\"\n\nWrite-Host \"Command line: aws apigatewayv2 get-routes --api-id \"\"$apiId\"\" --no-paginate\"\n$apiRoutes = aws apigatewayv2 get-routes --api-id \"$apiId\" --no-paginate\n$apiRoutes = ($apiRoutes | ConvertFrom-JSON)\n\n$routeList = @($apiRoutes.Items)\n$routeToUpdate = $null\n$routePath = \"$ApiIntegrationMethod $ApiRouteKey\"\n$routeTarget = \"integrations/$($integrationToUpdate.IntegrationId)\"\nforeach ($route in $routeList)\n{\n\tWrite-Host \"Comparing $($route.RouteKey) with $routePath and $($route.Target) with $routeTarget\"\n\tif ($route.RouteKey -eq $routePath -and $route.Target -eq $routeTarget)\n    {\n    \tWrite-Highlight \"Found the existing path $($route.RouteId)\"\n    \t$routeToUpdate = $route\n        break\n    }\n}\n\nif ($null -eq $routeToUpdate)\n{\n\tWrite-Highlight \"The route with the path $routePath pointing to integration $($integrationToUpdate.IntegrationId) does not exist.  Creating that one now.\"\n    $routeResult = aws apigatewayv2 create-route --api-id \"$apiId\" --route-key \"$routePath\" --target \"$routeTarget\"\n}\nelse\n{\n\tWrite-Highlight \"The route with the path $routePath pointing to integration $($integrationToUpdate.IntegrationId) already exists.  Leaving that alone.\"   \n}\n\n$accountInfo = aws sts get-caller-identity\n$accountInfo = ($accountInfo | ConvertFrom-JSON)\n\nif ($apiRoute -notcontains \"*default\")\n{\n\t$routeKeyToUse = $apiRouteKey\n    $statementIdToUse = \"$($ApiGatewayName)$($apiRouteKey.Replace(\"/\", \"-\"))\"\n}\nelse\n{\n\t$routeKeyToUse = \"\"\n    $statementIdToUse = \"$ApiGatewayName\"\n}\n$sourceArn = \"arn:aws:execute-api:$($apiRegion):$($accountInfo.Account):$($apiId)/*/*$routeKeyToUse\"\n\nWrite-Host \"Source ARN: $sourceArn\"\n$hasExistingPolicy = $false\n$deleteExistingPolicy = $false\n\ntry\n{\n\tWrite-Host \"Getting existing policies\"\n\t$existingPolicy = aws lambda get-policy --function-name \"$apiLambdaIntegrationArn\" 2> $null\n    \n    if ($LASTEXITCODE -eq 255 -or $LASTEXITCODE -eq 254)\n    {\n    \tWrite-Host \"Last exit code was $LASTEXITCODE the policy does not exist\"\n    \t$hasExistingPolicy = $false\n    }\n    else\n    {\n    \tWrite-Host \"The policy exists\"\n    \t$hasExistingPolicy = $true\n    }\n    \n    $existingPolicy = ($existingPolicy | ConvertFrom-JSON)\n    Write-Host $existingPolicy\n    \n    $policyObject = ($existingPolicy.Policy | ConvertFrom-JSON)\n    \n\t$statementList = @($policyObject.Statement)\n    Write-Host \"Statement List $statementList\"\n    \n    foreach ($existingStatement in $statementList)\n    {\n    \tWrite-Host $existingStatement\n    \tWrite-Host \"Comparing $($existingStatement.Sid) with $statementIdToUse and $($existingStatement.Condition.ArnLike.'AWS:SourceArn') with $sourceArn\"\n    \tif ($existingStatement.Sid -eq \"$statementIdToUse\" -and $existingStatement.Condition.ArnLike.'AWS:SourceArn' -ne \"$sourceArn\")\n        {\n        \tWrite-Host \"The policy exists but it is not pointing to the write source arn, recreating it.\"\n        \t$deleteExistingPolicy = $true\n        }\n    }\n}\ncatch\n{\n\tWrite-Host \"Error pulling back the policies, this typically means the policy does not exist\"\n\t$hasExistingPolicy = $false\n}\n\nif ($hasExistingPolicy -eq $true -and $deleteExistingPolicy -eq $true)\n{\n\tWrite-Highlight \"Removing the existing policy $statementIdToUse\"\n    aws lambda remove-permission --function-name \"$apiLambdaIntegrationArn\" --statement-id \"$statementIdToUse\"\n}\n\nif ($hasExistingPolicy -eq $false -or $deleteExistingPolicy -eq $true)\n{\n\tWrite-Highlight \"Adding the policy $statementIdToUse\"\n\taws lambda add-permission --function-name \"$apiLambdaIntegrationArn\" --statement-id \"$statementIdToUse\" --action \"lambda:InvokeFunction\" --principal \"apigateway.amazonaws.com\" --qualifier \"$ApiLambdaAlias\" --source-arn \"$sourceArn\"\n}\n\nWrite-Highlight \"Setting the output variable 'Octopus.Action[$($stepName)].Output.ApiGatewayEndPoint' to $($apiGatewayToUpdate.ApiEndpoint)\"\nSet-OctopusVariable -name \"ApiGatewayEndPoint\" -value \"$($apiGatewayToUpdate.ApiEndpoint)\"\n\nWrite-Highlight \"Setting the output variable 'Octopus.Action[$($stepName)].Output.ApiGatewayId' to $apiId\"\nSet-OctopusVariable -name \"ApiGatewayId\" -value \"$apiId\"\n\nWrite-Highlight \"Setting the output variable 'Octopus.Action[$($stepName)].Output.ApiGatewayArn' to $sourceArn\"\nSet-OctopusVariable -name \"ApiGatewayArn\" -value \"$sourceArn\"\n"
  },
  "Category": "AWS",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/aws-configure-lambda-api-gateway-integration.json",
  "Website": "/step-templates/7e818c42-8c59-4a14-b612-2b9cb69fcf4a",
  "Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRF////9o0R/eLD/Nu0/erS95Qg+bhr95sv/vHh+r96/vjw+bFc/NSl+KI++82W+saI+KpNeDqM1wAAA41JREFUeNrsnG2XazAURiuo0Cr//9feliIvR3DvXJFZe3+a6XpW5+xWEpyY2w0AAAAAAAAAAAAAAAAAAADgf1J0bda/9N70q83a3enzUHWVjbR1sW0xp6sd6fPI72VmUt3zA+kymD6N5vnIBMrHsxHTjsUXOX0e+iVaTNU5Q0A/Q+k+4oAp+ixMbw6A4rGVVjGHR92ulNXWuTAlBNJN/FFyr5yy3qN9rawmF9IxR4hqX4U1WMplmGtruVBDuiuswbKkzaGhX+cfXsqbZlXXv0dsYR13nw9fLenGXD7f6U5Ony4yTpzyZLNMUcpMr0xNzfwdRRMR1/LP2cqMctNqKx1LZFydm2U022ueEtLL6HbHfmSRYRn4HDXaXyzU4XRkkZWK/+JlRBBBBBFEEEEEEUQQQQQRRBBB5B9uYJc7SyuLw+nI7R2ptKWJcywd18Utza0rnM4iN66M6qzS5E93Lf1zLaviUL/ISs/Nt6W00DEyuRgiP2Yxvrd15z/Y26ncG76jy1Ta5jEy/L0p/VMWy33woVm8UYN1Y9fqKrzfZ5iedtaV34+kNxHak2Wg2SSkY7djx/bQWkNP6nkE0lH3Lyx7D1aak1Z1erWJ+U130Vz0Sude7mZqv995nW7mZxJd27Sg5XQppuMdWY3xl1XXOge8MasWjZfund0KbvrkE9fK7OPNne+2U9YEWX3nemtSbvLv6LJ7gZ9X45yBl9ZxrZ9d3vjT8rz62tOsny7jXkpYPX9jQmvF8yF55TdaslGviZy1vAmfoTobsZztGNEv7qZZSr/6HRc/0yzlb3HiKhURRBBBBBFEEEEEEUQQQQQRRBD5XSLav38tllbVzeH02Ww/UWA+6XgsHdXFKc2vK5Quoz/duVRnlrb26crpizzXOVU3l2Zb5Pfe+d1OX8ViqW7qH9gt51K44bukr2XxrW54vMaoy7mxa/cgvPRVKcQG7uOCD58HLQLt3r17Iy6AqjYeDG7TUenWW+p9Ot/IOF/lwuHV1nk6o8M469PWXhtr+0BeX/x7Ue40W3xacfb2gXFxUZcX8TYB3Kyfp+GThsjKti2zgZuMiLshxW3gpiQyrn/DXhR/i1NqIte5pkUEEUQQQQQRRBBBBBFEEEEEEUR+g4jQUZBEqjqFO9mOiyeShoXvYoukZOG4GCLpWZgu83/vTNRidhlE0rYAAAAAAAAAAAAAAAAAAACAZPkjwAAMDi+bsnPP/wAAAABJRU5ErkJggg==",
  "$Meta": {
    "Type": "ActionTemplate"
  }
}

History

Page updated on Tuesday, October 4, 2022