Skip to content

Commit

Permalink
Separate buckets for tls certs (#2885)
Browse files Browse the repository at this point in the history
* Update helm charts to allow separate AWS buckets for proxied TLS certificates
* Prefer 'include' to 'template' in helm charts
* Remove vagrant files from .gitignore
* Change become:no to become:false
* Remove support for `microk8s`
  • Loading branch information
jmgrady committed Mar 6, 2024
1 parent feb5334 commit b7b79f6
Show file tree
Hide file tree
Showing 18 changed files with 79 additions and 64 deletions.
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,6 @@ mongo_database
# User Guide
docs/user_guide/site

# Vagrant instances
.vagrant/

# Python
.tox
.mypy_cache
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ metadata:
namespace: {{ .Release.Namespace }}
data:
AWS_S3_BUCKET: {{ print "s3://" .Values.global.awsS3Location "/" .Values.awsS3CertLoc | quote }}
CERT_SECRET: {{ template "cert-proxy-client.certSecretName" . }}
CERT_SECRET: {{ include "cert-proxy-client.certSecretName" . }}
CERT_NAMESPACE: {{ .Release.Namespace }}
CERT_RENEW_BEFORE: "{{ .Values.certRenewBefore }}"
TEST_URL: "https://aws.amazon.com"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ spec:
spec:
serviceAccountName: {{ .Values.serviceAccount.name }}
containers:
- image: {{ template "cert-proxy-client.containerImage" . }}
- image: {{ include "cert-proxy-client.containerImage" . }}
imagePullPolicy: {{ .Values.global.imagePullPolicy }}
name: update-cert-cronjob
command:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ spec:
spec:
serviceAccountName: {{ .Values.serviceAccount.name }}
containers:
- image: {{ template "cert-proxy-client.containerImage" . }}
- image: {{ include "cert-proxy-client.containerImage" . }}
imagePullPolicy: {{ .Values.global.imagePullPolicy }}
name: update-cert-oneshot
command:
Expand Down
3 changes: 2 additions & 1 deletion deploy/helm/cert-proxy-client/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ global:
awsDefaultRegion: "Override"
awsAccessKeyId: "Override"
awsSecretAccessKey: "Override"
imageTag: "latest"
imagePullPolicy: "IfNotPresent"
# Define the image registry to use (may be blank for local images)
imageRegistry: awsEcr
imageTag: "latest"
# Default AWS S3 location
awsS3Location: "thecombine.app"

Expand Down
8 changes: 8 additions & 0 deletions deploy/helm/cert-proxy-server/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,11 @@
{{- printf "%s:%s" .Values.imageName .Values.global.imageTag }}
{{- end }}
{{- end }}

{{/* Build string of certificates for ConfigMap data */}}
{{- define "cert-proxy-server.cert-proxy-list-config-data" -}}
{{- $awsCertLoc := .Values.awsS3CertLoc }}
{{- range .Values.combineCertProxyList -}}
{{- printf "%s@%s/%s " .hostname .bucket $awsCertLoc -}}
{{- end }}
{{- end }}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ spec:
name: {{ .Values.envCertProxy }}
- name: CERT_PROXY_NAMESPACE
value: {{ .Release.Namespace }}
image: {{ template "cert-proxy-server.containerImage" . }}
image: {{ include "cert-proxy-server.containerImage" . }}
imagePullPolicy: {{ .Values.global.imagePullPolicy }}
name: combine-cert-proxy
resources:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ metadata:
namespace: {{ .Release.Namespace }}
data:
AWS_S3_BUCKET: {{ print "s3://" .Values.global.awsS3Location "/" .Values.awsS3CertLoc | quote }}
CERT_PROXY_CERTIFICATES: {{ .Values.combineCertProxyList | default "" | quote }}
CERT_PROXY_CERTIFICATES: {{ include "cert-proxy-server.cert-proxy-list-config-data" . | trim | default "" | quote }}
10 changes: 5 additions & 5 deletions deploy/helm/cert-proxy-server/templates/ingress-nuc.yaml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{{- range regexSplit "\\s+" .Values.combineCertProxyList -1 }}
{{- range .Values.combineCertProxyList }}
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ replace "." "-" . }}
name: {{ replace "." "-" .hostname }}
namespace: {{ $.Release.Namespace }}
annotations:
{{- if eq $.Values.ingressClass "nginx" }}
Expand All @@ -18,10 +18,10 @@ spec:
ingressClassName: {{ $.Values.ingressClass }}
tls:
- hosts:
- {{ . }}
secretName: {{ replace "." "-" . }}-tls
- {{ .hostname }}
secretName: {{ replace "." "-" .hostname }}-tls
rules:
- host: {{ . }}
- host: {{ .hostname }}
http:
paths:
- backend:
Expand Down
3 changes: 3 additions & 0 deletions deploy/helm/cert-proxy-server/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ awsEcr:
role: role-ecr-login-cert-proxy
roleBinding: role-ecr-login-cert-proxy-binding

combineCertProxyList:
- hostname: Override
bucket: Override
envCertProxy: env-cert-proxy
envNginxProxy: env-nginx-proxy
nginxPages: init-nginx-pages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ spec:
secretKeyRef:
key: COMBINE_ADMIN_EMAIL
name: admin-user-secrets
image: {{ template "create-admin-user.containerImage" . }}
image: {{ include "create-admin-user.containerImage" . }}
imagePullPolicy: {{ .Values.global.imagePullPolicy }}
name: create-admin-user
resources: {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ spec:
imagePullPolicy: IfNotPresent
containers:
- name: backend
image: {{ template "backend.containerImage" . }}
image: {{ include "backend.containerImage" . }}
imagePullPolicy: {{ .Values.global.imagePullPolicy }}
env:
- name: COMBINE_JWT_SECRET_KEY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ spec:
combine-component: database
spec:
containers:
- image: {{ template "database.containerImage" . }}
- image: {{ include "database.containerImage" . }}
imagePullPolicy: {{ .Values.global.imagePullPolicy }}
name: database
ports:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ spec:
spec:
containers:
- name: frontend
image: {{ template "frontend.containerImage" . }}
image: {{ include "frontend.containerImage" . }}
imagePullPolicy: {{ .Values.global.imagePullPolicy }}
env:
- name: CERT_ADDL_DOMAINS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ spec:
- name: maintenance
command: [ "/bin/bash", "-c", "--" ]
args: [ 'sleep infinity & PID=$! ; trap "kill $PID" INT TERM ; wait' ]
image: {{ template "maintenance.containerImage" . }}
image: {{ include "maintenance.containerImage" . }}
imagePullPolicy: {{ .Values.global.imagePullPolicy }}
securityContext:
runAsUser: 999
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ data:
# for this host from the list of backups. This is done as an environment variable
# to provide flexibility for future clean schemes while minimizing the need to
# rebuild the container image.
backup_filter: {{ template "maintenance.backupNameFilter" . }}
backup_filter: {{ include "maintenance.backupNameFilter" . }}
wait_time: {{ .Values.waitTime | quote }}
max_backups: {{ .Values.maxBackups | quote }}
font_dir: {{ .Values.fontsDir | quote }}
Expand Down
10 changes: 9 additions & 1 deletion deploy/scripts/setup_files/profiles/prod.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,12 @@ charts:
global:
awsS3Location: prod.thecombine.app
pullSecretName: None
combineCertProxyList: nuc1.thecombine.app nuc2.thecombine.app nuc3.thecombine.app local.thecombine.app
combineCertProxyList:
- hostname: nuc1.thecombine.app
bucket: prod.thecombine.app
- hostname: nuc2.thecombine.app
bucket: prod.thecombine.app
- hostname: nuc3.thecombine.app
bucket: prod.thecombine.app
- hostname: local.thecombine.app
bucket: local.thecombine.app
84 changes: 41 additions & 43 deletions maintenance/scripts/monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,48 @@
monitor.py will monitor the secrets specified in the CERT_PROXY_CERTIFICATES
environment variable. When a secret is updated, the updated secret is pushed
to the AWS_S3_BUCKET.
to the specified AWS S3 bucket.
"""

import base64
import os
from pathlib import Path
import tempfile
from typing import List
from typing import Dict

from aws_backup import AwsBackup
from kubernetes import client, config, watch


class TlsSecret:
def __init__(self, cert_spec: str) -> None:
(self.hostname, aws_bucket) = cert_spec.split("@")
self.aws = AwsBackup(bucket=aws_bucket)
self.name = f"{self.hostname.replace('.', '-')}-tls"

def push(self, data: bytes, filename: str) -> None:
"""
Push single file associated with the TLS secret to AWS S3 storage.
Args:
data: contents of the file to be pushed.
filename: name of the file, e.g. cert.pem, key.pem.
Example:
a_secret.push(data=b'<my cert data>', filename="cert.pem")
will create a file that contains the data received in the AWS
S3 bucket under my-cert-tls/cert.pem.
"""
secret_dest = f"{self.name}/{filename}"
print(f"Push {secret_dest} to AWS {self.aws.bucket}", flush=True)
with tempfile.TemporaryDirectory() as temp_dir:
secret_dir = Path(temp_dir) / self.name
secret_dir.mkdir(parents=True, exist_ok=True)
secret_filename = secret_dir / filename
secret_filename.write_bytes(data)
self.aws.push(secret_filename, secret_dest)


class CertMonitor:
"""
Monitor SSL certificate secrets and push a copy to the cloud on change.
Expand All @@ -37,53 +66,24 @@ class CertMonitor:
trigger_events = ("ADDED", "MODIFIED")

def __init__(self) -> None:
self.secrets_list = CertMonitor.get_secrets_list()
self.secrets_dict = CertMonitor.get_secrets_dict()
self.k8s_namespace = os.environ["CERT_PROXY_NAMESPACE"]
self.aws = AwsBackup(bucket=os.environ["AWS_S3_BUCKET"])

@staticmethod
def get_secrets_list() -> List[str]:
def get_secrets_dict() -> Dict[str, TlsSecret]:
"""
Create the list of secrets to monitor.
Create the list of secrets to monitor from the CERT_PROXY_CERTIFICATES
environment variable. This function assumes that the secret name is '-tls'
appended to the dns name of the server (with '.' converted to '-').
"""
secret_dict: Dict[str, TlsSecret] = {}
if "CERT_PROXY_CERTIFICATES" in os.environ:
domain_list = os.environ["CERT_PROXY_CERTIFICATES"].replace(".", "-").split()
for index, item in enumerate(domain_list):
domain_list[index] = f"{item}-tls"
return domain_list
return []

def push_secret_file(self, *, secret_name: str, data: bytes, filename: str) -> None:
"""
Push single file associated with the TLS secret to AWS S3 storage.
Args:
secret_name: name of the secret that is being pushed to AWS S3.
data: contents of the file to be pushed.
filename: name of the file.
Example:
push_secret_file(
secret_name="my-cert-tls",
data=b'<my cert data>',
filename="cert.pem")
will create a file that contains the data received in the AWS
S3 bucket under my-cert-tls/cert.pem.
"""
secret_dest = f"{secret_name}/{filename}"
print(f"Push {secret_dest} to AWS S3", flush=True)
with tempfile.TemporaryDirectory() as temp_dir:
secret_dir = Path(temp_dir) / secret_name
secret_dir.mkdir(parents=True, exist_ok=True)
secret_filename = secret_dir / filename
secret_filename.write_bytes(data)
self.aws.push(secret_filename, f"{secret_dest}")
for item in os.environ["CERT_PROXY_CERTIFICATES"].split():
secret = TlsSecret(item)
secret_dict[secret.name] = secret
return secret_dict

def monitor(self) -> None:
"""Monitor for updates to the secrets."""
Expand All @@ -99,14 +99,12 @@ def monitor(self) -> None:
secret_name = event["object"].metadata.name
event_type = event["type"]
print(f"Event: {event_type} {secret_name}", flush=True)
if (event_type in CertMonitor.trigger_events) and (secret_name in self.secrets_list):
self.push_secret_file(
secret_name=secret_name,
if (event_type in CertMonitor.trigger_events) and (secret_name in self.secrets_dict):
self.secrets_dict[secret_name].push(
data=base64.b64decode(event["object"].data["tls.key"]),
filename="key.pem",
)
self.push_secret_file(
secret_name=secret_name,
self.secrets_dict[secret_name].push(
data=base64.b64decode(event["object"].data["tls.crt"]),
filename="cert.pem",
)
Expand Down

0 comments on commit b7b79f6

Please sign in to comment.