OpenZiti Python SDK: Introduction

OpenZiti Python SDK: Introduction

Ziti Python SDK: Intro

OpenZiti project adds security layers that make your service available without exposing incoming ports, provides identity-specific end-to-end encryption, masks your network traffic protocols/ports, and allows developers to be more agile and secure than ever in all networking scenarios.

In our previous posts, we introduced the concept of Zitification -- taking an app and changing it to use a secure, zero-trust, overlay network -- and shared a few examples we developed internally.

This article will show how to zitify your Python applications with minor code changes.

Ziggy Loves Python.jpg

Setup

There are several ways to get started with OpenZiti.

  • follow instructions from previous posts

  • read quickstart docs

  • and even play in our sandbox/ZEDS -- fastest way to start. Ziti Edge Developer Sandbox(ZEDS) hosts a multi-tenant Ziti network.

Acquiring SDK

OpenZiti Python SDK is published to Python Package Index(PyPI) so just go ahead with standard install, or add it to your application's requirements.txt

$ pip install openziti

Basic Usage

In the following code examples the following is assumed (read more about Ziti identities and services):

  • id.jwt - enrollment token file

  • id.json - ziti identity file

  • best-service-ever - name of the ziti service

Ziti identity enrollment

$ python -m openziti enroll --jwt id.jwt --identity id.json

Open connection to Ziti service

import openziti

# load ziti context, provide full path to identity file if needed
ztx = openziti.load('id.json')

conn = ztx.connect('best-service-ever')

# do cool stuff here with conn (socket)

you can also connect with an intercepted address (each service may have one or more standard network address [protocol, host, port]):

conn = ztx.connect(('httpbin.ziti', 80))

Host(serve) Ziti service

import openziti

ztx = openziti.load(ziti_id)
server = ztx.bind(service)
server.listen()

while True:
    # conn is the incoming connection(socket)
    # peer is a tuple (connecting identity, 0)
    conn, peer = server.accept()

    # do some cool interaction with your client

It's 2022: WDIMMOS*?!!

*WDIMMOS: why do I manage my own sockets

Obviously when you develop your cool Python application you probably would not start with writing your own networking layer. Instead, you'd use excellent networking capabilities of Python standard library or other modules to do networking for you. The good news is that you can use OpenZiti SDK with other networking modules.

Client Side

For example, let's say you want to make an HTTP request with requests, urllib3, or even urllib:

import requests

r = requests.get('http://httpbin.org/json')
print(r.headers)
print(r.json())

In order to make requests library use Ziti socket, we monkeypatch the code. In this case you can request(get it?) with an intercepted address.

import requests
import openziti

ztx = openziti.load('id.json')

with openziti.monkeypatch():
    # FIY, httpbin.ziti is a common service you can use in our sandbox
    r = requests.get('http://httpbin.ziti/json')
    print(r.headers)
    print(r.json())

Server Side

On the hosting server side we need inform the monkey patching code what it needs to do when underlying networking code binds to an address. This is done via bindings parameter to the monkeypatch() method. The value must be a map from network address(host, port) to the Ziti context/service -- like this:

import sys
from http.server import BaseHTTPRequestHandler, HTTPServer
import openziti

class MyServer(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.send_header("Content-type", "application/json")
        self.end_headers()
        msg = """{"msg": "Hello! Have some ziti!"}"""
        self.wfile.write(bytes(msg, "utf-8"))

if __name__ == "__main__":
    bind_addr = ('localhost', 8080)
    srv_addr = {
        ztx: 'id.json',
        service: 'best-service-ever'
    }
    # map network bind address to Ziti Service target
    bind_map = { bind_addr: srv_addr }

    openziti.monkeypatch(bindings=bind_map)
    webServer = HTTPServer(bind_addr, MyServer)
    webServer.serve_forever(poll_interval=600)

Next Steps

We would love to hear from you about your applications and if decide that OpenZiti is the right fit to secure them.

Checkout some of our projects that use OpenZiti Python SDK:

Follow us: