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(framework) Add Keycloak user auth CLI integration #4602

Open
wants to merge 42 commits into
base: main
Choose a base branch
from

Conversation

danielnugraha
Copy link
Contributor

Issue

Description

We need user authentication logic when user wants to run via flwr run.

Related issues/PRs

Proposal

Explanation

Add flwr login command logic and user authentication logic in flwr run.

Checklist

  • Implement proposed change
  • Write tests
  • Update documentation
  • Make CI checks pass
  • Ping maintainers on Slack (channel #contributions)

Any other comments?

@danielnugraha danielnugraha changed the title feat(framework) Add Keycloak CLI user auth integration feat(framework) Add Keycloak user auth CLI integration Nov 28, 2024
src/py/flwr/cli/login/login.py Outdated Show resolved Hide resolved
src/py/flwr/cli/login/login.py Show resolved Hide resolved
src/py/flwr/common/auth_plugin/auth_plugin.py Outdated Show resolved Hide resolved
src/py/flwr/cli/run/run.py Show resolved Hide resolved
src/py/flwr/common/auth_plugin/keycloak_plugin.py Outdated Show resolved Hide resolved
src/py/flwr/common/auth_plugin/keycloak_plugin.py Outdated Show resolved Hide resolved
src/py/flwr/common/auth_plugin/keycloak_plugin.py Outdated Show resolved Hide resolved
src/py/flwr/common/auth_plugin/keycloak_plugin.py Outdated Show resolved Hide resolved
)

base_path = get_flwr_dir()
credentials_dir = base_path / ".credentials"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you make this .credentials as a constant? Like the APP_DIR in flwr.common.constant.

Comment on lines +37 to +42
try:
from flwr.ee.auth_plugin import get_cli_auth_plugins

auth_plugins = get_cli_auth_plugins()
except ImportError:
auth_plugins = []
Copy link
Contributor

@panh99 panh99 Dec 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we may use the trick as in simulation sub-package.

Suggested change
try:
from flwr.ee.auth_plugin import get_cli_auth_plugins
auth_plugins = get_cli_auth_plugins()
except ImportError:
auth_plugins = []
try:
from flwr.ee.auth_plugin import get_cli_auth_plugins
except ImportError:
AUTH_PLUGIN_IMPORT_ERROR: str = """Unable to import module `flwr.ee.auth_plugin`.
This is a feature available only in the enterprise extension.
"""
def get_cli_auth_plugins() -> dict[str, type[CliAuthPlugin]]:
raise ImportError(AUTH_PLUGIN_IMPORT_ERROR)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

May I suggest:

- This is a feature available only in the enterprise extension.
+ This feature is only available in the Flower Enterprise extension. Please visit https://flower.ai to learn more.

stub = _create_exec_stub(app, federation_config)
login_request = LoginRequest()
login_response: LoginResponse = stub.Login(login_request)
auth_plugin = auth_plugins[login_response.login_details.get("auth_type", "")]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
auth_plugin = auth_plugins[login_response.login_details.get("auth_type", "")]
auth_plugin = get_cli_auth_plugins()[login_response.login_details["auth_type"]]

typer.Argument(help="Name of the federation to login into."),
] = None,
) -> None:
"""Login to Flower SuperExec."""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"""Login to Flower SuperExec."""
"""Login to Flower SuperLink."""

Comment on lines +73 to +75
f"❌ The federation `{federation}` does not have `SuperExec` "
"address in its config.\n Please specify the address in "
"`pyproject.toml` and try again.",
Copy link
Contributor

@chongshenng chongshenng Dec 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
f"❌ The federation `{federation}` does not have `SuperExec` "
"address in its config.\n Please specify the address in "
"`pyproject.toml` and try again.",
"❌ `flwr login` currently works with Exec API. Ensure that the correct"
"Exec API address is provided in the `pyproject.toml`.",

This is to make it consistent with flwr ls and flwr log.

Comment on lines +92 to +97
server_address = federation_config["address"]
parsed_address = parse_address(server_address)
if not parsed_address:
sys.exit(f"Server IP address ({server_address}) cannot be parsed.")
host, port, is_v6 = parsed_address
address = f"[{host}]/{port}" if is_v6 else f"{host}/{port}"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you reuse the functionality here?

Copy link
Contributor

@chongshenng chongshenng left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reviewed only login.py so far. @danielnugraha, should I continue to review the remaining parts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants