Skip to content

Instantly share code, notes, and snippets.

@mtourne
Last active July 6, 2022 16:30
Show Gist options
  • Save mtourne/48426111b121bf007a50 to your computer and use it in GitHub Desktop.
Save mtourne/48426111b121bf007a50 to your computer and use it in GitHub Desktop.
zerorpc with zmq curve

Example of using zerorpc over zmq curve - for transport encryption and client / server authentication

this is modeled after the pyzmq security ironhouse example, where both endpoints are authed :

https://github.com/zeromq/pyzmq/blob/master/examples/security/ironhouse.py

Prerequisites

zmq curve enabled : brew install zmq --with-libsodium

installing pyzmq, and generate the certs

git clone https://github.com/zeromq/pyzmq`
cd pyzmq

(in a virtenv)

python setup.py install
cd examples/security
python generate_certificates
python ironhouse.py

[INFO] Ironhouse test OK

cd ../../..

installing zerorpc-python

git clone https://github.com/0rpc/zerorpc-python
cd zerorpc-python

(in a virtenv)

python setup.py install
cd ..

Running

(in this gist path)

cp -R pyzmq/examples/security/public_keys .
cp -R pyzmq/examples/security/private_keys .
cp -R pyzmq/examples/security/certificates .

python server_curve.py

endpoint: tcp://127.0.0.1:5555

Secure transport

python client_curve.py 'tcp://127.0.0.1:5555' echo foo

Secure transport

connecting to "tcp://127.0.0.1:5555"

'foo'

#!/usr/bin/env python
from pprint import pprint
import os
import zerorpc
import zmq
import zmq.auth
from zerorpc.cli import parser
SECURE = True
base_dir = os.path.dirname(__file__)
keys_dir = os.path.join(base_dir, 'certificates')
public_keys_dir = os.path.join(base_dir, 'public_keys')
secret_keys_dir = os.path.join(base_dir, 'private_keys')
def setup_links(args, socket):
if args.bind:
for endpoint in args.bind:
print 'binding to "{0}"'.format(endpoint)
socket.bind(endpoint)
addresses = []
if args.address:
addresses.append(args.address)
if args.connect:
addresses.extend(args.connect)
for endpoint in addresses:
print 'connecting to "{0}"'.format(endpoint)
socket.connect(endpoint)
def client(args):
ctx = zerorpc.Context.get_instance()
client = zerorpc.Client(timeout=args.timeout, heartbeat=args.heartbeat,
passive_heartbeat=not args.active_hb)
zmq_socket = client._events._socket
if SECURE:
print("Secure transport")
# We need two certificates, one for the client and one for
# the server. The client must know the server's public key
# to make a CURVE connection.
client_secret_file = os.path.join(secret_keys_dir, "client.key_secret")
client_public, client_secret = zmq.auth.load_certificate(client_secret_file)
zmq_socket.curve_secretkey = client_secret
zmq_socket.curve_publickey = client_public
server_public_file = os.path.join(public_keys_dir, "server.key")
server_public, _ = zmq.auth.load_certificate(server_public_file)
# The client must know the server's public key to make a CURVE connection.
zmq_socket.curve_serverkey = server_public
setup_links(args, client)
call_args = args.params
results = client(args.command, *call_args)
pprint(results)
def main():
args = parser.parse_args()
if args.bind or args.connect:
if args.command:
args.params.insert(0, args.command)
args.command = args.address
args.address = None
if not (args.bind or args.connect or args.address):
parser.print_help()
return -1
return client(args)
if __name__ == "__main__":
main()
#!/usr/bin/env python
import gevent
import os
import zerorpc
import zmq.auth
from zmq.auth.thread import ThreadAuthenticator
SECURE = True
base_dir = os.path.dirname(__file__)
keys_dir = os.path.join(base_dir, 'certificates')
public_keys_dir = os.path.join(base_dir, 'public_keys')
secret_keys_dir = os.path.join(base_dir, 'private_keys')
class Srv:
def echo(self, msg):
return msg
def run_server():
# XX (mtourne): maybe there is a way to do this with a zerorpc "Middleware"
# zerorpc.Context.get_instance().register_middleware(SharedSecretMiddleware('some_random_key'))
# server = zerorpc.Server(server_obj, heartbeat=args.heartbeat)
# endpoint = random_ipc_endpoint()
endpoint = 'tcp://127.0.0.1:5555'
print("endpoint: {}".format(endpoint))
# srv_relay = zerorpc.Server(SrvRelay(), context=srv_relay_ctx)
srv = zerorpc.Server(Srv())
ctx = zerorpc.Context.get_instance()
auth = ThreadAuthenticator(ctx)
auth.start()
auth.allow('127.0.0.1')
# Tell authenticator to use the certificate in a directory
auth.configure_curve(domain='*', location=public_keys_dir)
zmq_socket = srv._events._socket
server_secret_file = os.path.join(secret_keys_dir, "server.key_secret")
server_public, server_secret = zmq.auth.load_certificate(server_secret_file)
if SECURE:
print("Secure transport")
zmq_socket.curve_secretkey = server_secret
zmq_socket.curve_publickey = server_public
zmq_socket.curve_server = True
srv.bind(endpoint)
srv_task = gevent.spawn(srv.run)
srv_task.join()
def main():
run_server()
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment