Skip to content

Commit 29a3f89

Browse files
authored
fix: AsyncAPI 3.0 server security use ref (#2603)
* fix: use refs in server security section * chore: bump version
1 parent 784e1c2 commit 29a3f89

File tree

12 files changed

+305
-163
lines changed

12 files changed

+305
-163
lines changed

faststream/specification/asyncapi/v3_0_0/generate.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,11 @@ def get_broker_server(
139139
}
140140

141141
if specification.security is not None:
142-
broker_meta["security"] = specification.security.get_requirement()
142+
broker_meta["security"] = [
143+
Reference(**{"$ref": f"#/components/securitySchemes/{sec}"})
144+
for security_item in specification.security.get_requirement()
145+
for sec in security_item
146+
]
143147

144148
single_server = len(specification.url) == 1
145149
for i, broker_url in enumerate(specification.url, 1):

faststream/specification/asyncapi/v3_0_0/schema/servers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from faststream.specification.asyncapi.v2_6_0.schema import ServerVariable, Tag
77
from faststream.specification.asyncapi.v2_6_0.schema.utils import Reference
88

9-
SecurityRequirement = list[dict[str, list[str]]]
9+
SecurityRequirement = list[Reference]
1010

1111

1212
__all__ = (

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ classifiers = [
5454
"Framework :: Pydantic :: 2",
5555
]
5656

57-
version = "0.6.1"
57+
version = "0.6.2"
5858

5959
dependencies = [
6060
"fast-depends[pydantic]>=3.0.0",

tests/asyncapi/confluent/security.py

Lines changed: 0 additions & 140 deletions
This file was deleted.
Lines changed: 140 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,146 @@
11
import pytest
2+
from dirty_equals import IsPartialDict
23

3-
from tests.asyncapi.confluent.security import SecurityTestcase
4+
from faststream.confluent import KafkaBroker
5+
from faststream.security import (
6+
SASLGSSAPI,
7+
BaseSecurity,
8+
SASLOAuthBearer,
9+
SASLPlaintext,
10+
SASLScram256,
11+
SASLScram512,
12+
)
413

514
from .base import AsyncAPI26Mixin
615

716

8-
@pytest.mark.confluent()
9-
class TestSecurity(AsyncAPI26Mixin, SecurityTestcase):
10-
pass
17+
class SecurityTestcase(AsyncAPI26Mixin):
18+
@pytest.mark.parametrize(
19+
("security", "schema"),
20+
(
21+
pytest.param(
22+
BaseSecurity(use_ssl=True),
23+
IsPartialDict({
24+
"servers": IsPartialDict({
25+
"development": IsPartialDict({
26+
"protocol": "kafka-secure",
27+
"protocolVersion": "auto",
28+
"security": [],
29+
}),
30+
}),
31+
}),
32+
id="BaseSecurity",
33+
),
34+
pytest.param(
35+
SASLPlaintext(
36+
username="admin",
37+
password="password",
38+
use_ssl=True,
39+
),
40+
IsPartialDict({
41+
"servers": IsPartialDict({
42+
"development": IsPartialDict({
43+
"protocol": "kafka-secure",
44+
"security": [
45+
{"$ref": "#/components/securitySchemes/user-password"}
46+
],
47+
}),
48+
}),
49+
"components": IsPartialDict({
50+
"securitySchemes": {
51+
"user-password": {"type": "userPassword"},
52+
},
53+
}),
54+
}),
55+
id="SASLPlaintext",
56+
),
57+
pytest.param(
58+
SASLScram256(
59+
username="admin",
60+
password="password",
61+
use_ssl=True,
62+
),
63+
IsPartialDict({
64+
"servers": IsPartialDict({
65+
"development": IsPartialDict({
66+
"protocol": "kafka-secure",
67+
"security": [
68+
{"$ref": "#/components/securitySchemes/scram256"}
69+
],
70+
}),
71+
}),
72+
"components": IsPartialDict({
73+
"securitySchemes": {
74+
"scram256": {"type": "scramSha256"},
75+
},
76+
}),
77+
}),
78+
id="SASLScram256",
79+
),
80+
pytest.param(
81+
SASLScram512(
82+
username="admin",
83+
password="password",
84+
use_ssl=True,
85+
),
86+
IsPartialDict({
87+
"servers": IsPartialDict({
88+
"development": IsPartialDict({
89+
"protocol": "kafka-secure",
90+
"security": [
91+
{"$ref": "#/components/securitySchemes/scram512"}
92+
],
93+
}),
94+
}),
95+
"components": IsPartialDict({
96+
"securitySchemes": {
97+
"scram512": {"type": "scramSha512"},
98+
},
99+
}),
100+
}),
101+
id="SASLScram512",
102+
),
103+
pytest.param(
104+
SASLOAuthBearer(use_ssl=True),
105+
IsPartialDict({
106+
"servers": IsPartialDict({
107+
"development": IsPartialDict({
108+
"protocol": "kafka-secure",
109+
"security": [
110+
{"$ref": "#/components/securitySchemes/oauthbearer"}
111+
],
112+
}),
113+
}),
114+
"components": IsPartialDict({
115+
"securitySchemes": {
116+
"oauthbearer": {"type": "oauth2", "$ref": ""},
117+
},
118+
}),
119+
}),
120+
id="SASLOAuthBearer",
121+
),
122+
pytest.param(
123+
SASLGSSAPI(use_ssl=True),
124+
IsPartialDict({
125+
"servers": IsPartialDict({
126+
"development": IsPartialDict({
127+
"protocol": "kafka-secure",
128+
"security": [{"$ref": "#/components/securitySchemes/gssapi"}],
129+
}),
130+
}),
131+
"components": IsPartialDict({
132+
"securitySchemes": {"gssapi": {"type": "gssapi"}},
133+
}),
134+
}),
135+
id="SASLGSSAPI",
136+
),
137+
),
138+
)
139+
def test_security_schema(
140+
self,
141+
security: BaseSecurity,
142+
schema: dict[str, str],
143+
) -> None:
144+
broker = KafkaBroker(security=security)
145+
generated_schema = self.get_schema(broker)
146+
assert generated_schema.to_jsonable() == schema

tests/asyncapi/confluent/v3_0_0/test_fastapi.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def test_fastapi_security_schema() -> None:
4242
assert schema["servers"]["development"] == {
4343
"protocol": "kafka",
4444
"protocolVersion": "auto",
45-
"security": [{"user-password": []}],
45+
"security": [{"$ref": "#/components/securitySchemes/user-password"}],
4646
"host": "localhost:9092",
4747
"pathname": "",
4848
}

0 commit comments

Comments
 (0)