Removing other places whree saving logic existed; adding it to ProxyRESTRoutes so that 'anounced' nodes can be saved.

pull/446/head
jMyles 2018-09-21 21:44:19 +02:00
parent c5b2c9a457
commit dbe59d79e5
4 changed files with 24 additions and 21 deletions

View File

@ -468,6 +468,7 @@ class Ursula(Character, VerifiableNode, Miner):
stamp=self.stamp, stamp=self.stamp,
verifier=self.verify_from, verifier=self.verify_from,
suspicious_activity_tracker=self.suspicious_activities_witnessed, suspicious_activity_tracker=self.suspicious_activities_witnessed,
certificate_dir=self.known_certificates_dir,
) )
rest_server = ProxyRESTServer( rest_server = ProxyRESTServer(
@ -498,7 +499,9 @@ class Ursula(Character, VerifiableNode, Miner):
if certificate or certificate_filepath: if certificate or certificate_filepath:
tls_hosting_power = TLSHostingPower(rest_server=rest_server, tls_hosting_power = TLSHostingPower(rest_server=rest_server,
certificate_filepath=certificate_filepath, certificate_filepath=certificate_filepath,
certificate=certificate) certificate=certificate,
certificate_dir=self.known_certificates_dir,
common_name=self.checksum_public_address,)
else: else:
tls_hosting_keypair = HostingKeypair( tls_hosting_keypair = HostingKeypair(
common_name=self.checksum_public_address, common_name=self.checksum_public_address,
@ -580,7 +583,8 @@ class Ursula(Character, VerifiableNode, Miner):
@classmethod @classmethod
def from_bytes(cls, ursula_as_bytes: bytes, def from_bytes(cls, ursula_as_bytes: bytes,
federated_only: bool = False) -> 'Ursula': federated_only: bool = False,
) -> 'Ursula':
(signature, (signature,
identity_evidence, identity_evidence,
@ -598,14 +602,15 @@ class Ursula(Character, VerifiableNode, Miner):
rest_host=rest_info.host, rest_host=rest_info.host,
rest_port=rest_info.port, rest_port=rest_info.port,
certificate=certificate, certificate=certificate,
federated_only=federated_only # TODO: 289 federated_only=federated_only, # TODO: 289
) )
return stranger_ursula_from_public_keys return stranger_ursula_from_public_keys
@classmethod @classmethod
def batch_from_bytes(cls, def batch_from_bytes(cls,
ursulas_as_bytes: Iterable[bytes], ursulas_as_bytes: Iterable[bytes],
federated_only: bool = False) -> List['Ursula']: federated_only: bool = False,
) -> List['Ursula']:
# TODO: Make a better splitter for this. This is a workaround until bytestringSplitter #8 is closed. # TODO: Make a better splitter for this. This is a workaround until bytestringSplitter #8 is closed.

View File

@ -115,22 +115,16 @@ def ecdsa_verify(message: bytes,
def _save_tls_certificate(certificate: Certificate, def _save_tls_certificate(certificate: Certificate,
directory: str, full_filepath,
common_name: str = None,
force: bool = True, force: bool = True,
) -> str: ) -> str:
if force is False and os.path.isfile(full_filepath):
raise FileExistsError('A TLS certificate already exists at {}.'.format(full_filepath))
certificate_filepath = os.path.join(directory, '{}.pem'.format(common_name[2:8])) with open(full_filepath, 'wb') as certificate_file:
if force is False and os.path.isfile(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) public_pem_bytes = certificate.public_bytes(Encoding.PEM)
certificate_file.write(public_pem_bytes) certificate_file.write(public_pem_bytes)
return certificate_filepath
def load_tls_certificate(filepath: str) -> Certificate: def load_tls_certificate(filepath: str) -> Certificate:
"""Deserialize an X509 certificate from a filepath""" """Deserialize an X509 certificate from a filepath"""
@ -170,12 +164,7 @@ def generate_self_signed_certificate(common_name: str,
cert = cert.add_extension(x509.SubjectAlternativeName([x509.DNSName(host)]), critical=False) cert = cert.add_extension(x509.SubjectAlternativeName([x509.DNSName(host)]), critical=False)
cert = cert.sign(private_key, hashes.SHA512(), default_backend()) cert = cert.sign(private_key, hashes.SHA512(), default_backend())
if certificate_dir: # TODO: Make this more configurable? return cert, private_key
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
def encrypt_and_sign(recipient_pubkey_enc: UmbralPublicKey, def encrypt_and_sign(recipient_pubkey_enc: UmbralPublicKey,

View File

@ -167,6 +167,9 @@ class HostingKeypair(Keypair):
else: else:
raise TypeError("You didn't provide a cert, but also told us not to generate keys. Not sure what to do.") raise TypeError("You didn't provide a cert, but also told us not to generate keys. Not sure what to do.")
if not certificate_filepath:
certificate_filepath = constants.CERTIFICATE_NOT_SAVED
self.certificate = certificate self.certificate = certificate
self.certificate_filepath = certificate_filepath self.certificate_filepath = certificate_filepath
self.certificate_dir = certificate_dir self.certificate_dir = certificate_dir

View File

@ -52,6 +52,7 @@ class ProxyRESTRoutes:
stamp, stamp,
verifier, verifier,
suspicious_activity_tracker, suspicious_activity_tracker,
certificate_dir,
) -> None: ) -> None:
self.network_middleware = network_middleware self.network_middleware = network_middleware
@ -65,6 +66,7 @@ class ProxyRESTRoutes:
self._stamp = stamp self._stamp = stamp
self._verifier = verifier self._verifier = verifier
self._suspicious_activity_tracker = suspicious_activity_tracker self._suspicious_activity_tracker = suspicious_activity_tracker
self._certificate_dir = certificate_dir
self.datastore = None self.datastore = None
routes = [ routes = [
@ -128,7 +130,9 @@ class ProxyRESTRoutes:
return Response(bytes(signature) + ursulas_as_bytes, headers=headers) return Response(bytes(signature) + ursulas_as_bytes, headers=headers)
def node_metadata_exchange(self, request: http.Request, query_params: http.QueryParams): def node_metadata_exchange(self, request: http.Request, query_params: http.QueryParams):
nodes = self._node_class.batch_from_bytes(request.body, federated_only=self.federated_only) nodes = self._node_class.batch_from_bytes(request.body,
federated_only=self.federated_only,
)
# TODO: This logic is basically repeated in learn_from_teacher_node. Let's find a better way. # TODO: This logic is basically repeated in learn_from_teacher_node. Let's find a better way.
for node in nodes: for node in nodes:
@ -147,6 +151,8 @@ class ProxyRESTRoutes:
self._suspicious_activity_tracker['vladimirs'].append(node) # TODO: Maybe also record the bytes representation separately to disk? self._suspicious_activity_tracker['vladimirs'].append(node) # TODO: Maybe also record the bytes representation separately to disk?
else: else:
self.log.info("Previously unknown node: {}".format(node.checksum_public_address)) self.log.info("Previously unknown node: {}".format(node.checksum_public_address))
if self._certificate_dir:
node.save_certificate_to_disk(self._certificate_dir)
self._node_recorder(node) self._node_recorder(node)
# TODO: What's the right status code here? 202? Different if we already knew about the node? # TODO: What's the right status code here? 202? Different if we already knew about the node?