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

feat: add asyncapi_url broker arg #903

Merged
merged 9 commits into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ venv*
.cache
htmlcov
token
.DS_Store

site/
site_build/
4 changes: 2 additions & 2 deletions .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,10 @@
"filename": "faststream/rabbit/broker.py",
"hashed_secret": "35675e68f4b5af7b995d9205ad0fc43842f16450",
"is_verified": false,
"line_number": 53,
"line_number": 57,
"is_secret": false
}
]
},
"generated_at": "2023-10-02T18:19:34Z"
"generated_at": "2023-11-01T19:09:43Z"
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ That's **FastStream** in a nutshell—easy, efficient, and powerful. Whether you

---

**Documentation**: <a href="https://faststream.airt.ai/" target="_blank">https://faststream.airt.ai/</a>
**Documentation**: <a href="https://faststream.airt.ai/?utm_source=github&utm_medium=acquisition&utm_campaign=measure" target="_blank">https://faststream.airt.ai/</a>

---

Expand Down
3 changes: 3 additions & 0 deletions docs/docs/en/api/faststream/rabbit/shared/utils/build_url.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@


::: faststream.rabbit.shared.utils.build_url
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@


::: faststream.rabbit.shared.utils.removeprefix
3 changes: 3 additions & 0 deletions docs/docs/en/api/faststream/security/BaseSecurity.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@


::: faststream.security.BaseSecurity
3 changes: 3 additions & 0 deletions docs/docs/en/api/faststream/security/SASLPlaintext.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@


::: faststream.security.SASLPlaintext
3 changes: 3 additions & 0 deletions docs/docs/en/api/faststream/security/SASLScram256.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@


::: faststream.security.SASLScram256
3 changes: 3 additions & 0 deletions docs/docs/en/api/faststream/security/SASLScram512.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@


::: faststream.security.SASLScram512
2 changes: 1 addition & 1 deletion docs/docs_src/kafka/basic_security/app.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import ssl

from faststream import FastStream
from faststream.broker.security import BaseSecurity
from faststream.kafka import KafkaBroker
from faststream.security import BaseSecurity

ssl_context = ssl.create_default_context()
security = BaseSecurity(ssl_context=ssl_context)
Expand Down
2 changes: 1 addition & 1 deletion docs/docs_src/kafka/plaintext_security/app.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import ssl

from faststream import FastStream
from faststream.broker.security import SASLPlaintext
from faststream.kafka import KafkaBroker
from faststream.security import SASLPlaintext

ssl_context = ssl.create_default_context()
security = SASLPlaintext(ssl_context=ssl_context, username="admin", password="password")
Expand Down
2 changes: 1 addition & 1 deletion docs/docs_src/kafka/sasl_scram256_security/app.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import ssl

from faststream import FastStream
from faststream.broker.security import SASLScram256
from faststream.kafka import KafkaBroker
from faststream.security import SASLScram256

ssl_context = ssl.create_default_context()
security = SASLScram256(ssl_context=ssl_context, username="admin", password="password")
Expand Down
2 changes: 1 addition & 1 deletion docs/docs_src/kafka/sasl_scram512_security/app.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import ssl

from faststream import FastStream
from faststream.broker.security import SASLScram512
from faststream.kafka import KafkaBroker
from faststream.security import SASLScram512

ssl_context = ssl.create_default_context()
security = SASLScram512(ssl_context=ssl_context, username="admin", password="password")
Expand Down
6 changes: 3 additions & 3 deletions docs/docs_src/kafka/security_without_ssl/example.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import pytest

from faststream.broker.security import SASLPlaintext, ssl_not_set_error_msg
from faststream.security import SASLPlaintext, ssl_not_set_error_msg


def test_without_ssl_warning():
with pytest.raises(RuntimeError) as excinfo:
security = SASLPlaintext(username="admin", password="password")
SASLPlaintext(username="admin", password="password") # pragma: allowlist secret
assert str(excinfo.value) == ssl_not_set_error_msg, excinfo.value

security = SASLPlaintext(username="admin", password="password", use_ssl=False)
SASLPlaintext(username="admin", password="password", use_ssl=False) # pragma: allowlist secret
2 changes: 1 addition & 1 deletion faststream/__about__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""Simple and fast framework to create message brokers based microservices"""
__version__ = "0.2.9"
__version__ = "0.2.10"


INSTALL_YAML = """
Expand Down
5 changes: 3 additions & 2 deletions faststream/broker/core/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
from faststream.broker.publisher import BasePublisher
from faststream.broker.push_back_watcher import BaseWatcher
from faststream.broker.router import BrokerRouter
from faststream.broker.security import BaseSecurity
from faststream.broker.types import (
ConnectionType,
CustomDecoder,
Expand All @@ -51,6 +50,7 @@
)
from faststream.broker.wrapper import HandlerCallWrapper
from faststream.log import access_logger
from faststream.security import BaseSecurity
from faststream.types import AnyDict, F_Return, F_Spec
from faststream.utils import apply_types, context
from faststream.utils.functions import get_function_positional_arguments, to_async
Expand Down Expand Up @@ -116,6 +116,7 @@ def __init__(
protocol_version: Optional[str] = None,
description: Optional[str] = None,
tags: Optional[Sequence[Union[asyncapi.Tag, asyncapi.TagDict]]] = None,
asyncapi_url: Union[str, List[str], None] = None,
# broker kwargs
apply_types: bool = True,
logger: Optional[logging.Logger] = access_logger,
Expand Down Expand Up @@ -179,7 +180,7 @@ def __init__(
self.started = False

# AsyncAPI information
self.url = url
self.url = asyncapi_url or url
self.protocol = protocol
self.protocol_version = protocol_version
self.description = description
Expand Down
238 changes: 19 additions & 219 deletions faststream/broker/security.py
Original file line number Diff line number Diff line change
@@ -1,219 +1,19 @@
from ssl import SSLContext
from typing import Dict, List, Optional

from faststream.types import AnyDict

ssl_not_set_error_msg = """
SSL context is not set; if you don't want to use SSL encryption, set use_ssl to False.
Warning: This will send your data to the broker unencrypted!
"""


class BaseSecurity:
"""
Base class for defining security configurations.

This class provides a base for defining security configurations for communication with a broker. It allows setting
SSL encryption and provides methods to retrieve security requirements and schemas.

Args:
ssl_context (Optional[SSLContext]): An SSLContext object for SSL encryption. If None, SSL encryption is disabled.
use_ssl (Optional[bool]): A boolean indicating whether to use SSL encryption. Defaults to True.

Attributes:
use_ssl (bool): A boolean indicating whether SSL encryption is enabled.
ssl_context (Optional[SSLContext]): An SSLContext object for SSL encryption. None if SSL is not used.

Methods:
get_requirement(self) -> List[AnyDict]:
Get the security requirements in the form of a list of dictionaries.

get_schema(self) -> Dict[str, Dict[str, str]]:
Get the security schema as a dictionary.

"""

def __init__(
self,
ssl_context: Optional[SSLContext] = None,
use_ssl: Optional[bool] = None,
):
if use_ssl is None:
use_ssl = True

if use_ssl and ssl_context is None:
raise RuntimeError(ssl_not_set_error_msg)

self.use_ssl = use_ssl
self.ssl_context = ssl_context

def get_requirement(self) -> List[AnyDict]:
"""
Get the security requirements.

Returns:
List[AnyDict]: A list of dictionaries representing security requirements.
"""
return []

def get_schema(self) -> Dict[str, Dict[str, str]]:
"""
Get the security schema.

Returns:
Dict[str, Dict[str, str]]: A dictionary representing the security schema.
"""
return {}


class SASLPlaintext(BaseSecurity):
"""
Security configuration for SASL/PLAINTEXT authentication.

This class defines security configuration for SASL/PLAINTEXT authentication, which includes a username and password.

Args:
username (str): The username for authentication.
password (str): The password for authentication.
ssl_context (Optional[SSLContext]): An SSLContext object for SSL encryption. If None, SSL encryption is disabled.
use_ssl (Optional[bool]): A boolean indicating whether to use SSL encryption. Defaults to True.

Methods:
get_requirement(self) -> List[AnyDict]:
Get the security requirements for SASL/PLAINTEXT authentication.

get_schema(self) -> Dict[str, Dict[str, str]]:
Get the security schema for SASL/PLAINTEXT authentication.

"""

def __init__(
self,
username: str,
password: str,
ssl_context: Optional[SSLContext] = None,
use_ssl: Optional[bool] = None,
):
super().__init__(ssl_context, use_ssl)
self.username = username
self.password = password

def get_requirement(self) -> List[AnyDict]:
"""
Get the security requirements for SASL/PLAINTEXT authentication.

Returns:
List[AnyDict]: A list of dictionaries representing security requirements.
"""
return [{"user-password": []}]

def get_schema(self) -> Dict[str, Dict[str, str]]:
"""
Get the security schema for SASL/PLAINTEXT authentication.

Returns:
Dict[str, Dict[str, str]]: A dictionary representing the security schema.
"""
return {"user-password": {"type": "userPassword"}}


class SASLScram256(BaseSecurity):
"""
Security configuration for SASL/SCRAM-SHA-256 authentication.

This class defines security configuration for SASL/SCRAM-SHA-256 authentication, which includes a username and password.

Args:
username (str): The username for authentication.
password (str): The password for authentication.
ssl_context (Optional[SSLContext]): An SSLContext object for SSL encryption. If None, SSL encryption is disabled.
use_ssl (Optional[bool]): A boolean indicating whether to use SSL encryption. Defaults to True.

Methods:
get_requirement(self) -> List[AnyDict]:
Get the security requirements for SASL/SCRAM-SHA-256 authentication.

get_schema(self) -> Dict[str, Dict[str, str]]:
Get the security schema for SASL/SCRAM-SHA-256 authentication.

"""

def __init__(
self,
username: str,
password: str,
ssl_context: Optional[SSLContext] = None,
use_ssl: Optional[bool] = None,
):
super().__init__(ssl_context, use_ssl)
self.username = username
self.password = password

def get_requirement(self) -> List[AnyDict]:
"""
Get the security requirements for SASL/SCRAM-SHA-256 authentication.

Returns:
List[AnyDict]: A list of dictionaries representing security requirements.
"""
return [{"scram256": []}]

def get_schema(self) -> Dict[str, Dict[str, str]]:
"""
Get the security schema for SASL/SCRAM-SHA-256 authentication.

Returns:
Dict[str, Dict[str, str]]: A dictionary representing the security schema.
"""
return {"scram256": {"type": "scramSha256"}}


class SASLScram512(BaseSecurity):
"""
Security configuration for SASL/SCRAM-SHA-512 authentication.

This class defines security configuration for SASL/SCRAM-SHA-512 authentication, which includes a username and password.

Args:
username (str): The username for authentication.
password (str): The password for authentication.
ssl_context (Optional[SSLContext]): An SSLContext object for SSL encryption. If None, SSL encryption is disabled.
use_ssl (Optional[bool]): A boolean indicating whether to use SSL encryption. Defaults to True.

Methods:
get_requirement(self) -> List[AnyDict]:
Get the security requirements for SASL/SCRAM-SHA-512 authentication.

get_schema(self) -> Dict[str, Dict[str, str]]:
Get the security schema for SASL/SCRAM-SHA-512 authentication.

"""

def __init__(
self,
username: str,
password: str,
ssl_context: Optional[SSLContext] = None,
use_ssl: Optional[bool] = None,
):
super().__init__(ssl_context, use_ssl)
self.username = username
self.password = password

def get_requirement(self) -> List[AnyDict]:
"""
Get the security requirements for SASL/SCRAM-SHA-512 authentication.

Returns:
List[AnyDict]: A list of dictionaries representing security requirements.
"""
return [{"scram512": []}]

def get_schema(self) -> Dict[str, Dict[str, str]]:
"""
Get the security schema for SASL/SCRAM-SHA-512 authentication.

Returns:
Dict[str, Dict[str, str]]: A dictionary representing the security schema.
"""
return {"scram512": {"type": "scramSha512"}}
import warnings

from faststream.security import BaseSecurity, SASLPlaintext, SASLScram256, SASLScram512

warnings.warn(
(
"\n`faststream.broker.security` import path was deprecated and will be removed in 0.4.0"
"\nPlease, use `faststream.security` instead"
),
DeprecationWarning,
stacklevel=2,
)

__all__ = (
"SASLPlaintext",
"SASLScram256",
"SASLScram512",
"BaseSecurity",
)
Loading