Skip to content

Commit

Permalink
Merge pull request #12 from openziti/ziti-hosting
Browse files Browse the repository at this point in the history
Ziti hosting
  • Loading branch information
ekoby authored Jun 10, 2022
2 parents 134f247 + 5c4d947 commit 59831f9
Show file tree
Hide file tree
Showing 12 changed files with 320 additions and 49 deletions.
10 changes: 6 additions & 4 deletions sample/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,12 @@ OpenZiti Python SDK in Action

- get yourself a Ziti identity from [ZEDS](https://zeds.openziti.org)

follow enrollment instructions from the site.
these instructions assume that Ziti identity is stored in `id.json` file

_Enrollment with Python is coming soon_
follow enrollment instructions from the site, or better yet enroll with openziti Python module
```bash
$ python -m openziti enroll --jwt=<enrollment token file> --identity=<identity file>
```

the following instructions assume that Ziti identity is stored in `id.json` file


- set `ZITI_IDENTITIES` environment variable to location of `id.json` file
Expand Down
39 changes: 39 additions & 0 deletions sample/flask-of-ziti/helloFlazk.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright (c) NetFoundry Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from flask import Flask
import openziti
import sys

app = Flask(__name__)
bind_opts = {} # populated in main


@openziti.zitify(bindings={
('1.2.3.4', '18080'): bind_opts
})
def runApp():
from waitress import serve
serve(app,host='1.2.3.4',port=18080)


@app.route('/')
def hello_world(): # put application's code here
return 'Have some Ziti!'


if __name__ == '__main__':
bind_opts['ztx'] = sys.argv[1]
bind_opts['service'] = sys.argv[2]
runApp()
3 changes: 3 additions & 0 deletions sample/flask-of-ziti/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
flask
waitress
openziti
17 changes: 17 additions & 0 deletions sample/http-get.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import sys

import urllib3
import openziti

# to run this sample
# set ZITI_IDENTITIES environment variable to location of your Ziti identity file
#
# python http-get.py <url>
# url should be the intercept address of a ziti service
if __name__ == '__main__':
openziti.monkeypatch()
http = urllib3.PoolManager()
r = http.request('GET', sys.argv[1])
print("{0} {1}".format(r.status, r.reason))
print(r.data.decode('utf-8'))

39 changes: 39 additions & 0 deletions sample/ziti-echo-server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright (c) NetFoundry Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import sys
import openziti


def run(ziti_id, service):
ztx = openziti.load(ziti_id)
server = ztx.bind(service)
server.listen()

while True:
conn, peer = server.accept()
print(f'processing incoming client[{peer}]')
with conn:
count = 0
while True:
data = conn.recv(1024)
if not data:
print(f'client finished after sending {count} bytes')
break
count += len(data)
conn.sendall(data)


if __name__ == '__main__':
run(sys.argv[1], sys.argv[2])
49 changes: 49 additions & 0 deletions sample/ziti-http-server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Copyright (c) NetFoundry Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import sys
from http.server import BaseHTTPRequestHandler, HTTPServer
import time

import openziti

hostName = "localhost"
serverPort = 8080

cfg = dict(
ztx=sys.argv[1],
service=sys.argv[2]
)
openziti.monkeypatch(bindings={(hostName, serverPort): cfg})


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


if __name__ == "__main__":
webServer = HTTPServer((hostName, serverPort), MyServer)
print("Server started http://%s:%s" % (hostName, serverPort))

try:
webServer.serve_forever(poll_interval=600)
except KeyboardInterrupt:
pass

webServer.server_close()
print("Server stopped.")
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ tag_prefix = v
parentdir_prefix = openziti-

[openziti]
ziti_sdk_version = 0.28.4
ziti_sdk_version = 0.28.7
33 changes: 3 additions & 30 deletions src/openziti/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import socket as sock
from os import getenv

from . import _version, context, zitilib, zitisock
from . import _version, context, zitilib, zitisock, decor

_ziti_identities = filter(lambda p: p != '',
map(lambda s: s.strip(),
(getenv('ZITI_IDENTITIES') or "").split(';')))

_id_map = {}

zitilib.init()

enroll = zitilib.enroll
version = zitilib.version
shutdown = zitilib.shutdown
Expand All @@ -35,30 +30,8 @@
if identity != '':
load(identity)

_patch_methods = {
"create_connection": zitisock.create_ziti_connection,
"getaddrinfo": zitisock.ziti_getaddrinfo
}


class MonkeyPatch():
def __init__(self):
self.orig_socket = sock.socket
sock.socket = zitisock.ZitiSocket
self.orig_methods = {m: sock.__dict__[m] for m, _ in
_patch_methods.items()}
for m_name, _ in _patch_methods.items():
sock.__dict__[m_name] = _patch_methods[m_name]

def __enter__(self):
return self

def __exit__(self, exc_type, exc_val, exc_tb):
for m_name, _ in self.orig_methods.items():
sock.__dict__[m_name] = self.orig_methods[m_name]


monkeypatch = MonkeyPatch # pylint: disable=invalid-name
monkeypatch = decor.MonkeyPatch # pylint: disable=invalid-name
zitify = decor.zitify

__version__ = _version.get_versions()['version']
del _version
31 changes: 26 additions & 5 deletions src/openziti/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,42 @@

import socket

from . import zitilib
from . import zitilib, zitisock


class ZitiContext:
# pylint: disable=too-few-public-methods
def __init__(self, ctx_p):
self._ctx = ctx_p
def __init__(self, ctx):
ztx = ctx
if isinstance(ctx, str):
ztx = zitilib.load(ctx)
self._ctx = ztx

def connect(self, addr):
# pylint: disable=invalid-name
fd = zitilib.ziti_socket(socket.SOCK_STREAM)
service = bytes(addr, encoding="utf-8")
zitilib.ziti_connect(fd, self._ctx, service)
if addr is str:
zitilib.connect(fd, self._ctx, addr)
elif addr is tuple:
zitilib.connect_addr(fd, addr)
else:
raise RuntimeError(f'unsupported address {addr}')
return socket.socket(socket.AF_UNIX, socket.SOCK_STREAM, 0, fd)

def bind(self, service, sock=None):
if sock is None:
sock = zitisock.ZitiSocket(type=socket.SOCK_STREAM)
zitilib.bind(sock.fileno(), self._ctx, service)
return sock


def load_identity(path) -> ZitiContext:
return ZitiContext(zitilib.load(path))


def get_context(ztx) -> ZitiContext:
if isinstance(ztx, ZitiContext):
return ztx
if isinstance(ztx, str):
return ZitiContext(ztx)
raise RuntimeError(f'{ztx} is not a Ziti Context or a path')
56 changes: 56 additions & 0 deletions src/openziti/decor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copyright (c) NetFoundry Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import socket as sock
from . import zitisock


_patch_methods = {
"create_connection": zitisock.create_ziti_connection,
"getaddrinfo": zitisock.ziti_getaddrinfo
}


def _patchedSocket(patch_opts):
class patchedSocket(zitisock.ZitiSocket):
def __init__(self, *args, **kwargs):
super().__init__(*args, **dict(kwargs, opts=patch_opts))
return patchedSocket


class MonkeyPatch():
def __init__(self, **kwargs):
self.orig_socket = sock.socket
sock.socket = _patchedSocket(kwargs)
self.orig_methods = {m: sock.__dict__[m] for m, _ in
_patch_methods.items()}
for m_name, _ in _patch_methods.items():
sock.__dict__[m_name] = _patch_methods[m_name]

def __enter__(self):
return self

def __exit__(self, exc_type, exc_val, exc_tb):
for m_name, _ in self.orig_methods.items():
sock.__dict__[m_name] = self.orig_methods[m_name]




def zitify(**zkwargs):
def zitify_func(func):
def zitified(*args, **kwargs):
with MonkeyPatch(**zkwargs):
func(*args, **kwargs)
return zitified
return zitify_func
Loading

0 comments on commit 59831f9

Please sign in to comment.