Update Kubernetes Services Wiki / Generate and Update K8s Wiki (push) Successful in 9s
76 lines
2.7 KiB
Python
76 lines
2.7 KiB
Python
"""Publish client links for every external node, using its public DNS name."""
|
|
|
|
import base64
|
|
import json
|
|
import urllib.error
|
|
import urllib.parse
|
|
import urllib.request
|
|
|
|
|
|
API = "https://kubernetes.default.svc"
|
|
NAMESPACE = open("/var/run/secrets/kubernetes.io/serviceaccount/namespace", encoding="utf-8").read().strip()
|
|
TOKEN = open("/var/run/secrets/kubernetes.io/serviceaccount/token", encoding="utf-8").read().strip()
|
|
CA = "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
|
|
|
|
|
|
def request(method, path, body=None):
|
|
import ssl
|
|
|
|
data = json.dumps(body).encode() if body is not None else None
|
|
req = urllib.request.Request(
|
|
API + path,
|
|
data=data,
|
|
method=method,
|
|
headers={
|
|
"Authorization": "Bearer " + TOKEN,
|
|
"Content-Type": "application/json",
|
|
},
|
|
)
|
|
with urllib.request.urlopen(req, context=ssl.create_default_context(cafile=CA), timeout=15) as response:
|
|
return json.load(response)
|
|
|
|
|
|
def publish(name, links):
|
|
path = f"/api/v1/namespaces/{NAMESPACE}/secrets"
|
|
data = {node: base64.b64encode(link.encode()).decode() for node, link in links.items()}
|
|
try:
|
|
current = request("GET", f"{path}/{name}")
|
|
except urllib.error.HTTPError as error:
|
|
if error.code != 404:
|
|
raise
|
|
request("POST", path, {"apiVersion": "v1", "kind": "Secret", "metadata": {"name": name}, "type": "Opaque", "data": data})
|
|
return
|
|
if current.get("data", {}) == data:
|
|
return
|
|
# PUT replaces the data map, removing links for nodes that are no longer external.
|
|
request("PUT", f"{path}/{name}", {
|
|
"apiVersion": "v1",
|
|
"kind": "Secret",
|
|
"metadata": {"name": name, "resourceVersion": current["metadata"]["resourceVersion"]},
|
|
"type": "Opaque",
|
|
"data": data,
|
|
})
|
|
|
|
|
|
secret = open("/config/SECRET", encoding="utf-8").read().strip()
|
|
if len(secret) != 32 or any(char not in "0123456789abcdefABCDEF" for char in secret):
|
|
raise ValueError("Vaultwarden Secret must be 32 hexadecimal characters")
|
|
|
|
selector = urllib.parse.quote("homelab.hexor.cy/exposure=external", safe="")
|
|
nodes = request("GET", f"/api/v1/nodes?labelSelector={selector}")["items"]
|
|
if not nodes:
|
|
raise ValueError("No external nodes found")
|
|
|
|
classic = {}
|
|
tls = {}
|
|
for node in nodes:
|
|
name = node["metadata"]["name"]
|
|
# DNS is maintained outside the cluster; no public IP needs to be stored on a Node.
|
|
host = f"{name}.hexor.cy"
|
|
classic[name] = f"tg://proxy?server={host}&port=30443&secret={secret}"
|
|
tls[name] = f"tg://proxy?server={host}&port=30444&secret=ee{secret}79612e7275"
|
|
|
|
publish("mtproxy-links", classic)
|
|
publish("telemt-links", tls)
|
|
print(f"Published MTProxy links for {len(nodes)} external nodes")
|