Merge pull request 'Toolshed redis and domain rbac' (#1) from toolshed-redis-and-domain-rbac into main

Reviewed-on: http://gitea.100.90.248.118.nip.io/mukul/devops-infra-argo-config/pulls/1
This commit is contained in:
mukul
2026-09-09 07:29:49 +00:00
3 changed files with 119 additions and 0 deletions
@@ -85,3 +85,47 @@ roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: toolshed-deployer
---
# A custom domain's Ingress and TLS secret live in the gateway's own
# namespace (toolshed, same as above) — never an app's namespace. Scoped
# with a namespaced Role/RoleBinding rather than widening the ClusterRole
# above: Ingress management here only ever targets this one fixed
# namespace, unlike the per-app namespaces the ClusterRole necessarily
# spans. Added alongside toolshed's custom-domains feature — see
# internal/deploy.Client.EnsureDomainIngress/DomainCertReady/
# RemoveDomainIngress and this file's own header comment about keeping it
# and deploy/helm/toolshed/templates/rbac.yaml in sync.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: toolshed-deployer-ingress
namespace: toolshed
labels:
app.kubernetes.io/part-of: toolshed
rules:
- apiGroups: ["networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
# Reads the TLS secret cert-manager's ingress-shim populates for a domain
# Ingress, and deletes it (and the Ingress above) when a domain is
# removed. Never create/update — cert-manager, not deployer, writes this
# secret.
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: toolshed-deployer-ingress
namespace: toolshed
labels:
app.kubernetes.io/part-of: toolshed
subjects:
- kind: ServiceAccount
name: toolshed-deployer
namespace: toolshed
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: toolshed-deployer-ingress
@@ -0,0 +1,54 @@
# Redis admin password, backing toolshed's managed cache add-on.
#
# Only one consumer, unlike the Postgres credential next door: the Redis
# server itself needs it to seed its ACL file on first boot. toolshed's api
# reads it from the *connection* an operator configures in the dashboard
# (encrypted in toolshed's own database via the secretbox keyring), not from
# a Kubernetes Secret — so there is deliberately no second ExternalSecret
# into the toolshed namespace here.
#
# Put the credential in Vault BEFORE syncing this. External Secrets cannot
# create a Secret for a path that does not exist, and the Redis pod's init
# container will sit in CreateContainerConfigError until it can:
#
# kubectl -n vault exec -i vault-0 -- sh -lc '
# vault login <root-token> >/dev/null &&
# vault kv put secret/toolshed/redis \
# password=<a long alphanumeric password>'
#
# Use an alphanumeric password. It is written into the ACL file as
# `user default on ><password> ...` by the init container, where a space or
# a quote would split the directive and produce a server that either fails
# to start or, worse, starts with different rules than intended.
#
# Remember that `kubectl exec` into Vault is unauthenticated by default —
# without the `vault login` the commands fail with a "preflight capability
# check" error that reads like a permissions bug rather than a missing
# login.
#
# Rotating this password later does NOT propagate to a running server: the
# init container only ever writes the ACL file when it is absent, precisely
# so it cannot delete the per-app users toolshed has provisioned into it.
# To rotate, update Vault and then, against the running server:
#
# ACL SETUSER default >newpassword
# ACL SAVE
---
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: redis-credentials
namespace: redis
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: ClusterSecretStore
target:
name: redis-credentials
creationPolicy: Owner
data:
- secretKey: password
remoteRef:
key: toolshed/redis
property: password
@@ -132,6 +132,27 @@ appSpec:
namespace: postgres
chartDir: postgresql
valuesDir: postgresql
- name: redis
# Backs toolshed's managed cache add-on — toolshed provisions a per-app
# ACL user, scoped to its own key prefix, on request. Own namespace for
# the same reason postgresql has one: addressed over cluster DNS like
# any other platform component, outliving whatever consumes it:
# redis.redis.svc.cluster.local:6379
#
# Hand-written chart, not Bitnami's, for the same reason as postgresql
# (infra issue #4) — Redis ships no official chart either.
#
# Authentication is defined by an ACL file with no requirepass, which
# is a security property rather than a preference: see the chart's own
# values.yaml, where getting it wrong leaves the server open to
# unauthenticated access after its first restart.
#
# Requires secretstores/toolshed-redis-credentials.yaml to have synced
# first — the init container cannot seed the ACL file without it.
nameOverride: redis
namespace: redis
chartDir: redis
valuesDir: redis
- name: victoria-metrics-single
# Replaces the Prometheus server this entry briefly was (see git
# history on this file) — same job, lower RAM/disk footprint for the