Welcome to Knowledge Base!

KB at your finger tips

This is one stop global knowledge base where you can learn about all the products, solutions and support features.

Categories
All
Cloud-AWS
Pass API Gateway REST API data to Lambda or an HTTP endpoint

How do I pass data through an API Gateway REST API to a backend Lambda function or HTTP endpoint?

Last updated: 2022-08-26

I want my Amazon API Gateway REST API to pass data to a backend AWS Lambda function and an HTTP endpoint. How can I do that?

Short description

To configure a REST API to pass data to a backend Lambda function, use a Lambda custom integration.

To pass query string parameters to an HTTP endpoint, use an HTTP custom integration.

Important: Make sure that the input data is supplied as the integration request payload. It’s a best practice to use a mapping template to supply the payload. For more information, see Map request and response payloads between method and integration.

Resolution

Create a Lambda function to handle custom headers from your API Gateway API

1.    Open the Lambda console.

2.    Choose Create function . The Create function page opens with the Author from scratch option selected.

3.    In the Basic information pane, do the following: For Function name , enter a name that describes your function's purpose. For example: MapTemplate . For Runtime , choose Python 3.9 .

4.    For Permissions , expand Change default execution role .

5.    Choose Use an existing role . A dropdown list of existing roles appears.

6.    For Existing role , choose the Lambda execution role that you created earlier.

7.    Choose Create function .

8.    From the Code tab, in Code source , replace the code in lambda_function.py with the following:

import json

def lambda_handler(event, context):
    print(event)
    return {
        'statusCode': 200,
        'body': json.dumps(event) # returning the data sent to backend lambda function as API response.
    }

9.    Choose Deploy .

For more information, see Building Lambda functions with Python.

Pass data to the backend Lambda function or HTTP endpoint

1.    Open the API Gateway console.

2.    Choose Create API .

-or-

(If this is your first time using API Gateway) A page that introduces you to the features of the service appears. In REST API , choose Build . When the Create Example API popup appears, choose OK .

3.    For Choose an API type , in the REST API pane, choose Build .

4.    In Create new API , choose New API .

5.    In Settings , do the following: For API name , enter a name that describes your API's purpose. For example: MappingTemplateTutorial . (Optional) For Description , enter a short description your API's purpose. For example, Send Data to Backend Lambda function/HTTP endpoint . For Endpoint Type , choose Regional .

6.    Choose Create API .

Configure your API's resources, integration point, and body mapping template

1.    In the API Gateway console, choose the name of the API that you created in the previous step. Your API's Resources page opens.

2.    On the Resources page, choose Actions . Then, choose Create Resource .

3.    In the New Child Resource pane, for Configure as proxy resource , select the check mark icon , and then choose Create Resource .

4.    On the /{proxy+} - ANY - Setup page, do the following:

  • For Integration type , choose Lambda Function Proxy .
  • For Lambda Region , choose the AWS Region that hosts your function.
  • For Lambda Function , enter the function's name MappingTemplateTutorial .

Choose Save . An Add Permission to Lambda Function popup appears, choose OK .

7.    On the / {proxy+} - ANY - Method Execution page, choose Integration Request .

8.    On the / {proxy+} - ANY - Integration Request page, do the following:

  • Uncheck the Use Lambda Proxy integration icon box. A Switch to Lambda integration popup appears.
  • In the popup, choose OK. An Add Permission to Lambda Function popup appears. In the popup, choose OK
  • Expand Mapping Templates .
  • For Request body passthrough , choose When there are no templates defined (recommended) .

Choose Add mapping template . For Content-Type , enter application/json . Then, choose the check mark icon.

9.    Choose the Generate template dropdown list, and then choose Method Request passthrough .

10.    In the mapping template editor, enter the following:

##  See http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html
#set($allParams = $input.params())
{
"method" : "$context.httpMethod", ## API method
"authcontext" : "$context.authorizer.stringkey", ## Optional output from Lambda Authorizers
## passthrough body
"body-json" : $input.json('$'),
## passthrough headers, querystrings and path parameters
"params" : {
#foreach($type in $allParams.keySet())
    #set($params = $allParams.get($type))
"$type" : {
    #foreach($paramName in $params.keySet())
    "$paramName" : "$util.escapeJavaScript($params.get($paramName))"
        #if($foreach.hasNext),#end
    #end
}
    #if($foreach.hasNext),#end
#end
}
}

11.    Choose Save .

12.    Choose Method Execution to come back to / {proxy+} - ANY - Method Execution page.

13.    Choose Method Response to setup valid method response.

14.    On /{proxy+} - ANY - Method Response page, Choose Add Response .

15.    For HTTP status code, enter 200 . Then, choose the check mark icon.

16.    Choose Actions to Deploy API to a stage.

Deploy your API to a new stage

1.    Follow the instructions in Deploy a REST API to a stage. For more information, see Setting up a stage using the API Gateway console.

2.    In the Stage Editor pane, copy the Invoke URL to your clipboard.

REST API Invoke URL example

https://1a2bc3d456.execute-api.us-east-1.amazonaws.com/stage

Test your setup

To confirm that all data is being passed to backend Lambda function or HTTP endpoint by your API, run the following curl command:

Important: Replace https://restApiId.execute-api.region.amazonaws.com/stageName with your API's invoke URL.

curl -i --location --request POST 'https://1a2bc3d456.execute-api.us-east-1.amazonaws.com/stage/path1/path2?query1=querystring1&query2=querystring2' --header 'header1: value1' --header 'header2: value2' --header 'Content-Type: application/json' --data-raw '{"keybody":"valuebody"}'

The command output includes all data received by the backend Lambda function to the client. You can update the output message for your environment.

Note: To install curl on Windows, see Downloads on the Git website. For more information about curl, see the curl project website.


Tutorial: Build an API Gateway REST API with Lambda non-proxy integration

Setting up data transformations for REST APIs

How do I pass custom headers through API Gateway to a Lambda function using custom Lambda integration?

Did this article help?

Submit feedback

Do you need billing or technical support?

Contact AWS Support
Set up API Gateway access logging

How can I set up access logging for API Gateway?

Last updated: 2022-08-15

I'm trying to set up access logging for Amazon API Gateway. How can I do this?

Short description

To debug issues related to request execution or client access to your API, you can activate Amazon CloudWatch Logs to log API calls.

Resolution

Before you begin, make sure that you have:

  • Deployed your API to a stage.
  • Granted API Gateway permission to read and write logs to CloudWatch for your account.

Next, to activate access logging follow steps 1-5 and 7-8 (skip step 6) in the instructions for setting up CloudWatch API logging using the API Gateway console.

Note: It's a best practice not to log the full API requests and responses for production APIs. Full API requests and responses can result in logging sensitive data.

You now have CloudWatch logs activated for debugging. To find errors, see How do I find API Gateway REST API errors in my CloudWatch logs?

For more information, see Monitoring REST API execution with Amazon CloudWatch metrics.


How do I troubleshoot "Invalid permissions on Lambda function" errors from API Gateway REST APIs?

How do I find 5xx errors from API Gateway in my CloudWatch logs?

How do I turn on CloudWatch Logs for troubleshooting my API Gateway REST API or WebSocket API?

Did this article help?

Submit feedback

Do you need billing or technical support?

Contact AWS Support
Read article
Resolve errors deleting API Gatewway custom domain names

How can I resolve errors when deleting custom domain names with API Gateway?

Last updated: 2022-08-15

I tried to delete a custom domain name for Amazon API Gateway. However, I received an error when calling the DeleteDomainName API action.

Resolution

Follow these instructions for the error message received with your scenario.

An error occurred (AccessDeniedException) when calling the DeleteDomainName API

AWS Identity and Access Management (IAM) identity-based policies determine if the API Gateway resources can be deleted.

Check to confirm that the API caller has the necessary permission to delete a custom domain. The IAM policy attached to the client trying to delete the custom domain should have permissions similar to the following:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "apigateway:Delete"
        ],
      "Resource": "arn:aws:apigateway:*::/*"
    }
  ]
}

For more information, see Policy best practices.

An error occurred (TooManyRequestsException) when calling the DeleteDomainName API

The API Gateway quota for the DeleteDomainName API request is 1 request every 30 seconds per account. This limit can't be increased. If you tried to delete a custom domain using the AWS CLI or SDK with a built-in retry mechanism, the request might fail. This is because the quota has been reached of 1 request every 30 seconds.

To resolve this, use exponential backoff and jitter in the error retry so that there are progressively longer delays between retry attempts.


Exponential backoff and jitter

Did this article help?

Submit feedback

Do you need billing or technical support?

Contact AWS Support
Read article
Identify API key usage with API Gateway

How can I identify the usage associated with an API key for API Gateway?

Last updated: 2022-08-12

How can I get the usage associated with an API key for Amazon API Gateway?

Resolution

Follow these instructions to get the API key usage using either the AWS Management Console or the AWS Command Line Interface (AWS CLI).

Note: If you receive errors when running AWS CLI commands, make sure that you’re using the most recent version of the AWS CLI.

Use the AWS Management Console

  1. Open the API Gateway console.
  2. In the navigation pane, choose APIs .
  3. Choose your API, and then choose Usage Plans .
  4. Choose your Usage Plan .
  5. Choose Actions , and then choose Export Usage Data .
  6. Choose the export From and To date range.
  7. For Export as , choose JSON or CSV , and then choose Export .

For more information, see Create, configure, and test usage plans with the API Gateway console.

Use the AWS CLI

You can use the AWS CLI command get-usage to get the usage data of a usage plan in a date range similar to the following:

aws apigateway get-usage --usage-plan-id <usage-plan-id> --start-date "20xx-xx-xx" --end-date "20xx-xx-xx" --key-id <api-key-id>

Note: The usage date range can't exceed 90 days.

For more information, see Create, configure, and test usage plans using the API Gateway CLI and REST API.


Best practices for API keys and usage plans

Did this article help?

Submit feedback

Do you need billing or technical support?

Contact AWS Support
Read article
Fix authorization HTTP 403 errors from API Gateway Lambda authorizers

Why is my API Gateway proxy resource with a Lambda authorizer that has caching activated returning HTTP 403 "User is not authorized to access this resource" errors?

Last updated: 2022-08-17

My Amazon API Gateway proxy resource with an AWS Lambda authorizer that has caching activated returns the following HTTP 403 error message: "User is not authorized to access this resource". Why is this happening, and how do I resolve the error?

Short description

Note: API Gateway can return 403 User is not authorized to access this resource errors for a variety of reasons. This article addresses 403 errors related to API Gateway proxy resources with a Lambda authorizer that has caching activated only. For information on troubleshooting other types of 403 errors, see How do I troubleshoot HTTP 403 errors from API Gateway?

A Lambda authorizer's output returns an AWS Identity and Access Management (IAM) policy to API Gateway. The IAM policy includes an explicit API Gateway API "Resource" element that's in the following format:

"arn:aws:execute-api:<region>:<account>:<API_id>/<stage>/<http-method>/[<resource-path-name>/[<child-resources-path>]"

When Authorization Caching is activated on a Lambda authorizer, the returned IAM policy is cached. The cached IAM policy is then applied to any additional API requests made within the cache's specified time-to-live (TTL) period.

If the API has a proxy resource with a greedy path variable of {proxy+} , the first authorization succeeds. Any additional API requests made to a different path within the cache's TTL period fail and return the following error:

"message": "User is not authorized to access this resource"

The additional requests fail, because the paths don't match the explicit API Gateway API "Resource" element defined in the cached IAM policy.

To resolve the issue, you can modify the Lambda authorizer function's code to return a wildcard ( */* ) resource in the output instead. For more information, see Resources and conditions for Lambda actions.

Note : To activate authorizer caching, your authorizer must return a policy that is applicable to all methods across an API Gateway. The Lambda authorizer function's code must return a wildcard (*/*) resource in the output to allow all resources. The cache policy expects the same resource path cached, unless you made the same request twice on the same resource-path.

Resolution

Note: Modify the example Lambda authorizer function code snippets in this article to fit your use case.

In the following example setups, the Lambda functions extract the API Gateway's id value from the method's Amazon Resource Name (ARN) ( "event.methodArn" ). Then, the functions define a wildcard "Resource" variable by combining the method ARN's paths with the API's id value and a wildcard ( */* ).

Example token-based Lambda authorizer function code that returns a wildcard "Resource" variable

exports.handler =  function(event, context, callback) {
    var token = event.authorizationToken;
    var tmp = event.methodArn.split(':');
    var apiGatewayArnTmp = tmp[5].split('/');
    
    // Create wildcard resource
    var resource = tmp[0] + ":" + tmp[1] + ":" + tmp[2] + ":" + tmp[3] + ":" + tmp[4] + ":" + apiGatewayArnTmp[0] + '/*/*'; 
    switch (token) {
        case 'allow':
            callback(null, generatePolicy('user', 'Allow', resource));
            break;
        case 'deny':
            callback(null, generatePolicy('user', 'Deny', resource));
            break;
        case 'unauthorized':
            callback("Unauthorized");   // Return a 401 Unauthorized response
            break;
        default:
            callback("Error: Invalid token"); // Return a 500 Invalid token response
    }
};
// Help function to generate an IAM policy
var generatePolicy = function(principalId, effect, resource) {
    var authResponse = {};
    
    authResponse.principalId = principalId;
    if (effect && resource) {
        var policyDocument = {};
        policyDocument.Version = '2012-10-17'; 
        policyDocument.Statement = [];
        var statementOne = {};
        statementOne.Action = 'execute-api:Invoke'; 
        statementOne.Effect = effect;
        statementOne.Resource = resource;
        policyDocument.Statement[0] = statementOne;
        authResponse.policyDocument = policyDocument;
    }
    
    // Optional output with custom properties of the String, Number or Boolean type.
    authResponse.context = {
        "stringKey": "stringval",
        "numberKey": 123,
        "booleanKey": true
    };
    return authResponse;
}

Example request parameter-based Lambda authorizer function code that returns a wildcard "Resource" variable

exports.handler = function(event, context, callback) {        
   
    // Retrieve request parameters from the Lambda function input:
    var headers = event.headers;
    var queryStringParameters = event.queryStringParameters;
    var pathParameters = event.pathParameters;
    var stageVariables = event.stageVariables;
        
    // Parse the input for the parameter values
    var tmp = event.methodArn.split(':');
    var apiGatewayArnTmp = tmp[5].split('/');

    // Create wildcard resource
    var resource = tmp[0] + ":" + tmp[1] + ":" + tmp[2] + ":" + tmp[3] + ":" + tmp[4] + ":" + apiGatewayArnTmp[0] + '/*/*'; 
    console.log("resource: " + resource);
    // if (apiGatewayArnTmp[3]) {
    //     resource += apiGatewayArnTmp[3];
    // }
        
    // Perform authorization to return the Allow policy for correct parameters and 
    // the 'Unauthorized' error, otherwise.
    var authResponse = {};
    var condition = {};
    condition.IpAddress = {};
     
    
    if (headers.headerauth1 === "headerValue1"
        && queryStringParameters.QueryString1 === "queryValue1"
        && stageVariables.StageVar1 === "stageValue1") {
        callback(null, generateAllow('me', resource));
    }  else {
        callback("Unauthorized");
    }
}
     
// Help function to generate an IAM policy
var generatePolicy = function(principalId, effect, resource) {
    // Required output:
    console.log("Resource in generatePolicy(): " + resource);
    var authResponse = {};
    authResponse.principalId = principalId;
    if (effect && resource) {
        var policyDocument = {};
        policyDocument.Version = '2012-10-17'; // default version
        policyDocument.Statement = [];
        var statementOne = {};
        statementOne.Action = 'execute-api:Invoke'; // default action
        statementOne.Effect = effect;
        statementOne.Resource = resource;
        console.log("***Resource*** " + resource);
        policyDocument.Statement[0] = statementOne;
        console.log("***Generated Policy*** ");
        console.log(policyDocument);
        authResponse.policyDocument = policyDocument;
    }
    // Optional output with custom properties of the String, Number or Boolean type.
    authResponse.context = {
        "stringKey": "stringval",
        "numberKey": 123,
        "booleanKey": true
    };
    
    return authResponse;
}
     
var generateAllow = function(principalId, resource) {
    return generatePolicy(principalId, 'Allow', resource);
}
     
var generateDeny = function(principalId, resource) {
    return generatePolicy(principalId, 'Deny', resource);
}

For more information on how to edit Lambda function code, see Deploying Lambda functions defined as .zip file archives.


Edit code using the console editor

Did this article help?

Submit feedback

Do you need billing or technical support?

Contact AWS Support
Read article
Resolve mutual TLS 403 Forbidden errors from API Gateway

How do I troubleshoot HTTP 403 Forbidden errors from an API Gateway custom domain name that requires mutual TLS?

Last updated: 2021-12-08

My Amazon API Gateway custom domain name that has mutual Transport Layer Security (TLS) authentication activated returns HTTP 403 Forbidden errors. Why is this happening, and how do I troubleshoot the issue?

Short description

Note: API Gateway can return 403 Forbidden errors for a variety of reasons. This article addresses 403 Forbidden errors related to mutual TLS only. For information on troubleshooting other types of 403 Forbidden errors, see How do I troubleshoot HTTP 403 Forbidden errors from API Gateway?

To invoke an API Gateway API using a custom domain name that requires mutual TLS, clients must present a trusted certificate in the API request. When a client attempts to invoke the API, API Gateway looks for the client certificate's issuer in your truststore.

If any of the following conditions occur, then API Gateway fails the TLS connection and returns a 403 status code:

  • API Gateway can't find the issuer of the client certificate in your truststore.
  • The client certificate is using an insecure signature algorithm.
  • The client certificate is self signed.

If Amazon CloudWatch logging is activated for your API, then an error message that indicates the cause of the error appears in your execution logs.

Important: If the API request doesn't produce any CloudWatch Logs after logging is activated, then the 403 Forbidden error isn't related to mutual TLS.

For REST APIs

If you set up Amazon CloudWatch logging for your REST API, then one of the following error messages also appears in your execution logs:

  • Access denied. Reason: Could not find issuer for certificate
  • Access denied. Reason: Client cert using an insecure Signature Algorithm
  • Access denied. Reason: self signed certificate

For HTTP APIs

HTTP APIs don't support execution logging. To troubleshoot 403 Forbidden errors returned by a custom domain name that requires mutual TLS and invokes an HTTP API, you must do the following:

1.    Create a new API mapping for your custom domain name that invokes a REST API for testing only.
Note: If you don't have a REST API available for testing, then use the example PetStore REST API. Then, deploy the example API to a new stage and create a new API mapping for it that uses your custom domain name.

2.    Follow the instructions in the Resolution section of this article using the new API mapping that you created to your REST API.

3.    After the error is identified and resolved, reroute the API mapping for your custom domain name back to your HTTP API.

Resolution

Confirm the cause of the error

1.    If you haven't already, turn on CloudWatch logging for your REST API. Make sure that you configure execution and access logging.

Note: When configuring access logging for this use case, it's a best practice to use the following $context variables. These variables do two things:

  • They tell API Gateway to generate CloudWatch Logs when your custom domain name that requires mutual TLS returns a 403 Forbidden error.
  • They make it easier to identify the caller that tried to invoke your API when you review your CloudWatch Logs.

Recommended $context variables for CloudWatch access logging that will allow API Gateway to generate execution and access logs

{ "accountId":"$context.accountId", "apiId":"$context.apiId", "domainName":"$context.domainName", "domainPrefix":"$context.domainPrefix", "error.message":"$context.error.message", "error.responseType":"$context.error.responseType", "extendedRequestId":"$context.extendedRequestId", "httpMethod":"$context.httpMethod", "identity.sourceIp":"$context.identity.sourceIp", "identity.clientCert.clientCertPem":"$context.identity.clientCert.clientCertPem", "identity.clientCert.subjectDN":"$context.identity.clientCert.subjectDN", "identity.clientCert.issuerDN":"$context.identity.clientCert.issuerDN", "identity.clientCert.serialNumber":"$context.identity.clientCert.serialNumber", "identity.clientCert.validity.notBefore":"$context.identity.clientCert.validity.notBefore", "identity.clientCert.validity.notAfter":"$context.identity.clientCert.validity.notAfter", "identity.userAgent":"$context.identity.userAgent", "path":"$context.path", "protocol":"$context.protocol", "requestId":"$context.requestId", "requestTime":"$context.requestTime", "requestTimeEpoch":"$context.requestTimeEpoch", "resourceId":"$context.resourceId", "resourcePath":"$context.resourcePath", "stage":"$context.stage", "responseLatency":"$context.responseLatency", "responseLength":"$context.responseLength", "status":"$context.status" }

2.    Identify what's causing the 403 Forbidden errors by viewing your REST API's execution logs in CloudWatch. If a 403 Forbidden error related to mutual TLS is logged, then an error message similar to the following example appears.

Example CloudWatch Logs error message for when a custom domain name that requires mutual TLS returns a 403 Forbidden error

Extended Request Id: {extendedRequestId} 
Access denied. Reason: {reason} 
ForbiddenException Forbidden: {requestId}

To resolve "Access denied. Reason: Could not find issuer for certificate" errors

Verify that the issuer of the client certificate in the API request is included in the custom domain name's truststore

The issuer of the client certificate ( client.pem ) in the API request must be included in your custom domain name's truststore. The issuer must also be included as part of the certificate bundle ( bundle.pem ) in Amazon Simple Storage Service (Amazon S3).

To verify if the issuer of the client certificate is included in the required truststore, run the following OpenSSL command:

$ openssl verify -CAfile bundle.pem client.pem

-or-

If the certificate bundle contains intermediate certificate authorities, then run the following OpenSSL command:

$ openssl verify -CAfile rootCA.pem -untrusted intCA.pem client.pem

The command returns an OK response if the issuer of the client certificate in the API request is included in the required truststore.

The command returns the following error if the issuer of the client certificate isn't included in the required truststore: "error X at Y depth lookup: unable to get local issuer certificate"

Verify that all of the client certificates in your custom domain name's truststore are valid

If one of the client certificate's in your custom domain name's truststore isn't valid, then some clients might not be able to access your API.

To verify whether all of the client certificates in your truststore are valid, do the following:

1.    Open the API Gateway console.

2.    In the left navigation pane, choose Custom domain names . Then, choose your custom domain name that requires mutual TLS.

3.    In the Details section, see whether there's the following error message: There is an invalid certificate in your truststore bundle .

4.    If you see the error message, then you must decode the certificates in your truststore to identify which certificate produced the warning.
Note: The following OpenSSL command displays the contents of a certificate, including its subject:

$ openssl x509 -in certificate.crt -text -noout

5.    Update or remove the certificates that produced the warning. Then, upload a new truststore to Amazon S3.

For more information, see Troubleshooting certificate warnings.

Note: API Gateway accepts client certificates signed directly by the root certificate authority or any other intermediate if their certificate chain is preserved. To validate client certificates signed by the last intermediate certificate authority only, use a request parameter-based AWS Lambda authorizer. You can use your custom validation algorithm at the Lambda function level by accepting the client certificate as input from the API request.

To resolve "Access denied. Reason: Client cert using an insecure Signature Algorithm" errors

Verify that your truststore text file uses a supported hashing algorithm

API Gateway supports the following hashing algorithms in the truststore:

  • SHA-256 or stronger
  • RSA-2048 or stronger
  • ECDSA-256 or stronger

To verify if your truststore text file uses a supported hashing algorithm or not, then run the following OpenSSL command:

$ openssl x509 -in client.crt -text -noout | grep 'Signature Algorithm'

The command response returns your truststore's signature algorithm.

For more information, see Configuring your truststore.

To resolve "Access denied. Reason: self signed certificate" errors

Verify that the self-signed client certificate in the API request isn't altered or corrupted

The following must match exactly:

  • The modulus of the private key ( private.key ) used to sign the self-signed certificate within the truststore in S3 ( bundle.crt or bundle.pem ).
  • The modulus from the client's certificate passed in the API request ( client.crt ).

To compare the two modulus, run the following OpenSSL commands:

$ openssl rsa -noout -modulus -in private.key
$ openssl x509 -noout -modulus -in bundle.crt
$ openssl x509 -noout -modulus -in client.crt

Note: To produce a shorter hash value for easier comparison, you can PIPE- ing the output modulus into a cryptographic hash function. For example: openssl sha1 .

$ openssl [operation] -noout -modulus -in [data] | openssl sha1

Valid command output examples

2143831a73a8bb28467860df18550c696c03fbcb
2143831a73a8bb28467860df18550c696c03fbcb
2143831a73a8bb28467860df18550c696c03fbcb

To confirm data integrity, verify that there wasn't any data modification at the content level by running the following diff command:

$ diff client.crt bundle.crt

For more information, see Configuring your truststore.


Did this article help?

Submit feedback

Do you need billing or technical support?

Contact AWS Support
Read article