Шлюз API с MTLS и авторизацией — несовместимый $context.identity.sourceIP

#aws-api-gateway

Вопрос:

Для решения со следующей архитектурой AWS:

 Client A --> API Gateway A --> Server A
                  |
                  |--> Lambda Authorizer (custom and shared)
                  |
Client B --> API Gateway B --> Server B
                  |
              S3 Bucket
              (trustore)
 

Где, чтобы использовать API-шлюз, открытые API:

  • Оба IP-адреса клиентов должны быть занесены в белый список
  • Оба клиента должны иметь действительные учетные данные/токен
  • Клиенту B требуется MTLS (использует шлюз API B)

Используемый тип шлюза AWS API — HTTP API (v2)-в основном из-за экономичных API REST.

Созданный пользовательский Лямбда-авторизатор является общим для обоих шлюзов API и авторизует клиентов на основе их:

  • Проверка блока IPs — CIDR
  • Учетные данные/Токен — аутентификация

Конфигурация безопасности для обоих шлюзов API (A и B) является:

   securitySchemes:
    oauth:
      in: header
      name: IpAuthorizer
      type: apiKey
      x-amazon-apigateway-authtype: oauth2
      x-amazon-apigateway-authorizer:
        type: request
        authorizerPayloadFormatVersion: 1.0
        identitySource: "$request.header.Authorization,$context.identity.sourceIp"
        authorizerUri: !Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaAuthorizerArn}/invocations"
 

Но содержимое событий лямбда-авторизатора отличается и непоследовательно:

  • Для клиента A — из шлюза API A:
 {
    "version": "1.0",
    "type": "REQUEST",
    "identitySource": "<Token_ClientA>, <IP_ClientA>",
    "headers": {
        "x-forwarded-for": "<IP_ClientA>",
        ...
    },
    "requestContext": {
        "identity": {
            "sourceIp": " <IP_ClientA>",
            ...
        },
        ...
    },
    ...
}
 

Вопрос 1:
Почему $context.identity.sourceIp части в $.identitySource и $.requestContext.identity.sourceIp предшествуют дополнительные пробелы (‘ ‘)?


  • Для клиента B — из шлюза API B:
 {
    "version": "1.0",
    "type": "REQUEST",
    "identitySource": "<Token_ClientB>,10.1.9.160:35840",
    "headers": {
        "x-forwarded-for": "<IP_ClientB>",
        ...
    },
    "requestContext": {
        "identity": {
            "sourceIp": "10.1.9.160:35840",
            ...
        },
        ...
    },
    ...
}
 

Question 2:
Why the Client IP ( $context.identity.sourceIp ) is not present in neither $.identitySource nor $.requestContext.identity.sourceIp ?


Question 3:
What is the 10.1.9.160:35840 (not constant) and where does it come from?


The only consistency in the Lambda Authorizer Events content seems to be the presence of the X-Forwarded-For header, containing the source IP address of the immediate TCP API Gateway connection.

But even the X-Forwarded-For header usage is not really consistent, because if we place both Clients behind the same reverse proxy with X-Forwarded-* settings enabled, we have different contents for the header in the Lambda Authorizer Events content:

  • For Client A — from API Gateway A:
 {
    ...
    "headers": {
        "x-forwarded-for": "<IP_ClientA>, <IP_ReverseProxy>",
        ...
    },
    ...
}
 
  • For Client B — from API Gateway B:
 {
    ...
    "headers": {
        "x-forwarded-for": "<IP_ReverseProxy>",
        ...
    },
    ...
}
 

Question 4:
Why is the X-Forwarded-For header not being correctly passed through API Gateway B?