Skip to content

Commit cd16a8e

Browse files
committed
feat(event_handler): add support for OpenAPI security
1 parent 0447eec commit cd16a8e

File tree

1 file changed

+55
-0
lines changed

1 file changed

+55
-0
lines changed

aws_lambda_powertools/event_handler/api_gateway.py

+55
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,11 @@
8383
Contact,
8484
License,
8585
OpenAPI,
86+
SecurityScheme,
8687
Server,
8788
Tag,
8889
)
90+
from aws_lambda_powertools.event_handler.openapi.oauth2 import OAuth2Config
8991
from aws_lambda_powertools.event_handler.openapi.params import Dependant
9092
from aws_lambda_powertools.event_handler.openapi.types import (
9193
TypeModelOrEnum,
@@ -282,6 +284,7 @@ def __init__(
282284
tags: Optional[List[str]],
283285
operation_id: Optional[str],
284286
include_in_schema: bool,
287+
security: Optional[List[Dict[str, List[str]]]],
285288
middlewares: Optional[List[Callable[..., Response]]],
286289
):
287290
"""
@@ -317,6 +320,8 @@ def __init__(
317320
The OpenAPI operationId for this route
318321
include_in_schema: bool
319322
Whether or not to include this route in the OpenAPI schema
323+
security: List[Dict[str, List[str]]], optional
324+
The OpenAPI security for this route
320325
middlewares: Optional[List[Callable[..., Response]]]
321326
The list of route middlewares to be called in order.
322327
"""
@@ -339,6 +344,7 @@ def __init__(
339344
self.response_description = response_description
340345
self.tags = tags or []
341346
self.include_in_schema = include_in_schema
347+
self.security = security
342348
self.middlewares = middlewares or []
343349
self.operation_id = operation_id or self._generate_operation_id()
344350

@@ -486,6 +492,10 @@ def _get_openapi_path(
486492
)
487493
parameters.extend(operation_params)
488494

495+
# Add security if present
496+
if self.security:
497+
operation["security"] = self.security
498+
489499
# Add the parameters to the OpenAPI operation
490500
if parameters:
491501
all_parameters = {(param["in"], param["name"]): param for param in parameters}
@@ -885,6 +895,7 @@ def route(
885895
tags: Optional[List[str]] = None,
886896
operation_id: Optional[str] = None,
887897
include_in_schema: bool = True,
898+
security: Optional[List[Dict[str, List[str]]]] = None,
888899
middlewares: Optional[List[Callable[..., Any]]] = None,
889900
):
890901
raise NotImplementedError()
@@ -943,6 +954,7 @@ def get(
943954
tags: Optional[List[str]] = None,
944955
operation_id: Optional[str] = None,
945956
include_in_schema: bool = True,
957+
security: Optional[List[Dict[str, List[str]]]] = None,
946958
middlewares: Optional[List[Callable[..., Any]]] = None,
947959
):
948960
"""Get route decorator with GET `method`
@@ -980,6 +992,7 @@ def lambda_handler(event, context):
980992
tags,
981993
operation_id,
982994
include_in_schema,
995+
security,
983996
middlewares,
984997
)
985998

@@ -996,6 +1009,7 @@ def post(
9961009
tags: Optional[List[str]] = None,
9971010
operation_id: Optional[str] = None,
9981011
include_in_schema: bool = True,
1012+
security: Optional[List[Dict[str, List[str]]]] = None,
9991013
middlewares: Optional[List[Callable[..., Any]]] = None,
10001014
):
10011015
"""Post route decorator with POST `method`
@@ -1034,6 +1048,7 @@ def lambda_handler(event, context):
10341048
tags,
10351049
operation_id,
10361050
include_in_schema,
1051+
security,
10371052
middlewares,
10381053
)
10391054

@@ -1050,6 +1065,7 @@ def put(
10501065
tags: Optional[List[str]] = None,
10511066
operation_id: Optional[str] = None,
10521067
include_in_schema: bool = True,
1068+
security: Optional[List[Dict[str, List[str]]]] = None,
10531069
middlewares: Optional[List[Callable[..., Any]]] = None,
10541070
):
10551071
"""Put route decorator with PUT `method`
@@ -1088,6 +1104,7 @@ def lambda_handler(event, context):
10881104
tags,
10891105
operation_id,
10901106
include_in_schema,
1107+
security,
10911108
middlewares,
10921109
)
10931110

@@ -1104,6 +1121,7 @@ def delete(
11041121
tags: Optional[List[str]] = None,
11051122
operation_id: Optional[str] = None,
11061123
include_in_schema: bool = True,
1124+
security: Optional[List[Dict[str, List[str]]]] = None,
11071125
middlewares: Optional[List[Callable[..., Any]]] = None,
11081126
):
11091127
"""Delete route decorator with DELETE `method`
@@ -1141,6 +1159,7 @@ def lambda_handler(event, context):
11411159
tags,
11421160
operation_id,
11431161
include_in_schema,
1162+
security,
11441163
middlewares,
11451164
)
11461165

@@ -1157,6 +1176,7 @@ def patch(
11571176
tags: Optional[List[str]] = None,
11581177
operation_id: Optional[str] = None,
11591178
include_in_schema: bool = True,
1179+
security: Optional[List[Dict[str, List[str]]]] = None,
11601180
middlewares: Optional[List[Callable]] = None,
11611181
):
11621182
"""Patch route decorator with PATCH `method`
@@ -1197,6 +1217,7 @@ def lambda_handler(event, context):
11971217
tags,
11981218
operation_id,
11991219
include_in_schema,
1220+
security,
12001221
middlewares,
12011222
)
12021223

@@ -1419,6 +1440,8 @@ def get_openapi_schema(
14191440
terms_of_service: Optional[str] = None,
14201441
contact: Optional["Contact"] = None,
14211442
license_info: Optional["License"] = None,
1443+
security_schemes: Optional[Dict[str, "SecurityScheme"]] = None,
1444+
security: Optional[List[Dict[str, List[str]]]] = None,
14221445
) -> "OpenAPI":
14231446
"""
14241447
Returns the OpenAPI schema as a pydantic model.
@@ -1445,6 +1468,10 @@ def get_openapi_schema(
14451468
The contact information for the exposed API.
14461469
license_info: License, optional
14471470
The license information for the exposed API.
1471+
security_schemes: Dict[str, "SecurityScheme"]], optional
1472+
A declaration of the security schemes available to be used in the specification.
1473+
security: List[Dict[str, List[str]]], optional
1474+
A declaration of which security mechanisms are applied globally across the API.
14481475
14491476
Returns
14501477
-------
@@ -1498,6 +1525,16 @@ def get_openapi_schema(
14981525
# with an url value of /.
14991526
output["servers"] = [Server(url="/")]
15001527

1528+
if security:
1529+
if not security_schemes:
1530+
raise ValueError("security_schemes must be provided if security is provided")
1531+
1532+
# Check if all keys in security are present in the security_schemes
1533+
if not all(key in security_schemes for sec in security for key in sec):
1534+
raise ValueError("Some security schemes not found in security_schemes")
1535+
1536+
output["security"] = security
1537+
15011538
components: Dict[str, Dict[str, Any]] = {}
15021539
paths: Dict[str, Dict[str, Any]] = {}
15031540
operation_ids: Set[str] = set()
@@ -1534,6 +1571,8 @@ def get_openapi_schema(
15341571

15351572
if definitions:
15361573
components["schemas"] = {k: definitions[k] for k in sorted(definitions)}
1574+
if security_schemes:
1575+
components["securitySchemes"] = security_schemes
15371576
if components:
15381577
output["components"] = components
15391578
if tags:
@@ -1556,6 +1595,8 @@ def get_openapi_json_schema(
15561595
terms_of_service: Optional[str] = None,
15571596
contact: Optional["Contact"] = None,
15581597
license_info: Optional["License"] = None,
1598+
security_schemes: Optional[Dict[str, "SecurityScheme"]] = None,
1599+
security: Optional[List[Dict[str, List[str]]]] = None,
15591600
) -> str:
15601601
"""
15611602
Returns the OpenAPI schema as a JSON serializable dict
@@ -1582,6 +1623,10 @@ def get_openapi_json_schema(
15821623
The contact information for the exposed API.
15831624
license_info: License, optional
15841625
The license information for the exposed API.
1626+
security_schemes: Dict[str, "SecurityScheme"]], optional
1627+
A declaration of the security schemes available to be used in the specification.
1628+
security: List[Dict[str, List[str]]], optional
1629+
A declaration of which security mechanisms are applied globally across the API.
15851630
15861631
Returns
15871632
-------
@@ -1602,6 +1647,8 @@ def get_openapi_json_schema(
16021647
terms_of_service=terms_of_service,
16031648
contact=contact,
16041649
license_info=license_info,
1650+
security_schemes=security_schemes,
1651+
security=security,
16051652
),
16061653
by_alias=True,
16071654
exclude_none=True,
@@ -1623,6 +1670,7 @@ def enable_swagger(
16231670
contact: Optional["Contact"] = None,
16241671
license_info: Optional["License"] = None,
16251672
swagger_base_url: Optional[str] = None,
1673+
oauth2: Optional["OAuth2Config"] = None,
16261674
middlewares: Optional[List[Callable[..., Response]]] = None,
16271675
compress: bool = False,
16281676
):
@@ -1655,6 +1703,8 @@ def enable_swagger(
16551703
The license information for the exposed API.
16561704
swagger_base_url: str, optional
16571705
The base url for the swagger UI. If not provided, we will serve a recent version of the Swagger UI.
1706+
oauth2: OAuth2Config, optional
1707+
The OAuth2 configuration for the Swagger UI.
16581708
middlewares: List[Callable[..., Response]], optional
16591709
List of middlewares to be used for the swagger route.
16601710
compress: bool, default = False
@@ -1719,6 +1769,7 @@ def swagger_handler():
17191769
swagger_js,
17201770
swagger_css,
17211771
swagger_base_url,
1772+
oauth2,
17221773
)
17231774

17241775
return Response(
@@ -1741,6 +1792,7 @@ def route(
17411792
tags: Optional[List[str]] = None,
17421793
operation_id: Optional[str] = None,
17431794
include_in_schema: bool = True,
1795+
security: Optional[List[Dict[str, List[str]]]] = None,
17441796
middlewares: Optional[List[Callable[..., Any]]] = None,
17451797
):
17461798
"""Route decorator includes parameter `method`"""
@@ -1767,6 +1819,7 @@ def register_resolver(func: Callable):
17671819
tags,
17681820
operation_id,
17691821
include_in_schema,
1822+
security,
17701823
middlewares,
17711824
)
17721825

@@ -2318,6 +2371,7 @@ def route(
23182371
tags: Optional[List[str]] = None,
23192372
operation_id: Optional[str] = None,
23202373
include_in_schema: bool = True,
2374+
security: Optional[List[Dict[str, List[str]]]] = None,
23212375
middlewares: Optional[List[Callable[..., Any]]] = None,
23222376
):
23232377
# NOTE: see #1552 for more context.
@@ -2334,6 +2388,7 @@ def route(
23342388
tags,
23352389
operation_id,
23362390
include_in_schema,
2391+
security,
23372392
middlewares,
23382393
)
23392394

0 commit comments

Comments
 (0)