Just to be clear - the server never supports both TLS and plaintext connections at the same time. (I don't believe this is possible in gRPC.) The URI scheme determines how the server listens so if you don't use grpc+tls:// it will use plaintext regardless of if you pass certificates or not. The code could do more input validation in this case but it was never listening using TLS in the first place.
On Sat, Dec 30, 2023, at 18:57, Bryce Mecum wrote: > Hi Rick, > > You're right that TLS support is built into PyArrow Flight [1]. I > think the issue with your code is that your client isn't attempting to > connect over TLS and that the default behavior of the FlightServerBase > must be to allow both TLS and non-TLS connections. This seems to be > similar to how web servers might choose to accept connections over > HTTP and HTTPS (though many may not). > > To make your code fail as you expect, see [1] and, in your client > code, either change server_location to use > pyarrow.flight.Location.for_grpc_tls to construct the Location object > or change your URI to "grpc+tls://localhost:8081" instead of just > "grpc://localhost:8081". Once you change this, your client should fail > with an SSL handshake error. > > [1] https://arrow.apache.org/docs/python/flight.html#enabling-tls > > On Sat, Dec 30, 2023 at 2:20 PM Rick Spencer > <richard.linger.spence...@gmail.com> wrote: >> >> I am working on supporting TLS, and it looks like everything that I need is >> built into FlightServerBase. >> >> However, I am struggling to understand how it works, or how to test that it >> is working. For example, I don't understand why I can pass garbage in for >> the tls_certs, and still get results when called from a client. Here is a >> minimal example I put together to show where I am confused. >> >> Server that I think should not work: >> ```python >> from pyarrow import flight, Table >> >> class SampleServer(flight.FlightServerBase): >> def __init__(self, *args, **kwargs): >> tls_certificates = [("garbage", "garbage")] >> location = flight.Location.for_grpc_tcp("localhost", 8081) >> super(SampleServer, self).__init__(location, >> None, >> tls_certificates, >> False, >> None, >> *args, **kwargs) >> >> def do_get(self, context, ticket): >> data = {'col': [1]} >> table = Table.from_pydict(data) >> return flight.RecordBatchStream(table) >> >> if __name__ == "__main__": >> server = SampleServer() >> server.serve() >> ``` >> >> Client code that I think should not work: ```python >> import pyarrow.flight as fl >> import json >> def main(): >> server_location = "grpc://localhost:8081" >> >> client = fl.FlightClient(server_location) >> ticket = fl.Ticket(json.dumps({})) >> reader = client.do_get(ticket) >> print(reader.read_all().to_pandas()) >> >> if __name__ == "__main__": >> main() >> ``` >> >> But when I run the server, and then the client, I get a result: ``` % >> python3 client.py >> col >> 0 1 ``` I would expect some kind of TLS error. >> >> I am sure that I am confused about something, but if someone could help me >> with my reasoning, I would appreciate it.