def certify():
    """Create certificate authority for federation."""
    from openfl.cryptography.ca import generate_root_cert, generate_signing_csr, sign_certificate
    from cryptography.hazmat.primitives import serialization

    echo('Setting Up Certificate Authority...\n')

    echo('1.  Create Root CA')
    echo('1.1 Create Directories')

    (PKI_DIR / 'ca/root-ca/private').mkdir(parents=True,
                                           exist_ok=True,
                                           mode=0o700)
    (PKI_DIR / 'ca/root-ca/db').mkdir(parents=True, exist_ok=True)

    echo('1.2 Create Database')

    with open(PKI_DIR / 'ca/root-ca/db/root-ca.db', 'w') as f:
        pass  # write empty file
    with open(PKI_DIR / 'ca/root-ca/db/root-ca.db.attr', 'w') as f:
        pass  # write empty file

    with open(PKI_DIR / 'ca/root-ca/db/root-ca.crt.srl', 'w') as f:
        f.write('01')  # write file with '01'
    with open(PKI_DIR / 'ca/root-ca/db/root-ca.crl.srl', 'w') as f:
        f.write('01')  # write file with '01'

    echo('1.3 Create CA Request and Certificate')

    root_crt_path = 'ca/root-ca.crt'
    root_key_path = 'ca/root-ca/private/root-ca.key'

    root_private_key, root_cert = generate_root_cert()

    # Write root CA certificate to disk
    with open(PKI_DIR / root_crt_path, 'wb') as f:
        f.write(root_cert.public_bytes(encoding=serialization.Encoding.PEM, ))

    with open(PKI_DIR / root_key_path, "wb") as f:
        f.write(
            root_private_key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption()))

    echo('2.  Create Signing Certificate')
    echo('2.1 Create Directories')

    (PKI_DIR / 'ca/signing-ca/private').mkdir(parents=True,
                                              exist_ok=True,
                                              mode=0o700)
    (PKI_DIR / 'ca/signing-ca/db').mkdir(parents=True, exist_ok=True)

    echo('2.2 Create Database')

    with open(PKI_DIR / 'ca/signing-ca/db/signing-ca.db', 'w') as f:
        pass  # write empty file
    with open(PKI_DIR / 'ca/signing-ca/db/signing-ca.db.attr', 'w') as f:
        pass  # write empty file

    with open(PKI_DIR / 'ca/signing-ca/db/signing-ca.crt.srl', 'w') as f:
        f.write('01')  # write file with '01'
    with open(PKI_DIR / 'ca/signing-ca/db/signing-ca.crl.srl', 'w') as f:
        f.write('01')  # write file with '01'

    echo('2.3 Create Signing Certificate CSR')

    signing_csr_path = 'ca/signing-ca.csr'
    signing_crt_path = 'ca/signing-ca.crt'
    signing_key_path = 'ca/signing-ca/private/signing-ca.key'

    signing_private_key, signing_csr = generate_signing_csr()

    # Write Signing CA CSR to disk
    with open(PKI_DIR / signing_csr_path, 'wb') as f:
        f.write(signing_csr.public_bytes(
            encoding=serialization.Encoding.PEM, ))

    with open(PKI_DIR / signing_key_path, "wb") as f:
        f.write(
            signing_private_key.private_bytes(
                encoding=serialization.Encoding.PEM,
                format=serialization.PrivateFormat.TraditionalOpenSSL,
                encryption_algorithm=serialization.NoEncryption()))

    echo('2.4 Sign Signing Certificate CSR')

    signing_cert = sign_certificate(signing_csr,
                                    root_private_key,
                                    root_cert.subject,
                                    ca=True)

    with open(PKI_DIR / signing_crt_path, 'wb') as f:
        f.write(
            signing_cert.public_bytes(encoding=serialization.Encoding.PEM, ))

    echo('3   Create Certificate Chain')

    # create certificate chain file by combining root-ca and signing-ca
    with open(PKI_DIR / 'cert_chain.crt', 'w') as d:
        with open(PKI_DIR / 'ca/root-ca.crt') as s:
            d.write(s.read())
        with open(PKI_DIR / 'ca/signing-ca.crt') as s:
            d.write(s.read())

    echo('\nDone.')
def certify(fqdn, silent):
    """Sign/certify the aggregator certificate key pair."""
    from openfl.cryptography.ca import sign_certificate
    from openfl.cryptography.io import read_key, read_crt, read_csr
    from openfl.cryptography.io import write_crt

    from click import confirm

    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 not Path(PKI_DIR / f'{cert_name}.csr').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(PKI_DIR / f'{cert_name}.csr')

    # Load private signing key
    if not Path(PKI_DIR / signing_key_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(PKI_DIR / signing_key_path)

    # Load signing cert
    if not Path(PKI_DIR / signing_crt_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(PKI_DIR / signing_crt_path)

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

    if silent:

        echo(' Signing AGGREGATOR certificate')
        signed_agg_cert = sign_certificate(csr, signing_key, signing_crt.subject)
        write_crt(signed_agg_cert, PKI_DIR / f'{cert_name}.crt')

    else:

        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, PKI_DIR / f'{cert_name}.crt')

        else:
            echo(style('Not signing certificate.', fg='red')
                 + ' Please check with this AGGREGATOR to get the correct'
                   ' certificate for this federation.')
Esempio n. 3
0
def certify(collaborator_name, silent, request_pkg=False, import_=False):
    """Sign/certify collaborator certificate key pair."""
    from click import confirm

    from shutil import unpack_archive
    from shutil import make_archive, copy
    from glob import glob
    from os.path import basename, join, splitext
    from os import remove
    from tempfile import mkdtemp
    from openfl.cryptography.ca import sign_certificate
    from openfl.cryptography.io import read_key, read_crt, read_csr
    from openfl.cryptography.io import write_crt

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

    if not import_:
        if request_pkg:
            Path(f'{PKI_DIR}/client').mkdir(parents=True, exist_ok=True)
            unpack_archive(request_pkg, extract_dir=f'{PKI_DIR}/client')
            csr = glob(f'{PKI_DIR}/client/*.csr')[0]
        else:
            if collaborator_name is None:
                echo('collaborator_name can only be omitted if signing\n'
                     'a zipped request package.\n'
                     '\n'
                     'Example: fx collaborator certify --request-pkg '
                     'col_one_to_agg_cert_request.zip')
                return
            csr = glob(f'{PKI_DIR}/client/col_{common_name}.csr')[0]
            copy(csr, PKI_DIR)
        cert_name = splitext(csr)[0]
        file_name = basename(cert_name)
        signing_key_path = 'ca/signing-ca/private/signing-ca.key'
        signing_crt_path = 'ca/signing-ca.crt'

        # Load CSR
        if not Path(f'{cert_name}.csr').exists():
            echo(
                style('Collaborator certificate signing request not found.',
                      fg='red') +
                ' Please run `fx collaborator generate-cert-request`'
                ' to generate the certificate request.')

        csr, csr_hash = read_csr(f'{cert_name}.csr')

        # Load private signing key
        if not Path(PKI_DIR / signing_key_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(PKI_DIR / signing_key_path)

        # Load signing cert
        if not Path(PKI_DIR / signing_crt_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(PKI_DIR / signing_crt_path)

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

        if silent:

            echo(' Signing COLLABORATOR certificate')
            signed_col_cert = sign_certificate(csr, signing_key,
                                               signing_crt.subject)
            write_crt(signed_col_cert, f'{cert_name}.crt')
            RegisterCollaborator(PKI_DIR / 'client' / f'{file_name}.crt')

        else:

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

                echo(' Signing COLLABORATOR certificate')
                signed_col_cert = sign_certificate(csr, signing_key,
                                                   signing_crt.subject)
                write_crt(signed_col_cert, f'{cert_name}.crt')
                RegisterCollaborator(PKI_DIR / 'client' / f'{file_name}.crt')

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

        if len(common_name) == 0:
            # If the collaborator name is provided, the collaborator and
            # certificate does not need to be exported
            return

        # Remove unneeded CSR
        remove(f'{cert_name}.csr')

        archiveType = 'zip'
        archiveName = f'agg_to_{file_name}_signed_cert'
        # archiveFileName = archiveName + '.' + archiveType

        # Collaborator certificate signing request
        tmpDir = join(mkdtemp(), 'openfl', archiveName)

        Path(f'{tmpDir}/client').mkdir(parents=True, exist_ok=True)
        # Copy the signed cert to the temporary directory
        copy(f'{PKI_DIR}/client/{file_name}.crt', f'{tmpDir}/client/')
        # Copy the CA certificate chain to the temporary directory
        copy(f'{PKI_DIR}/cert_chain.crt', tmpDir)

        # Create Zip archive of directory
        make_archive(archiveName, archiveType, tmpDir)

    else:
        # Copy the signed certificate and cert chain into PKI_DIR
        previous_crts = glob(f'{PKI_DIR}/client/*.crt')
        unpack_archive(import_, extract_dir=PKI_DIR)
        updated_crts = glob(f'{PKI_DIR}/client/*.crt')
        cert_difference = list(set(updated_crts) - set(previous_crts))
        if len(cert_difference) == 0:
            crt = basename(cert_difference[0])
            echo(f"Certificate {crt} installed to PKI directory")
        else:
            crt = basename(updated_crts[0])
            echo("Certificate updated in the PKI directory")