Modify character classes to use runtime files and directories: certificates and metadata

pull/437/head
Kieran Prasch 2018-09-17 14:10:48 -07:00 committed by jMyles
parent 47d50a9e1a
commit 9842b5d096
6 changed files with 55 additions and 44 deletions

View File

@ -45,7 +45,7 @@ class NucypherTokenActor:
self.checksum_public_address = checksum_address
if registry_filepath is not None:
EthereumContractRegistry.from_config(registry_filepath=registry_filepath)
EthereumContractRegistry(registry_filepath=registry_filepath)
self.token_agent = token_agent if token_agent is not None else NucypherTokenAgent()
self._transaction_cache = list() # track transactions transmitted

View File

@ -304,8 +304,9 @@ class Character(Teacher):
def __init__(self,
is_me: bool = True,
config_root=DEFAULT_CONFIG_ROOT,
network_middleware: RestMiddleware = None,
known_certificates_dir: str = None,
known_metadata_dir: str = None,
crypto_power: CryptoPower = None,
crypto_power_ups: List[CryptoPowerUp] = None,
federated_only: bool = False,
@ -337,8 +338,9 @@ class Character(Teacher):
"""
super().__init__(*args, **kwargs)
self.config_root = config_root
self.federated_only = federated_only # type: bool
self.known_certificates_dir = known_certificates_dir
self.known_metadata_dir = known_metadata_dir
#
# Power-ups and Powers
@ -487,9 +489,12 @@ class Character(Teacher):
unresponsive_nodes = set()
try:
# FIXME
response = self.network_middleware.get_nodes_via_rest(rest_url,
nodes_i_need=self._node_ids_to_learn_about_immediately,
announce_nodes=announce_nodes)
announce_nodes=announce_nodes,
certificate_path=current_teacher.certificate_filepath)
except requests.exceptions.ConnectionError:
unresponsive_nodes.add(current_teacher)
teacher_rest_info = current_teacher.rest_information()[0]

View File

@ -405,7 +405,7 @@ class Ursula(Character, VerifiableNode, Miner):
rest_host,
rest_port,
certificate=None,
certificate_dir=None,
certificate_filepath: str = None,
db_name=None,
is_me=True,
interface_signature=None,
@ -413,6 +413,7 @@ class Ursula(Character, VerifiableNode, Miner):
# Blockchain
miner_agent=None,
checksum_address: str = None,
registry_filepath: str = None,
# Character
abort_on_learning_error: bool = False,
@ -443,7 +444,8 @@ class Ursula(Character, VerifiableNode, Miner):
Miner.__init__(self,
is_me=is_me,
miner_agent=miner_agent,
checksum_address=checksum_address)
checksum_address=checksum_address,
registry_filepath=registry_filepath)
blockchain_power = BlockchainPower(blockchain=self.blockchain, account=self.checksum_public_address)
self._crypto_power.consume_power_up(blockchain_power)
@ -489,26 +491,34 @@ class Ursula(Character, VerifiableNode, Miner):
curve=tls_curve,
host=rest_host,
certificate=certificate,
certificate_dir=certificate_dir)
certificate_dir=self.known_certificates_dir)
tls_hosting_power = TLSHostingPower(rest_server=rest_server,
keypair=tls_hosting_keypair)
else:
# Unless the caller passed a crypto power, we'll make our own TLSHostingPower for this stranger.
rest_server = ProxyRESTServer(
rest_host=rest_host,
rest_port=rest_port,
)
if certificate:
tls_hosting_power = TLSHostingPower(rest_server=rest_server, certificate=certificate)
if certificate or certificate_filepath:
tls_hosting_power = TLSHostingPower(rest_server=rest_server,
certificate_filepath=certificate_filepath,
certificate=certificate)
else:
tls_hosting_keypair = HostingKeypair(
common_name=self.checksum_public_address,
curve=tls_curve,
host=rest_host,
certificate_dir=certificate_dir)
certificate_filepath=certificate_filepath,
certificate_dir=self.known_certificates_dir)
tls_hosting_power = TLSHostingPower(rest_server=rest_server,
keypair=tls_hosting_keypair)
self._crypto_power.consume_power_up(tls_hosting_power) # Make this work for not me for certificate to work
else:
self.log.info("Not adhering rest_server; we'll use the one on crypto_power..")

View File

@ -117,17 +117,13 @@ def ecdsa_verify(
def _save_tls_certificate(certificate: Certificate,
directory: str,
common_name: str = None,
is_me: bool = False,
force: bool = True,
) -> str:
if is_me is False and not common_name:
raise NucypherConfigurationError('A common name must be passed to save another node\'s certificate.')
certificate_filepath = os.path.join(directory, '{}.pem'.format(common_name[:6]))
certificate_filepath = os.path.join(directory, '{}.pem'.format(common_name[2:8]))
if force is False and os.path.isfile(certificate_filepath):
raise NucypherConfigurationError('A TLS certificate already exists at {}.'.format(certificate_filepath))
raise FileExistsError('A TLS certificate already exists at {}.'.format(certificate_filepath))
with open(certificate_filepath, 'wb') as certificate_file:
public_pem_bytes = certificate.public_bytes(Encoding.PEM)
@ -146,9 +142,10 @@ def load_tls_certificate(filepath):
def generate_self_signed_certificate(common_name,
curve,
host,
certificate_dir,
private_key=None,
days_valid=365,
certificate_dir=None):
):
if not private_key:
private_key = ec.generate_private_key(curve, default_backend())
@ -169,10 +166,10 @@ def generate_self_signed_certificate(common_name,
cert = cert.add_extension(x509.SubjectAlternativeName([x509.DNSName(host)]), critical=False)
cert = cert.sign(private_key, hashes.SHA512(), default_backend())
if certificate_dir:
tls_certificate_filepath = _save_tls_certificate(cert, directory=certificate_dir, common_name=common_name)
else:
tls_certificate_filepath = constants.CERTIFICATE_NOT_SAVED
# if certificate_dir:
tls_certificate_filepath = _save_tls_certificate(cert, directory=certificate_dir, common_name=common_name)
# else:
# tls_certificate_filepath = constants.CERTIFICATE_NOT_SAVED
return cert, private_key, tls_certificate_filepath

View File

@ -13,7 +13,7 @@ from umbral.keys import UmbralPrivateKey, UmbralPublicKey
from umbral.signing import Signature, Signer
from nucypher.crypto import api as API
from nucypher.crypto.api import generate_self_signed_certificate, _save_tls_certificate
from nucypher.crypto.api import generate_self_signed_certificate, _save_tls_certificate, load_tls_certificate
from nucypher.crypto.kits import MessageKit
from nucypher.crypto.signing import SignatureStamp, StrangerStamp
@ -132,46 +132,47 @@ class HostingKeypair(Keypair):
common_name=None,
host=None,
private_key: Union[UmbralPrivateKey, UmbralPublicKey] = None,
certificate=None,
curve=None,
generate_keys_if_needed=True,
certificate=None,
certificate_filepath: str = None,
certificate_dir=None,
) -> None:
self.curve = curve or self._DEFAULT_CURVE
self.certificate_filepath = None
if private_key:
super().__init__(private_key=private_key)
elif certificate:
self.certificate = certificate
super().__init__(public_key=certificate.public_key())
elif generate_keys_if_needed:
elif certificate_filepath:
certificate = load_tls_certificate(filepath=certificate_filepath)
elif generate_certificate:
if not all((common_name, host)):
message = "If you don't supply the certificate, one will be generated for you." \
"But for that, you need to pass both host and common_name.."
raise TypeError(message)
self.certificate, private_key, self.certificate_filepath = generate_self_signed_certificate(common_name=common_name,
private_key=private_key,
curve=self.curve,
host=host,
)
certificate, private_key, certificate_filepath = generate_self_signed_certificate(common_name=common_name,
private_key=private_key,
curve=self.curve,
host=host,
certificate_dir=certificate_dir)
super().__init__(private_key=private_key)
else:
raise TypeError("You didn't provide a cert, but also told us not to generate keys. Not sure what to do.")
if certificate_dir:
self.certificate_filepath = _save_tls_certificate(self.certificate,
directory=certificate_dir,
common_name=common_name,
is_me=False,
force=False,
)
self.certificate = certificate
self.certificate_filepath = certificate_filepath
self.certificate_dir = certificate_dir
def generate_self_signed_cert(self, common_name):
cryptography_key = self._privkey.to_cryptography_privkey()
return generate_self_signed_certificate(common_name, default_curve(), cryptography_key)
return generate_self_signed_certificate(common_name, default_curve(),
cryptography_key, certificate_dir=self.certificate_dir)
def get_deployer(self, rest_app, port):
return HendrixDeployTLS("start",

View File

@ -9,20 +9,18 @@ from umbral.fragments import CapsuleFrag
class RestMiddleware:
def consider_arrangement(self, arrangement, certificate_path):
certificate = load_tls_certificate(filepath=certificate_path)
node = arrangement.ursula
port = node.rest_interface.port
address = node.rest_interface.host
response = requests.post("https://{}:{}/consider_arrangement".format(address, port), bytes(arrangement), verify=certificate)
response = requests.post("https://{}:{}/consider_arrangement".format(address, port), bytes(arrangement), verify=certificate_path)
if not response.status_code == 200:
raise RuntimeError("Bad response: {}".format(response.content))
return response
def enact_policy(self, ursula, id, payload, certificate_path):
certificate = load_tls_certificate(filepath=certificate_path)
port = ursula.rest_interface.port
address = ursula.rest_interface.host
response = requests.post('https://{}:{}/kFrag/{}'.format(address, port, id.hex()), payload, verify=certificate)
response = requests.post('https://{}:{}/kFrag/{}'.format(address, port, id.hex()), payload, verify=certificate_path)
if not response.status_code == 200:
raise RuntimeError("Bad response: {}".format(response.content))
return True, ursula.stamp.as_umbral_pubkey()