Skip to content

Add Support for API Gateway Lambda authorizer #33

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gwlester opened this issue Jul 19, 2021 · 10 comments
Closed

Add Support for API Gateway Lambda authorizer #33

gwlester opened this issue Jul 19, 2021 · 10 comments
Labels
all_runtimes Changes that should be applied to all runtimes Event Handler Proposed Community submited

Comments

@gwlester
Copy link

Is your feature request related to a problem? Please describe.

The API Gateway Resolver does not (appear) to support the ability to dispatch to a function as a Lambda authorizer.

Describe the solution you'd like

Add support to be able to dispatch to a function that is a Lambda authorizer.

Describe alternatives you've considered

Additional context

@michaelbrewer
Copy link
Contributor

@gwlester Do you have an example json event for this?

@gwlester
Copy link
Author

The type is "token" the exact format of the rest will vary depending on if it is a SAML, OpernID, or some other type of authentication token .

@michaelbrewer
Copy link
Contributor

@gwlester we have an example event for a lambda authorizer, tests/events/apiGatewayProxyV2LambdaAuthorizerEvent.json and you see if this looks correct, because then we already support it.

@gwlester
Copy link
Author

gwlester commented Aug 4, 2021

I'm not sure, but here is what the event passed into the authorizer looks like:
{'type': 'TOKEN', 'methodArn': 'arn:aws:execute-api:us-east-1:223734810375:jroo52upc7/v1/GET/agent/clientlist', 'authorizationToken': 'Bearer eyJraWQiOiJjUmlLRUw1VEsxck5Ya3pseFVwU0Vjbk5HeXNwU1V5TktMTkJBbDhKcTNVIiwiYWxnIjoiUlMyNTYifQ.eyJ2ZXIiOjEsImp0aSI6IkFULmJHM0t5MUV1REwteDZwVmFMVl9tRHFwSmxNTEp0ZjdScjZnbU0tNlJ3WDgiLCJpc3MiOiJodHRwczovL2VudC1zc28td29ya2ZvcmNlLXByZXZpZXcuYW1mYW0uY29tL29hdXRoMi9hdXNzYXBobjh0ZTBINXBKbTBoNyIsImF1ZCI6ImFwaTovL2FnZW50c29ubHkiLCJpYXQiOjE2MjgwMTc3OTcsImV4cCI6MTYyODAzMjE5NywiY2lkIjoiMG9hczJ1NWczbE53V09icEYwaDciLCJ1aWQiOiIwMHVzbGF4b2g2WmhRaEhUVzBoNyIsInNjcCI6WyJvcGVuaWQiLCJlbWFpbCIsInByb2ZpbGUiXSwic3ViIjoiU0NoYXZhQG1zYXFhLmxvY2FsIn0.DKhChNZG1jdJ-quXr1_fpFliff3UeYBjdgUt5lkiUUB1apYAOHoQJkC5apiET440-t87CmRp23ZwypZCeAgR3iTUQv2zy37DkYWRHUBAgYzaelfZS0cM01SWpQc02ZGjpIJTsn_CMVAn-2CqNsBB6I-R-1_fdorKFq1HD4Z1tMmiq8CxOWBlQ8EIILiXg4_k1mQql3ni8XYTiuBSWsZt4rGso6KJSXadPm7iRKHmz5tqvSB1pYfZhUzH9lXcwJ8rEb0E1R8BZe-a52YatzxN9EQ3OUyfvCkHds4WReux25Q63HzIy1zrlSIJ7YRYql8MjNYGdlS5RNYMc8rZjWFS4A'}

@michaelbrewer
Copy link
Contributor

michaelbrewer commented Aug 12, 2021

@gwlester @heitorlessa

Ok I see the docs for this is in various places:

REST API (API GATEWAY)

{
    "type":"TOKEN",
    "authorizationToken":"{caller-supplied-token}",
    "methodArn":"arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]"
}

And also covers the other type REQUEST, example:

{
  "type": "REQUEST",
  "methodArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
  "resource": "/request",
  "path": "/request",
  "httpMethod": "GET",
  "headers": {
    "X-AMZ-Date": "20170718T062915Z",
    "Accept": "*/*",
    "HeaderAuth1": "headerValue1",
    "CloudFront-Viewer-Country": "US",
    "CloudFront-Forwarded-Proto": "https",
    "CloudFront-Is-Tablet-Viewer": "false",
    "CloudFront-Is-Mobile-Viewer": "false",
    "User-Agent": "..."
  },
  "queryStringParameters": {
    "QueryString1": "queryValue1"
  },
  "pathParameters": {},
  "stageVariables": {
    "StageVar1": "stageValue1"
  },
  "requestContext": {
    "path": "/request",
    "accountId": "123456789012",
    "resourceId": "05c7jb",
    "stage": "test",
    "requestId": "...",
    "identity": {
      "apiKey": "...",
      "sourceIp": "...",
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "resourcePath": "/request",
    "httpMethod": "GET",
    "apiId": "abcdef123"
  }
}

And both types expects an output like:

{
  "principalId": "yyyyyyyy", // The principal user identification associated with the token sent by the client.
  "policyDocument": {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Allow|Deny",
        "Resource": "arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]"
      }
    ]
  },
  "context": {
    "stringKey": "value",
    "numberKey": "1",
    "booleanKey": "true"
  },
  "usageIdentifierKey": "{api-key}"
}

So this could be a good candidate for an event source data class and some helpers for building the response.

HTTP API

As for Http api it also supports 2 variations:

Version 2 (which i assume we would want to support first)

{
  "version": "2.0",
  "type": "REQUEST",
  "routeArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
  "identitySource": ["user1", "123"],
  "routeKey": "$default",
  "rawPath": "/my/path",
  "rawQueryString": "parameter1=value1&parameter1=value2&parameter2=value",
  "cookies": ["cookie1", "cookie2"],
  "headers": {
    "Header1": "value1",
    "Header2": "value2"
  },
  "queryStringParameters": {
    "parameter1": "value1,value2",
    "parameter2": "value"
  },
  "requestContext": {
    "accountId": "123456789012",
    "apiId": "api-id",
    "authentication": {
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "domainName": "id.execute-api.us-east-1.amazonaws.com",
    "domainPrefix": "id",
    "http": {
      "method": "POST",
      "path": "/my/path",
      "protocol": "HTTP/1.1",
      "sourceIp": "IP",
      "userAgent": "agent"
    },
    "requestId": "id",
    "routeKey": "$default",
    "stage": "$default",
    "time": "12/Mar/2020:19:03:58 +0000",
    "timeEpoch": 1583348638390
  },
  "pathParameters": { "parameter1": "value1" },
  "stageVariables": { "stageVariable1": "value1", "stageVariable2": "value2" }
}

Version 1 (which is similar to the REST API)

{
  "version": "1.0",
  "type": "REQUEST",
  "methodArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
  "identitySource": "user1,123",
  "authorizationToken": "user1,123",
  "resource": "/request",
  "path": "/request",
  "httpMethod": "GET",
  "headers": {
    "X-AMZ-Date": "20170718T062915Z",
    "Accept": "*/*",
    "HeaderAuth1": "headerValue1",
    "CloudFront-Viewer-Country": "US",
    "CloudFront-Forwarded-Proto": "https",
    "CloudFront-Is-Tablet-Viewer": "false",
    "CloudFront-Is-Mobile-Viewer": "false",
    "User-Agent": "..."
  },
  "queryStringParameters": {
    "QueryString1": "queryValue1"
  },
  "pathParameters": {},
  "stageVariables": {
    "StageVar1": "stageValue1"
  },
  "requestContext": {
    "path": "/request",
    "accountId": "123456789012",
    "resourceId": "05c7jb",
    "stage": "test",
    "requestId": "...",
    "identity": {
      "apiKey": "...",
      "sourceIp": "...",
      "clientCert": {
        "clientCertPem": "CERT_CONTENT",
        "subjectDN": "www.example.com",
        "issuerDN": "Example issuer",
        "serialNumber": "a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1:a1",
        "validity": {
          "notBefore": "May 28 12:30:02 2019 GMT",
          "notAfter": "Aug  5 09:36:04 2021 GMT"
        }
      }
    },
    "resourcePath": "/request",
    "httpMethod": "GET",
    "apiId": "abcdef123"
  }
}

This also supports the old complex IAM response format:

Version 1 style response

{
  "principalId": "abcdef", // The principal user identification associated with the token sent by the client.
  "policyDocument": {
    "Version": "2012-10-17",
    "Statement": [
      {
        "Action": "execute-api:Invoke",
        "Effect": "Allow|Deny",
        "Resource": "arn:aws:execute-api:{regionId}:{accountId}:{apiId}/{stage}/{httpVerb}/[{resource}/[{child-resources}]]"
      }
    ]
  },
  "context": {
    "exampleKey": "exampleValue"
  }
}

Version 2 simple response

{
  "isAuthorized": true/false,
  "context": {
    "exampleKey": "exampleValue"
  }
}

@michaelbrewer
Copy link
Contributor

@heitorlessa based on our last discussion, we agreed to tackle this for the most common event types and also cover AppSync lambda authorizor.

@heitorlessa could you help supply a list of real world fixtures for all of the possible variations for requests. And examples for the responses.

@michaelbrewer
Copy link
Contributor

@gwlester - i added an example implementation for AppSync. See this PR for the usage:

@heitorlessa once we are happy with the api, i can look at the API Gateway Authorizer.

@heitorlessa
Copy link
Contributor

Moving this to the Roadmap to improve visibility of what's being worked on.

@heitorlessa heitorlessa transferred this issue from aws-powertools/powertools-lambda-python Aug 15, 2021
@heitorlessa heitorlessa added all_runtimes Changes that should be applied to all runtimes Proposed Community submited Event Handler labels Aug 15, 2021
@michaelbrewer
Copy link
Contributor

@gwlester - this is getting a little closer to being done. The next PR is focusing on the HTTP api lambda authorizer and then finally Rest api lambda authorizer will be done.

@heitorlessa
Copy link
Contributor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
all_runtimes Changes that should be applied to all runtimes Event Handler Proposed Community submited
Projects
None yet
Development

No branches or pull requests

3 participants