Skip to content
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

Security configuration for route does not work for APIGatewayHttpRouter #4375

Closed
mdwornicki opened this issue May 20, 2024 · 9 comments · Fixed by #4421
Closed

Security configuration for route does not work for APIGatewayHttpRouter #4375

mdwornicki opened this issue May 20, 2024 · 9 comments · Fixed by #4421
Labels
bug Something isn't working openapi-schema

Comments

@mdwornicki
Copy link

mdwornicki commented May 20, 2024

Expected Behaviour

Method get_openapi_json_schema from APIGatewayHttpResolver should work for routes from APIGatewayHttpRouter with the security parameter.

Current Behaviour

When the security parameter is a part of the router (APIGatewayHttpRouter), it doesn't work - /openapispec has: {"message": "Internal Server Error"}.

If I remove the security parameter from the router file, it works, and it means that the security configuration is correct only for APIGatewayHttpResolver.

Error in CloudWatch after /openapispec execution:

[ERROR] TypeError: unhashable type: 'list' Traceback (most recent call last): File "/var/lang/lib/python3.12/importlib/__init__.py", line 90, in import_module return _bootstrap._gcd_import(name[level:], package, level) File "<frozen importlib._bootstrap>", line 1387, in _gcd_import File "<frozen importlib._bootstrap>", line 1360, in _find_and_load File "<frozen importlib._bootstrap>", line 1331, in _find_and_load_unlocked File "<frozen importlib._bootstrap>", line 935, in _load_unlocked File "<frozen importlib._bootstrap_external>", line 995, in exec_module File "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removed File "/var/task/app.py", line 14, in <module> from project_member_v1 import router as project_member_router File "/var/task/project_member_v1/router.py", line 27, in <module> @router.get( File "/opt/python/aws_lambda_powertools/event_handler/api_gateway.py", line 2412, in register_route self._routes_with_middleware[route_key] = []

Code snippet

`
app = APIGatewayHttpResolver(enable_validation=True)
logger = Logger()
metrics = Metrics(namespace="Powertools")

OpenApiConfiguration.configure_swagger(app)

app.include_router(test_router.router, prefix="/v1/test")

@app.get("/hello", tags=["Test"], summary="An endpoint to test", security=[{"TestAuth": []}],)
def hello():
    return {"message": f"Hello!"}

@app.get("/openapispec", tags=["Docs"], summary="Get the OpenAPI specification")
def get_openapi():
    return app.get_openapi_json_schema(**OpenApiConfiguration.get_meta_data())


@logger.inject_lambda_context(correlation_id_path=correlation_paths.API_GATEWAY_REST)
@metrics.log_metrics(capture_cold_start_metric=True)
def lambda_handler(event: dict, context: LambdaContext) -> dict:
    return app.resolve(event, context)
`

Router file:
`
router = APIGatewayHttpRouter()

@router.get(
    "/<test_id>",
    tags=["Test"],
    summary="Test endpoint",
    security=[{"TestAuth": []}],
)
def get_test_item(test_id: str) -> TestItemResponse:
    return TestItemResponse(test_id= test_id)
`

`
class OpenApiConfiguration:
    @staticmethod
    def get_meta_data():
        return {
            "title": "TestAPI",
            "version": "0.0.1",
            Contact(name="Test", url=Url("test.com")),
            "description": "TestAPI",
            "terms_of_service": None,
            "license_info": None,
            "openapi_version": "3.0.1",
            "security_schemes": {
                "TestAuth": HTTPBearer(scheme="bearer", bearerFormat="JWT", description="JWT token authentication"),
            },
        }

    @staticmethod
    def configure_swagger(resolver: ApiGatewayResolver) -> None:
        resolver.enable_swagger(
            **OpenApiConfiguration.get_meta_data(),
            path="/swagger",
            swagger_base_url="https://cdnjs.cloudflare.com/ajax/libs/swagger-ui/5.11.0"
        )
`

Route `openspec` should returns a definition of 3 endpoints:
- `/hello` with `TestAuth` security
- `/openapispec` without security
- `/test/< test_id >`  with `TestAuth` security

Possible Solution

No response

Steps to Reproduce

  1. Create instance of APIGatewayHttpResolver
  2. Create instance of APIGatewayHttpRouter
  3. Implement OpenApiConfiguration and define security_schemes
  4. Add route to APIGatewayHttpRouter with security
  5. Add route to openapispec:
    @app.get("/openapispec", tags=["Docs"], summary="Get the OpenAPI specification") def get_openapi(): return app.get_openapi_json_schema(**OpenApiConfiguration.get_meta_data())
  6. Execute /openapispec

Powertools for AWS Lambda (Python) version

latest

AWS Lambda function runtime

3.12

Packaging format used

Lambda Layers

Debugging logs

No response

@mdwornicki mdwornicki added bug Something isn't working triage Pending triage from maintainers labels May 20, 2024
Copy link

boring-cyborg bot commented May 20, 2024

Thanks for opening your first issue here! We'll come back to you as soon as we can.
In the meantime, check out the #python channel on our Powertools for AWS Lambda Discord: Invite link

@leandrodamascena
Copy link
Contributor

Hey @mdwornicki! Thanks for reporting this bug! I was able to reproduce the error and I expect to send a PR tomorrow to fix the problem.

@leandrodamascena leandrodamascena moved this from Triage to Working on it in Powertools for AWS Lambda (Python) May 21, 2024
@leandrodamascena leandrodamascena added openapi-schema and removed triage Pending triage from maintainers labels May 21, 2024
@leandrodamascena
Copy link
Contributor

Hi @mdwornicki! This has been a little harder than I expected. Made some progress, but still validating the solution.

@leandrodamascena
Copy link
Contributor

leandrodamascena commented May 28, 2024

Hey @mdwornicki! I submitted a PR to fix this.

#4421

@heitorlessa
Copy link
Contributor

@mdwornicki, we're releasing it next Thursday (13th) - do let us know otherwise whether you can't wait until then.

@mdwornicki
Copy link
Author

Thank you! It's not a problem, can wait!

@heitorlessa
Copy link
Contributor

great, thanks!!


For anyone reading this later as it's useful context but not blocking this fix for next week's release...

As part of the security scheme bug fix review (#4421), we found that the responsibilities between OpenAPI and SwaggerUI are ambiguous, leading to confusion among customers and maintainers at times.

As of now, these are common use cases:

  1. Setting up OpenAPI. Customers use a combination of implicit type annotations, OpenAPI params at the route level, and extra params via enable_swagger.
  2. Setting up SwaggerUI. Customers use enable_swagger to render the implicit OpenAPI Schema in a web app (SwaggerUI), customize assets, etc.
  3. Serializing OpenAPI JSON Schema. Customers create an explicit route e.g., /schema, and use app.get_openapi_json_schema to serialize it. Those using SwaggerUI can download it at the homepage (https://endpoint.url/swagger?format=json).

We're confusing customers on 1 and 2, because enable_swagger or get_openapi_*schema is the only way to further extend / override OpenAPI. Customers should not need to use enable_swagger or get_openapi_*schema to further customize OpenAPI.

How do we fix it in a backwards compatible way and improve everyone's experience?

need two new issues

  • Introduce a new API to configure / extend OpenAPI in the resolver instance (app)
  • Improve docs by surfacing that API instead of get_openapi_*schema and enable_swagger - example
  • Rename and revamp OpenAPI docs sections to match the use-case driven docs we have. For now, it should be easier to find how to
    • extend OpenAPI spec
    • export OpenAPI schema programmatically
    • override OpenAPI schema when exporting
    • when to override OpenAPI metadata in SwaggerUI

@github-project-automation github-project-automation bot moved this from Working on it to Coming soon in Powertools for AWS Lambda (Python) Jun 7, 2024
Copy link
Contributor

github-actions bot commented Jun 7, 2024

⚠️COMMENT VISIBILITY WARNING⚠️

This issue is now closed. Please be mindful that future comments are hard for our team to see.

If you need more assistance, please either tag a team member or open a new issue that references this one.

If you wish to keep having a conversation with other community members under this issue feel free to do so.

@github-actions github-actions bot added the pending-release Fix or implementation already in dev waiting to be released label Jun 7, 2024
@heitorlessa heitorlessa moved this from Coming soon to Shipped in Powertools for AWS Lambda (Python) Jun 10, 2024
@heitorlessa heitorlessa moved this from Shipped to Coming soon in Powertools for AWS Lambda (Python) Jun 10, 2024
Copy link
Contributor

This is now released under 2.39.0 version!

@github-actions github-actions bot removed the pending-release Fix or implementation already in dev waiting to be released label Jun 13, 2024
@heitorlessa heitorlessa moved this from Coming soon to Shipped in Powertools for AWS Lambda (Python) Jun 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working openapi-schema
Projects
Status: Shipped
3 participants