Skip to content

Commit

Permalink
[Bug: 768] FX CLI: Separate create, cert gen commands (securefederate…
Browse files Browse the repository at this point in the history
…dai#807)

This change separates existing command
"fx collaborator.py generate-cert-request" command into two
commands.
"fx collaborator create -n {NAME} -d {DATA_PATH: optional}".
"fx collaborator generate-cert-request -n {NAME}".

Fixes securefederatedai#768

Signed-off-by: Emmanuel Jillela <emmanuel.jillela@intel.com>
Co-authored-by: Emmanuel Jillela <emmanuel.jillela@intel.com>
Signed-off-by: Patrick Foley <psfoley@gmail.com>
  • Loading branch information
2 people authored and psfoley committed Jun 29, 2023
1 parent 43fe913 commit c697005
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 21 deletions.
1 change: 1 addition & 0 deletions docs/running_the_federation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1047,6 +1047,7 @@ Importing the Workspace

.. code-block:: console
fx collaborator create -n {COL_LABEL} -d {DATA_PATH:optional}
fx collaborator generate-cert-request -n {COL_LABEL}
Expand Down
39 changes: 25 additions & 14 deletions openfl/interface/collaborator.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,24 @@ def start_(plan, collaborator_name, data_config, secure):
plan.get_collaborator(collaborator_name).run()


@collaborator.command(name='create')
@option('-n', '--collaborator_name', required=True,
help='The certified common name of the collaborator')
@option('-d', '--data_path',
help='The data path to be associated with the collaborator')
@option('-s', '--silent', help='Do not prompt', is_flag=True)
def create_(collaborator_name, data_path, silent):
"""Creates a user for an experiment."""
if data_path and is_directory_traversal(data_path):
echo('Data path is out of the openfl workspace scope.')
sys.exit(1)

common_name = f'{collaborator_name}'.lower()

# TODO: There should be some association with the plan made here as well
register_data_path(common_name, data_path=data_path, silent=silent)


def register_data_path(collaborator_name, data_path=None, silent=False):
"""Register dataset path in the plan/data.yaml file.
Expand Down Expand Up @@ -103,30 +121,26 @@ def register_data_path(collaborator_name, data_path=None, silent=False):
d[collaborator_name] = dir_path

# Write the data.yaml
with open(data_yaml, 'w', encoding='utf-8') as f:
for key, val in d.items():
f.write(f'{key}{separator}{val}\n')
if isfile(data_yaml):
with open(data_yaml, 'w', encoding='utf-8') as f:
for key, val in d.items():
f.write(f'{key}{separator}{val}\n')


@collaborator.command(name='generate-cert-request')
@option('-n', '--collaborator_name', required=True,
help='The certified common name of the collaborator')
@option('-d', '--data_path',
help='The data path to be associated with the collaborator')
@option('-s', '--silent', help='Do not prompt', is_flag=True)
@option('-x', '--skip-package',
help='Do not package the certificate signing request for export',
is_flag=True)
def generate_cert_request_(collaborator_name,
data_path, silent, skip_package):
silent, skip_package):
"""Generate certificate request for the collaborator."""
if data_path and is_directory_traversal(data_path):
echo('Data path is out of the openfl workspace scope.')
sys.exit(1)
generate_cert_request(collaborator_name, data_path, silent, skip_package)
generate_cert_request(collaborator_name, silent, skip_package)


def generate_cert_request(collaborator_name, data_path, silent, skip_package):
def generate_cert_request(collaborator_name, silent, skip_package):
"""
Create collaborator certificate key pair.
Expand Down Expand Up @@ -197,9 +211,6 @@ def generate_cert_request(collaborator_name, data_path, silent, skip_package):
echo('This file should be sent to the certificate authority'
' (typically hosted by the aggregator) for signing')

# TODO: There should be some association with the plan made here as well
register_data_path(common_name, data_path=data_path, silent=silent)


def find_certificate_name(file_name):
"""Parse the collaborator name."""
Expand Down
8 changes: 5 additions & 3 deletions openfl/native/native.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,8 @@ def init(workspace_template: str = 'default', log_level: str = 'INFO',
aggregator.certify(agg_fqdn, silent=True)
data_path = 1
for col_name in col_names:
collaborator.create(
col_name, str(data_path), silent=True)
collaborator.generate_cert_request(
col_name, str(data_path), silent=True, skip_package=True)
collaborator.certify(col_name, silent=True)
Expand All @@ -208,7 +210,7 @@ def init(workspace_template: str = 'default', log_level: str = 'INFO',
setup_logging(level=log_level, log_file=log_file)


def create_collaborator(plan, name, model, aggregator):
def get_collaborator(plan, name, model, aggregator):
"""
Create the collaborator.
Expand Down Expand Up @@ -282,9 +284,9 @@ def run_experiment(collaborator_dict: dict, override_config: dict = None):

aggregator = plan.get_aggregator()

# Create the collaborators
# get the collaborators
collaborators = {
collaborator: create_collaborator(
collaborator: get_collaborator(
plan, collaborator, collaborator_dict[collaborator], aggregator
) for collaborator in plan.authorized_cols
}
Expand Down
7 changes: 6 additions & 1 deletion tests/github/pki_wrong_cn.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,14 @@ def prepare_workspace():
])
for col in ['one', 'two']:
subprocess.check_call([
'fx', 'collaborator', 'generate-cert-request',
'fx', 'collaborator', 'create',
'-n', col,
'-d', '1',
'-s'
])
subprocess.check_call([
'fx', 'collaborator', 'generate-cert-request',
'-n', col,
'-s', '-x'
])
subprocess.check_call([
Expand Down
3 changes: 2 additions & 1 deletion tests/github/test_graminize.sh
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ create_collaborator() {

# Create collaborator certificate request
cd ${COL_DIRECTORY}/${FED_WORKSPACE}
fx collaborator generate-cert-request -d ${DATA_PATH} -n ${COL} --silent # Remove '--silent' if you run this manually
fx collaborator create -d ${DATA_PATH} -n ${COL} --silent # Remove '--silent' if you run this manually
fx collaborator generate-cert-request -n ${COL} --silent # Remove '--silent' if you run this manually

# Sign collaborator certificate
cd ${FED_DIRECTORY} # Move back to the Aggregator
Expand Down
11 changes: 9 additions & 2 deletions tests/github/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,13 @@ def create_collaborator(col, workspace_root, data_path, archive_name, fed_worksp
)

# Create collaborator certificate request
check_call(
['fx', 'collaborator', 'create', '-d', data_path, '-n', col, '--silent'],
cwd=col_path / fed_workspace
)
# Remove '--silent' if you run this manually
check_call(
['fx', 'collaborator', 'generate-cert-request', '-d', data_path, '-n', col, '--silent'],
['fx', 'collaborator', 'generate-cert-request', '-n', col, '--silent'],
cwd=col_path / fed_workspace
)

Expand Down Expand Up @@ -84,7 +88,10 @@ def create_signed_cert_for_collaborator(col, data_path):
print(f'Certifying collaborator {col} with data path {data_path}...')
# Create collaborator certificate request
check_call([
'fx', 'collaborator', 'generate-cert-request', '-d', data_path, '-n', col, '--silent'
'fx', 'collaborator', 'create', '-d', data_path, '-n', col, '--silent'
])
check_call([
'fx', 'collaborator', 'generate-cert-request', '-n', col, '--silent'
])
# Sign collaborator certificate
check_call([
Expand Down

0 comments on commit c697005

Please sign in to comment.