AWSTemplateFormatVersion: 2010-09-09 Description: HTTP API Gateway website that returns AWS IP prefixes ( https://github.com/aws-samples/aws-ipranges-api ) (uksb-shhz98vv80) (tag:apiGateway) Metadata: License: Description: > Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: MIT-0 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. AWS::CloudFormation::Interface: ParameterGroups: - Label: default: HTTP API Parameters: - awsServices - allowNetworks - allowIPv6Networks - ipAddressType - Label: default: Lambda Parameters: - pythonRuntime - cpuArchitecture - Label: default: "[Optional] Custom domain name" Parameters: - customDomainName - certificateArn - disableDefaultEndPoint ParameterLabels: awsServices: default: "Default AWS Service IP prefixes to return separated by commas ( https://docs.aws.amazon.com/vpc/latest/userguide/aws-ip-ranges.html#aws-ip-syntax )" allowNetworks: default: "Allowed source IPv4 prefixes separated by commas (e.g. 1.2.3.4/32,100.0.0.0/24). Get your IPv4 address from https://checkip.amazonaws.com" allowIPv6Networks: default: "Allowed source IPv6 prefixes separated by commas (e.g. 1:2:3:4::/64). Get your IPv6 address (if any) from https://ifconfig.co" ipAddressType: default: IPv4 only or dual stack (IPv4-and-IPv6) pythonRuntime: default: Python 3 runtime version ( https://docs.aws.amazon.com/lambda/latest/dg/lambda-python.html ) cpuArchitecture: default: Instruction set architecture ( https://docs.aws.amazon.com/lambda/latest/dg/foundation-arch.html ) customDomainName: default: "Custom domain name to use (e.g. api.example.com)" certificateArn: default: "Certificate ARN. Get from https://console.aws.amazon.com/acm/home?#/certificates/list ( aws acm list-certificates )" disableDefaultEndPoint: default: "Disable default endpoint" Mappings: ipTypeMapping: IPv4: Value: ipv4 IPv4-and-IPv6: Value: dualstack Parameters: awsServices: Type: CommaDelimitedList AllowedValues: - AMAZON - AMAZON_APPFLOW - AMAZON_CONNECT - API_GATEWAY - AURORA_DSQL - CHIME_MEETINGS - CHIME_VOICECONNECTOR - CLOUD9 - CLOUDFRONT - CLOUDFRONT_ORIGIN_FACING - CODEBUILD - DATADEPOT - DYNAMODB - EBS - EC2 - EC2_INSTANCE_CONNECT - GLOBALACCELERATOR - IVS_LOW_LATENCY - IVS_REALTIME - KINESIS_VIDEO_STREAMS - MEDIA_PACKAGE_V2 - ROUTE53 - ROUTE53_HEALTHCHECKS - ROUTE53_HEALTHCHECKS_PUBLISHING - ROUTE53_RESOLVER - S3 - WORKSPACES_GATEWAYS Default: CLOUDFRONT_ORIGIN_FACING ConstraintDescription: Enter a valid AWS service allowNetworks: Type: String Default: 0.0.0.0/0 allowIPv6Networks: Type: String Default: ::/0 ipAddressType: Type: String AllowedValues: - IPv4 - IPv4-and-IPv6 Default: IPv4 pythonRuntime: Type: String AllowedPattern: "python3\\.\\d{1,2}" ConstraintDescription: Enter a valid Python version Default: python3.14 cpuArchitecture: Type: String AllowedValues: - x86_64 - arm64 Default: arm64 customDomainName: Type: String Default: "" certificateArn: Type: String Default: "" disableDefaultEndPoint: Type: String AllowedValues: - "Yes" - "No" Default: "No" Conditions: useCustomDomainName: !And [ !Not [!Equals [!Ref customDomainName, ""]], !Not [!Equals [!Ref certificateArn, ""]], ] enableDefaultEndPoint: !Equals [!Ref disableDefaultEndPoint, "No"] Resources: lambdaFunctionIamRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Policies: # Access logs at https://docs.aws.amazon.com/lambda/latest/operatorguide/access-logs.html - PolicyName: lambdaFunctionPolicy PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - logs:CreateLogStream - logs:PutLogEvents Resource: !Sub - "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${AWS::StackName}-lambdaFunction-${UID}:*" - UID: !Select [ 3, !Split [ "-", !Select [2, !Split ["/", !Ref AWS::StackId]], ], ] Tags: - Key: StackName Value: !Ref AWS::StackName - Key: StackId Value: !Ref AWS::StackId - Key: GitHub Value: https://github.com/aws-samples/aws-ipranges-api lambdaFunctionLogGroup: Type: AWS::Logs::LogGroup DeletionPolicy: Delete UpdateReplacePolicy: Delete Properties: KmsKeyId: !Ref AWS::NoValue RetentionInDays: !Ref AWS::NoValue LogGroupName: !Sub - "/aws/lambda/${AWS::StackName}-lambdaFunction-${UID}" - UID: !Select [ 3, !Split ["-", !Select [2, !Split ["/", !Ref AWS::StackId]]], ] Tags: - Key: StackName Value: !Ref AWS::StackName - Key: StackId Value: !Ref AWS::StackId - Key: GitHub Value: https://github.com/aws-samples/aws-ipranges-api lambdaFunction: Type: AWS::Lambda::Function Properties: Description: !Sub "[${AWS::StackName}] - Returns AWS IP prefixes for API Gateway" FunctionName: !Sub - "${AWS::StackName}-lambdaFunction-${UID}" - UID: !Select [ 3, !Split ["-", !Select [2, !Split ["/", !Ref AWS::StackId]]], ] Handler: "index.lambda_handler" MemorySize: 1769 ReservedConcurrentExecutions: !Ref AWS::NoValue Role: !GetAtt lambdaFunctionIamRole.Arn Environment: Variables: SERVICES: !Join [",", !Ref awsServices] Runtime: !Ref pythonRuntime Timeout: 25 Architectures: - !Ref cpuArchitecture Code: # https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html ZipFile: | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 import os import json from urllib import request import ipaddress # AWS services to return for default API default_services = os.getenv('SERVICES', 'CLOUDFRONT_ORIGIN_FACING').split(',') if default_services == ['']: default_services = ['CLOUDFRONT_ORIGIN_FACING'] # Search function: check if valid IP address def is_ipAddress(address): try: ipaddress.ip_address(address) return True except ValueError: return False def is_ipv4(address): try: ipaddress.IPv4Address(address) return True except ValueError: return False def lambda_handler(event, context): # load ip-ranges.json response = request.urlopen('https://ip-ranges.amazonaws.com/ip-ranges.json') data = response.read() ipranges_json = json.loads(data) createDate = ipranges_json['createDate'] syncToken = ipranges_json['syncToken'] hstsValue = "max-age=31536000" url = event['requestContext']['http']['path'] if url.lower() == '/favicon.ico': return { 'statusCode': 404, 'body': 'Not Found!', "headers": { "content-type": "text/html", "Strict-Transport-Security": hstsValue } } elif url.lower() == '/robots.txt': return { 'statusCode': 200, 'body' : 'User-agent: *\nDisallow: /', "headers": { "content-type": "text/plain", "Strict-Transport-Security": hstsValue } } elif url.lower() == '/createdate': return { 'statusCode': 200, 'body' : createDate, "headers": { "content-type": "text/plain", "Strict-Transport-Security": hstsValue } } elif url.lower() == '/synctoken': return { 'statusCode': 200, 'body' : syncToken, "headers": { "content-type": "text/plain", "Strict-Transport-Security": hstsValue } } # available aws services/regions/network_border_groups all_aws_services = list() all_aws_regions = list() all_aws_networks = list() for i in ipranges_json['prefixes']: if i['service'] not in all_aws_services: all_aws_services.append(i['service']) if i['region'] not in all_aws_regions: all_aws_regions.append(i['region']) if i['network_border_group'] not in all_aws_networks: all_aws_networks.append(i['network_border_group']) args = url.split('/') responseBody = '' # SERVICES and REGIONS to filter by? SERVICES = all_aws_services.copy() REGIONS = all_aws_regions.copy() NETWORKS = all_aws_networks.copy() # return list of all prefixes / services / regions / network_border_groups if len(args) == 2: SERVICES = default_services if args[1].upper() == 'SERVICE': responseBody = all_aws_services elif args[1].upper() == 'REGION': responseBody = all_aws_regions elif args[1].upper() == 'NETWORK': responseBody = all_aws_networks elif args[1].upper() == "SEARCH": responseBody = list() responseBody.append("Enter a IP address to query") if responseBody != '': return { 'statusCode': 200, 'body': '\n'.join(sorted(responseBody)), "headers": { "content-type": "text/plain", "path" : url, "syncToken": ipranges_json['syncToken'], "createDate": ipranges_json['createDate'], "Strict-Transport-Security": hstsValue } } elif len(args) >= 3: # /SERVICE// if args[1].upper()=='SERVICE' and args[2] in all_aws_services: SERVICES = [args[2]] if len(args) >=4 and args[3] in all_aws_regions: REGIONS = [args[3]] # /REGION// elif args[1].upper()=='REGION' and args[2] in all_aws_regions: REGIONS = [args[2]] if len(args) >=4 and args[3] in all_aws_services: SERVICES= [args[3]] # /NETWORK// elif args[1].upper()=='NETWORK' and args[2] in all_aws_networks: NETWORKS = [args[2]] if len(args) >=4 and args[3] in all_aws_services: SERVICES= [args[3]] # /SEARCH/ elif args[1].upper() == 'SEARCH' and is_ipAddress(args[2]): aws_ranges = list() ip_object = ipaddress.ip_address(args[2]) if is_ipv4(args[2]): for i in ipranges_json['prefixes']: if ip_object in ipaddress.ip_network(i['ip_prefix']): aws_ranges.append(i['ip_prefix'] + "," + i['region'] + "," + i["service"] + "," + i["network_border_group"]) else: for i in ipranges_json['ipv6_prefixes']: if ip_object in ipaddress.ip_network(i['ipv6_prefix']): aws_ranges.append(i['ipv6_prefix'] + "," + i['region'] + "," + i["service"] + "," + i["network_border_group"]) if len(aws_ranges) > 0: aws_ranges.insert(0, 'ip_prefix,region,service,network_border_group') return { 'statusCode': 200, 'body': '\n'.join(aws_ranges), "headers": { "content-type": "text/plain", "path" : url, "syncToken": ipranges_json['syncToken'], "createDate": ipranges_json['createDate'], "Strict-Transport-Security": hstsValue } } else: return { 'statusCode': 404, 'body': 'Not AWS IP address', "headers": { "content-type": "text/html", "Strict-Transport-Security": hstsValue } } else: return { 'statusCode': 404, 'body': 'Not Found!', "headers": { "content-type": "text/html", "Strict-Transport-Security": hstsValue } } # IPv4 / IPv6 only? : ipv4_only = url.upper().endswith('/IPV4.TXT') ipv6_only = url.upper().endswith('/IPV6.TXT') prefixes = '' aws_region = list() aws_service = list() aws_network = list() ipv4_prefixes = list() if not ipv6_only: for i in ipranges_json['prefixes']: if i['service'] in SERVICES and i['region'] in REGIONS and i['network_border_group'] in NETWORKS and i['ip_prefix'] not in ipv4_prefixes: ipv4_prefixes.append(i['ip_prefix']) if i['region'] not in aws_region: aws_region.append(i['region']) if i['service'] not in aws_service: aws_service.append(i['service']) if i['network_border_group'] not in aws_network: aws_network.append(i['network_border_group']) prefixes = '\n'.join(sorted(ipv4_prefixes, key = ipaddress.IPv4Network)) ipv6_prefixes = list() if not ipv4_only: for i in ipranges_json['ipv6_prefixes']: if i['service'] in SERVICES and i['region'] in REGIONS and i['network_border_group'] in NETWORKS and i['ipv6_prefix'] not in ipv6_prefixes: ipv6_prefixes.append(i['ipv6_prefix']) if i['region'] not in aws_region: aws_region.append(i['region']) if i['service'] not in aws_service: aws_service.append(i['service']) if i['network_border_group'] not in aws_network: aws_network.append(i['network_border_group']) if len(prefixes) > 0: prefixes += '\n' prefixes += '\n'.join(sorted(ipv6_prefixes, key = ipaddress.IPv6Network)) sourceIp = event['requestContext']['http']['sourceIp'] print(f'Source IP:{sourceIp}, Path:{url}, IPv4 Prefixes:{len(ipv4_prefixes)}, IPv6 Prefixes:{len(ipv6_prefixes)}, createDate:{createDate}, syncToken:{syncToken}') return { 'statusCode': 200, 'body': prefixes, "headers": { "content-type": "text/plain", "aws-service" : ','.join(sorted(aws_service)), "aws-region" : ','.join(sorted(aws_region)), "aws-network" : ','.join(sorted(aws_network)), "path" : url, "syncToken": syncToken, "createDate": createDate, "Strict-Transport-Security": hstsValue } } Tags: - Key: StackName Value: !Ref AWS::StackName - Key: StackId Value: !Ref AWS::StackId - Key: GitHub Value: https://github.com/aws-samples/aws-ipranges-api - Key: Description Value: Returns AWS IP prefixes from ip-ranges.json lambdaVersion: Type: AWS::Lambda::Version Properties: FunctionName: !Ref lambdaFunction Description: Version 1.0 lambdaAuthorizerFunctionIamRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Principal: Service: - lambda.amazonaws.com Action: - sts:AssumeRole Policies: - PolicyName: lambdaAuthorizerFunctionPolicy PolicyDocument: Version: "2012-10-17" Statement: - Effect: Allow Action: - logs:CreateLogStream - logs:PutLogEvents Resource: !Sub - "arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/aws/lambda/${AWS::StackName}-lambdaAuthorizerFunction-${UID}:*" - UID: !Select [ 3, !Split [ "-", !Select [2, !Split ["/", !Ref AWS::StackId]], ], ] Tags: - Key: StackName Value: !Ref AWS::StackName - Key: StackId Value: !Ref AWS::StackId - Key: GitHub Value: https://github.com/aws-samples/aws-ipranges-api - Key: Description Value: !Sub - "For lambda function ${AWS::StackName}-lambdaAuthorizerFunction-${UID}" - UID: !Select [ 3, !Split ["-", !Select [2, !Split ["/", !Ref AWS::StackId]]], ] lambdaAuthorizerFunctionLogGroup: Type: AWS::Logs::LogGroup DeletionPolicy: Delete UpdateReplacePolicy: Delete Properties: KmsKeyId: !Ref AWS::NoValue RetentionInDays: !Ref AWS::NoValue LogGroupName: !Sub - "/aws/lambda/${AWS::StackName}-lambdaAuthorizerFunction-${UID}" - UID: !Select [ 3, !Split ["-", !Select [2, !Split ["/", !Ref AWS::StackId]]], ] Tags: - Key: StackName Value: !Ref AWS::StackName - Key: StackId Value: !Ref AWS::StackId - Key: GitHub Value: https://github.com/aws-samples/aws-ipranges-api lambdaAuthorizerFunction: Type: AWS::Lambda::Function Properties: Description: !Sub "[${AWS::StackName}] - Lambda Authorizer for API Gateway" FunctionName: !Sub - "${AWS::StackName}-lambdaAuthorizerFunction-${UID}" - UID: !Select [ 3, !Split ["-", !Select [2, !Split ["/", !Ref AWS::StackId]]], ] Handler: "index.lambda_handler" MemorySize: 128 ReservedConcurrentExecutions: !Ref AWS::NoValue Role: !GetAtt lambdaAuthorizerFunctionIamRole.Arn Environment: Variables: ALLOWED_NETWORKS: !Ref allowNetworks ALLOWED_IPv6_NETWORKS: !Ref allowIPv6Networks Runtime: !Ref pythonRuntime Timeout: 5 Architectures: - !Ref cpuArchitecture Code: ZipFile: | # Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. # SPDX-License-Identifier: MIT-0 import os import ipaddress # Allowed source IP prefixes allowed_networks = os.getenv('ALLOWED_NETWORKS', '0.0.0.0/0').split(',') if allowed_networks == ['']: allowed_networks = ['0.0.0.0/0'] allowed_ipv6_networks = os.getenv('ALLOWED_IPv6_NETWORKS', '::/0').split(',') if allowed_ipv6_networks == ['']: allowed_ipv6_networks = ['::/0'] # See https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-lambda-authorizer.html for payload format def lambda_handler(event, context): sourceIp = event['requestContext']['http']['sourceIp'] source_address = ipaddress.ip_address(sourceIp) if source_address.version == 4: print(f'Source IP:{sourceIp}, Allowed Networks:{allowed_networks}') for allowed in allowed_networks: if source_address in ipaddress.ip_network(allowed, False): print('Authorized: Yes') return { "isAuthorized": True } else: print(f'Source IP:{sourceIp}, Allowed Networks:{allowed_ipv6_networks}') for allowed in allowed_ipv6_networks: if source_address in ipaddress.ip_network(allowed, False): print('Authorized: Yes') return { "isAuthorized": True } print('Authorized: No') return { "isAuthorized": False } Tags: - Key: StackName Value: !Ref AWS::StackName - Key: StackId Value: !Ref AWS::StackId - Key: GitHub Value: https://github.com/aws-samples/aws-ipranges-api lambdaAuthorizerVersion: Type: AWS::Lambda::Version Properties: FunctionName: !Ref lambdaAuthorizerFunction Description: version 1.0 apiGateway: Type: AWS::ApiGatewayV2::Api Properties: Name: !Sub - "${AWS::StackName}-apiGateway-${UID}" - UID: !Select [ 3, !Split ["-", !Select [2, !Split ["/", !Ref AWS::StackId]]], ] Description: !Sub "[${AWS::StackName}] - returns AWS IP prefixes from ip-ranges.json" ProtocolType: HTTP DisableExecuteApiEndpoint: !If [enableDefaultEndPoint, false, true] IpAddressType: !FindInMap [ipTypeMapping, !Ref ipAddressType, Value] Tags: StackName: !Ref AWS::StackName StackId: !Ref AWS::StackId GitHub: "https://github.com/aws-samples/aws-ipranges-api" apiRoute: Type: AWS::ApiGatewayV2::Route Properties: ApiId: !Ref apiGateway RouteKey: "$default" AuthorizationType: CUSTOM AuthorizerId: !Ref apiAuthorizer Target: !Sub "integrations/${apiGatewayIntegration}" apiGatewayIntegration: Type: "AWS::ApiGatewayV2::Integration" Properties: # Uri at https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-custom-integrations.html ApiId: !Ref apiGateway Description: !Sub ${AWS::StackName} Lambda integration with ${apiGateway} IntegrationType: AWS_PROXY IntegrationUri: !Sub "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaFunction.Arn}/invocations" IntegrationMethod: POST PayloadFormatVersion: "2.0" TimeoutInMillis: 25000 apiLogGroup: Type: "AWS::Logs::LogGroup" DeletionPolicy: Delete UpdateReplacePolicy: Delete Properties: # Size limit considerations at https://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AWS-logs-and-resource-policy.html#AWS-logs-infrastructure-CWL KmsKeyId: !Ref AWS::NoValue RetentionInDays: !Ref AWS::NoValue LogGroupName: !Sub /${AWS::StackName}/apiLog Tags: - Key: StackName Value: !Ref AWS::StackName - Key: StackId Value: !Ref AWS::StackId - Key: GitHub Value: "https://github.com/aws-samples/aws-ipranges-api" apiLogResourcePolicy: Type: AWS::Logs::ResourcePolicy Properties: PolicyName: !Sub AWSLogDeliveryWrite-${AWS::StackName} PolicyDocument: !Sub '{"Version":"2012-10-17","Statement":[{"Sid":"AWSLogDeliveryWrite","Effect":"Allow","Principal":{"Service":"delivery.logs.amazonaws.com"},"Action":["logs:CreateLogStream","logs:PutLogEvents"],"Resource":"arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:log-group:/${AWS::StackName}/apiLog:log-stream:*","Condition":{"StringEquals":{"aws:SourceAccount":"${AWS::AccountId}"},"ArnLike":{"aws:SourceArn":"arn:${AWS::Partition}:logs:${AWS::Region}:${AWS::AccountId}:*"}}}]}' apiStage: Type: "AWS::ApiGatewayV2::Stage" DependsOn: apiLogResourcePolicy Properties: # Account limits at https://docs.aws.amazon.com/apigateway/latest/developerguide/limits.html#apigateway-account-level-limits-table Description: !Sub ${AWS::StackName} API stage for ${apiGateway} StageName: $default AutoDeploy: true ApiId: !Ref apiGateway DefaultRouteSettings: DetailedMetricsEnabled: true #ThrottlingBurstLimit: 50 #ThrottlingRateLimit: 10 AccessLogSettings: # https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html DestinationArn: !GetAtt apiLogGroup.Arn Format: "$context.identity.sourceIp,$context.path,$context.requestTime,$context.httpMethod,$context.routeKey,$context.protocol,$context.status,$context.responseLength,$context.requestId" Tags: StackName: !Ref AWS::StackName StackId: !Ref AWS::StackId GitHub: "https://github.com/aws-samples/aws-ipranges-api" apiAuthorizer: Type: AWS::ApiGatewayV2::Authorizer Properties: ApiId: !Ref apiGateway AuthorizerType: REQUEST AuthorizerPayloadFormatVersion: 2.0 AuthorizerResultTtlInSeconds: 10 IdentitySource: - $context.identity.sourceIp AuthorizerUri: !Sub arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaAuthorizerFunction.Arn}/invocations EnableSimpleResponses: True Name: !Sub - "${AWS::StackName}-apiAuthorizer-${UID}" - UID: !Select [ 3, !Split ["-", !Select [2, !Split ["/", !Ref AWS::StackId]]], ] apiTriggerAuthorizerPermission: Type: "AWS::Lambda::Permission" Properties: Action: lambda:InvokeFunction FunctionName: !GetAtt lambdaAuthorizerFunction.Arn Principal: apigateway.amazonaws.com SourceArn: !Sub arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/* apiTriggerPermission: Type: "AWS::Lambda::Permission" Properties: # See https://docs.aws.amazon.com/lambda/latest/dg/services-apigateway.html#apigateway-permissions Action: lambda:InvokeFunction FunctionName: !GetAtt lambdaFunction.Arn Principal: apigateway.amazonaws.com SourceArn: !Sub "arn:${AWS::Partition}:execute-api:${AWS::Region}:${AWS::AccountId}:${apiGateway}/*" apiCustomDomainName: Condition: useCustomDomainName Type: AWS::ApiGatewayV2::DomainName Properties: DomainName: !Ref customDomainName DomainNameConfigurations: - CertificateArn: !Ref certificateArn EndpointType: REGIONAL SecurityPolicy: TLS_1_2 IpAddressType: !FindInMap [ipTypeMapping, !Ref ipAddressType, Value] Tags: StackName: !Ref AWS::StackName StackId: !Ref AWS::StackId GitHub: "https://github.com/aws-samples/aws-ipranges-api" Description: !Sub "Custom domain name for ${apiGateway}" apiMapping: Condition: useCustomDomainName DependsOn: - apiCustomDomainName - apiStage Type: AWS::ApiGatewayV2::ApiMapping Properties: DomainName: !Ref customDomainName ApiId: !Ref apiGateway Stage: $default Outputs: apiConsole: Description: "API Gateway console" Value: !Sub "https://${AWS::Region}.console.aws.amazon.com/apigateway/main/api-detail?api=${apiGateway.ApiId}®ion=${AWS::Region}" apiInvokeURL: Condition: useCustomDomainName Description: "Custom domain name for use by firewall or application. Create DNS record first" Value: !Sub "https://${customDomainName}" apiFQDN: Condition: useCustomDomainName Description: "Create your customDomainName DNS record to this FQDN" Value: !GetAtt apiCustomDomainName.RegionalDomainName apiGatewayInvokeURL: Condition: enableDefaultEndPoint Description: URL for use by firewall or application Value: !GetAtt apiGateway.ApiEndpoint apiGatewayLog: Description: Cloudwatch log for API Gateway Value: !Sub https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#logsV2:log-groups/log-group/$252F${AWS::StackName}$252FapiLog lambdaFunctionLog: Description: Cloudwatch log for Lambda function Value: !Sub - "https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#logsV2:log-groups/log-group/$252Faws$252Flambda$252F${AWS::StackName}-lambdaFunction-${UID}" - UID: !Select [ 3, !Split ["-", !Select [2, !Split ["/", !Ref AWS::StackId]]], ] lambdaAuthorizerFunctionLog: Description: Cloudwatch log for Lambda authorizer function Value: !Sub - "https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#logsV2:log-groups/log-group/$252Faws$252Flambda$252F${AWS::StackName}-lambdaAuthorizerFunction-${UID}" - UID: !Select [ 3, !Split ["-", !Select [2, !Split ["/", !Ref AWS::StackId]]], ]