Fix application specific password handling
All checks were successful
continuous-integration/drone Build is passing
All checks were successful
continuous-integration/drone Build is passing
This commit is contained in:
parent
8a39056599
commit
817acc3ecf
44
deployment.yaml
Normal file
44
deployment.yaml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
---
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: wildduck-exporter
|
||||||
|
namespace: wildduck
|
||||||
|
spec:
|
||||||
|
replicas: 1
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: wildduck-exporter
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: wildduck-exporter
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: wildduck-exporter
|
||||||
|
image: harbor.k-space.ee/k-space/wildduck-exporter
|
||||||
|
securityContext:
|
||||||
|
readOnlyRootFilesystem: true
|
||||||
|
runAsNonRoot: true
|
||||||
|
runAsUser: 65534
|
||||||
|
command:
|
||||||
|
- /wildduck_exporter.py
|
||||||
|
args:
|
||||||
|
- info
|
||||||
|
- accounting
|
||||||
|
ports:
|
||||||
|
- containerPort: 3001
|
||||||
|
name: metrics
|
||||||
|
env:
|
||||||
|
- name: MONGODB_HOST
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: wildduck
|
||||||
|
key: MONGO_URI
|
||||||
|
- name: PROMETHEUS_BEARER_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: wildduck-exporter
|
||||||
|
key: PROMETHEUS_BEARER_TOKEN
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: regcred
|
18
skaffold.yaml
Normal file
18
skaffold.yaml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
apiVersion: skaffold/v3
|
||||||
|
kind: Config
|
||||||
|
metadata:
|
||||||
|
name: wildduck-exporter
|
||||||
|
build:
|
||||||
|
artifacts:
|
||||||
|
- docker:
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
image: harbor.k-space.ee/k-space/wildduck-exporter
|
||||||
|
deploy:
|
||||||
|
kubectl:
|
||||||
|
flags:
|
||||||
|
global:
|
||||||
|
- --namespace=wildduck
|
||||||
|
manifests:
|
||||||
|
rawYaml:
|
||||||
|
- deployment.yaml
|
@ -1,7 +1,9 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
from motor.motor_asyncio import AsyncIOMotorClient
|
from motor.motor_asyncio import AsyncIOMotorClient
|
||||||
from sanic import Sanic, response, exceptions
|
from sanic import Sanic, exceptions
|
||||||
|
from sanic.log import logger
|
||||||
|
|
||||||
MONGODB_HOST = os.getenv("MONGODB_HOST")
|
MONGODB_HOST = os.getenv("MONGODB_HOST")
|
||||||
if not MONGODB_HOST:
|
if not MONGODB_HOST:
|
||||||
@ -12,6 +14,7 @@ if not PROMETHEUS_BEARER_TOKEN:
|
|||||||
raise ValueError("No PROMETHEUS_BEARER_TOKEN specified")
|
raise ValueError("No PROMETHEUS_BEARER_TOKEN specified")
|
||||||
|
|
||||||
app = Sanic("exporter")
|
app = Sanic("exporter")
|
||||||
|
usernames = list(set(sys.argv[1:]))
|
||||||
|
|
||||||
|
|
||||||
@app.listener("before_server_start")
|
@app.listener("before_server_start")
|
||||||
@ -32,30 +35,44 @@ async def wrap(i, prefix="wildduck_"):
|
|||||||
|
|
||||||
|
|
||||||
async def fetch():
|
async def fetch():
|
||||||
async for u in app.ctx.db.users.find():
|
last_login = {}
|
||||||
|
user_labels = {}
|
||||||
|
args = []
|
||||||
|
if usernames:
|
||||||
|
args.append({"username": {"$in": usernames}})
|
||||||
|
async for u in app.ctx.db.users.find(*args):
|
||||||
labels = {
|
labels = {
|
||||||
"username": u["username"],
|
"username": u["username"],
|
||||||
"email": u["address"],
|
"email": u["address"],
|
||||||
}
|
}
|
||||||
|
user_labels[u["_id"]] = labels
|
||||||
|
|
||||||
if u["lastLogin"]["time"]:
|
if u["lastLogin"]["time"]:
|
||||||
yield "last_login", "gauge", u["lastLogin"]["time"].timestamp(), labels
|
last_login[u["_id"]] = u["lastLogin"]["time"]
|
||||||
|
|
||||||
if u["storageUsed"]:
|
if u["storageUsed"]:
|
||||||
yield "storage_used", "gauge", u["storageUsed"], labels
|
yield "storage_used", "gauge", u["storageUsed"], labels
|
||||||
if u["targets"]:
|
if u["targets"]:
|
||||||
yield "forwarding_addresses", "gauge", len(u["targets"]), labels
|
yield "forwarding_addresses", "gauge", len(u["targets"]), labels
|
||||||
yield "account_enabled", "gauge", not u["disabled"], labels
|
yield "account_enabled", "gauge", not u["disabled"], labels
|
||||||
|
|
||||||
|
# Merge application specific passwords last used timestamps
|
||||||
|
async for a in app.ctx.db.asps.find({"user": {"$in": list(last_login.keys())}}):
|
||||||
|
if a["used"] > last_login[a["user"]]:
|
||||||
|
last_login[a["user"]] = a["used"]
|
||||||
|
|
||||||
|
for user, dt in last_login.items():
|
||||||
|
yield "last_login", "gauge", dt.timestamp(), user_labels[user]
|
||||||
|
|
||||||
|
|
||||||
@app.route("/metrics")
|
@app.route("/metrics")
|
||||||
async def view_export(request):
|
async def view_export(request):
|
||||||
if request.token != PROMETHEUS_BEARER_TOKEN:
|
if request.token != PROMETHEUS_BEARER_TOKEN:
|
||||||
raise exceptions.Forbidden("Invalid bearer token")
|
raise exceptions.Forbidden("Invalid bearer token")
|
||||||
|
response = await request.respond(content_type="text/plain")
|
||||||
|
async for line in wrap(fetch()):
|
||||||
|
await response.send(line + "\n")
|
||||||
|
|
||||||
async def streaming_fn(response):
|
|
||||||
async for line in wrap(fetch()):
|
|
||||||
await response.write(line + "\n")
|
|
||||||
|
|
||||||
return response.stream(streaming_fn, content_type="text/plain")
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app.run(host="0.0.0.0", port=3001, single_process=True)
|
app.run(host="0.0.0.0", port=3001, single_process=True)
|
||||||
|
Loading…
Reference in New Issue
Block a user