solo-io / gloo

The Feature-rich, Kubernetes-native, Next-Generation API Gateway Built on Envoy

Home Page:https://docs.solo.io/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Gloo Edge does not populate the identity object with the relevant data when wrapAsApiGateway is enabled

sadieleob opened this issue · comments

Gloo Edge Product

Enterprise

Gloo Edge Version

1.16.8

Kubernetes Version

v1.27.13-eks-3af4770

Describe the bug

When setting GE to mimic the AWS API GW behavior by setting to true unwrapAsApiGateway and wrapAsApiGateway, it looks like GE might not be wrapping the request in a way that Lambda function expects.

AWS Lambda logs:
java.lang.NullPointerException: Cannot invoke "com.amazonaws.serverless.proxy.model.ApiGatewayRequestIdentity.getAccessKey()" because the return value of "com.amazonaws.serverless.proxy.model.AwsProxyRequestContext.getIdentity()" is null

Expected Behavior

GE wraps the request to AWS Lambda in a manner identical to how API Gateway does, including fields such as the identity in the event object.

Steps to reproduce the bug

  1. Create AWS lambda:
mvn archetype:generate -DgroupId=my.service -DartifactId=my-service -Dversion=1.0-SNAPSHOT \
       -DarchetypeGroupId=com.amazonaws.serverless.archetypes \
       -DarchetypeArtifactId=aws-serverless-jersey-archetype \
       -DarchetypeVersion=2.0.1

Run "mvn clean package" to generate a zip file.
Deploy the zip file in a Lambda function. Select Lambda Java version for the Lambda runtime same as what you have in pom.xml.

AWS Lambda

  • Runtime: Java 21,
  • Handler: my.service.StreamLambdaHandler::handleRequest,
  • Arch: x86_64

Testing
Use following test event:

{
       "resource": "/ping",
       "path": "/ping",
       "httpMethod": "GET",
       "requestContext": {
           "stage": "stage1",
           "identity": {
             "apikey": "XXXXXXXXXXXXX",
             "userAgent": "curl/7.79.1"
           },
          "resourcePath": "/",
           "httpMethod": "GET",
           "path": "/"
       },
       "headers": {
            "Host": "www.example.com"
        },
        "multiValueHeaders": {
              "Host": ["www.example.com"]
        },
       "queryStringParameters": null,
       "multiValueQueryStringParameters": null,
       "pathParameters": null,
       "stageVariables": null,
       "body": null,
       "isBase64Encoded": false
   }
  1. Define the following VS and US:
apiVersion: gloo.solo.io/v1
kind: Upstream
metadata:
  name: hello-lambda
  namespace: suresh
spec:
  aws:
    destinationOverrides:
      requestTransformation: false
      unwrapAsApiGateway: true
      wrapAsApiGateway: true
    lambdaFunctions:
    - logicalName: sadiel-mvn
      qualifier: $LATEST
    region: us-west-2
    secretRef:
      name: aws-creds
      namespace: gloo-system
  connectionConfig:
    maxRequestsPerConnection: 1
---                                                                                                 
apiVersion: gateway.solo.io/v1
kind: VirtualService
metadata:
  name: cbp-portal
  namespace: default
spec:
  virtualHost:
    domains:
    - soloist.servebeer.com
    routes:
    - matchers:
      - prefix: /
      routeAction:
        single:
          destinationSpec:
            aws:
              logicalName: sadiel-mvn
          upstream:
            name: hello-lambda
            namespace: suresh
  1. GE Settings
gloo:
    awsOptions:
      fallbackToFirstFunction: true
  1. Requests:
curl -v -H"Host: soloist.servebeer.com" http://soloist.servebeer.com/v1/ping

curl -v -H"Host: soloist.servebeer.com" http://soloist.servebeer.com/v1/ping -H "api-key: $API_KEY" -H "Content-Type: application/json" -d '{"resource": "/ping","path": "/ping","httpMethod": "GET","requestContext": {"stage": "stage1","identity": {"apikey": "xxxxxxxxxx","userAgent": "curl/7.79.1"},"resourcePath": "/","httpMethod": "GET","path": "/"},"headers": {"Host": "www.example.com"},"multiValueHeaders": {"Host": ["www.example.com"]},"queryStringParameters": null,"multiValueQueryStringParameters": null,"pathParameters": null,"stageVariables": null,"body": null,"isBase64Encoded": false}'
  1. Response:
    {
    "upstream_host": ""18.246.196.137:443"",
    "method": ""POST",
    "protocol": "HTTP/1.1"",
    "path": "/2015-03-31/functions/sadiel-mvn/invocations?Qualifier=%24LATEST",
    "duration": 19,
    "response_code": 502,
    "upstreamCluster": "hello-lambda_suresh",
    "x-forwarded-for": ""-"",
    "response_flag": "-",
    "starttime": "[2024-05-29T17:28:57.019Z]",
    "request-id": ""2699f1e0-6f5f-4947-9c70-65e7c6b48b8b"",
    "requestHeaders": null,
    "upstreamHost": "18.246.196.137:443",
    "upstream_svc_time": null
    }

Additional Environment Detail

No response

Additional Context

No response

┆Issue is synchronized with this Asana task by Unito

Zendesk ticket #3749 has been linked to this issue.

tested in 1.16.10 and the issue persists.

helm list -n gloo-system                                                                                                                               
NAME	NAMESPACE  	REVISION	UPDATED                             	STATUS  	CHART          	APP VERSION
gloo	gloo-system	17      	2024-06-17 09:54:43.728908 -0500 CDT	deployed	gloo-ee-1.16.10

curl -v -H"Host: soloist.servebeer.com" http://soloist.servebeer.com/v1/ping -H "api-key: $API_KEY" -H "Content-Type: application/json" -d '{"resource": "/ping","path": "/ping","httpMethod": "GET","requestContext": {"stage": "stage1","identity": {"apikey": "xxxxxxxxxxxxx","userAgent": "curl/7.79.1"},"resourcePath": "/","httpMethod": "GET","path": "/"},"headers": {"Host": "www.example.com"},"multiValueHeaders": {"Host": ["www.example.com"]},"queryStringParameters": null,"multiValueQueryStringParameters": null,"pathParameters": null,"stageVariables": null,"body": null,"isBase64Encoded": false}'

* Host soloist.servebeer.com:80 was resolved.
* IPv6: (none)
* IPv4: 35.167.216.82
*   Trying 35.167.216.82:80...
* Connected to soloist.servebeer.com (35.167.216.82) port 80
> POST /v1/ping HTTP/1.1
> Host: soloist.servebeer.com
> User-Agent: curl/8.6.0
> Accept: */*
> api-key: xxxxxxxxxx
> Content-Type: application/json
> Content-Length: 485
>
< HTTP/1.1 502 Bad Gateway
< content-type: application/json
< content-length: 29
< x-ratelimit-limit: 1000
< x-ratelimit-remaining: 999
< x-ratelimit-reset: 1
< date: Mon, 17 Jun 2024 15:06:28 GMT
< server: envoy
<
* Connection #0 to host soloist.servebeer.com left intact
{"message": "Gateway Timeout"}%

2024-06-17T14:51:45.840Z
java.lang.NullPointerException: Cannot invoke "com.amazonaws.serverless.proxy.model.ApiGatewayRequestIdentity.getAccessKey()" because the return value of "com.amazonaws.serverless.proxy.model.AwsProxyRequestContext.getIdentity()" is null

We need to make sure that we compare the full requests that are being sent by Gloo Edge with the full requests that are being sent by the AWS API Gateway to verify that there are no other fields and objects not being populated.

@nfuden to look at this issue for scope/estimation.