flwr 1.21.0__py3-none-any.whl → 1.23.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (175) hide show
  1. flwr/cli/app.py +17 -1
  2. flwr/cli/auth_plugin/__init__.py +15 -6
  3. flwr/cli/auth_plugin/auth_plugin.py +95 -0
  4. flwr/cli/auth_plugin/noop_auth_plugin.py +58 -0
  5. flwr/cli/auth_plugin/oidc_cli_plugin.py +16 -25
  6. flwr/cli/build.py +118 -47
  7. flwr/cli/{cli_user_auth_interceptor.py → cli_account_auth_interceptor.py} +6 -5
  8. flwr/cli/log.py +2 -2
  9. flwr/cli/login/login.py +34 -23
  10. flwr/cli/ls.py +13 -9
  11. flwr/cli/new/new.py +196 -42
  12. flwr/cli/new/templates/app/README.flowertune.md.tpl +1 -1
  13. flwr/cli/new/templates/app/code/client.baseline.py.tpl +64 -47
  14. flwr/cli/new/templates/app/code/client.huggingface.py.tpl +68 -30
  15. flwr/cli/new/templates/app/code/client.jax.py.tpl +63 -42
  16. flwr/cli/new/templates/app/code/client.mlx.py.tpl +80 -51
  17. flwr/cli/new/templates/app/code/client.numpy.py.tpl +36 -13
  18. flwr/cli/new/templates/app/code/client.pytorch.py.tpl +71 -46
  19. flwr/cli/new/templates/app/code/client.pytorch_legacy_api.py.tpl +55 -0
  20. flwr/cli/new/templates/app/code/client.sklearn.py.tpl +75 -30
  21. flwr/cli/new/templates/app/code/client.tensorflow.py.tpl +69 -44
  22. flwr/cli/new/templates/app/code/client.xgboost.py.tpl +110 -0
  23. flwr/cli/new/templates/app/code/flwr_tune/client_app.py.tpl +56 -90
  24. flwr/cli/new/templates/app/code/flwr_tune/models.py.tpl +1 -23
  25. flwr/cli/new/templates/app/code/flwr_tune/server_app.py.tpl +37 -58
  26. flwr/cli/new/templates/app/code/flwr_tune/strategy.py.tpl +39 -44
  27. flwr/cli/new/templates/app/code/model.baseline.py.tpl +0 -14
  28. flwr/cli/new/templates/app/code/server.baseline.py.tpl +27 -29
  29. flwr/cli/new/templates/app/code/server.huggingface.py.tpl +23 -19
  30. flwr/cli/new/templates/app/code/server.jax.py.tpl +27 -14
  31. flwr/cli/new/templates/app/code/server.mlx.py.tpl +29 -19
  32. flwr/cli/new/templates/app/code/server.numpy.py.tpl +30 -17
  33. flwr/cli/new/templates/app/code/server.pytorch.py.tpl +36 -26
  34. flwr/cli/new/templates/app/code/server.pytorch_legacy_api.py.tpl +31 -0
  35. flwr/cli/new/templates/app/code/server.sklearn.py.tpl +29 -21
  36. flwr/cli/new/templates/app/code/server.tensorflow.py.tpl +28 -19
  37. flwr/cli/new/templates/app/code/server.xgboost.py.tpl +56 -0
  38. flwr/cli/new/templates/app/code/task.huggingface.py.tpl +16 -20
  39. flwr/cli/new/templates/app/code/task.jax.py.tpl +1 -1
  40. flwr/cli/new/templates/app/code/task.numpy.py.tpl +1 -1
  41. flwr/cli/new/templates/app/code/task.pytorch.py.tpl +14 -27
  42. flwr/cli/new/templates/app/code/{task.pytorch_msg_api.py.tpl → task.pytorch_legacy_api.py.tpl} +27 -14
  43. flwr/cli/new/templates/app/code/task.tensorflow.py.tpl +1 -2
  44. flwr/cli/new/templates/app/code/task.xgboost.py.tpl +67 -0
  45. flwr/cli/new/templates/app/pyproject.baseline.toml.tpl +4 -4
  46. flwr/cli/new/templates/app/pyproject.flowertune.toml.tpl +2 -2
  47. flwr/cli/new/templates/app/pyproject.huggingface.toml.tpl +4 -4
  48. flwr/cli/new/templates/app/pyproject.jax.toml.tpl +1 -1
  49. flwr/cli/new/templates/app/pyproject.mlx.toml.tpl +2 -2
  50. flwr/cli/new/templates/app/pyproject.numpy.toml.tpl +1 -1
  51. flwr/cli/new/templates/app/pyproject.pytorch.toml.tpl +3 -3
  52. flwr/cli/new/templates/app/{pyproject.pytorch_msg_api.toml.tpl → pyproject.pytorch_legacy_api.toml.tpl} +3 -3
  53. flwr/cli/new/templates/app/pyproject.sklearn.toml.tpl +1 -1
  54. flwr/cli/new/templates/app/pyproject.tensorflow.toml.tpl +1 -1
  55. flwr/cli/new/templates/app/pyproject.xgboost.toml.tpl +61 -0
  56. flwr/cli/pull.py +100 -0
  57. flwr/cli/run/run.py +11 -7
  58. flwr/cli/stop.py +2 -2
  59. flwr/cli/supernode/__init__.py +25 -0
  60. flwr/cli/supernode/ls.py +260 -0
  61. flwr/cli/supernode/register.py +185 -0
  62. flwr/cli/supernode/unregister.py +138 -0
  63. flwr/cli/utils.py +109 -69
  64. flwr/client/__init__.py +2 -1
  65. flwr/client/grpc_adapter_client/connection.py +6 -8
  66. flwr/client/grpc_rere_client/connection.py +59 -31
  67. flwr/client/grpc_rere_client/grpc_adapter.py +28 -12
  68. flwr/client/grpc_rere_client/{client_interceptor.py → node_auth_client_interceptor.py} +3 -6
  69. flwr/client/mod/secure_aggregation/secaggplus_mod.py +7 -5
  70. flwr/client/rest_client/connection.py +82 -37
  71. flwr/clientapp/__init__.py +1 -2
  72. flwr/clientapp/mod/__init__.py +4 -1
  73. flwr/clientapp/mod/centraldp_mods.py +156 -40
  74. flwr/clientapp/mod/localdp_mod.py +169 -0
  75. flwr/clientapp/typing.py +22 -0
  76. flwr/{client/clientapp → clientapp}/utils.py +1 -1
  77. flwr/common/constant.py +56 -13
  78. flwr/common/exit/exit_code.py +24 -10
  79. flwr/common/inflatable_utils.py +10 -10
  80. flwr/common/record/array.py +3 -3
  81. flwr/common/record/arrayrecord.py +10 -1
  82. flwr/common/record/typeddict.py +12 -0
  83. flwr/common/secure_aggregation/crypto/symmetric_encryption.py +1 -89
  84. flwr/common/serde.py +4 -2
  85. flwr/common/typing.py +7 -6
  86. flwr/compat/client/app.py +1 -1
  87. flwr/compat/client/grpc_client/connection.py +2 -2
  88. flwr/proto/control_pb2.py +48 -31
  89. flwr/proto/control_pb2.pyi +95 -5
  90. flwr/proto/control_pb2_grpc.py +136 -0
  91. flwr/proto/control_pb2_grpc.pyi +52 -0
  92. flwr/proto/fab_pb2.py +11 -7
  93. flwr/proto/fab_pb2.pyi +21 -1
  94. flwr/proto/fleet_pb2.py +31 -23
  95. flwr/proto/fleet_pb2.pyi +63 -23
  96. flwr/proto/fleet_pb2_grpc.py +98 -28
  97. flwr/proto/fleet_pb2_grpc.pyi +45 -13
  98. flwr/proto/node_pb2.py +3 -1
  99. flwr/proto/node_pb2.pyi +48 -0
  100. flwr/server/app.py +152 -114
  101. flwr/server/superlink/fleet/grpc_adapter/grpc_adapter_servicer.py +17 -7
  102. flwr/server/superlink/fleet/grpc_rere/fleet_servicer.py +132 -38
  103. flwr/server/superlink/fleet/grpc_rere/{server_interceptor.py → node_auth_server_interceptor.py} +27 -51
  104. flwr/server/superlink/fleet/message_handler/message_handler.py +67 -22
  105. flwr/server/superlink/fleet/rest_rere/rest_api.py +52 -31
  106. flwr/server/superlink/fleet/vce/backend/backend.py +1 -1
  107. flwr/server/superlink/fleet/vce/backend/raybackend.py +1 -1
  108. flwr/server/superlink/fleet/vce/vce_api.py +18 -5
  109. flwr/server/superlink/linkstate/in_memory_linkstate.py +167 -73
  110. flwr/server/superlink/linkstate/linkstate.py +107 -24
  111. flwr/server/superlink/linkstate/linkstate_factory.py +2 -1
  112. flwr/server/superlink/linkstate/sqlite_linkstate.py +306 -255
  113. flwr/server/superlink/linkstate/utils.py +3 -54
  114. flwr/server/superlink/serverappio/serverappio_servicer.py +2 -2
  115. flwr/server/superlink/simulation/simulationio_servicer.py +1 -1
  116. flwr/server/utils/validator.py +2 -3
  117. flwr/server/workflow/secure_aggregation/secaggplus_workflow.py +4 -2
  118. flwr/serverapp/strategy/__init__.py +26 -0
  119. flwr/serverapp/strategy/bulyan.py +238 -0
  120. flwr/serverapp/strategy/dp_adaptive_clipping.py +335 -0
  121. flwr/serverapp/strategy/dp_fixed_clipping.py +71 -49
  122. flwr/serverapp/strategy/fedadagrad.py +0 -3
  123. flwr/serverapp/strategy/fedadam.py +0 -3
  124. flwr/serverapp/strategy/fedavg.py +89 -64
  125. flwr/serverapp/strategy/fedavgm.py +198 -0
  126. flwr/serverapp/strategy/fedmedian.py +105 -0
  127. flwr/serverapp/strategy/fedprox.py +174 -0
  128. flwr/serverapp/strategy/fedtrimmedavg.py +176 -0
  129. flwr/serverapp/strategy/fedxgb_bagging.py +117 -0
  130. flwr/serverapp/strategy/fedxgb_cyclic.py +220 -0
  131. flwr/serverapp/strategy/fedyogi.py +0 -3
  132. flwr/serverapp/strategy/krum.py +112 -0
  133. flwr/serverapp/strategy/multikrum.py +247 -0
  134. flwr/serverapp/strategy/qfedavg.py +252 -0
  135. flwr/serverapp/strategy/strategy_utils.py +48 -0
  136. flwr/simulation/app.py +1 -1
  137. flwr/simulation/ray_transport/ray_actor.py +1 -1
  138. flwr/simulation/ray_transport/ray_client_proxy.py +1 -1
  139. flwr/simulation/run_simulation.py +28 -32
  140. flwr/supercore/cli/flower_superexec.py +26 -1
  141. flwr/supercore/constant.py +41 -0
  142. flwr/supercore/object_store/in_memory_object_store.py +0 -4
  143. flwr/supercore/object_store/object_store_factory.py +26 -6
  144. flwr/supercore/object_store/sqlite_object_store.py +252 -0
  145. flwr/{client/clientapp → supercore/primitives}/__init__.py +1 -1
  146. flwr/supercore/primitives/asymmetric.py +117 -0
  147. flwr/supercore/primitives/asymmetric_ed25519.py +165 -0
  148. flwr/supercore/sqlite_mixin.py +156 -0
  149. flwr/supercore/superexec/plugin/exec_plugin.py +11 -1
  150. flwr/supercore/superexec/run_superexec.py +16 -2
  151. flwr/supercore/utils.py +20 -0
  152. flwr/superlink/artifact_provider/__init__.py +22 -0
  153. flwr/superlink/artifact_provider/artifact_provider.py +37 -0
  154. flwr/{common → superlink}/auth_plugin/__init__.py +6 -6
  155. flwr/superlink/auth_plugin/auth_plugin.py +91 -0
  156. flwr/superlink/auth_plugin/noop_auth_plugin.py +87 -0
  157. flwr/superlink/servicer/control/{control_user_auth_interceptor.py → control_account_auth_interceptor.py} +19 -19
  158. flwr/superlink/servicer/control/control_event_log_interceptor.py +1 -1
  159. flwr/superlink/servicer/control/control_grpc.py +16 -11
  160. flwr/superlink/servicer/control/control_servicer.py +207 -58
  161. flwr/supernode/cli/flower_supernode.py +19 -26
  162. flwr/supernode/runtime/run_clientapp.py +2 -2
  163. flwr/supernode/servicer/clientappio/clientappio_servicer.py +1 -1
  164. flwr/supernode/start_client_internal.py +17 -9
  165. {flwr-1.21.0.dist-info → flwr-1.23.0.dist-info}/METADATA +6 -16
  166. {flwr-1.21.0.dist-info → flwr-1.23.0.dist-info}/RECORD +170 -140
  167. flwr/cli/new/templates/app/code/client.pytorch_msg_api.py.tpl +0 -80
  168. flwr/cli/new/templates/app/code/server.pytorch_msg_api.py.tpl +0 -41
  169. flwr/common/auth_plugin/auth_plugin.py +0 -149
  170. flwr/serverapp/dp_fixed_clipping.py +0 -352
  171. flwr/serverapp/strategy/strategy_utils_tests.py +0 -304
  172. /flwr/cli/new/templates/app/code/{__init__.pytorch_msg_api.py.tpl → __init__.pytorch_legacy_api.py.tpl} +0 -0
  173. /flwr/{client → clientapp}/client_app.py +0 -0
  174. {flwr-1.21.0.dist-info → flwr-1.23.0.dist-info}/WHEEL +0 -0
  175. {flwr-1.21.0.dist-info → flwr-1.23.0.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,91 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Abstract classes for Flower account auth plugins."""
16
+
17
+
18
+ from abc import ABC, abstractmethod
19
+ from collections.abc import Sequence
20
+ from pathlib import Path
21
+ from typing import Optional, Union
22
+
23
+ from flwr.common.typing import (
24
+ AccountAuthCredentials,
25
+ AccountAuthLoginDetails,
26
+ AccountInfo,
27
+ )
28
+
29
+
30
+ class ControlAuthnPlugin(ABC):
31
+ """Abstract Flower Authentication Plugin class for ControlServicer.
32
+
33
+ Parameters
34
+ ----------
35
+ account_auth_config_path : Path
36
+ Path to the YAML file containing the authentication configuration.
37
+ verify_tls_cert : bool
38
+ Boolean indicating whether to verify the TLS certificate
39
+ when making requests to the server.
40
+ """
41
+
42
+ @abstractmethod
43
+ def __init__(
44
+ self,
45
+ account_auth_config_path: Path,
46
+ verify_tls_cert: bool,
47
+ ):
48
+ """Abstract constructor."""
49
+
50
+ @abstractmethod
51
+ def get_login_details(self) -> Optional[AccountAuthLoginDetails]:
52
+ """Get the login details."""
53
+
54
+ @abstractmethod
55
+ def validate_tokens_in_metadata(
56
+ self, metadata: Sequence[tuple[str, Union[str, bytes]]]
57
+ ) -> tuple[bool, Optional[AccountInfo]]:
58
+ """Validate authentication tokens in the provided metadata."""
59
+
60
+ @abstractmethod
61
+ def get_auth_tokens(self, device_code: str) -> Optional[AccountAuthCredentials]:
62
+ """Get authentication tokens."""
63
+
64
+ @abstractmethod
65
+ def refresh_tokens(
66
+ self, metadata: Sequence[tuple[str, Union[str, bytes]]]
67
+ ) -> tuple[
68
+ Optional[Sequence[tuple[str, Union[str, bytes]]]], Optional[AccountInfo]
69
+ ]:
70
+ """Refresh authentication tokens in the provided metadata."""
71
+
72
+
73
+ class ControlAuthzPlugin(ABC): # pylint: disable=too-few-public-methods
74
+ """Abstract Flower Authorization Plugin class for ControlServicer.
75
+
76
+ Parameters
77
+ ----------
78
+ account_auth_config_path : Path
79
+ Path to the YAML file containing the authorization configuration.
80
+ verify_tls_cert : bool
81
+ Boolean indicating whether to verify the TLS certificate
82
+ when making requests to the server.
83
+ """
84
+
85
+ @abstractmethod
86
+ def __init__(self, account_auth_config_path: Path, verify_tls_cert: bool):
87
+ """Abstract constructor."""
88
+
89
+ @abstractmethod
90
+ def authorize(self, account_info: AccountInfo) -> bool:
91
+ """Verify account authorization request."""
@@ -0,0 +1,87 @@
1
+ # Copyright 2025 Flower Labs GmbH. All Rights Reserved.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ # ==============================================================================
15
+ """Concrete NoOp implementation for Servicer-side account authentication and
16
+ authorization plugins."""
17
+
18
+
19
+ from collections.abc import Sequence
20
+ from pathlib import Path
21
+ from typing import Optional, Union
22
+
23
+ from flwr.common.constant import NOOP_ACCOUNT_NAME, NOOP_FLWR_AID, AuthnType
24
+ from flwr.common.typing import (
25
+ AccountAuthCredentials,
26
+ AccountAuthLoginDetails,
27
+ AccountInfo,
28
+ )
29
+
30
+ from .auth_plugin import ControlAuthnPlugin, ControlAuthzPlugin
31
+
32
+ NOOP_ACCOUNT_INFO = AccountInfo(
33
+ flwr_aid=NOOP_FLWR_AID,
34
+ account_name=NOOP_ACCOUNT_NAME,
35
+ )
36
+
37
+
38
+ class NoOpControlAuthnPlugin(ControlAuthnPlugin):
39
+ """No-operation implementation of ControlAuthnPlugin."""
40
+
41
+ def __init__(
42
+ self,
43
+ account_auth_config_path: Path,
44
+ verify_tls_cert: bool,
45
+ ):
46
+ pass
47
+
48
+ def get_login_details(self) -> Optional[AccountAuthLoginDetails]:
49
+ """Get the login details."""
50
+ # This allows the `flwr login` command to load the NoOp plugin accordingly,
51
+ # which then raises a LoginError when attempting to login.
52
+ return AccountAuthLoginDetails(
53
+ authn_type=AuthnType.NOOP, # No operation authn type
54
+ device_code="",
55
+ verification_uri_complete="",
56
+ expires_in=0,
57
+ interval=0,
58
+ )
59
+
60
+ def validate_tokens_in_metadata(
61
+ self, metadata: Sequence[tuple[str, Union[str, bytes]]]
62
+ ) -> tuple[bool, Optional[AccountInfo]]:
63
+ """Return valid for no-op plugin."""
64
+ return True, NOOP_ACCOUNT_INFO
65
+
66
+ def get_auth_tokens(self, device_code: str) -> Optional[AccountAuthCredentials]:
67
+ """Get authentication tokens."""
68
+ raise RuntimeError("NoOp plugin does not support getting auth tokens.")
69
+
70
+ def refresh_tokens(
71
+ self, metadata: Sequence[tuple[str, Union[str, bytes]]]
72
+ ) -> tuple[
73
+ Optional[Sequence[tuple[str, Union[str, bytes]]]], Optional[AccountInfo]
74
+ ]:
75
+ """Refresh authentication tokens in the provided metadata."""
76
+ return metadata, NOOP_ACCOUNT_INFO
77
+
78
+
79
+ class NoOpControlAuthzPlugin(ControlAuthzPlugin):
80
+ """No-operation implementation of ControlAuthzPlugin."""
81
+
82
+ def __init__(self, account_auth_config_path: Path, verify_tls_cert: bool):
83
+ pass
84
+
85
+ def authorize(self, account_info: AccountInfo) -> bool:
86
+ """Return True for no-op plugin."""
87
+ return True
@@ -20,7 +20,6 @@ from typing import Any, Callable, Union
20
20
 
21
21
  import grpc
22
22
 
23
- from flwr.common.auth_plugin import ControlAuthPlugin, ControlAuthzPlugin
24
23
  from flwr.common.typing import AccountInfo
25
24
  from flwr.proto.control_pb2 import ( # pylint: disable=E0611
26
25
  GetAuthTokensRequest,
@@ -32,6 +31,7 @@ from flwr.proto.control_pb2 import ( # pylint: disable=E0611
32
31
  StreamLogsRequest,
33
32
  StreamLogsResponse,
34
33
  )
34
+ from flwr.superlink.auth_plugin import ControlAuthnPlugin, ControlAuthzPlugin
35
35
 
36
36
  Request = Union[
37
37
  StartRunRequest,
@@ -50,15 +50,15 @@ shared_account_info: contextvars.ContextVar[AccountInfo] = contextvars.ContextVa
50
50
  )
51
51
 
52
52
 
53
- class ControlUserAuthInterceptor(grpc.ServerInterceptor): # type: ignore
54
- """Control API interceptor for user authentication."""
53
+ class ControlAccountAuthInterceptor(grpc.ServerInterceptor): # type: ignore
54
+ """Control API interceptor for account authentication."""
55
55
 
56
56
  def __init__(
57
57
  self,
58
- auth_plugin: ControlAuthPlugin,
58
+ authn_plugin: ControlAuthnPlugin,
59
59
  authz_plugin: ControlAuthzPlugin,
60
60
  ):
61
- self.auth_plugin = auth_plugin
61
+ self.authn_plugin = authn_plugin
62
62
  self.authz_plugin = authz_plugin
63
63
 
64
64
  def intercept_service(
@@ -96,45 +96,45 @@ class ControlUserAuthInterceptor(grpc.ServerInterceptor): # type: ignore
96
96
  if isinstance(request, (GetLoginDetailsRequest, GetAuthTokensRequest)):
97
97
  return call(request, context) # type: ignore
98
98
 
99
- # For other requests, check if the user is authenticated
100
- valid_tokens, account_info = self.auth_plugin.validate_tokens_in_metadata(
99
+ # For other requests, check if the account is authenticated
100
+ valid_tokens, account_info = self.authn_plugin.validate_tokens_in_metadata(
101
101
  metadata
102
102
  )
103
103
  if valid_tokens:
104
104
  if account_info is None:
105
105
  context.abort(
106
106
  grpc.StatusCode.UNAUTHENTICATED,
107
- "Tokens validated, but user info not found",
107
+ "Tokens validated, but account info not found",
108
108
  )
109
109
  raise grpc.RpcError()
110
- # Store user info in contextvars for authenticated users
110
+ # Store account info in contextvars for authenticated accounts
111
111
  shared_account_info.set(account_info)
112
- # Check if the user is authorized
113
- if not self.authz_plugin.verify_user_authorization(account_info):
112
+ # Check if the account is authorized
113
+ if not self.authz_plugin.authorize(account_info):
114
114
  context.abort(
115
115
  grpc.StatusCode.PERMISSION_DENIED,
116
- "❗️ User not authorized. "
116
+ "❗️ Account not authorized. "
117
117
  "Please contact the SuperLink administrator.",
118
118
  )
119
119
  raise grpc.RpcError()
120
120
  return call(request, context) # type: ignore
121
121
 
122
- # If the user is not authenticated, refresh tokens
123
- tokens, account_info = self.auth_plugin.refresh_tokens(metadata)
122
+ # If the account is not authenticated, refresh tokens
123
+ tokens, account_info = self.authn_plugin.refresh_tokens(metadata)
124
124
  if tokens is not None:
125
125
  if account_info is None:
126
126
  context.abort(
127
127
  grpc.StatusCode.UNAUTHENTICATED,
128
- "Tokens refreshed, but user info not found",
128
+ "Tokens refreshed, but account info not found",
129
129
  )
130
130
  raise grpc.RpcError()
131
- # Store user info in contextvars for authenticated users
131
+ # Store account info in contextvars for authenticated accounts
132
132
  shared_account_info.set(account_info)
133
- # Check if the user is authorized
134
- if not self.authz_plugin.verify_user_authorization(account_info):
133
+ # Check if the account is authorized
134
+ if not self.authz_plugin.authorize(account_info):
135
135
  context.abort(
136
136
  grpc.StatusCode.PERMISSION_DENIED,
137
- "❗️ User not authorized. "
137
+ "❗️ Account not authorized. "
138
138
  "Please contact the SuperLink administrator.",
139
139
  )
140
140
  raise grpc.RpcError()
@@ -24,7 +24,7 @@ from google.protobuf.message import Message as GrpcMessage
24
24
  from flwr.common.event_log_plugin.event_log_plugin import EventLogWriterPlugin
25
25
  from flwr.common.typing import LogEntry
26
26
 
27
- from .control_user_auth_interceptor import shared_account_info
27
+ from .control_account_auth_interceptor import shared_account_info
28
28
 
29
29
 
30
30
  class ControlEventLogInterceptor(grpc.ServerInterceptor): # type: ignore
@@ -21,7 +21,6 @@ from typing import Optional
21
21
  import grpc
22
22
 
23
23
  from flwr.common import GRPC_MAX_MESSAGE_LENGTH
24
- from flwr.common.auth_plugin import ControlAuthPlugin, ControlAuthzPlugin
25
24
  from flwr.common.event_log_plugin import EventLogWriterPlugin
26
25
  from flwr.common.exit import ExitCode, flwr_exit
27
26
  from flwr.common.grpc import generic_create_grpc_server
@@ -31,11 +30,17 @@ from flwr.server.superlink.linkstate import LinkStateFactory
31
30
  from flwr.supercore.ffs import FfsFactory
32
31
  from flwr.supercore.license_plugin import LicensePlugin
33
32
  from flwr.supercore.object_store import ObjectStoreFactory
33
+ from flwr.superlink.artifact_provider import ArtifactProvider
34
+ from flwr.superlink.auth_plugin import (
35
+ ControlAuthnPlugin,
36
+ ControlAuthzPlugin,
37
+ NoOpControlAuthnPlugin,
38
+ )
34
39
 
40
+ from .control_account_auth_interceptor import ControlAccountAuthInterceptor
35
41
  from .control_event_log_interceptor import ControlEventLogInterceptor
36
42
  from .control_license_interceptor import ControlLicenseInterceptor
37
43
  from .control_servicer import ControlServicer
38
- from .control_user_auth_interceptor import ControlUserAuthInterceptor
39
44
 
40
45
  try:
41
46
  from flwr.ee import get_license_plugin
@@ -53,9 +58,10 @@ def run_control_api_grpc(
53
58
  objectstore_factory: ObjectStoreFactory,
54
59
  certificates: Optional[tuple[bytes, bytes, bytes]],
55
60
  is_simulation: bool,
56
- auth_plugin: Optional[ControlAuthPlugin] = None,
57
- authz_plugin: Optional[ControlAuthzPlugin] = None,
61
+ authn_plugin: ControlAuthnPlugin,
62
+ authz_plugin: ControlAuthzPlugin,
58
63
  event_log_plugin: Optional[EventLogWriterPlugin] = None,
64
+ artifact_provider: Optional[ArtifactProvider] = None,
59
65
  ) -> grpc.Server:
60
66
  """Run Control API (gRPC, request-response)."""
61
67
  license_plugin: Optional[LicensePlugin] = get_license_plugin()
@@ -67,14 +73,13 @@ def run_control_api_grpc(
67
73
  ffs_factory=ffs_factory,
68
74
  objectstore_factory=objectstore_factory,
69
75
  is_simulation=is_simulation,
70
- auth_plugin=auth_plugin,
76
+ authn_plugin=authn_plugin,
77
+ artifact_provider=artifact_provider,
71
78
  )
72
- interceptors: list[grpc.ServerInterceptor] = []
79
+ interceptors = [ControlAccountAuthInterceptor(authn_plugin, authz_plugin)]
73
80
  if license_plugin is not None:
74
81
  interceptors.append(ControlLicenseInterceptor(license_plugin))
75
- if auth_plugin is not None and authz_plugin is not None:
76
- interceptors.append(ControlUserAuthInterceptor(auth_plugin, authz_plugin))
77
- # Event log interceptor must be added after user auth interceptor
82
+ # Event log interceptor must be added after account auth interceptor
78
83
  if event_log_plugin is not None:
79
84
  interceptors.append(ControlEventLogInterceptor(event_log_plugin))
80
85
  log(INFO, "Flower event logging enabled")
@@ -87,12 +92,12 @@ def run_control_api_grpc(
87
92
  interceptors=interceptors or None,
88
93
  )
89
94
 
90
- if auth_plugin is None:
95
+ if isinstance(authn_plugin, NoOpControlAuthnPlugin):
91
96
  log(INFO, "Flower Deployment Runtime: Starting Control API on %s", address)
92
97
  else:
93
98
  log(
94
99
  INFO,
95
- "Flower Deployment Runtime: Starting Control API with user "
100
+ "Flower Deployment Runtime: Starting Control API with account "
96
101
  "authentication on %s",
97
102
  address,
98
103
  )