mirror of
https://github.com/tahoe-lafs/tahoe-lafs.git
synced 2025-02-20 17:52:50 +00:00
Hook up NURL generation to the new Foolscap/HTTPS protocol switch.
This commit is contained in:
parent
5e0c32708b
commit
11f4ebc0d9
@ -37,6 +37,7 @@ import allmydata
|
||||
from allmydata.crypto import rsa, ed25519
|
||||
from allmydata.crypto.util import remove_prefix
|
||||
from allmydata.storage.server import StorageServer, FoolscapStorageServer
|
||||
from allmydata.storage.http_server import build_nurl
|
||||
from allmydata import storage_client
|
||||
from allmydata.immutable.upload import Uploader
|
||||
from allmydata.immutable.offloaded import Helper
|
||||
@ -658,6 +659,12 @@ class _Client(node.Node, pollmixin.PollMixin):
|
||||
if webport:
|
||||
self.init_web(webport) # strports string
|
||||
|
||||
# TODO this may be the wrong location for now? but as temporary measure
|
||||
# it allows us to get NURLs for testing in test_istorageserver.py Will
|
||||
# eventually get fixed one way or another in
|
||||
# https://tahoe-lafs.org/trac/tahoe-lafs/ticket/3901
|
||||
self.storage_nurls = []
|
||||
|
||||
def init_stats_provider(self):
|
||||
self.stats_provider = StatsProvider(self)
|
||||
self.stats_provider.setServiceParent(self)
|
||||
@ -820,6 +827,15 @@ class _Client(node.Node, pollmixin.PollMixin):
|
||||
furl = self.tub.registerReference(FoolscapStorageServer(ss), furlFile=furl_file)
|
||||
(_, _, swissnum) = furl.rpartition("/")
|
||||
self.tub.negotiationClass.add_storage_server(ss, swissnum.encode("ascii"))
|
||||
for location_hint in self.tub.locationHints:
|
||||
if location_hint.startswith("tcp:"):
|
||||
_, hostname, port = location_hint.split(":")
|
||||
port = int(port)
|
||||
self.storage_nurls.append(
|
||||
build_nurl(
|
||||
hostname, port, swissnum, self.tub.myCertificate.original.to_cryptography()
|
||||
)
|
||||
)
|
||||
|
||||
announcement["anonymous-storage-FURL"] = furl
|
||||
|
||||
|
@ -66,14 +66,6 @@ class _FoolscapOrHttps(Protocol, metaclass=_PretendToBeNegotiation):
|
||||
Add the various storage server-related attributes needed by a
|
||||
``Tub``-specific ``_FoolscapOrHttps`` subclass.
|
||||
"""
|
||||
# TODO tub.locationHints will be in the format ["tcp:hostname:port"]
|
||||
# (and maybe some other things we can ignore for now). We also have
|
||||
# access to the certificate. Together, this should be sufficient to
|
||||
# construct NURLs, one per hint. The code for NURls should be
|
||||
# refactored out of http_server.py's build_nurl; that code might want
|
||||
# to skip around for the future when we don't do foolscap, but for now
|
||||
# this module will be main way we set up HTTPS.
|
||||
|
||||
# Tub.myCertificate is a twisted.internet.ssl.PrivateCertificate
|
||||
# instance.
|
||||
certificate_options = CertificateOptions(
|
||||
|
@ -10,6 +10,7 @@ from base64 import b64decode
|
||||
import binascii
|
||||
from tempfile import TemporaryFile
|
||||
|
||||
from cryptography.x509 import Certificate
|
||||
from zope.interface import implementer
|
||||
from klein import Klein
|
||||
from twisted.web import http
|
||||
@ -843,6 +844,29 @@ class _TLSEndpointWrapper(object):
|
||||
)
|
||||
|
||||
|
||||
def build_nurl(
|
||||
hostname: str, port: int, swissnum: str, certificate: Certificate
|
||||
) -> DecodedURL:
|
||||
"""
|
||||
Construct a HTTPS NURL, given the hostname, port, server swissnum, and x509
|
||||
certificate for the server. Clients can then connect to the server using
|
||||
this NURL.
|
||||
"""
|
||||
return DecodedURL().replace(
|
||||
fragment="v=1", # how we know this NURL is HTTP-based (i.e. not Foolscap)
|
||||
host=hostname,
|
||||
port=port,
|
||||
path=(swissnum,),
|
||||
userinfo=(
|
||||
str(
|
||||
get_spki_hash(certificate),
|
||||
"ascii",
|
||||
),
|
||||
),
|
||||
scheme="pb",
|
||||
)
|
||||
|
||||
|
||||
def listen_tls(
|
||||
server: HTTPServer,
|
||||
hostname: str,
|
||||
@ -862,22 +886,14 @@ def listen_tls(
|
||||
"""
|
||||
endpoint = _TLSEndpointWrapper.from_paths(endpoint, private_key_path, cert_path)
|
||||
|
||||
def build_nurl(listening_port: IListeningPort) -> DecodedURL:
|
||||
nurl = DecodedURL().replace(
|
||||
fragment="v=1", # how we know this NURL is HTTP-based (i.e. not Foolscap)
|
||||
host=hostname,
|
||||
port=listening_port.getHost().port,
|
||||
path=(str(server._swissnum, "ascii"),),
|
||||
userinfo=(
|
||||
str(
|
||||
get_spki_hash(load_pem_x509_certificate(cert_path.getContent())),
|
||||
"ascii",
|
||||
),
|
||||
),
|
||||
scheme="pb",
|
||||
def get_nurl(listening_port: IListeningPort) -> DecodedURL:
|
||||
return build_nurl(
|
||||
hostname,
|
||||
listening_port.getHost().port,
|
||||
str(server._swissnum, "ascii"),
|
||||
load_pem_x509_certificate(cert_path.getContent()),
|
||||
)
|
||||
return nurl
|
||||
|
||||
return endpoint.listen(Site(server.get_resource())).addCallback(
|
||||
lambda listening_port: (build_nurl(listening_port), listening_port)
|
||||
lambda listening_port: (get_nurl(listening_port), listening_port)
|
||||
)
|
||||
|
@ -1084,40 +1084,17 @@ class _FoolscapMixin(_SharedMixin):
|
||||
class _HTTPMixin(_SharedMixin):
|
||||
"""Run tests on the HTTP version of ``IStorageServer``."""
|
||||
|
||||
def setUp(self):
|
||||
self._port_assigner = SameProcessStreamEndpointAssigner()
|
||||
self._port_assigner.setUp()
|
||||
self.addCleanup(self._port_assigner.tearDown)
|
||||
return _SharedMixin.setUp(self)
|
||||
|
||||
@inlineCallbacks
|
||||
def _get_istorage_server(self):
|
||||
swissnum = b"1234"
|
||||
http_storage_server = HTTPServer(self.server, swissnum)
|
||||
|
||||
# Listen on randomly assigned port, using self-signed cert:
|
||||
private_key = generate_private_key()
|
||||
certificate = generate_certificate(private_key)
|
||||
_, endpoint_string = self._port_assigner.assign(reactor)
|
||||
nurl, listening_port = yield listen_tls(
|
||||
http_storage_server,
|
||||
"127.0.0.1",
|
||||
serverFromString(reactor, endpoint_string),
|
||||
private_key_to_file(FilePath(self.mktemp()), private_key),
|
||||
cert_to_file(FilePath(self.mktemp()), certificate),
|
||||
)
|
||||
self.addCleanup(listening_port.stopListening)
|
||||
nurl = self.clients[0].storage_nurls[0]
|
||||
|
||||
# Create HTTP client with non-persistent connections, so we don't leak
|
||||
# state across tests:
|
||||
returnValue(
|
||||
_HTTPStorageServer.from_http_client(
|
||||
StorageClient.from_nurl(nurl, reactor, persistent=False)
|
||||
)
|
||||
client: IStorageServer = _HTTPStorageServer.from_http_client(
|
||||
StorageClient.from_nurl(nurl, reactor, persistent=False)
|
||||
)
|
||||
self.assertTrue(IStorageServer.providedBy(client))
|
||||
|
||||
# Eventually should also:
|
||||
# self.assertTrue(IStorageServer.providedBy(client))
|
||||
return succeed(client)
|
||||
|
||||
|
||||
class FoolscapSharedAPIsTests(
|
||||
|
Loading…
x
Reference in New Issue
Block a user