Skip to content

Commit

Permalink
parameterize cert and key locations
Browse files Browse the repository at this point in the history
  • Loading branch information
mansishr committed Jan 12, 2023
1 parent c519c91 commit 47c8632
Show file tree
Hide file tree
Showing 7 changed files with 535 additions and 263 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/pki-certs-location.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Test PKI certs location

on:
push:
branches: [ develop ]
pull_request:
branches: [ develop ]

permissions:
contents: read

jobs:
build:
strategy:
matrix:
os: ['ubuntu-latest', 'windows-latest']
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v3
- name: Set up Python 3.8
uses: actions/setup-python@v3
with:
python-version: "3.8"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .
- name: Test PKI certs location
run: |
python -m tests.github.test_pki_cert_location --agg-cert-path ~/.openfl/agg --agg-key-path ~/.openfl/agg --col1-cert-path ~/.openfl/col1/ --col1-key-path ~/.openfl/col1 --col2-cert-path ~/.openfl/col2 --col2-key-path ~/.openfl/col2/
16 changes: 0 additions & 16 deletions .github/workflows/pki.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,4 @@ jobs:
- name: Test PKI
run: |
python tests/github/pki_wrong_cn.py
test_pki_cert_location:

runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Python 3.8
uses: actions/setup-python@v3
with:
python-version: "3.8"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install .
- name: Test PKI
run: |
python tests/github/test_pki_cert_location.py
219 changes: 145 additions & 74 deletions openfl/interface/aggregator.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ def aggregator(context):
@option('-s', '--secure', required=False,
help='Enable Intel SGX Enclave', is_flag=True, default=False)
@option('-c', '--cert_path',
help='The cert path where pki certs will reside', required=False)
def start_(plan, authorized_cols, secure, cert_path):
help='The path where aggregator certificate resides', required=False)
@option('-k', '--key_path',
help='The path where aggregator key resides', required=False)
def start_(plan, authorized_cols, secure, cert_path, key_path):
"""Start the aggregator service."""
from pathlib import Path

Expand All @@ -56,19 +58,18 @@ def start_(plan, authorized_cols, secure, cert_path):

logger.info('🧿 Starting the Aggregator Service.')

if cert_path:
if cert_path and key_path:
cert_path = Path(cert_path).absolute()
(cert_path / 'cert').mkdir(parents=True, exist_ok=True)
cert_dir_path = cert_path / 'cert'
if not Path(cert_dir_path).exists():
key_path = Path(key_path).absolute()
if not Path(cert_path).exists() or not Path(key_path).exists():
echo(style('Certificate Path not found.', fg='red')
+ ' Please run `fx aggregator generate-cert-request --cert_path`'
' to generate certs under this directory first.')

common_name = plan.config['network']['settings']['agg_addr'].lower()
plan.get_server(root_certificate=f'{cert_dir_path}/cert_chain.crt',
private_key=f'{cert_dir_path}/server/agg_{common_name}.key',
certificate=f'{cert_dir_path}/server/agg_{common_name}.crt').serve()
plan.get_server(root_certificate=f'{cert_path}/cert_chain.crt',
private_key=f'{cert_path}/agg_{common_name}.key',
certificate=f'{key_path}/agg_{common_name}.crt').serve()
else:
plan.get_server().serve()

Expand All @@ -79,12 +80,14 @@ def start_(plan, authorized_cols, secure, cert_path):
f' aggregator node [{getfqdn_env()}]',
default=getfqdn_env())
@option('-c', '--cert_path',
help='The cert path where pki certs will reside', required=False)
def _generate_cert_request(fqdn, cert_path):
generate_cert_request(fqdn, cert_path)
help='The path where aggregator certificate will reside', required=False)
@option('-k', '--key_path',
help='The path where aggregator key will reside', required=False)
def _generate_cert_request(fqdn, cert_path, key_path):
generate_cert_request(fqdn, cert_path, key_path)


def generate_cert_request(fqdn, cert_path=None):
def generate_cert_request(fqdn, cert_path=None, key_path=None):
"""Create aggregator certificate key pair."""
from pathlib import Path
from openfl.cryptography.participant import generate_csr
Expand All @@ -105,21 +108,29 @@ def generate_cert_request(fqdn, cert_path=None):

server_private_key, server_csr = generate_csr(common_name, server=True)

if cert_path:
if cert_path and key_path:
cert_path = Path(cert_path).absolute()
(cert_path / 'cert').mkdir(parents=True, exist_ok=True)
cert_dir_path = cert_path / 'cert'
else:
cert_dir_path = CERT_DIR
key_path = Path(key_path).absolute()

echo(' Writing AGGREGATOR certificate to: ' + style(
f'{cert_path}', fg='green'))
echo(' Writing AGGREGATOR key to: ' + style(
f'{key_path}', fg='green'))

(cert_dir_path / 'server').mkdir(parents=True, exist_ok=True)
# Write aggregator csr and key to disk
write_crt(server_csr, cert_path / f'{file_name}.csr')
write_key(server_private_key, key_path / f'{file_name}.key')
else:
if cert_path and not key_path or not cert_path and key_path:
echo(f'Both cert_path and key_path should be provided. Using default {CERT_DIR}.')
(CERT_DIR / 'server').mkdir(parents=True, exist_ok=True)

echo(' Writing AGGREGATOR certificate key pair to: ' + style(
f'{cert_dir_path}/server', fg='green'))
echo(' Writing AGGREGATOR certificate key pair to: ' + style(
f'{CERT_DIR}/server', fg='green'))

# Write aggregator csr and key to disk
write_crt(server_csr, cert_dir_path / 'server' / f'{file_name}.csr')
write_key(server_private_key, cert_dir_path / 'server' / f'{file_name}.key')
# Write aggregator csr and key to disk
write_crt(server_csr, CERT_DIR / 'server' / f'{file_name}.csr')
write_key(server_private_key, CERT_DIR / 'server' / f'{file_name}.key')


# TODO: function not used
Expand All @@ -140,12 +151,14 @@ def find_certificate_name(file_name):
default=getfqdn_env())
@option('-s', '--silent', help='Do not prompt', is_flag=True)
@option('-c', '--cert_path',
help='The cert path where pki certs will reside', required=False)
def _certify(fqdn, silent, cert_path):
certify(fqdn, silent, cert_path)
help='The path where signing CA certificate resides', required=False)
@option('-k', '--key_path',
help='The path where signing CA key resides', required=False)
def _certify(fqdn, silent, cert_path, key_path):
certify(fqdn, silent, cert_path, key_path)


def certify(fqdn, silent, cert_path=None):
def certify(fqdn, silent, cert_path=None, key_path=None):
"""Sign/certify the aggregator certificate key pair."""
from pathlib import Path

Expand All @@ -163,82 +176,140 @@ def certify(fqdn, silent, cert_path=None):

common_name = f'{fqdn}'.lower()
file_name = f'agg_{common_name}'
cert_name = f'server/{file_name}'
signing_key_path = 'ca/signing-ca/private/signing-ca.key'
signing_crt_path = 'ca/signing-ca.crt'

# Load CSR
if cert_path:
if cert_path and key_path:
cert_path = Path(cert_path).absolute()
(cert_path / 'cert').mkdir(parents=True, exist_ok=True)
cert_dir_path = cert_path / 'cert'
else:
cert_dir_path = CERT_DIR
key_path = Path(key_path).absolute()

agg_cert_name = f'{file_name}'
csr_path_absolute_path = Path(cert_path / f'{agg_cert_name}.csr').absolute()

if not csr_path_absolute_path.exists():
echo(style('Aggregator certificate signing request not found.', fg='red')
+ ' Please run `fx aggregator generate-cert-request -c -k`'
' to generate the certificate request.')

csr_path_absolute_path = Path(cert_dir_path / f'{cert_name}.csr').absolute()
if not csr_path_absolute_path.exists():
echo(style('Aggregator certificate signing request not found.', fg='red')
+ ' Please run `fx aggregator generate-cert-request`'
' to generate the certificate request.')
csr, csr_hash = read_csr(csr_path_absolute_path)

csr, csr_hash = read_csr(csr_path_absolute_path)
# Load private signing key
signing_key_path = 'signing-ca.key'
private_sign_key_absolute_path = Path(cert_path / signing_key_path).absolute()
if not private_sign_key_absolute_path.exists():
echo(style('Signing key not found.', fg='red')
+ ' Please run `fx workspace certify -c -k`'
' to initialize the local certificate authority.')

# Load private signing key
private_sign_key_absolute_path = Path(cert_dir_path / signing_key_path).absolute()
if not private_sign_key_absolute_path.exists():
echo(style('Signing key not found.', fg='red')
+ ' Please run `fx workspace certify`'
' to initialize the local certificate authority.')
signing_key = read_key(private_sign_key_absolute_path)

signing_key = read_key(private_sign_key_absolute_path)
# Load signing cert
signing_crt_path = 'signing-ca.crt'
signing_crt_absolute_path = Path(cert_path / signing_crt_path).absolute()
if not signing_crt_absolute_path.exists():
echo(style('Signing certificate not found.', fg='red')
+ ' Please run `fx workspace certify -c -k`'
' to initialize the local certificate authority.')

# Load signing cert
signing_crt_absolute_path = Path(cert_dir_path / signing_crt_path).absolute()
if not signing_crt_absolute_path.exists():
echo(style('Signing certificate not found.', fg='red')
+ ' Please run `fx workspace certify`'
' to initialize the local certificate authority.')
signing_crt = read_crt(signing_crt_absolute_path)

signing_crt = read_crt(signing_crt_absolute_path)
echo('The CSR Hash for file '
+ style(f'{agg_cert_name}.csr', fg='green')
+ ' = '
+ style(f'{csr_hash}', fg='red'))

echo('The CSR Hash for file '
+ style(f'{cert_name}.csr', fg='green')
+ ' = '
+ style(f'{csr_hash}', fg='red'))
crt_path_absolute_path = Path(cert_path / f'{agg_cert_name}.crt').absolute()

crt_path_absolute_path = Path(cert_dir_path / f'{cert_name}.crt').absolute()
if silent:

echo(' Signing AGGREGATOR certificate')
signed_agg_cert = sign_certificate(csr, signing_key, signing_crt.subject)
write_crt(signed_agg_cert, crt_path_absolute_path)

else:

if silent:
if confirm('Do you want to sign this certificate?'):

echo(' Signing AGGREGATOR certificate')
signed_agg_cert = sign_certificate(csr, signing_key, signing_crt.subject)
write_crt(signed_agg_cert, crt_path_absolute_path)
echo(' Signing AGGREGATOR certificate')
signed_agg_cert = sign_certificate(csr, signing_key, signing_crt.subject)
write_crt(signed_agg_cert, crt_path_absolute_path)

else:
echo(style('Not signing certificate.', fg='red')
+ ' Please check with this AGGREGATOR to get the correct'
' certificate for this federation.')

else:
agg_cert_name = f'server/{file_name}'
signing_key_path = 'ca/signing-ca/private/signing-ca.key'
signing_crt_path = 'ca/signing-ca.crt'
csr_path_absolute_path = Path(CERT_DIR / f'{agg_cert_name}.csr').absolute()
if not csr_path_absolute_path.exists():
echo(style('Aggregator certificate signing request not found.', fg='red')
+ ' Please run `fx aggregator generate-cert-request`'
' to generate the certificate request.')

csr, csr_hash = read_csr(csr_path_absolute_path)

# Load private signing key
private_sign_key_absolute_path = Path(CERT_DIR / signing_key_path).absolute()
if not private_sign_key_absolute_path.exists():
echo(style('Signing key not found.', fg='red')
+ ' Please run `fx workspace certify`'
' to initialize the local certificate authority.')

signing_key = read_key(private_sign_key_absolute_path)

# Load signing cert
signing_crt_absolute_path = Path(CERT_DIR / signing_crt_path).absolute()
if not signing_crt_absolute_path.exists():
echo(style('Signing certificate not found.', fg='red')
+ ' Please run `fx workspace certify`'
' to initialize the local certificate authority.')

signing_crt = read_crt(signing_crt_absolute_path)

if confirm('Do you want to sign this certificate?'):
echo('The CSR Hash for file '
+ style(f'{agg_cert_name}.csr', fg='green')
+ ' = '
+ style(f'{csr_hash}', fg='red'))

crt_path_absolute_path = Path(CERT_DIR / f'{agg_cert_name}.crt').absolute()

if silent:

echo(' Signing AGGREGATOR certificate')
signed_agg_cert = sign_certificate(csr, signing_key, signing_crt.subject)
write_crt(signed_agg_cert, crt_path_absolute_path)

else:
echo(style('Not signing certificate.', fg='red')
+ ' Please check with this AGGREGATOR to get the correct'
' certificate for this federation.')

if confirm('Do you want to sign this certificate?'):

echo(' Signing AGGREGATOR certificate')
signed_agg_cert = sign_certificate(csr, signing_key, signing_crt.subject)
write_crt(signed_agg_cert, crt_path_absolute_path)

else:
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)
@option('-k', '--key_path',
help='The key path where key reside', required=True)
def _uninstall_cert(cert_path, key_path):
uninstall_cert(cert_path, key_path)


def uninstall_cert(cert_path=None):
def uninstall_cert(cert_path=None, key_path=None):
"""Uninstall certs under a given directory."""
import shutil
from openfl.utilities.utils import rmtree
from pathlib import Path

cert_path = Path(cert_path).absolute()
shutil.rmtree(cert_path, ignore_errors=True)
rmtree(cert_path, ignore_errors=True)
key_path = Path(key_path).absolute()
rmtree(key_path, ignore_errors=True)

0 comments on commit 47c8632

Please sign in to comment.