Skip to content

Commit

Permalink
add platform init script
Browse files Browse the repository at this point in the history
  • Loading branch information
Ralf Grubenmann committed Apr 10, 2024
1 parent 82156d3 commit f448637
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 13 deletions.
26 changes: 13 additions & 13 deletions scripts/init-db/utils.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,13 @@
import base64
import logging

import requests
from kubernetes import client, config
from kubernetes.config.config_exception import ConfigException
from kubernetes.config.incluster_config import (
SERVICE_CERT_FILENAME,
SERVICE_TOKEN_FILENAME,
InClusterConfigLoader,
)

from psycopg2 import connect
from tenacity import (
before_sleep_log,
retry, stop_after_attempt,
stop_after_delay,
before_sleep_log,
retry,
stop_after_attempt,
stop_after_delay,
wait_fixed,
)

Expand All @@ -29,10 +23,16 @@ def get_db_connection(*args, **kwargs):
return connect(*args, **kwargs, connect_timeout=10)


@retry(stop=(stop_after_attempt(200) | stop_after_delay(600)), wait=wait_fixed(3), reraise=True)
@retry(
stop=(stop_after_attempt(200) | stop_after_delay(600)),
wait=wait_fixed(3),
reraise=True,
)
def gitlab_is_online(url: str) -> int:
logging.info("Waiting for gitlab to come online...")
res = requests.get(url, timeout=10)
if res.status_code != 200:
raise ValueError(f"Gitlab is not available at {url}, status code is {res.status_code}")
raise ValueError(
f"Gitlab is not available at {url}, status code is {res.status_code}"
)
return res.status_code
7 changes: 7 additions & 0 deletions scripts/platform-init/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FROM python:3.12-alpine

COPY requirements.txt platform-init.py /app/
WORKDIR /app
RUN pip install -r requirements.txt
USER 1000:1000

95 changes: 95 additions & 0 deletions scripts/platform-init/platform-init.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import logging
from kubernetes import client as k8s_client, config as k8s_config
from dataclasses import dataclass, field
import os
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization


@dataclass
class Config:
k8s_namespace: str
renku_fullname: str
secret_service_public_key: str | None
secret_service_private_key: str | None = field(repr=False)

@classmethod
def from_env(cls):
return cls(
k8s_namespace=os.environ["K8S_NAMESPACE"],
renku_fullname=os.environ["RENKU_FULLNAME"],
secret_service_public_key=os.environ.get("SECRET_SERVICE_PUBLIC_KEY"),
secret_service_private_key=os.environ.get("SECRET_SERVICE_SECRET_KEY"),
)


def init_secret_service_secret(config: Config):
logging.info("Initializing secret service secret")
v1 = k8s_client.CoreV1Api()

private_key_secret = f"{config.renku_fullname}-secret-service-private-key"
try:
existing_private_key = v1.read_namespaced_secret(
private_key_secret, config.k8s_namespace
)
except k8s_client.rest.ApiException:
existing_private_key = None

public_key_secret = f"{config.renku_fullname}-secret-service-public-key"
try:
existing_public_key = v1.read_namespaced_secret(
public_key_secret, config.k8s_namespace
)
except k8s_client.rest.ApiException:
existing_public_key = None
if existing_private_key is None and config.secret_service_private_key is None:
# generate new secret
private_key = rsa.generate_private_key(public_exponent=65537, key_size=4096)
private_key_pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption(),
)
v1.create_namespaced_secret(
config.k8s_namespace,
k8s_client.V1Secret(
api_version="v1",
data={"private_key": private_key_pem.decode()},
kind="Secret",
metadata={"name": private_key_secret},
type="Opaque",
),
)
elif (
existing_private_key != config.secret_service_private_key
and config.secret_service_private_key is not None
):
# update private key
private_key = serialization.load_pem_private_key(
config.secret_service_private_key.encode(), password=None
)
v1.create_namespaced_secret(
config.k8s_namespace,
k8s_client.V1Secret(
api_version="v1",
data={"private_key": config.secret_service_private_key},
kind="Secret",
metadata={"name": private_key_secret},
type="Opaque",
),
)
else:
private_key = serialization.load_pem_private_key(
existing_private_key.encode(), password=None
)


def main():
config = Config.from_env()
k8s_config.load_kube_config()
logging.info("Initializing Renku platform")
init_secret_service_secret(config)


if __name__ == "__main__":
main()
2 changes: 2 additions & 0 deletions scripts/platform-init/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
kubernetes==29.0.0
cryptography==42.0.5

0 comments on commit f448637

Please sign in to comment.