First...if you are NOT using GRPC...you should. Google developed the GRPC protocol, a high performance, open-source universal RPC framework
that is fast and efficient by leveraging HTTP/2 and Protocol Buffers.
This is a great option for internal service to service communications. However, if you intent to secure these communications, this feature is perhaps not as well documented as it should be.
First and foremost, you'll need to create a certificate. For now, we'll use a self-signed certificate. When entering the information, be sure to use the system name, not an IP address:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
Obviously a self-signed certificate may not be the best option for a production environment. Since we are just testing, let's also remove the certificate password:
openssl rsa -in key.pem -out key2.pem
Here is a sample GRPC configuration using Python, which is based on the Python quickstart examples from the GRPC website.
The Server:
def serve():
server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))
helloworld_pb2.add_GreeterServicer_to_server(Greeter(), server)
private_key = open('key2.pem').read()
certificate_chain = open('cert.pem').read()
credentials = grpc.ssl_server_credentials(
[(private_key, certificate_chain)])
server.add_secure_port('[::]:50001', credentials)
server.start()
try:
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop(0)
if __name__ == '__main__':
serve()
The Client:
def run():
global text
creds = grpc.ssl_channel_credentials(open('cert.pem').read())
channel = grpc.secure_channel('system_name:50001', creds)
stub = helloworld_pb2.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name=text))
print("Client received: " + response.message)
if __name__ == '__main__':
run()
Finally, note that GRPC will give you issues if you try to use an IP address and complain that the system name does not match the IP address. You need to connect using the system name, and add the necessary entries in DNS and in the hosts file as necessary.
However, in some cases, the real server's name may be different from the public DNS name. In this case, you can do the following:
from grpc._cython.cygrpc import CompressionAlgorithm
from grpc._cython.cygrpc import CompressionLevel
def run():
global text
creds = grpc.ssl_channel_credentials(open('cert.pem', 'rb').read())
chan_ops = [('grpc.default_compression_algorithm', CompressionAlgorithm.gzip),
('grpc.grpc.default_compression_level', CompressionLevel.high),
('grpc.ssl_target_name_override', 'real_server_name')]
channel = grpc.secure_channel('system_name:50001', creds, chan_ops)
stub = helloworld_pb2.GreeterStub(channel)
response = stub.SayHello(helloworld_pb2.HelloRequest(name=text))
print("Client received: " + response.message)
if __name__ == '__main__':
run()
|
Security >