-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathcmcvncproxy.py
119 lines (92 loc) · 2.89 KB
/
cmcvncproxy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#
# Work-in-progress jwt-authz/authn'ed websocket VNC server integrated with
# hscloud/cmc-proxy (Warsaw Hackerspace Dell M1000e management)
#
import os
import mimetypes
from http.server import HTTPStatus
import urllib.parse
import logging
import websockets
import asyncio
import jwt
import grpc
from client import KVMClient
from vncproxy import VNCHandler
import proxy_pb2
import proxy_pb2_grpc
config = {
"jwt_secret": "secret",
}
def serve_static(path):
"""
Returns a static files server for specified path to be used as
`process_request` handler with websockets
"""
base = os.path.abspath(path)
mimetypes.init()
async def handler(path, headers):
path = urllib.parse.urlparse(path).path
if path == "/":
path = "index.html"
else:
path = path[1:]
target = os.path.abspath(os.path.join(base, path))
if not target.startswith(base) or not os.path.exists(target):
return None
with open(target, "rb") as fd:
return (
HTTPStatus.OK,
{
"content-type": mimetypes.guess_type(path)[0],
},
fd.read(),
)
return handler
def read_key(name):
with open(
"/home/informatic/gopath/src/code.hackerspace.pl/hscloud/go/svc/cmc-proxy/pki/%s"
% name,
"rb",
) as fd:
return fd.read()
def grpc_connect():
credentials = grpc.ssl_channel_credentials(
root_certificates=read_key("ca.pem"),
private_key=read_key("service-key.pem"),
certificate_chain=read_key("service.pem"),
)
channel = grpc.secure_channel("cmc-proxy.dev.svc.cluster.local:4200", credentials)
stub = proxy_pb2_grpc.CMCProxyStub(channel)
return stub
if __name__ == "__main__":
HOST, PORT = "0.0.0.0", 8081
logger = logging.getLogger("proxy")
loop = asyncio.get_event_loop()
async def handler(websocket, path):
logger.info("Incoming conection on %s" % path)
token = path.split("/")[-1]
data = jwt.decode(token, config["jwt_secret"], algorithms=["HS256"])
if "blade" not in data or data["blade"] < 1 or data["blade"] > 16:
logger.warning("Invalid data?")
return
stub = grpc_connect()
arguments = stub.GetKVMData(
proxy_pb2.GetKVMDataRequest(blade_num=data["blade"])
).arguments
logger.debug("KVM arguments: %r", arguments)
client = KVMClient.from_arguments(arguments)
handler = VNCHandler(websocket, client, loop)
try:
await handler.handle()
finally:
handler.finish()
start_server = websockets.serve(
handler,
HOST,
PORT,
subprotocols=["binary"],
process_request=serve_static("./noVNC-1.0.0/"),
)
loop.run_until_complete(start_server)
loop.run_forever()