From a6bd93fdf3de86ece0c0de7a603b78743ab5d75a Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Tue, 14 Sep 2021 21:35:19 +0200 Subject: [PATCH 01/31] Add secure gRPC client implemenation --- src/py/flwr/client/app.py | 20 ++++++-- src/py/flwr/client/grpc_client/connection.py | 51 +++++++++++++++---- .../client/grpc_client/connection_test.py | 4 +- 3 files changed, 59 insertions(+), 16 deletions(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 920793986fbd..ec5e593b3567 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -17,12 +17,13 @@ import time from logging import INFO +from typing import Optional from flwr.common import GRPC_MAX_MESSAGE_LENGTH from flwr.common.logger import log from .client import Client -from .grpc_client.connection import insecure_grpc_connection +from .grpc_client.connection import grpc_connection from .grpc_client.message_handler import handle from .keras_client import KerasClient, KerasClientWrapper from .numpy_client import NumPyClient, NumPyClientWrapper @@ -32,6 +33,7 @@ def start_client( server_address: str, client: Client, grpc_max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, + root_certificates: Optional[str] = None, ) -> None: """Start a Flower Client which connects to a gRPC server. @@ -48,14 +50,20 @@ class `flwr.client.Client`. value. Note that the Flower server needs to be started with the same value (see `flwr.server.start_server`), otherwise it will not know about the increased limit and block larger messages. + root_certificates: str (default: None) + Path to the PEM-encoded root certificates. If provided a secure connection + using the certificate will be established to a SSL/TLS enabled Flower server + (default: None) Returns: None. """ while True: sleep_duration: int = 0 - with insecure_grpc_connection( - server_address, max_message_length=grpc_max_message_length + with grpc_connection( + server_address, + max_message_length=grpc_max_message_length, + root_certificates=root_certificates, ) as conn: receive, send = conn log(INFO, "Opened (insecure) gRPC connection") @@ -84,6 +92,7 @@ def start_numpy_client( server_address: str, client: NumPyClient, grpc_max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, + root_certificates: Optional[str] = None, ) -> None: """Start a Flower NumPyClient which connects to a gRPC server. @@ -100,6 +109,10 @@ class `flwr.client.NumPyClient`. value. Note that the Flower server needs to be started with the same value (see `flwr.server.start_server`), otherwise it will not know about the increased limit and block larger messages. + root_certificates: str (default: None) + Path to the PEM-encoded root certificates. If provided a secure connection + using the certificate will be established to a SSL/TLS enabled Flower server + (default: None) Returns: None. @@ -113,6 +126,7 @@ class `flwr.client.NumPyClient`. server_address=server_address, client=flower_client, grpc_max_message_length=grpc_max_message_length, + root_certificates=root_certificates, ) diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index 31588c5e1628..8020f9a40f77 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -17,7 +17,7 @@ from contextlib import contextmanager from logging import DEBUG from queue import Queue -from typing import Callable, Iterator, Tuple +from typing import Callable, Iterator, Optional, Tuple import grpc @@ -37,17 +37,46 @@ def on_channel_state_change(channel_connectivity: str) -> None: @contextmanager -def insecure_grpc_connection( - server_address: str, max_message_length: int = GRPC_MAX_MESSAGE_LENGTH +def grpc_connection( + server_address: str, + max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, + root_certificates: Optional[str] = None, ) -> Iterator[Tuple[Callable[[], ServerMessage], Callable[[ClientMessage], None]]]: - """Establish an insecure gRPC connection to a gRPC server.""" - channel = grpc.insecure_channel( - server_address, - options=[ - ("grpc.max_send_message_length", max_message_length), - ("grpc.max_receive_message_length", max_message_length), - ], - ) + """Establish an insecure gRPC connection to a gRPC server. + + Parameters + ---------- + server_address : str + The IPv6 address of the server. If the Flower server runs on the same machine + on port 8080, then `server_address` would be `"[::]:8080"`. + grpc_max_message_length : int + The maximum length of gRPC messages that can be exchanged with the Flower + server. The default should be sufficient for most models. Users who train + very large models might need to increase this value. Note that the Flower + server needs to be started with the same value + (see `flwr.server.start_server`), otherwise it will not know about the + increased limit and block larger messages. + (default: 536_870_912, this equals 512MB) + root_certificates : str + Path to the PEM-encoded root certificates. If provided a secure connection + using the certificate will be established to a SSL/TLS enabled Flower server + (default: None) + """ + channel_options = [ + ("grpc.max_send_message_length", max_message_length), + ("grpc.max_receive_message_length", max_message_length), + ] + + if root_certificates is not None: + with open(root_certificates, "rb") as file: + ssl_channel_credentials = grpc.ssl_channel_credentials(file.read()) + + channel = grpc.secure_channel( + server_address, ssl_channel_credentials, options=channel_options + ) + else: + channel = grpc.insecure_channel(server_address, options=channel_options) + channel.subscribe(on_channel_state_change) queue: Queue[ClientMessage] = Queue( # pylint: disable=unsubscriptable-object diff --git a/src/py/flwr/client/grpc_client/connection_test.py b/src/py/flwr/client/grpc_client/connection_test.py index 84ea9fc0164e..0ce5e9b934f2 100644 --- a/src/py/flwr/client/grpc_client/connection_test.py +++ b/src/py/flwr/client/grpc_client/connection_test.py @@ -26,7 +26,7 @@ from flwr.server.client_manager import SimpleClientManager from flwr.server.grpc_server.grpc_server import start_insecure_grpc_server -from .connection import insecure_grpc_connection +from .connection import grpc_connection EXPECTED_NUM_SERVER_MESSAGE = 10 @@ -91,7 +91,7 @@ def test_integration_connection() -> None: def run_client() -> int: messages_received: int = 0 - with insecure_grpc_connection(server_address=f"[::]:{port}") as conn: + with grpc_connection(server_address=f"[::]:{port}") as conn: receive, send = conn # Setup processing loop From 9f06b9cde2d62005270c541a8f95a485fe50887e Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Tue, 14 Sep 2021 23:25:55 +0200 Subject: [PATCH 02/31] Document how to enable SSL in public API --- src/py/flwr/server/app.py | 90 ++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 34 deletions(-) diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index 02a611e87c89..5bad743db96c 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -21,7 +21,7 @@ from flwr.common import GRPC_MAX_MESSAGE_LENGTH from flwr.common.logger import log from flwr.server.client_manager import SimpleClientManager -from flwr.server.grpc_server.grpc_server import start_insecure_grpc_server +from flwr.server.grpc_server.grpc_server import SSLFILES, start_grpc_server from flwr.server.server import Server from flwr.server.strategy import FedAvg, Strategy @@ -35,50 +35,72 @@ def start_server( # pylint: disable=too-many-arguments strategy: Optional[Strategy] = None, grpc_max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, force_final_distributed_eval: bool = False, + ssl_files: Optional[SSLFILES] = None, ) -> None: """Start a Flower server using the gRPC transport layer. - Arguments: - server_address: Optional[str] (default: `"[::]:8080"`). The IPv6 - address of the server. - server: Optional[flwr.server.Server] (default: None). An implementation - of the abstract base class `flwr.server.Server`. If no instance is - provided, then `start_server` will create one. - config: Optional[Dict[str, int]] (default: None). The only currently - supported values is `num_rounds`, so a full configuration object - instructing the server to perform three rounds of federated - learning looks like the following: `{"num_rounds": 3}`. - strategy: Optional[flwr.server.Strategy] (default: None). An - implementation of the abstract base class `flwr.server.Strategy`. - If no strategy is provided, then `start_server` will use - `flwr.server.strategy.FedAvg`. - grpc_max_message_length: int (default: 536_870_912, this equals 512MB). - The maximum length of gRPC messages that can be exchanged with the - Flower clients. The default should be sufficient for most models. - Users who train very large models might need to increase this - value. Note that the Flower clients need to be started with the - same value (see `flwr.client.start_client`), otherwise clients will - not know about the increased limit and block larger messages. - force_final_distributed_eval: bool (default: False). - Forces a distributed evaulation to occur after the last training - epoch when enabled. - - Returns: - None. + Parameters + ---------- + server_address : str + The IPv6 address of the server. (default: `"[::]:8080"`) + server : flwr.server.Server + An implementation of the abstract base class `flwr.server.Server`. If no + instance is provided, then `start_server` will create one. (default: None) + config : Dict[str, int] + The only currently supported values is `num_rounds`, so a full + configuration object instructing the server to perform three rounds of + federated learning looks like the following: `{"num_rounds": 3}`. + (default: None) + strategy : flwr.server.Strategy + An implementation of the abstract base class `flwr.server.Strategy`. + If no strategy is provided, then `start_server` will use + `flwr.server.strategy.FedAvg`. (default: None) + grpc_max_message_length : int + The maximum length of gRPC messages that can be exchanged with the + Flower clients. The default should be sufficient for most models. + Users who train very large models might need to increase this + value. Note that the Flower clients need to be started with the + same value (see `flwr.client.start_client`), otherwise clients will + not know about the increased limit and block larger messages. + (default: 536_870_912, this equals 512MB) + force_final_distributed_eval : bool + Forces a distributed evaluation to occur after the last training + epoch when enabled. (default: False) + ssl_files : tuple of union of (str, bytes) + Certificates to start secure SSL/TLS server. Expected parameter is a tuple + with three elements in this order beeing a file like of + + * CA certificate. + * server certificate. + * server private key. + + (default: None) + + Examples + -------- + Starting a insecure server. + + >>> start_server() + + Starting a SSL/TLS enabled server. + + >>> start_server( + >>> ssl_files=("/crts/root.pem", "/crts/localhost.crt", "/crts/localhost.key") + >>> ) """ initialized_server, initialized_config = _init_defaults(server, config, strategy) # Start gRPC server - grpc_server = start_insecure_grpc_server( + grpc_server = start_grpc_server( client_manager=initialized_server.client_manager(), server_address=server_address, max_message_length=grpc_max_message_length, + ssl_files=ssl_files, ) - log( - INFO, - "Flower server running (insecure, %s rounds)", - initialized_config["num_rounds"], - ) + num_rounds = initialized_config["num_rounds"] + ssl_status = "enabled" if ssl_files is not None else "disabled" + msg = f"Flower server running ({num_rounds} rounds)\nSSL/TLS is {ssl_status}" + log(INFO, msg) _fl( server=initialized_server, From c0b425c106b5039c98996dcc5900aa41a4a327bc Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 12:48:27 +0100 Subject: [PATCH 03/31] Update src/py/flwr/client/app.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index ec5e593b3567..0519a3edd0aa 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -33,7 +33,7 @@ def start_client( server_address: str, client: Client, grpc_max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, - root_certificates: Optional[str] = None, + root_certificate: Optional[str] = None, ) -> None: """Start a Flower Client which connects to a gRPC server. From a1a3c38bb22bc6912f29ebce7f0e1a6ae0285ae9 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 12:49:21 +0100 Subject: [PATCH 04/31] Update src/py/flwr/client/app.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/app.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 0519a3edd0aa..dfd3a6474942 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -50,10 +50,10 @@ class `flwr.client.Client`. value. Note that the Flower server needs to be started with the same value (see `flwr.server.start_server`), otherwise it will not know about the increased limit and block larger messages. - root_certificates: str (default: None) - Path to the PEM-encoded root certificates. If provided a secure connection - using the certificate will be established to a SSL/TLS enabled Flower server - (default: None) + root_certificate: str (default: None) + Path to the PEM-encoded root certificates file. If provided, a secure + connection using the certificate(s) will be established to a SSL/TLS-enabled + Flower server (default: None) Returns: None. From 410e911d6adb8cef6008bfec8958a61ea1a3ebf4 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 12:49:35 +0100 Subject: [PATCH 05/31] Update src/py/flwr/client/app.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/app.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index dfd3a6474942..b0257432861a 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -109,9 +109,9 @@ class `flwr.client.NumPyClient`. value. Note that the Flower server needs to be started with the same value (see `flwr.server.start_server`), otherwise it will not know about the increased limit and block larger messages. - root_certificates: str (default: None) - Path to the PEM-encoded root certificates. If provided a secure connection - using the certificate will be established to a SSL/TLS enabled Flower server + root_certificate: str (default: None) + Path to the PEM-encoded root certificate file. If provided, a secure connection + using the certificate(s) will be established to a SSL/TLS enabled Flower server (default: None) Returns: From ea424225fec250d73a65ca2eb1c5d63630a4ea16 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 12:49:46 +0100 Subject: [PATCH 06/31] Update src/py/flwr/client/app.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index b0257432861a..1e5ad7fa604f 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -126,7 +126,7 @@ class `flwr.client.NumPyClient`. server_address=server_address, client=flower_client, grpc_max_message_length=grpc_max_message_length, - root_certificates=root_certificates, + root_certificate=root_certificate, ) From e0e9c922552112c429f6a0e2239b7a31c86fd3cf Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 12:49:59 +0100 Subject: [PATCH 07/31] Update src/py/flwr/client/grpc_client/connection.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/grpc_client/connection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index 8020f9a40f77..31fee5c4765d 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -40,7 +40,7 @@ def on_channel_state_change(channel_connectivity: str) -> None: def grpc_connection( server_address: str, max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, - root_certificates: Optional[str] = None, + root_certificate: Optional[str] = None, ) -> Iterator[Tuple[Callable[[], ServerMessage], Callable[[ClientMessage], None]]]: """Establish an insecure gRPC connection to a gRPC server. From 3fba0f8c4f4f912aed2a64d1e9d03cca3dc827f4 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 12:50:03 +0100 Subject: [PATCH 08/31] Update src/py/flwr/client/grpc_client/connection.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/grpc_client/connection.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index 31fee5c4765d..64f729ae0700 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -57,9 +57,9 @@ def grpc_connection( (see `flwr.server.start_server`), otherwise it will not know about the increased limit and block larger messages. (default: 536_870_912, this equals 512MB) - root_certificates : str - Path to the PEM-encoded root certificates. If provided a secure connection - using the certificate will be established to a SSL/TLS enabled Flower server + root_certificate : str + Path to the PEM-encoded root certificate file. If provided, a secure connection + using the certificate(s) will be established to a SSL/TLS enabled Flower server (default: None) """ channel_options = [ From c4a8afd46732fbbcd850e619266088d3060ad20d Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 12:50:09 +0100 Subject: [PATCH 09/31] Update src/py/flwr/client/grpc_client/connection.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/grpc_client/connection.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index 64f729ae0700..d0d8ee401cea 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -67,8 +67,8 @@ def grpc_connection( ("grpc.max_receive_message_length", max_message_length), ] - if root_certificates is not None: - with open(root_certificates, "rb") as file: + if root_certificate is not None: + with open(root_certificate, "rb") as file: ssl_channel_credentials = grpc.ssl_channel_credentials(file.read()) channel = grpc.secure_channel( From c3a1db51da077728aa48e780616180da03aed781 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 12:51:14 +0100 Subject: [PATCH 10/31] Update src/py/flwr/client/app.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 1e5ad7fa604f..3650ffc85921 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -92,7 +92,7 @@ def start_numpy_client( server_address: str, client: NumPyClient, grpc_max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, - root_certificates: Optional[str] = None, + root_certificate: Optional[str] = None, ) -> None: """Start a Flower NumPyClient which connects to a gRPC server. From 157d83e8f6aedd30599a7317b02228a3e7237662 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 12:51:21 +0100 Subject: [PATCH 11/31] Update src/py/flwr/client/app.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 3650ffc85921..c6eec576ef49 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -63,7 +63,7 @@ class `flwr.client.Client`. with grpc_connection( server_address, max_message_length=grpc_max_message_length, - root_certificates=root_certificates, + root_certificate=root_certificate, ) as conn: receive, send = conn log(INFO, "Opened (insecure) gRPC connection") From fe962dfd4661a4119bf8af80ee2a344dba93b915 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 16:56:20 +0100 Subject: [PATCH 12/31] Fix --- src/py/flwr/client/grpc_client/connection.py | 23 ++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index d0d8ee401cea..b244971d9868 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -57,10 +57,29 @@ def grpc_connection( (see `flwr.server.start_server`), otherwise it will not know about the increased limit and block larger messages. (default: 536_870_912, this equals 512MB) - root_certificate : str - Path to the PEM-encoded root certificate file. If provided, a secure connection + root_certificate : ByteString + PEM-encoded root certificate as ByteString. If provided, a secure connection using the certificate(s) will be established to a SSL/TLS enabled Flower server (default: None) + + Returns + ------- + receive, send : Callable, Callable + + Examples + -------- + Starting a SSL/TLS enabled connection to server. + + >>> from pathlib import Path + >>> with grpc_connection( + >>> server_address, + >>> max_message_length=grpc_max_message_length, + >>> root_certificate=Path("/crts/root.pem").read_bytes(), + >>> ) as conn: + >>> receive, send = conn + >>> server_message = receive() + >>> # do something here + >>> send(client_message) """ channel_options = [ ("grpc.max_send_message_length", max_message_length), From 717d47194e55c96f0ba98e8045f9e0dcd09fa62c Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 17:00:38 +0100 Subject: [PATCH 13/31] Fix --- src/py/flwr/client/app.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index c6eec576ef49..a423d60cddf6 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -17,7 +17,7 @@ import time from logging import INFO -from typing import Optional +from typing import ByteString, Optional from flwr.common import GRPC_MAX_MESSAGE_LENGTH from flwr.common.logger import log @@ -33,7 +33,7 @@ def start_client( server_address: str, client: Client, grpc_max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, - root_certificate: Optional[str] = None, + root_certificate: Optional[ByteString] = None, ) -> None: """Start a Flower Client which connects to a gRPC server. @@ -50,13 +50,31 @@ class `flwr.client.Client`. value. Note that the Flower server needs to be started with the same value (see `flwr.server.start_server`), otherwise it will not know about the increased limit and block larger messages. - root_certificate: str (default: None) - Path to the PEM-encoded root certificates file. If provided, a secure + root_certificate: ByteString (default: None) + PEM-encoded root certificate as ByteString. If provided, a secure connection using the certificate(s) will be established to a SSL/TLS-enabled Flower server (default: None) Returns: None. + + Examples + -------- + Starting a client with unsecure server connection. + + >>> start_client( + >>> server_address=localhost:8080, + >>> client=FlowerClient(), + >>> ) + + Starting a SSL/TLS enabled client. + + >>> from pathlib import Path + >>> start_client( + >>> server_address=localhost:8080, + >>> client=FlowerClient(), + >>> root_certificate=Path("/crts/root.pem").read_bytes(), + >>> ) """ while True: sleep_duration: int = 0 From 5b31a466ae6125e0ebf5eff596084b7fa4263dc4 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 17:03:32 +0100 Subject: [PATCH 14/31] Fix docs --- src/py/flwr/client/app.py | 38 +++++++++++++++----- src/py/flwr/client/grpc_client/connection.py | 4 +-- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index a423d60cddf6..2f367d5fc8ce 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -37,7 +37,8 @@ def start_client( ) -> None: """Start a Flower Client which connects to a gRPC server. - Arguments: + Parameters + ---------- server_address: str. The IPv6 address of the server. If the Flower server runs on the same machine on port 8080, then `server_address` would be `"[::]:8080"`. @@ -55,8 +56,9 @@ class `flwr.client.Client`. connection using the certificate(s) will be established to a SSL/TLS-enabled Flower server (default: None) - Returns: - None. + Returns + ------- + None Examples -------- @@ -110,11 +112,12 @@ def start_numpy_client( server_address: str, client: NumPyClient, grpc_max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, - root_certificate: Optional[str] = None, + root_certificate: Optional[ByteString] = None, ) -> None: """Start a Flower NumPyClient which connects to a gRPC server. - Arguments: + Parameters + ---------- server_address: str. The IPv6 address of the server. If the Flower server runs on the same machine on port 8080, then `server_address` would be `"[::]:8080"`. @@ -128,12 +131,31 @@ class `flwr.client.NumPyClient`. same value (see `flwr.server.start_server`), otherwise it will not know about the increased limit and block larger messages. root_certificate: str (default: None) - Path to the PEM-encoded root certificate file. If provided, a secure connection + PEM-encoded root certificate as ByteString. If provided, a secure connection using the certificate(s) will be established to a SSL/TLS enabled Flower server (default: None) - Returns: - None. + Returns + ------- + None + + Examples + -------- + Starting a client with unsecure server connection. + + >>> start_client( + >>> server_address=localhost:8080, + >>> client=FlowerClient(), + >>> ) + + Starting a SSL/TLS enabled client. + + >>> from pathlib import Path + >>> start_client( + >>> server_address=localhost:8080, + >>> client=FlowerClient(), + >>> root_certificate=Path("/crts/root.pem").read_bytes(), + >>> ) """ # Wrap the NumPyClient diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index b244971d9868..bf21d5fa6ca3 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -17,7 +17,7 @@ from contextlib import contextmanager from logging import DEBUG from queue import Queue -from typing import Callable, Iterator, Optional, Tuple +from typing import ByteString, Callable, Iterator, Optional, Tuple import grpc @@ -40,7 +40,7 @@ def on_channel_state_change(channel_connectivity: str) -> None: def grpc_connection( server_address: str, max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, - root_certificate: Optional[str] = None, + root_certificate: Optional[ByteString] = None, ) -> Iterator[Tuple[Callable[[], ServerMessage], Callable[[ClientMessage], None]]]: """Establish an insecure gRPC connection to a gRPC server. From cf37dde61916ed45ebb4944b9ae80bf0c8472d4d Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 17:07:49 +0100 Subject: [PATCH 15/31] Fix --- src/py/flwr/client/app.py | 12 ++++++------ src/py/flwr/client/grpc_client/connection.py | 12 +++++------- src/py/flwr/server/grpc_server/grpc_server.py | 8 ++++---- 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 2f367d5fc8ce..6e418e48b43b 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -17,7 +17,7 @@ import time from logging import INFO -from typing import ByteString, Optional +from typing import Optional from flwr.common import GRPC_MAX_MESSAGE_LENGTH from flwr.common.logger import log @@ -33,7 +33,7 @@ def start_client( server_address: str, client: Client, grpc_max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, - root_certificate: Optional[ByteString] = None, + root_certificate: Optional[bytes] = None, ) -> None: """Start a Flower Client which connects to a gRPC server. @@ -51,8 +51,8 @@ class `flwr.client.Client`. value. Note that the Flower server needs to be started with the same value (see `flwr.server.start_server`), otherwise it will not know about the increased limit and block larger messages. - root_certificate: ByteString (default: None) - PEM-encoded root certificate as ByteString. If provided, a secure + root_certificate: bytes (default: None) + PEM-encoded root certificate as bytes. If provided, a secure connection using the certificate(s) will be established to a SSL/TLS-enabled Flower server (default: None) @@ -112,7 +112,7 @@ def start_numpy_client( server_address: str, client: NumPyClient, grpc_max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, - root_certificate: Optional[ByteString] = None, + root_certificate: Optional[bytes] = None, ) -> None: """Start a Flower NumPyClient which connects to a gRPC server. @@ -131,7 +131,7 @@ class `flwr.client.NumPyClient`. same value (see `flwr.server.start_server`), otherwise it will not know about the increased limit and block larger messages. root_certificate: str (default: None) - PEM-encoded root certificate as ByteString. If provided, a secure connection + PEM-encoded root certificate as bytes. If provided, a secure connection using the certificate(s) will be established to a SSL/TLS enabled Flower server (default: None) diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index bf21d5fa6ca3..a936131c3850 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -17,7 +17,7 @@ from contextlib import contextmanager from logging import DEBUG from queue import Queue -from typing import ByteString, Callable, Iterator, Optional, Tuple +from typing import Callable, Iterator, Optional, Tuple import grpc @@ -40,7 +40,7 @@ def on_channel_state_change(channel_connectivity: str) -> None: def grpc_connection( server_address: str, max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, - root_certificate: Optional[ByteString] = None, + root_certificate: Optional[bytes] = None, ) -> Iterator[Tuple[Callable[[], ServerMessage], Callable[[ClientMessage], None]]]: """Establish an insecure gRPC connection to a gRPC server. @@ -57,8 +57,8 @@ def grpc_connection( (see `flwr.server.start_server`), otherwise it will not know about the increased limit and block larger messages. (default: 536_870_912, this equals 512MB) - root_certificate : ByteString - PEM-encoded root certificate as ByteString. If provided, a secure connection + root_certificate : bytes + PEM-encoded root certificate as bytes. If provided, a secure connection using the certificate(s) will be established to a SSL/TLS enabled Flower server (default: None) @@ -87,9 +87,7 @@ def grpc_connection( ] if root_certificate is not None: - with open(root_certificate, "rb") as file: - ssl_channel_credentials = grpc.ssl_channel_credentials(file.read()) - + ssl_channel_credentials = grpc.ssl_channel_credentials(root_certificate) channel = grpc.secure_channel( server_address, ssl_channel_credentials, options=channel_options ) diff --git a/src/py/flwr/server/grpc_server/grpc_server.py b/src/py/flwr/server/grpc_server/grpc_server.py index 44d464cdb7cc..3ef15a7b3842 100644 --- a/src/py/flwr/server/grpc_server/grpc_server.py +++ b/src/py/flwr/server/grpc_server/grpc_server.py @@ -18,7 +18,7 @@ import concurrent.futures import sys from logging import ERROR -from typing import ByteString, Optional, Tuple +from typing import Optional, Tuple import grpc @@ -34,7 +34,7 @@ """ -def valid_ssl_files(ssl_files: Tuple[ByteString, ByteString, ByteString]) -> bool: +def valid_ssl_files(ssl_files: Tuple[bytes, bytes, bytes]) -> bool: """Validate ssl_files tuple.""" is_valid = ( all(isinstance(ssl_file, bytes) for ssl_file in ssl_files) @@ -52,7 +52,7 @@ def start_grpc_server( server_address: str, max_concurrent_workers: int = 1000, max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, - ssl_files: Optional[Tuple[ByteString, ByteString, ByteString]] = None, + ssl_files: Optional[Tuple[bytes, bytes, bytes]] = None, ) -> grpc.Server: """Create gRPC server and return instance of grpc.Server. @@ -75,7 +75,7 @@ def start_grpc_server( max_message_length : int Maximum message length that the server can send or receive. Int valued in bytes. -1 means unlimited. (default: GRPC_MAX_MESSAGE_LENGTH) - ssl_files : Tuple[ByteString, ByteString, ByteString] + ssl_files : Tuple[bytes, bytes, bytes] Tuple containing root certificate, server certificate, and private key to start a secure SSL/TLS server. The tuple is expected to have three byte string elements in the following order: From adb2f101e58b98c6989ed3e8405f12de30834c98 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 17:09:49 +0100 Subject: [PATCH 16/31] fix --- src/py/flwr/client/app.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 6e418e48b43b..31184580d8ef 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -130,10 +130,10 @@ class `flwr.client.NumPyClient`. value. Note that the Flower server needs to be started with the same value (see `flwr.server.start_server`), otherwise it will not know about the increased limit and block larger messages. - root_certificate: str (default: None) + root_certificate: bytes (default: None) PEM-encoded root certificate as bytes. If provided, a secure connection - using the certificate(s) will be established to a SSL/TLS enabled Flower server - (default: None) + using the certificate(s) will be established to a SSL/TLS enabled Flower + server Returns ------- From 034ab70d2dffd53e79f7d62ffb4eda64b6d81c82 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 17:10:59 +0100 Subject: [PATCH 17/31] fix --- src/py/flwr/client/app.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 31184580d8ef..d07228831b47 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -52,9 +52,9 @@ class `flwr.client.Client`. same value (see `flwr.server.start_server`), otherwise it will not know about the increased limit and block larger messages. root_certificate: bytes (default: None) - PEM-encoded root certificate as bytes. If provided, a secure - connection using the certificate(s) will be established to a SSL/TLS-enabled - Flower server (default: None) + PEM-encoded root certificate as bytes. If provided, a secure connection + using the certificate(s) will be established to a SSL/TLS-enabled Flower + server (default: None) Returns ------- @@ -132,8 +132,8 @@ class `flwr.client.NumPyClient`. know about the increased limit and block larger messages. root_certificate: bytes (default: None) PEM-encoded root certificate as bytes. If provided, a secure connection - using the certificate(s) will be established to a SSL/TLS enabled Flower - server + using the certificate(s) will be established to a SSL/TLS-enabled Flower + server (default: None) Returns ------- From d4739dc2236178c08f706377351b19be1f3d48d1 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 18:05:45 +0100 Subject: [PATCH 18/31] Update src/py/flwr/client/app.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index d07228831b47..87ae7718e526 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -54,7 +54,7 @@ class `flwr.client.Client`. root_certificate: bytes (default: None) PEM-encoded root certificate as bytes. If provided, a secure connection using the certificate(s) will be established to a SSL/TLS-enabled Flower - server (default: None) + server Returns ------- From b78375bc20cac78c08d5e5842493adc9cb40b08a Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 18:05:54 +0100 Subject: [PATCH 19/31] Update src/py/flwr/client/app.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 87ae7718e526..9053a5c66016 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -62,7 +62,7 @@ class `flwr.client.Client`. Examples -------- - Starting a client with unsecure server connection. + Starting a client with insecure server connection: >>> start_client( >>> server_address=localhost:8080, From 9253a6fb872cb773cd5e72f06cfa6b916c0b115c Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 18:06:00 +0100 Subject: [PATCH 20/31] Update src/py/flwr/client/app.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 9053a5c66016..14ecbdf9da5a 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -69,7 +69,7 @@ class `flwr.client.Client`. >>> client=FlowerClient(), >>> ) - Starting a SSL/TLS enabled client. + Starting a SSL/TLS-enabled client: >>> from pathlib import Path >>> start_client( From 169560bb4d2702da8b1b37953c4439ce2ac0ff9f Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 18:06:07 +0100 Subject: [PATCH 21/31] Update src/py/flwr/client/app.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 14ecbdf9da5a..0e5a33c05ceb 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -133,7 +133,7 @@ class `flwr.client.NumPyClient`. root_certificate: bytes (default: None) PEM-encoded root certificate as bytes. If provided, a secure connection using the certificate(s) will be established to a SSL/TLS-enabled Flower - server (default: None) + server Returns ------- From fc4e54040422458cff588517b855ec2f8e77cec4 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 18:06:12 +0100 Subject: [PATCH 22/31] Update src/py/flwr/client/app.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/app.py b/src/py/flwr/client/app.py index 0e5a33c05ceb..8a74f04a62a8 100644 --- a/src/py/flwr/client/app.py +++ b/src/py/flwr/client/app.py @@ -141,7 +141,7 @@ class `flwr.client.NumPyClient`. Examples -------- - Starting a client with unsecure server connection. + Starting a client with insecure server connection. >>> start_client( >>> server_address=localhost:8080, From 09823bddd92c63a3ddbcd81e3e36c6ba4dfad57a Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 18:07:15 +0100 Subject: [PATCH 23/31] Update src/py/flwr/client/grpc_client/connection.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/grpc_client/connection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index a936131c3850..3196f97b210d 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -57,7 +57,7 @@ def grpc_connection( (see `flwr.server.start_server`), otherwise it will not know about the increased limit and block larger messages. (default: 536_870_912, this equals 512MB) - root_certificate : bytes + root_certificate : Optional[bytes] (default: None) PEM-encoded root certificate as bytes. If provided, a secure connection using the certificate(s) will be established to a SSL/TLS enabled Flower server (default: None) From 6067301fed6da5f11820583d7d696b4b60a33909 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 18:07:22 +0100 Subject: [PATCH 24/31] Update src/py/flwr/client/grpc_client/connection.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/grpc_client/connection.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index 3196f97b210d..98372d9f6bd1 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -60,7 +60,6 @@ def grpc_connection( root_certificate : Optional[bytes] (default: None) PEM-encoded root certificate as bytes. If provided, a secure connection using the certificate(s) will be established to a SSL/TLS enabled Flower server - (default: None) Returns ------- From fe9ee8995a487f0f4e0fc736213e078bb7f5eb9a Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 18:07:33 +0100 Subject: [PATCH 25/31] Update src/py/flwr/client/grpc_client/connection.py Co-authored-by: Daniel J. Beutel --- src/py/flwr/client/grpc_client/connection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index 98372d9f6bd1..de8ca8db1b9a 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -67,7 +67,7 @@ def grpc_connection( Examples -------- - Starting a SSL/TLS enabled connection to server. + Establishing a SSL/TLS-enabled connection to server: >>> from pathlib import Path >>> with grpc_connection( From 7ea086752fe40c9daf5a9bc3b403eb64bfbc9cd4 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 18:09:41 +0100 Subject: [PATCH 26/31] fix --- src/py/flwr/client/grpc_client/connection.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/py/flwr/client/grpc_client/connection.py b/src/py/flwr/client/grpc_client/connection.py index de8ca8db1b9a..cbd93606fbe0 100644 --- a/src/py/flwr/client/grpc_client/connection.py +++ b/src/py/flwr/client/grpc_client/connection.py @@ -58,8 +58,8 @@ def grpc_connection( increased limit and block larger messages. (default: 536_870_912, this equals 512MB) root_certificate : Optional[bytes] (default: None) - PEM-encoded root certificate as bytes. If provided, a secure connection - using the certificate(s) will be established to a SSL/TLS enabled Flower server + PEM-encoded root certificate as bytes. If provided, a secure connection using + the certificate(s) will be established to a SSL/TLS enabled Flower server Returns ------- From 6f23a9ca00eb4e6c298da5c347f5bd68d988c9d1 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 18:54:13 +0100 Subject: [PATCH 27/31] Update docs --- src/py/flwr/server/app.py | 11 ++++++++--- src/py/flwr/server/grpc_server/grpc_server.py | 14 ++++++-------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index 08c507bca13b..bc6bbbd6c39a 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -36,6 +36,7 @@ def start_server( # pylint: disable=too-many-arguments strategy: Optional[Strategy] = None, grpc_max_message_length: int = GRPC_MAX_MESSAGE_LENGTH, force_final_distributed_eval: bool = False, + ssl_files: Optional[Tuple[bytes, bytes, bytes]] = None, ) -> History: """Start a Flower server using the gRPC transport layer. @@ -65,8 +66,8 @@ def start_server( # pylint: disable=too-many-arguments Forces a distributed evaluation to occur after the last training epoch when enabled. ssl_files : Tuple[bytes, bytes, bytes] (default: None) - Tuple containing root certificate, server certificate, and private key to start - a secure SSL/TLS server. The tuple is expected to have three byte string + Tuple containing root certificate, server certificate, and private key to + start a secure SSL/TLS server. The tuple is expected to have three bytes elements in the following order: * CA certificate. @@ -86,7 +87,11 @@ def start_server( # pylint: disable=too-many-arguments Starting a SSL/TLS enabled server. >>> start_server( - >>> ssl_files=("/crts/root.pem", "/crts/localhost.crt", "/crts/localhost.key") + >>> ssl_files=( + >>> Path("/crts/root.pem").read_bytes(), + >>> Path("/crts/localhost.crt").read_bytes(), + >>> Path("/crts/localhost.key").read_bytes() + >>> ) >>> ) """ initialized_server, initialized_config = _init_defaults(server, config, strategy) diff --git a/src/py/flwr/server/grpc_server/grpc_server.py b/src/py/flwr/server/grpc_server/grpc_server.py index 3ef15a7b3842..dbaea57a6ba9 100644 --- a/src/py/flwr/server/grpc_server/grpc_server.py +++ b/src/py/flwr/server/grpc_server/grpc_server.py @@ -76,15 +76,13 @@ def start_grpc_server( Maximum message length that the server can send or receive. Int valued in bytes. -1 means unlimited. (default: GRPC_MAX_MESSAGE_LENGTH) ssl_files : Tuple[bytes, bytes, bytes] - Tuple containing root certificate, server certificate, and private key to start - a secure SSL/TLS server. The tuple is expected to have three byte string - elements in the following order: + Tuple containing root certificate, server certificate, and private key to + start a secure SSL/TLS server. The tuple is expected to have three bytes + elements in the following order: - * CA certificate. - * server certificate. - * server private key. - - (default: None) + * CA certificate. + * server certificate. + * server private key. Returns ------- From 40d6036f1bdb1a7a35845173e043e0a6ee557553 Mon Sep 17 00:00:00 2001 From: Taner Topal Date: Wed, 5 Jan 2022 19:17:05 +0100 Subject: [PATCH 28/31] Update grpc_server.py --- src/py/flwr/server/grpc_server/grpc_server.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/server/grpc_server/grpc_server.py b/src/py/flwr/server/grpc_server/grpc_server.py index 3cc826dbbb08..8f2e5d8eb815 100644 --- a/src/py/flwr/server/grpc_server/grpc_server.py +++ b/src/py/flwr/server/grpc_server/grpc_server.py @@ -75,7 +75,7 @@ def start_grpc_server( max_message_length : int Maximum message length that the server can send or receive. Int valued in bytes. -1 means unlimited. (default: GRPC_MAX_MESSAGE_LENGTH) - ssl_files : Tuple[bytes, bytes, bytes] + ssl_files : Tuple[bytes, bytes, bytes] (default: None) Tuple containing root certificate, server certificate, and private key to start a secure SSL/TLS server. The tuple is expected to have three bytes elements in the following order: From d2a926ef53c0404f96a1586335a521d7c8da0ab2 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Wed, 5 Jan 2022 19:24:33 +0100 Subject: [PATCH 29/31] Update src/py/flwr/server/app.py --- src/py/flwr/server/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index bc6bbbd6c39a..184394d38416 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -80,7 +80,7 @@ def start_server( # pylint: disable=too-many-arguments Examples -------- - Starting a insecure server. + Starting an insecure server: >>> start_server() From 22d281b6c8515350d86d76472b6b3c09b6d44954 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Wed, 5 Jan 2022 19:24:44 +0100 Subject: [PATCH 30/31] Update src/py/flwr/server/app.py --- src/py/flwr/server/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index 184394d38416..8349fede838f 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -84,7 +84,7 @@ def start_server( # pylint: disable=too-many-arguments >>> start_server() - Starting a SSL/TLS enabled server. + Starting an SSL/TLS-enabled server: >>> start_server( >>> ssl_files=( From 8aade22e09c841d71b77e4051d993d9090ef7251 Mon Sep 17 00:00:00 2001 From: "Daniel J. Beutel" Date: Thu, 6 Jan 2022 08:01:16 +0100 Subject: [PATCH 31/31] Update src/py/flwr/server/app.py --- src/py/flwr/server/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/py/flwr/server/app.py b/src/py/flwr/server/app.py index 8349fede838f..4e3cb03aa089 100644 --- a/src/py/flwr/server/app.py +++ b/src/py/flwr/server/app.py @@ -84,7 +84,7 @@ def start_server( # pylint: disable=too-many-arguments >>> start_server() - Starting an SSL/TLS-enabled server: + Starting a SSL/TLS-enabled server: >>> start_server( >>> ssl_files=(