From ccb8f71d4708b55a63d31fe8268f427b465cea94 Mon Sep 17 00:00:00 2001 From: Maarten de Waard <maarten@greenhost.nl> Date: Wed, 11 Aug 2021 14:50:47 +0200 Subject: [PATCH] first version of python script that can check if a secret exists, and generate it if necessary --- charts/oas-secrets/.helmignore | 23 --- charts/oas-secrets/Chart.yaml | 28 ---- charts/oas-secrets/templates/NOTES.txt | 1 - charts/oas-secrets/templates/_helpers.tpl | 84 ---------- .../oas-alertmanager-basic-auth.yaml | 12 -- .../oas-kube-prometheus-stack-variables.yaml | 7 - .../templates/oas-nextcloud-variables.yaml | 12 -- .../templates/oas-oauth-variables.yaml | 12 -- .../templates/oas-prometheus-basic-auth.yaml | 11 -- .../templates/oas-rocketchat-variables.yaml | 8 - .../oas-single-sign-on-variables.yaml | 10 -- .../templates/oas-wekan-variables.yaml | 7 - .../templates/oas-wordpress-variables.yaml | 9 -- charts/oas-secrets/values.yaml | 6 - install/generate_secret.py | 145 ++++++++++++++++++ install/install-app.sh | 4 + install/install-openappstack.sh | 3 + .../oas-alertmanager-basic-auth.yaml | 9 ++ .../oas-kube-prometheus-stack-variables.yaml | 7 + .../templates/oas-nextcloud-variables.yaml | 12 ++ install/templates/oas-oauth-variables.yaml | 12 ++ .../templates/oas-prometheus-basic-auth.yaml | 10 ++ .../templates/oas-rocketchat-variables.yaml | 8 + .../oas-single-sign-on-variables.yaml | 10 ++ install/templates/oas-wekan-variables.yaml | 7 + .../templates/oas-wordpress-variables.yaml | 9 ++ requirements.in | 6 +- requirements.txt | 23 ++- 28 files changed, 257 insertions(+), 238 deletions(-) delete mode 100644 charts/oas-secrets/.helmignore delete mode 100644 charts/oas-secrets/Chart.yaml delete mode 100644 charts/oas-secrets/templates/NOTES.txt delete mode 100644 charts/oas-secrets/templates/_helpers.tpl delete mode 100644 charts/oas-secrets/templates/oas-alertmanager-basic-auth.yaml delete mode 100644 charts/oas-secrets/templates/oas-kube-prometheus-stack-variables.yaml delete mode 100644 charts/oas-secrets/templates/oas-nextcloud-variables.yaml delete mode 100644 charts/oas-secrets/templates/oas-oauth-variables.yaml delete mode 100644 charts/oas-secrets/templates/oas-prometheus-basic-auth.yaml delete mode 100644 charts/oas-secrets/templates/oas-rocketchat-variables.yaml delete mode 100644 charts/oas-secrets/templates/oas-single-sign-on-variables.yaml delete mode 100644 charts/oas-secrets/templates/oas-wekan-variables.yaml delete mode 100644 charts/oas-secrets/templates/oas-wordpress-variables.yaml delete mode 100644 charts/oas-secrets/values.yaml create mode 100644 install/generate_secret.py create mode 100644 install/templates/oas-alertmanager-basic-auth.yaml create mode 100644 install/templates/oas-kube-prometheus-stack-variables.yaml create mode 100644 install/templates/oas-nextcloud-variables.yaml create mode 100644 install/templates/oas-oauth-variables.yaml create mode 100644 install/templates/oas-prometheus-basic-auth.yaml create mode 100644 install/templates/oas-rocketchat-variables.yaml create mode 100644 install/templates/oas-single-sign-on-variables.yaml create mode 100644 install/templates/oas-wekan-variables.yaml create mode 100644 install/templates/oas-wordpress-variables.yaml diff --git a/charts/oas-secrets/.helmignore b/charts/oas-secrets/.helmignore deleted file mode 100644 index 0e8a0eb36..000000000 --- a/charts/oas-secrets/.helmignore +++ /dev/null @@ -1,23 +0,0 @@ -# Patterns to ignore when building packages. -# This supports shell glob matching, relative path matching, and -# negation (prefixed with !). Only one pattern per line. -.DS_Store -# Common VCS dirs -.git/ -.gitignore -.bzr/ -.bzrignore -.hg/ -.hgignore -.svn/ -# Common backup files -*.swp -*.bak -*.tmp -*.orig -*~ -# Various IDEs -.project -.idea/ -*.tmproj -.vscode/ diff --git a/charts/oas-secrets/Chart.yaml b/charts/oas-secrets/Chart.yaml deleted file mode 100644 index cbc26985a..000000000 --- a/charts/oas-secrets/Chart.yaml +++ /dev/null @@ -1,28 +0,0 @@ ---- -apiVersion: v2 -name: secrets -description: | - A helm chart to generate secrets that are needed by other helm charts. Values - inside the secret will only be generated if they do not exist yet, so it is - safe to run `helm upgrade` on this chart. - -# A chart can be either an 'application' or a 'library' chart. -# -# Application charts are a collection of templates that can be packaged into versioned archives -# to be deployed. -# -# Library charts provide useful utilities or functions for the chart developer. They're included as -# a dependency of application charts to inject those utilities and functions into the rendering -# pipeline. Library charts do not define any templates and therefore cannot be deployed. -type: application - -# This is the chart version. This version number should be incremented each time you make changes -# to the chart and its templates, including the app version. -# Versions are expected to follow Semantic Versioning (https://semver.org/) -version: 0.1.9 - -# This is the version number of the application being deployed. This version number should be -# incremented each time you make changes to the application. Versions are not expected to -# follow Semantic Versioning. They should reflect the version the application is using. -# It is recommended to use it with quotes. -# appVersion: "0.1.0" diff --git a/charts/oas-secrets/templates/NOTES.txt b/charts/oas-secrets/templates/NOTES.txt deleted file mode 100644 index 5e349b352..000000000 --- a/charts/oas-secrets/templates/NOTES.txt +++ /dev/null @@ -1 +0,0 @@ -Secrets generated diff --git a/charts/oas-secrets/templates/_helpers.tpl b/charts/oas-secrets/templates/_helpers.tpl deleted file mode 100644 index d791991ea..000000000 --- a/charts/oas-secrets/templates/_helpers.tpl +++ /dev/null @@ -1,84 +0,0 @@ -{{/* -Expand the name of the chart. -*/}} -{{- define "secrets.name" -}} -{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Create a default fully qualified app name. -We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). -If release name contains chart name it will be used as a full name. -*/}} -{{- define "secrets.fullname" -}} -{{- if .Values.fullnameOverride }} -{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- $name := default .Chart.Name .Values.nameOverride }} -{{- if contains $name .Release.Name }} -{{- .Release.Name | trunc 63 | trimSuffix "-" }} -{{- else }} -{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} -{{- end }} -{{- end }} -{{- end }} - -{{/* -Create chart name and version as used by the chart label. -*/}} -{{- define "secrets.chart" -}} -{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} -{{- end }} - -{{/* -Common labels -*/}} -{{- define "secrets.labels" -}} -helm.sh/chart: {{ include "secrets.chart" . }} -{{ include "secrets.selectorLabels" . }} -{{- if .Chart.AppVersion }} -app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} -{{- end }} -app.kubernetes.io/managed-by: {{ .Release.Service }} -{{- end }} - -{{/* -Selector labels -*/}} -{{- define "secrets.selectorLabels" -}} -app.kubernetes.io/name: {{ include "secrets.name" . }} -app.kubernetes.io/instance: {{ .Release.Name }} -{{- end }} - -{{/* -Create the name of the service account to use -*/}} -{{- define "secrets.serviceAccountName" -}} -{{- if .Values.serviceAccount.create }} -{{- default (include "secrets.fullname" .) .Values.serviceAccount.name }} -{{- else }} -{{- default "default" .Values.serviceAccount.name }} -{{- end }} -{{- end }} - - -{{/* -Returns a secret if it already in Kubernetes, otherwise it creates -it randomly. -Special thanks to @iTaybb: https://github.com/helm/charts/issues/5167#issuecomment-840698657 -*/}} -{{- define "getOrGeneratePass" }} -{{- $len := (default 16 .Length) | int -}} -{{- $obj := (lookup "v1" .Kind .Namespace .Name).data -}} -{{- $val := "" -}} -{{- if $obj }} -{{- $val := (index $obj .Key) -}} -{{- end -}} -{{- if $val }} -{{- $val -}} -{{- else if (eq (lower .Kind) "secret") -}} -{{- randAlphaNum $len | b64enc -}} -{{- else -}} -{{- randAlphaNum $len -}} -{{- end -}} -{{- end }} \ No newline at end of file diff --git a/charts/oas-secrets/templates/oas-alertmanager-basic-auth.yaml b/charts/oas-secrets/templates/oas-alertmanager-basic-auth.yaml deleted file mode 100644 index f4471fda9..000000000 --- a/charts/oas-secrets/templates/oas-alertmanager-basic-auth.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -apiVersion: v1 -kind: Secret -metadata: - namespace: "oas" - name: "oas-alertmanager-basic-auth" -data: - {{- $pass := (include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-alertmanager-basic-auth" "Key" "pass")) | b64dec -}} - {{/* Readable version of the password for humans who want to log in */}} - pass: {{ $pass | b64enc }} - {{/* Encoded version of the password for nginx ingress */}} - auth: {{ htpasswd "admin" $pass | b64enc }} diff --git a/charts/oas-secrets/templates/oas-kube-prometheus-stack-variables.yaml b/charts/oas-secrets/templates/oas-kube-prometheus-stack-variables.yaml deleted file mode 100644 index 0781a9b19..000000000 --- a/charts/oas-secrets/templates/oas-kube-prometheus-stack-variables.yaml +++ /dev/null @@ -1,7 +0,0 @@ ---- -apiVersion: v1 -kind: Secret -metadata: - name: oas-kube-prometheus-stack-variables -data: - grafana_admin_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-kube-prometheus-stack-variables" "Key" "grafana_admin_password") }}" diff --git a/charts/oas-secrets/templates/oas-nextcloud-variables.yaml b/charts/oas-secrets/templates/oas-nextcloud-variables.yaml deleted file mode 100644 index 017cc8083..000000000 --- a/charts/oas-secrets/templates/oas-nextcloud-variables.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -apiVersion: v1 -kind: Secret -metadata: - name: oas-nextcloud-variables -data: - nextcloud_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-nextcloud-variables" "Key" "nextcloud_password") }}" - nextcloud_mariadb_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-nextcloud-variables" "Key" "nextcloud_mariadb_password") }}" - nextcloud_mariadb_root_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-nextcloud-variables" "Key" "nextcloud_mariadb_root_password") }}" - onlyoffice_jwt_secret: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-nextcloud-variables" "Key" "onlyoffice_jwt_secret") }}" - onlyoffice_postgresql_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-nextcloud-variables" "Key" "onlyoffice_postgresql_password") }}" - onlyoffice_rabbitmq_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-nextcloud-variables" "Key" "onlyoffice_rabbitmq_password") }}" diff --git a/charts/oas-secrets/templates/oas-oauth-variables.yaml b/charts/oas-secrets/templates/oas-oauth-variables.yaml deleted file mode 100644 index 4f4f67a8d..000000000 --- a/charts/oas-secrets/templates/oas-oauth-variables.yaml +++ /dev/null @@ -1,12 +0,0 @@ ---- -apiVersion: v1 -kind: Secret -metadata: - name: oas-oauth-variables -data: - grafana_oauth_client_secret: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-oauth-variables" "Key" "grafana_oauth_client_secret") }}" - nextcloud_oauth_client_secret: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-oauth-variables" "Key" "nextcloud_oauth_client_secret") }}" - rocketchat_oauth_client_secret: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-oauth-variables" "Key" "rocketchat_oauth_client_secret") }}" - userpanel_oauth_client_secret: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-oauth-variables" "Key" "userpanel_oauth_client_secret") }}" - wekan_oauth_client_secret: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-oauth-variables" "Key" "wekan_oauth_client_secret") }}" - wordpress_oauth_client_secret: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-oauth-variables" "Key" "wordpress_oauth_client_secret") }}" diff --git a/charts/oas-secrets/templates/oas-prometheus-basic-auth.yaml b/charts/oas-secrets/templates/oas-prometheus-basic-auth.yaml deleted file mode 100644 index f094270a2..000000000 --- a/charts/oas-secrets/templates/oas-prometheus-basic-auth.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - namespace: "oas" - name: "oas-prometheus-basic-auth" -data: - {{- $pass := (include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-prometheus-basic-auth" "Key" "pass")) | b64dec -}} - {{/* Readable version of the password for humans who want to log in */}} - pass: {{ $pass | b64enc }} - {{/* Encoded version of the password for nginx ingress */}} - auth: {{ htpasswd "admin" $pass | b64enc }} diff --git a/charts/oas-secrets/templates/oas-rocketchat-variables.yaml b/charts/oas-secrets/templates/oas-rocketchat-variables.yaml deleted file mode 100644 index 747ed200b..000000000 --- a/charts/oas-secrets/templates/oas-rocketchat-variables.yaml +++ /dev/null @@ -1,8 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: oas-rocketchat-variables -data: - mongodb_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-rocketchat-variables" "Key" "mongodb_password") }}" - mongodb_root_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-rocketchat-variables" "Key" "mongodb_root_password") }}" - rocketchat_admin_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-rocketchat-variables" "Key" "rocketchat_admin_password") }}" diff --git a/charts/oas-secrets/templates/oas-single-sign-on-variables.yaml b/charts/oas-secrets/templates/oas-single-sign-on-variables.yaml deleted file mode 100644 index 55b29a84b..000000000 --- a/charts/oas-secrets/templates/oas-single-sign-on-variables.yaml +++ /dev/null @@ -1,10 +0,0 @@ ---- -apiVersion: v1 -kind: Secret -metadata: - name: oas-single-sign-on-variables -data: - userbackend_admin_username: {{ b64enc "admin" }} - userbackend_admin_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-single-sign-on-variables" "Key" "userbackend_admin_password") }}" - userbackend_postgres_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-single-sign-on-variables" "Key" "userbackend_postgres_password") }}" - hydra_system_secret: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-single-sign-on-variables" "Key" "hydra_system_secret") }}" diff --git a/charts/oas-secrets/templates/oas-wekan-variables.yaml b/charts/oas-secrets/templates/oas-wekan-variables.yaml deleted file mode 100644 index 1f0ffccc1..000000000 --- a/charts/oas-secrets/templates/oas-wekan-variables.yaml +++ /dev/null @@ -1,7 +0,0 @@ -apiVersion: v1 -kind: Secret -metadata: - name: oas-wekan-variables -data: - mongodb_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-wekan-variables" "Key" "mongodb_password") }}" - mongodb_root_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-wekan-variables" "Key" "mongodb_root_password") }}" diff --git a/charts/oas-secrets/templates/oas-wordpress-variables.yaml b/charts/oas-secrets/templates/oas-wordpress-variables.yaml deleted file mode 100644 index 37df56499..000000000 --- a/charts/oas-secrets/templates/oas-wordpress-variables.yaml +++ /dev/null @@ -1,9 +0,0 @@ ---- -apiVersion: v1 -kind: Secret -metadata: - name: oas-wordpress-variables -data: - wordpress_admin_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-wordpress-variables" "Key" "wordpress_admin_password") }}" - wordpress_mariadb_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-wordpress-variables" "Key" "wordpress_mariadb_password") }}" - wordpress_mariadb_root_password: "{{ include "getOrGeneratePass" (dict "Namespace" .Release.Namespace "Kind" "Secret" "Name" "oas-wordpress-variables" "Key" "wordpress_mariadb_root_password") }}" diff --git a/charts/oas-secrets/values.yaml b/charts/oas-secrets/values.yaml deleted file mode 100644 index 449682fa4..000000000 --- a/charts/oas-secrets/values.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# The domain OpenAppStack runs on. There needs to be an A record to -# oas.example.com and an additional record *.oas.example.com, that both point to -# this machine -domain: oas.example.com -# The email address of the cluster administrator -admin_email: admin@oas.example.com \ No newline at end of file diff --git a/install/generate_secret.py b/install/generate_secret.py new file mode 100644 index 000000000..74d210c35 --- /dev/null +++ b/install/generate_secret.py @@ -0,0 +1,145 @@ +""" +Generates Kubernetes secrets based on a provided app name. + +If the `templates` directory contains a secret called `oas-{app}-variables`, it +will check if that secret already exists in the cluster, and if not: generate +it. It does the same for an `oas-{app}-basic-auth` secret that will contain a +password as well as a htpasswd encoded version of it. + +usage: python generate_secrets.py template_filename.j2 +""" + +import crypt +import os +import secrets +import string +import sys +import yaml + +import jinja2 +import jinja2_base64_filters # pylint: disable=unused-import +from kubernetes import client, config +from kubernetes.client.exceptions import ApiException +from kubernetes.utils import create_from_yaml + + +def main(): + """Run everything""" + # Add jinja filters we want to use + env = jinja2.Environment(extensions=["jinja2_base64_filters.Base64Filters"]) + env.filters["generate_password"] = generate_password + + if len(sys.argv) < 2: + print("Please provide an app name as an argument") + sys.exit(1) + app_name = sys.argv[1] + + create_variables_secret(app_name, env) + create_basic_auth_secret(app_name, env) + + +def get_templates_dir(): + """Returns directory that contains the Jinja templates used to create app + secrets""" + return os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates') + + +def create_variables_secret(app_name, env): + """Checks if a variables secret for app_name already exists, generates it if necessary""" + variables_filename = \ + os.path.join(get_templates_dir(), f"oas-{app_name}-variables.yaml") + if os.path.exists(variables_filename): + # Check if k8s secret already exists, if not, generate it + with open(variables_filename) as template_file: + lines = template_file.read() + secret_name, secret_namespace = get_secret_metadata(lines) + if get_kubernetes_secret(secret_name, secret_namespace) is None: + print(f"Adding secret {secret_name} in namespace" + f" {secret_namespace} to cluster.") + template = env.from_string(lines) + store_kubernetes_secret(template.render(), secret_namespace) + else: + print(f"Secret {secret_name} in namespace {secret_namespace}" + " already exists. Not generating new secrets.") + + +def create_basic_auth_secret(app_name, env): + """Checks if a basic auth secret for app_name already exists, generates it if necessary""" + basic_auth_filename = \ + os.path.join(get_templates_dir(), f"oas-{app_name}-basic-auth.yaml") + if os.path.exists(basic_auth_filename): + with open(basic_auth_filename) as template_file: + lines = template_file.read() + secret_name, secret_namespace = get_secret_metadata(lines) + + if get_kubernetes_secret(secret_name, secret_namespace) is None: + basic_auth_username = 'admin' + basic_auth_password = generate_password(32) + basic_auth_htpasswd = gen_htpasswd( + basic_auth_username, + basic_auth_password) + print(f"Adding secret {secret_name} in namespace" + f" {secret_namespace} to cluster.") + template = env.from_string( + lines, + globals={ + 'pass': basic_auth_password, + 'htpasswd': basic_auth_htpasswd + }) + store_kubernetes_secret(template.render(), secret_namespace) + else: + print(f"Secret {secret_name} in namespace {secret_namespace}" + " already exists. Not generating new secrets.") + +def get_secret_metadata(yaml_string): + """Returns secret name and namespace from metadata field in a yaml string""" + secret_info = yaml.safe_load(yaml_string) + secret_name = secret_info['metadata']['name'] + # default namespace is flux-system, but other namespace can be + # provided in secret metadata + if 'namespace' in secret_info['metadata']: + secret_namespace = secret_info['metadata']['namespace'] + else: + secret_namespace = 'flux-system' + return secret_name, secret_namespace + + +def get_kubernetes_secret(secret_name, namespace): + """Returns the contents of a kubernetes secret or None if the secret does not exist.""" + try: + secret = API.read_namespaced_secret(secret_name, namespace).data + except ApiException as ex: + # 404 is expected when the optional secret does not exist. + if ex.status != 404: + raise ex + return None + return secret + +def store_kubernetes_secret(secret_string, namespace): + """Converts secret_string into a yaml object and adds it to the cluster""" + secret_yaml = yaml.safe_load(secret_string) + api_client = client.api_client.ApiClient() + api_response = create_from_yaml( + api_client, + yaml_objects=[secret_yaml], + namespace=namespace) + print(f"Secret created with api response: {api_response}") + +def generate_password(length): + """Generates a password of "length" characters""" + length = int(length) + password = ''.join((secrets.choice(string.ascii_letters) for i in range(length))) + return password + + +def gen_htpasswd(user, password): + """generate htpasswd entry for user with password""" + return "{}:{}".format(user, crypt.crypt( + password, crypt.mksalt(crypt.METHOD_SHA512) + ), + ) + +if __name__ == "__main__": + config.load_kube_config() + API = client.CoreV1Api() + main() diff --git a/install/install-app.sh b/install/install-app.sh index a3f7b47cf..bd9d58a7a 100755 --- a/install/install-app.sh +++ b/install/install-app.sh @@ -7,6 +7,10 @@ app=$1 # shellcheck disable=SC1090 . "$(dirname "$0")/flux-version-check.sh" +# Check if the secrets for the app already exist in the cluster, and if not, +# generate them and add them to the cluster. +python "$(dirname "$0")/generate_secrets.py" $app + # This kustomization's only purpose is to add the kustomization that is in the # flxu2/cluster/optional/$app folder. After this kustomization is applied # an `add-$app` kustomization will be present on the cluster, as well as a diff --git a/install/install-openappstack.sh b/install/install-openappstack.sh index ee2fb2e44..d08989d60 100755 --- a/install/install-openappstack.sh +++ b/install/install-openappstack.sh @@ -15,6 +15,9 @@ branch=${CI_COMMIT_REF_NAME:-} echo "Tracking branch $branch for https://open.greenhost.net/openappstack/openappstack flux repo" +# Generate oauth secrets to link all the apps to SSO +python "$(dirname "$0")/generate_secrets.py" oauth + flux create source git openappstack \ --url=https://open.greenhost.net/openappstack/openappstack \ --branch=$branch \ diff --git a/install/templates/oas-alertmanager-basic-auth.yaml b/install/templates/oas-alertmanager-basic-auth.yaml new file mode 100644 index 000000000..fedb272ab --- /dev/null +++ b/install/templates/oas-alertmanager-basic-auth.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + namespace: "oas" + name: "oas-alertmanager-basic-auth" +data: + pass: "{{ pass | b64encode }}" + auth: "{{ htpasswd | b64encode }}" diff --git a/install/templates/oas-kube-prometheus-stack-variables.yaml b/install/templates/oas-kube-prometheus-stack-variables.yaml new file mode 100644 index 000000000..035baf54b --- /dev/null +++ b/install/templates/oas-kube-prometheus-stack-variables.yaml @@ -0,0 +1,7 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: oas-kube-prometheus-stack-variables +data: + grafana_admin_password: "{{ 32 | generate_password | b64encode }}" diff --git a/install/templates/oas-nextcloud-variables.yaml b/install/templates/oas-nextcloud-variables.yaml new file mode 100644 index 000000000..6ef7809d8 --- /dev/null +++ b/install/templates/oas-nextcloud-variables.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: oas-nextcloud-variables +data: + nextcloud_password: "{{ 32 | generate_password | b64encode }}" + nextcloud_mariadb_password: "{{ 32 | generate_password | b64encode }}" + nextcloud_mariadb_root_password: "{{ 32 | generate_password | b64encode }}" + onlyoffice_jwt_secret: "{{ 32 | generate_password | b64encode }}" + onlyoffice_postgresql_password: "{{ 32 | generate_password | b64encode }}" + onlyoffice_rabbitmq_password: "{{ 32 | generate_password | b64encode }}" diff --git a/install/templates/oas-oauth-variables.yaml b/install/templates/oas-oauth-variables.yaml new file mode 100644 index 000000000..befd2f774 --- /dev/null +++ b/install/templates/oas-oauth-variables.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: oas-oauth-variables +data: + grafana_oauth_client_secret: "{{ 32 | generate_password | b64encode }}" + nextcloud_oauth_client_secret: "{{ 32 | generate_password | b64encode }}" + rocketchat_oauth_client_secret: "{{ 32 | generate_password | b64encode }}" + userpanel_oauth_client_secret: "{{ 32 | generate_password | b64encode }}" + wekan_oauth_client_secret: "{{ 32 | generate_password | b64encode }}" + wordpress_oauth_client_secret: "{{ 32 | generate_password | b64encode }}" diff --git a/install/templates/oas-prometheus-basic-auth.yaml b/install/templates/oas-prometheus-basic-auth.yaml new file mode 100644 index 000000000..d4d2d3552 --- /dev/null +++ b/install/templates/oas-prometheus-basic-auth.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + namespace: "oas" + name: "oas-prometheus-basic-auth" +data: + # Readable version of the password for humans who want to log in + pass: "{{ pass | b64encode }}" + # Encoded version of the password for nginx ingress + auth: "{{ htpasswd | b64encode }}" diff --git a/install/templates/oas-rocketchat-variables.yaml b/install/templates/oas-rocketchat-variables.yaml new file mode 100644 index 000000000..4bce7f291 --- /dev/null +++ b/install/templates/oas-rocketchat-variables.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: oas-rocketchat-variables +data: + mongodb_password: "{{ 32 | generate_password | b64encode }}" + mongodb_root_password: "{{ 32 | generate_password | b64encode }}" + rocketchat_admin_password: "{{ 32 | generate_password | b64encode }}" diff --git a/install/templates/oas-single-sign-on-variables.yaml b/install/templates/oas-single-sign-on-variables.yaml new file mode 100644 index 000000000..a5e52e6a5 --- /dev/null +++ b/install/templates/oas-single-sign-on-variables.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: oas-single-sign-on-variables +data: + userbackend_admin_username: {{ "admin" | b64encode }} + userbackend_admin_password: "{{ 32 | generate_password | b64encode }}" + userbackend_postgres_password: "{{ 32 | generate_password | b64encode }}" + hydra_system_secret: "{{ 32 | generate_password | b64encode }}" diff --git a/install/templates/oas-wekan-variables.yaml b/install/templates/oas-wekan-variables.yaml new file mode 100644 index 000000000..f3cc5a366 --- /dev/null +++ b/install/templates/oas-wekan-variables.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Secret +metadata: + name: oas-wekan-variables +data: + mongodb_password: "{{ 32 | generate_password | b64encode }}" + mongodb_root_password: "{{ 32 | generate_password | b64encode }}" diff --git a/install/templates/oas-wordpress-variables.yaml b/install/templates/oas-wordpress-variables.yaml new file mode 100644 index 000000000..18bf4339c --- /dev/null +++ b/install/templates/oas-wordpress-variables.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: v1 +kind: Secret +metadata: + name: oas-wordpress-variables +data: + wordpress_admin_password: "{{ 32 | generate_password | b64encode }}" + wordpress_mariadb_password: "{{ 32 | generate_password | b64encode }}" + wordpress_mariadb_root_password: "{{ 32 | generate_password | b64encode }}" diff --git a/requirements.in b/requirements.in index 670886666..f0998c31a 100644 --- a/requirements.in +++ b/requirements.in @@ -15,7 +15,8 @@ ansible<2.10 # needed for test_dns.py dnspython -kubernetes +# kubernetes -- We need an unreleased version (post 13814c0f7e0e587c46512386da3d08c64fc83e04), so we install from git directly: +-e git+git://github.com/kubernetes-client/python.git@2f9643eac71535f7802cd16a078ce50e8866f1ad#egg=kubernetes # Needed for testinfra using the ansible module paramiko psutil @@ -28,3 +29,6 @@ setuptools wheel -e git+https://open.greenhost.net/greenhost/cloud-api#egg=greenhost_cloud passlib +# Needed for secrets generation in install/generate_secret.py +jinja2-base64-filters +htpasswd diff --git a/requirements.txt b/requirements.txt index b56d665d4..036e5ae92 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,9 @@ # -e git+https://open.greenhost.net/greenhost/cloud-api#egg=greenhost_cloud # via -r requirements.in -ansible==2.9.23 +-e git+git://github.com/kubernetes-client/python.git@2f9643eac71535f7802cd16a078ce50e8866f1ad#egg=kubernetes + # via -r requirements.in +ansible==2.9.24 # via -r requirements.in attrs==21.2.0 # via pytest @@ -23,7 +25,7 @@ cffi==1.14.6 # bcrypt # cryptography # pynacl -charset-normalizer==2.0.1 +charset-normalizer==2.0.4 # via requests cryptography==3.4.7 # via @@ -32,20 +34,26 @@ cryptography==3.4.7 # pyopenssl dnspython==2.1.0 # via -r requirements.in -google-auth==1.32.1 +google-auth==1.34.0 # via kubernetes +htpasswd==2.3 + # via -r requirements.in idna==3.2 # via requests iniconfig==1.1.1 # via pytest jinja2==3.0.1 - # via ansible -kubernetes==17.17.0 + # via + # ansible + # jinja2-base64-filters +jinja2-base64-filters==0.1.4 # via -r requirements.in markupsafe==2.0.1 # via jinja2 oauthlib==3.1.1 # via requests-oauthlib +orderedmultidict==1.0.1 + # via htpasswd packaging==21.0 # via pytest paramiko==2.7.2 @@ -102,6 +110,7 @@ six==1.16.0 # bcrypt # google-auth # kubernetes + # orderedmultidict # pynacl # pyopenssl # python-dateutil @@ -115,9 +124,9 @@ urllib3==1.26.6 # via # kubernetes # requests -websocket-client==1.1.0 +websocket-client==1.2.0 # via kubernetes -wheel==0.36.2 +wheel==0.37.0 # via -r requirements.in # The following packages are considered to be unsafe in a requirements file: -- GitLab