You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
generated-secret-operator/generated-secret-operator.py

93 lines
3.2 KiB

#!/usr/bin/env python3
import asyncio
import os
import prometheus_async
import random
import string
from passlib.context import CryptContext
from prometheus_client import Counter, Gauge
from kubernetes_asyncio.client.api_client import ApiClient
from kubernetes_asyncio.client.exceptions import ApiException
from kubernetes_asyncio import client, config, watch
from time import time
counter_opened_watch_streams = Counter(
"meta_operator_opened_watch_streams",
"Count of watch streams opened")
gauge_watch_stream_begin_timestamp = Gauge(
"meta_operator_watch_stream_begin_timestamp",
"Timestamp of last watch stream open")
bcrypt_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
async def apply_changes(item, v1, apps_api, api_instance):
namespace = item["metadata"]["namespace"]
name = item["metadata"]["name"]
password = "".join([random.choice(string.ascii_letters + string.digits) for j in range(item["spec"]["size"])])
data = {}
for o in item["spec"]["mapping"]:
data[o["key"]] = o["value"] % {
"name": name,
"namespace": namespace,
"password": password,
"bcrypt": bcrypt_context.hash(password),
}
try:
await v1.create_namespaced_secret(namespace, body={
"metadata": {
"name": name,
"annotations": {},
"ownerReferences": [{
"apiVersion": "codemowers.io/v1alpha1",
"kind": "GeneratedSecret",
"uid": item["metadata"]["uid"],
"name": name
}]
},
"stringData": data
})
print("Generated secret %s/%s" % (namespace, name))
except ApiException as e:
if e.status == 409:
print("Secret %s/%s already generated" % (namespace, name))
else:
raise
async def main():
if os.getenv("KUBECONFIG"):
await config.load_kube_config()
else:
config.load_incluster_config()
async with ApiClient() as api:
v1 = client.CoreV1Api(api)
apps_api = client.AppsV1Api()
api_instance = client.CustomObjectsApi(api)
while True:
try:
gauge_watch_stream_begin_timestamp.set(time())
print("Subscribing to updates in every namespace")
w = watch.Watch()
counter_opened_watch_streams.inc()
flt = "codemowers.io", "v1alpha1", "", "generatedsecrets"
method = api_instance.list_namespaced_custom_object
async for event in w.stream(method, *flt):
if event["type"] == "ADDED":
await apply_changes(event["object"], v1, apps_api, api_instance)
except ApiException as e:
print("Caught exception: %s" % e)
if e.status == 410:
pass
else:
raise
except asyncio.exceptions.TimeoutError:
pass
if __name__ == "__main__":
loop = asyncio.new_event_loop()
loop.create_task(prometheus_async.aio.web.start_http_server(port=5000))
loop.run_until_complete(main())
loop.close()