From bf0576dca14843c890a9fed62844eeb1e5af8992 Mon Sep 17 00:00:00 2001 From: Mansi Sharma Date: Mon, 2 Jan 2023 10:36:04 -0800 Subject: [PATCH] update cert dir Signed-off-by: Mansi Sharma --- docs/running_the_federation.rst | 69 +++++++++++++++++++++++--- openfl/interface/aggregator.py | 28 +++++++++-- openfl/interface/collaborator.py | 31 ++++++++++-- openfl/interface/workspace.py | 20 +++++++- tests/github/test_pki_cert_location.sh | 37 ++++++++++---- 5 files changed, 160 insertions(+), 25 deletions(-) diff --git a/docs/running_the_federation.rst b/docs/running_the_federation.rst index d507126fc0d..cb406414822 100644 --- a/docs/running_the_federation.rst +++ b/docs/running_the_federation.rst @@ -952,12 +952,26 @@ Setting Up the Certificate Authority fx workspace certify + By default, all certificates are stored under :code:`WORKSPACE_PATH/cert` folder inside workspace. To store certificates elsewhere: + + .. code-block:: console + + fx workspace certify -c CERT_PATH + + where :code:`CERT_PATH` is the path where the certificates will be stored for this node. + 3. Run the aggregator certificate creation command, replacing :code:`AFQDN` with the actual `fully qualified domain name (FQDN) `_ for the aggregator node. .. code-block:: console fx aggregator generate-cert-request --fqdn AFQDN + To store certificates under :code:`CERT_PATH`: + + .. code-block:: console + + fx aggregator generate-cert-request --fqdn AFQDN -c CERT_PATH + .. note:: On Linux\*\, you can discover the FQDN with this command: @@ -986,6 +1000,11 @@ Setting Up the Certificate Authority fx aggregator certify --fqdn AFQDN + If :code:`CERT_PATH` was used to store CA signing certificates, specify the same path here: + + .. code-block:: console + + fx aggregator certify --fqdn AFQDN -c CERT_PATH .. note:: @@ -1000,14 +1019,14 @@ Setting Up the Certificate Authority +---------------------------+--------------------------------------------------+ | File Type | Filename | +===========================+==================================================+ - | Certificate chain | WORKSPACE.PATH/cert/cert_chain.crt | + | Certificate chain | CERT.PATH/cert/cert_chain.crt | +---------------------------+--------------------------------------------------+ - | Aggregator certificate | WORKSPACE.PATH/cert/server/agg_{AFQDN}.crt | + | Aggregator certificate | CERT.PATH/cert/server/agg_{AFQDN}.crt | +---------------------------+--------------------------------------------------+ - | Aggregator key | WORKSPACE.PATH/cert/server/agg_{AFQDN}.key | + | Aggregator key | CERT.PATH/cert/server/agg_{AFQDN}.key | +---------------------------+--------------------------------------------------+ - where **AFQDN** is the fully-qualified domain name of the aggregator node. + where **CERT.PATH** is :code:`WORKSPACE.PATH` by default or the path specified by the user and **AFQDN** is the fully-qualified domain name of the aggregator node. .. _workspace_export: @@ -1049,6 +1068,13 @@ Importing the Workspace fx collaborator generate-cert-request -n {COL_LABEL} + To store certs under :code:`CERT_PATH_COL/cert` other than :code:`WORKSPACE_PATH/cert`: + + .. code-block:: console + + fx collaborator generate-cert-request -n {COL_LABEL} -c {CERT_PATH_COL} + + where **CERT_PATH_COL** is the path where collaborator certificates (client) will be stored. The creation script will also ask you to specify the path to the data. For this example, enter the integer that represents which MNIST shard to use on this collaborator node. For the first collaborator node enter **1**. For the second collaborator node enter **2**. @@ -1057,13 +1083,14 @@ Importing the Workspace +-----------------------------+--------------------------------------------------------+ | File Type | Filename | +=============================+========================================================+ - | Collaborator CSR | WORKSPACE.PATH/cert/client/col_{COL_LABEL}.csr | + | Collaborator CSR | CERT.PATH.COL/cert/client/col_{COL_LABEL}.csr | +-----------------------------+--------------------------------------------------------+ - | Collaborator key | WORKSPACE.PATH/cert/client/col_{COL_LABEL}.key | + | Collaborator key | CERT.PATH.COL/cert/client/col_{COL_LABEL}.key | +-----------------------------+--------------------------------------------------------+ | Collaborator CSR Package | WORKSPACE.PATH/col_{COL_LABEL}_to_agg_cert_request.zip | +-----------------------------+--------------------------------------------------------+ + where **CERT.PATH.COL** is :code:`WORKSPACE.PATH` by default or the path specified by the user. 4. On the aggregator node (i.e., the certificate authority in this example), sign the Collaborator CSR Package from the collaborator nodes. @@ -1073,6 +1100,12 @@ Importing the Workspace where :code:`/PATH/TO/col_{COL_LABEL}_to_agg_cert_request.zip` is the path to the Collaborator CSR Package containing the :code:`.csr` file from the collaborator node. The certificate authority will sign this certificate for use in the federation. + If :code:`CERT_PATH` was used at the aggregator node to store CA signing certificates, specify the same path here: + + .. code-block:: console + + fx collaborator certify --request-pkg /PATH/TO/col_{COL_LABEL}_to_agg_cert_request.zip -c CERT_PATH + The command packages the signed collaborator certificate, along with the **cert_chain.crt** file needed to verify certificate signatures, for transport back to the collaborator node: +---------------------------------+------------------------------------------------------------+ @@ -1087,6 +1120,11 @@ Importing the Workspace fx collaborator certify --import /PATH/TO/agg_to_col_{COL_LABEL}_signed_cert.zip + If :code:`CERT_PATH_COL` was used to store collaborator certificates for this node, specify the collaborator certificate path here: + + .. code-block:: console + + fx collaborator certify --import /PATH/TO/agg_to_col_{COL_LABEL}_signed_cert.zip -c CERT_PATH_COL .. _running_the_federation.start_nodes: @@ -1103,6 +1141,12 @@ STEP 3: Start the Federation fx aggregator start + If :code:`CERT_PATH` was used to store certificates for this node, specify the same path here: + + .. code-block:: console + + fx aggregator start -c ${CERT_PATH} + Now, the Aggregator is running and waiting for Collaborators to connect. .. _running_collaborators: @@ -1119,6 +1163,12 @@ STEP 3: Start the Federation where :code:`COLLABORATOR_LABEL` is the label for this Collaborator. + If :code:`CERT_PATH_COL` was used to store certificates for this node, specify the same path here: + + .. code-block:: console + + fx collaborator start -n {COLLABORATOR_LABEL} -c ${CERT_PATH_COL} + .. note:: Each workspace may have multiple FL plans and multiple collaborator lists associated with it. @@ -1160,6 +1210,13 @@ Another way to access the trained model is by calling the API command directly f In fact, the :code:`get_model()` method returns a **TaskRunner** object loaded with the chosen model snapshot. Users may utilize the linked model as a regular Python object. +If :code:`CERT_PATH` was used to store certificates for any node, uninstall them: + +.. code-block:: console + + fx workspace uninstall-cert -c ${CERT_PATH} + fx aggregator uninstall-cert -c ${CERT_PATH} + fx collaborator uninstall-cert -c ${CERT_PATH_COL} .. _running_the_federation_docker: diff --git a/openfl/interface/aggregator.py b/openfl/interface/aggregator.py index 4dc2c78c7fc..b22bb61d3f3 100644 --- a/openfl/interface/aggregator.py +++ b/openfl/interface/aggregator.py @@ -61,7 +61,9 @@ def start_(plan, authorized_cols, secure, cert_path, fqdn): logger.info('🧿 Starting the Aggregator Service.') if cert_path: - CERT_DIR = Path(cert_path).absolute() + CERT_PATH = Path(cert_path).absolute() + (CERT_PATH / 'cert').mkdir(parents=True, exist_ok=True) + CERT_DIR = CERT_PATH / 'cert' if not Path(CERT_DIR).exists(): echo(style('Certificate Path not found.', fg='red') + ' Please run `fx aggregator generate-cert-request --cert_path`' @@ -109,7 +111,9 @@ def generate_cert_request(fqdn, cert_path=None): server_private_key, server_csr = generate_csr(common_name, server=True) if cert_path: - CERT_DIR = Path(cert_path).absolute() # NOQA + CERT_PATH = Path(cert_path).absolute() + (CERT_PATH / 'cert').mkdir(parents=True, exist_ok=True) + CERT_DIR = CERT_PATH/ 'cert' # NOQA (CERT_DIR / 'server').mkdir(parents=True, exist_ok=True) echo(' Writing AGGREGATOR certificate key pair to: ' + style( @@ -167,7 +171,9 @@ def certify(fqdn, silent, cert_path=None): # Load CSR if cert_path: - CERT_DIR = Path(cert_path).absolute() # NOQA + CERT_PATH = Path(cert_path).absolute() + (CERT_PATH / 'cert').mkdir(parents=True, exist_ok=True) + CERT_DIR = CERT_PATH/ 'cert' # NOQA csr_path_absolute_path = Path(CERT_DIR / f'{cert_name}.csr').absolute() if not csr_path_absolute_path.exists(): @@ -220,3 +226,19 @@ def certify(fqdn, silent, cert_path=None): echo(style('Not signing certificate.', fg='red') + ' Please check with this AGGREGATOR to get the correct' ' certificate for this federation.') + + +@aggregator.command(name='uninstall-cert') +@option('-c', '--cert_path', + help='The cert path where pki certs reside', required=True) +def _uninstall_cert(cert_path): + uninstall_cert(cert_path) + + +def uninstall_cert(cert_path=None): + """Uninstall certs under a given directory.""" + import shutil + from pathlib import Path + + cert_path = Path(cert_path).absolute() + shutil.rmtree(cert_path, ignore_errors=True) diff --git a/openfl/interface/collaborator.py b/openfl/interface/collaborator.py index 792d1521421..1d2b42bd510 100644 --- a/openfl/interface/collaborator.py +++ b/openfl/interface/collaborator.py @@ -61,7 +61,9 @@ def start_(plan, collaborator_name, data_config, secure, cert_path): logger.info('🧿 Starting a Collaborator Service.') if cert_path: - CERT_DIR = Path(cert_path).absolute() + CERT_PATH = Path(cert_path).absolute() + (CERT_PATH / 'cert').mkdir(parents=True, exist_ok=True) + CERT_DIR = CERT_PATH / 'cert' if not Path(CERT_DIR).exists(): echo(style('Certificate Path not found.', fg='red') + ' Please run `fx collaborator generate-cert-request --cert_path`' @@ -165,11 +167,14 @@ def generate_cert_request(collaborator_name, data_path, silent, skip_package, ce client_private_key, client_csr = generate_csr(common_name, server=False) if cert_path: - CERT_DIR = Path(cert_path).absolute() # NOQA + CERT_PATH = Path(cert_path).absolute() + (CERT_PATH / 'cert').mkdir(parents=True, exist_ok=True) + CERT_DIR = CERT_PATH/ 'cert' # NOQA + (CERT_DIR / 'client').mkdir(parents=True, exist_ok=True) echo(' Moving COLLABORATOR certificate to: ' + style( - f'{CERT_DIR}/{file_name}', fg='green')) + f'{CERT_DIR}', fg='green')) # Write collaborator csr and key to disk write_crt(client_csr, CERT_DIR / 'client' / f'{file_name}.csr') @@ -307,7 +312,9 @@ def certify(collaborator_name, silent, request_pkg=None, import_=False, cert_pat common_name = f'{collaborator_name}'.lower() if cert_path: - CERT_DIR = Path(cert_path).absolute() # NOQA + CERT_PATH = Path(cert_path).absolute() + (CERT_PATH / 'cert').mkdir(parents=True, exist_ok=True) + CERT_DIR = CERT_PATH/ 'cert' # NOQA if not import_: if request_pkg: @@ -414,3 +421,19 @@ def certify(collaborator_name, silent, request_pkg=None, import_=False, cert_pat echo(f'Certificate {crt} installed to PKI directory') else: echo('Certificate updated in the PKI directory') + + +@collaborator.command(name='uninstall-cert') +@option('-c', '--cert_path', + help='The cert path where pki certs reside', required=True) +def _uninstall_cert(cert_path): + uninstall_cert(cert_path) + + +def uninstall_cert(cert_path=None): + """Uninstall certs under a given directory.""" + import shutil + from pathlib import Path + + cert_path = Path(cert_path).absolute() + shutil.rmtree(cert_path, ignore_errors=True) diff --git a/openfl/interface/workspace.py b/openfl/interface/workspace.py index 41ec553ceaa..81e95b1da6a 100644 --- a/openfl/interface/workspace.py +++ b/openfl/interface/workspace.py @@ -235,7 +235,9 @@ def certify(cert_path=None): echo('1.1 Create Directories') if cert_path: - CERT_DIR = Path(cert_path).absolute() # NOQA + CERT_PATH = Path(cert_path).absolute() + (CERT_PATH / 'cert').mkdir(parents=True, exist_ok=True) + CERT_DIR = CERT_PATH/ 'cert' # NOQA (CERT_DIR / 'ca/root-ca/private').mkdir( parents=True, exist_ok=True, mode=0o700) @@ -531,6 +533,22 @@ def open_pipe(command: str): echo(f'\n ✔️ The image saved to file: {workspace_name}.tar.gz') +@workspace.command(name='uninstall-cert') +@option('-c', '--cert_path', + help='The cert path where pki certs reside', required=True) +def _uninstall_cert(cert_path): + uninstall_cert(cert_path) + + +def uninstall_cert(cert_path=None): + """Uninstall certs under a given directory.""" + import shutil + from pathlib import Path + + cert_path = Path(cert_path).absolute() + shutil.rmtree(cert_path, ignore_errors=True) + + def apply_template_plan(prefix, template): """Copy plan file from template folder. diff --git a/tests/github/test_pki_cert_location.sh b/tests/github/test_pki_cert_location.sh index e5c8ed45c86..1161834e9d3 100755 --- a/tests/github/test_pki_cert_location.sh +++ b/tests/github/test_pki_cert_location.sh @@ -7,7 +7,10 @@ COL1=${3:-'one123dragons'} # This can be any unique label (lowercase) COL2=${4:-'beta34unicorns'} # This can be any unique label (lowercase) FQDN=${5:-$(hostname --all-fqdns | awk '{print $1}')} -CERT_PATH=${6:-"${HOME}/.openfl"} + +CERT_PATH_AG=${6:-"${HOME}/.openfl/aggregator"} +CERT_PATH_COL1=${7:-"${HOME}/.openfl/one123dragons"} +CERT_PATH_COL2=${8:-"${HOME}/.openfl/beta34unicorns"} COL1_DATA_PATH=1 COL2_DATA_PATH=2 @@ -49,6 +52,8 @@ create_collaborator() { COL=$3 COL_DIRECTORY=$4 DATA_PATH=$5 + CERT_PATH_COL=$6 + CERT_PATH=$7 ARCHIVE_NAME="${FED_WORKSPACE}.zip" @@ -60,7 +65,7 @@ create_collaborator() { # Create collaborator certificate request cd ${COL_DIRECTORY}/${FED_WORKSPACE} - fx collaborator generate-cert-request -d ${DATA_PATH} -n ${COL} -c ${CERT_PATH} --silent # Remove '--silent' if you run this manually + fx collaborator generate-cert-request -d ${DATA_PATH} -n ${COL} -c ${CERT_PATH_COL} --silent # Remove '--silent' if you run this manually # Sign collaborator certificate cd ${FED_DIRECTORY} # Move back to the Aggregator @@ -68,7 +73,7 @@ create_collaborator() { #Import the signed certificate from the aggregator cd ${COL_DIRECTORY}/${FED_WORKSPACE} - fx collaborator certify --import ${FED_DIRECTORY}/agg_to_col_${COL}_signed_cert.zip -c ${CERT_PATH} + fx collaborator certify --import ${FED_DIRECTORY}/agg_to_col_${COL}_signed_cert.zip -c ${CERT_PATH_COL} } @@ -92,33 +97,33 @@ then fi # Create certificate authority for workspace -fx workspace certify -c ${CERT_PATH} +fx workspace certify -c ${CERT_PATH_AG} # Export FL workspace fx workspace export # Create aggregator certificate -fx aggregator generate-cert-request --fqdn ${FQDN} -c ${CERT_PATH} +fx aggregator generate-cert-request --fqdn ${FQDN} -c ${CERT_PATH_AG} # Sign aggregator certificate -fx aggregator certify --fqdn ${FQDN} -c ${CERT_PATH} --silent # Remove '--silent' if you run this manually +fx aggregator certify --fqdn ${FQDN} -c ${CERT_PATH_AG} --silent # Remove '--silent' if you run this manually # Create collaborator #1 COL1_DIRECTORY=${FED_DIRECTORY}/${COL1} -create_collaborator ${FED_WORKSPACE} ${FED_DIRECTORY} ${COL1} ${COL1_DIRECTORY} ${COL1_DATA_PATH} +create_collaborator ${FED_WORKSPACE} ${FED_DIRECTORY} ${COL1} ${COL1_DIRECTORY} ${COL1_DATA_PATH} ${CERT_PATH_COL1} ${CERT_PATH_AG} # Create collaborator #2 COL2_DIRECTORY=${FED_DIRECTORY}/${COL2} -create_collaborator ${FED_WORKSPACE} ${FED_DIRECTORY} ${COL2} ${COL2_DIRECTORY} ${COL2_DATA_PATH} +create_collaborator ${FED_WORKSPACE} ${FED_DIRECTORY} ${COL2} ${COL2_DIRECTORY} ${COL2_DATA_PATH} ${CERT_PATH_COL2} ${CERT_PATH_AG} # # Run the federation cd ${FED_DIRECTORY} -fx aggregator start -c ${CERT_PATH} --fqdn ${FQDN} & +fx aggregator start -c ${CERT_PATH_AG} --fqdn ${FQDN} & sleep 5 cd ${COL1_DIRECTORY}/${FED_WORKSPACE} -fx collaborator start -n ${COL1} -c ${CERT_PATH} & +fx collaborator start -n ${COL1} -c ${CERT_PATH_COL1} & cd ${COL2_DIRECTORY}/${FED_WORKSPACE} -fx collaborator start -n ${COL2} -c ${CERT_PATH} +fx collaborator start -n ${COL2} -c ${CERT_PATH_COL2} wait # # Convert model to native format @@ -128,4 +133,14 @@ then fx model save -i "./save/${TEMPLATE}_last.pbuf" -o ${SAVE_MODEL} fi +# Clear cert directories + +cd ${FED_DIRECTORY} +fx aggregator uninstall-cert -c ${CERT_PATH_AG} +cd ${COL1_DIRECTORY}/${FED_WORKSPACE} +fx collaborator uninstall-cert -c ${CERT_PATH_COL1} +cd ${COL2_DIRECTORY}/${FED_WORKSPACE} +fx collaborator uninstall-cert -c ${CERT_PATH_COL2} + rm -rf ${FED_DIRECTORY} +