Skip to content

Commit

Permalink
Make flower-server start server with HTTPS by default (#2591)
Browse files Browse the repository at this point in the history
Co-authored-by: Daniel J. Beutel <[email protected]>
Co-authored-by: Taner Topal <[email protected]>
  • Loading branch information
3 people authored Nov 17, 2023
1 parent b43515c commit bc346ac
Show file tree
Hide file tree
Showing 12 changed files with 234 additions and 6 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ jobs:
include:
- directory: bare

- directory: bare-https

- directory: jax

- directory: pytorch
Expand Down Expand Up @@ -135,7 +137,7 @@ jobs:
- name: Run virtual client test
run: python simulation.py
- name: Run driver test
run: ./../test_driver.sh
run: ./../test_driver.sh "${{ matrix.directory }}"

strategies:
runs-on: ubuntu-22.04
Expand Down
3 changes: 3 additions & 0 deletions e2e/bare-https/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Bare Flower testing

This directory is used for testing Flower in a bare minimum scenario, that is, with a dummy model and dummy operations. This is mainly to test the core functionnality of Flower independently from any framework. It can easily be extendended to test more complex communication set-ups.
20 changes: 20 additions & 0 deletions e2e/bare-https/certificate.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
[req]
default_bits = 4096
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn

[dn]
C = DE
ST = HH
O = Flower
CN = localhost

[req_ext]
subjectAltName = @alt_names

[alt_names]
DNS.1 = localhost
IP.1 = ::1
IP.2 = 127.0.0.1
35 changes: 35 additions & 0 deletions e2e/bare-https/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import flwr as fl
import numpy as np
from pathlib import Path


model_params = np.array([1])
objective = 5

# Define Flower client
class FlowerClient(fl.client.NumPyClient):
def get_parameters(self, config):
return model_params

def fit(self, parameters, config):
model_params = parameters
model_params = [param * (objective/np.mean(param)) for param in model_params]
return model_params, 1, {}

def evaluate(self, parameters, config):
model_params = parameters
loss = min(np.abs(1 - np.mean(model_params)/objective), 1)
accuracy = 1 - loss
return loss, 1, {"accuracy": accuracy}

def client_fn(cid):
return FlowerClient()


if __name__ == "__main__":
# Start Flower client
fl.client.start_numpy_client(
server_address="127.0.0.1:8080",
client=FlowerClient(),
root_certificates=Path("certificates/ca.crt").read_bytes(),
)
12 changes: 12 additions & 0 deletions e2e/bare-https/driver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import flwr as fl
from pathlib import Path


# Start Flower server
hist = fl.driver.start_driver(
server_address="127.0.0.1:9091",
config=fl.server.ServerConfig(num_rounds=3),
root_certificates=Path("certificates/ca.crt").read_bytes(),
)

assert hist.losses_distributed[-1][1] == 0
55 changes: 55 additions & 0 deletions e2e/bare-https/generate.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/bin/bash
# This script will generate all certificates if ca.crt does not exist

set -e
# Change directory to the script's directory
cd "$(dirname "${BASH_SOURCE[0]}")"

CA_PASSWORD=notsafe

CERT_DIR=certificates

# Generate directories if not exists
mkdir -p $CERT_DIR

# Uncomment the below block if you want to skip certificate generation if they already exist.
# if [ -f "$CERT_DIR/ca.crt" ]; then
# echo "Skipping certificate generation as they already exist."
# exit 0
# fi

# Clearing any existing files in the certificates directory
rm -f $CERT_DIR/*

# Generate the root certificate authority key and certificate based on key
openssl genrsa -out $CERT_DIR/ca.key 4096
openssl req \
-new \
-x509 \
-key $CERT_DIR/ca.key \
-sha256 \
-subj "/C=DE/ST=HH/O=CA, Inc." \
-days 365 -out $CERT_DIR/ca.crt

# Generate a new private key for the server
openssl genrsa -out $CERT_DIR/server.key 4096

# Create a signing CSR
openssl req \
-new \
-key $CERT_DIR/server.key \
-out $CERT_DIR/server.csr \
-config certificate.conf

# Generate a certificate for the server
openssl x509 \
-req \
-in $CERT_DIR/server.csr \
-CA $CERT_DIR/ca.crt \
-CAkey $CERT_DIR/ca.key \
-CAcreateserial \
-out $CERT_DIR/server.pem \
-days 365 \
-sha256 \
-extfile certificate.conf \
-extensions req_ext
13 changes: 13 additions & 0 deletions e2e/bare-https/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[build-system]
requires = ["poetry-core>=1.4.0"]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "bare_https_test"
version = "0.1.0"
description = "HTTPS-enabled bare Federated Learning test with Flower"
authors = ["The Flower Authors <[email protected]>"]

[tool.poetry.dependencies]
python = "^3.8"
flwr = { path = "../../", develop = true }
15 changes: 15 additions & 0 deletions e2e/bare-https/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import flwr as fl
from pathlib import Path


hist = fl.server.start_server(
server_address="127.0.0.1:8080",
config=fl.server.ServerConfig(num_rounds=3),
certificates=(
Path("certificates/ca.crt").read_bytes(),
Path("certificates/server.pem").read_bytes(),
Path("certificates/server.key").read_bytes(),
)
)

assert hist.losses_distributed[-1][1] == 0 or (hist.losses_distributed[0][1] / hist.losses_distributed[-1][1]) >= 0.98
1 change: 1 addition & 0 deletions e2e/bare-https/simulation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# No simulation test for bare-https
4 changes: 4 additions & 0 deletions e2e/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ case "$1" in
pandas)
server_file="server.py"
;;
bare-https)
./generate.sh
server_file="server.py"
;;
*)
server_file="../server.py"
;;
Expand Down
12 changes: 11 additions & 1 deletion e2e/test_driver.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
#!/bin/bash
set -e

timeout 2m flower-server --grpc-bidi --grpc-bidi-fleet-api-address 0.0.0.0:8080 &
case "$1" in
bare-https)
./generate.sh
cert_arg="--certificates certificates/ca.crt certificates/server.pem certificates/server.key"
;;
*)
cert_arg="--insecure"
;;
esac

timeout 2m flower-server $cert_arg --grpc-bidi --grpc-bidi-fleet-api-address 0.0.0.0:8080 &
sleep 3

python client.py &
Expand Down
Loading

0 comments on commit bc346ac

Please sign in to comment.