diff --git a/kube/clusters/biohazard/flux/kustomization.yaml b/kube/clusters/biohazard/flux/kustomization.yaml index eab818ab..c93de7fc 100644 --- a/kube/clusters/biohazard/flux/kustomization.yaml +++ b/kube/clusters/biohazard/flux/kustomization.yaml @@ -43,6 +43,7 @@ resources: - ../../../deploy/core/db/pg/ - ../../../deploy/core/db/pg/clusters/default/ - ../../../deploy/core/db/pg/clusters/home/ + - ../../../deploy/core/db/emqx/ - ../../../deploy/core/monitoring/metrics-server/ - ../../../deploy/core/monitoring/kps/ - ../../../deploy/core/monitoring/victoria/ diff --git a/kube/deploy/core/db/emqx/app/hr.yaml b/kube/deploy/core/db/emqx/app/hr.yaml new file mode 100644 index 00000000..071ec3ba --- /dev/null +++ b/kube/deploy/core/db/emqx/app/hr.yaml @@ -0,0 +1,46 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2beta2 +kind: HelmRelease +metadata: + name: &app emqx-operator + namespace: emqx +spec: + interval: 5m + chart: + spec: + chart: emqx-operator + version: 2.2.22 + sourceRef: + name: emqx + kind: HelmRepository + namespace: flux-system + dependsOn: + - name: cert-manager + namespace: cert-manager + values: + fullnameOverride: *app + image: + repository: ghcr.io/emqx/emqx-operator + postRenderers: + - kustomize: + patches: + - target: + kind: Deployment + labelSelector: control-plane=controller-manager + patch: | + - op: add + path: /spec/template/metadata/labels + value: + egress.home.arpa/apiserver: allow + - target: + kind: ClusterRoleBinding + patch: | + - op: replace + path: /kind + value: RoleBinding + - target: + kind: ClusterRole + patch: | + - op: replace + path: /kind + value: RoleBinding diff --git a/kube/deploy/core/db/emqx/cluster/emqx.yaml b/kube/deploy/core/db/emqx/cluster/emqx.yaml new file mode 100644 index 00000000..ead1ae07 --- /dev/null +++ b/kube/deploy/core/db/emqx/cluster/emqx.yaml @@ -0,0 +1,79 @@ +--- +# yaml-language-server: $schema=https://kubernetes-schemas.pages.dev/apps.emqx.io/emqx_v2beta1.json +apiVersion: apps.emqx.io/v2beta1 +kind: EMQX +metadata: + name: emqx +spec: + image: public.ecr.aws/emqx/emqx:5.6.1 + config: + # the `$${env}` in the env var means Flux's Kustomize controller should escape the envsubst and output `${env}` exactly + data: | + authentication [{ + enable = true + backend = "ldap" + mechanism = "password_based" + method { + type = bind + bind_password = "$${password}" + } + server = "glauth.emqx.svc.cluster.local.:636" + query_timeout = "10s" + username = "search" + password = "file:///secrets/ldap-search.password" + pool_size = 1 + base_dn = "cn=$${username},ou=emqx,ou=users,dc=emqx,dc=io" + filter = "(objectClass=*)" + ssl { + enable = true + server_name_indication = "emqx-glauth.${DNS_SHORT}" + } + }] + authorization { + sources = [{ + enable = true + type = ldap + publish_attribute = "mqttPublishTopic" + subscribe_attribute = "mqttSubscriptionTopic" + all_attribute = "mqttPubSubTopic" + server = "glauth.emqx.svc.cluster.local.:636" + query_timeout = "10s" + username = "search" + password = "file:///secrets/ldap-search.password" + pool_size = 1 + base_dn = "cn=$${username},ou=emqx,ou=users,dc=emqx,dc=io" + filter = "(objectClass=*)" + ssl { + enable = true + server_name_indication = "emqx-glauth.${DNS_SHORT}" + } + }] + no_match = "deny" + } + bootstrapAPIKeys: + - secretRef: + key: + secretName: emqx-secrets + secretKey: X_EMQX_APIKEY_KEY + secret: + secretName: emqx-secrets + secretKey: X_EMQX_APIKEY_SECRET + coreTemplate: + spec: + replicas: 3 + envFrom: &envFrom + - secretRef: + name: emqx-secrets + volumeClaimTemplates: + storageClassName: local + accessModes: [ReadWriteOnce] + resources: + requests: + storage: 1Gi + listenersServiceTemplate: + metadata: + annotations: + coredns.io/hostname: "${APP_DNS_EMQX}" + io.cilium/lb-ipam-ips: "${APP_IP_EMQX}" + spec: + type: LoadBalancer diff --git a/kube/deploy/core/db/emqx/cluster/es.yaml b/kube/deploy/core/db/emqx/cluster/es.yaml new file mode 100644 index 00000000..c6df5f09 --- /dev/null +++ b/kube/deploy/core/db/emqx/cluster/es.yaml @@ -0,0 +1,64 @@ +--- +# yaml-language-server: $schema=https://crds.jank.ing/external-secrets.io/externalsecret_v1beta1.json +apiVersion: external-secrets.io/v1beta1 +kind: ExternalSecret +metadata: + name: &name emqx-secrets + namespace: emqx +spec: + refreshInterval: 1m + secretStoreRef: + kind: ClusterSecretStore + name: 1p + dataFrom: + - extract: + key: "EMQX - ${CLUSTER_NAME}" + target: + creationPolicy: Owner + deletionPolicy: Retain + name: *name + template: + type: Opaque + data: + EMQX_DASHBOARD__DEFAULT_USERNAME: "{{ .EMQX_DASHBOARD__DEFAULT_USERNAME }}" + EMQX_DASHBOARD__DEFAULT_PASSWORD: "{{ .EMQX_DASHBOARD__DEFAULT_PASSWORD }}" + X_EMQX_APIKEY_KEY: "{{ .X_EMQX_APIKEY_KEY }}" + X_EMQX_APIKEY_SECRET: "{{ .X_EMQX_APIKEY_SECRET }}" + ldap-search.password: "{{ .GLAUTH_SEARCH_PASSWORD }}" + glauth.toml: | + debug = true + [ldap] + enabled = false + [ldaps] + enabled = true + listen = "0.0.0.0:6636" + cert = "/tls/tls.crt" + key = "/tls/tls.key" + [backend] + datastore = "config" + baseDN = "dc=emqx,dc=io" + nameformat = "cn" + groupformat = "ou" + [[users]] + name = "search" + uidnumber = 99991 + primarygroup = 99991 + passsha256 = "{{ .GLAUTH_SEARCH_PASSWORD_SHA256 }}" + [[users.capabilities]] + action = "search" + object = "ou=emqx,dc=emqx,dc=io" + [[groups]] + name = "search" + gidnumber = 99991 + [[users]] + name = "hass" + uidnumber = 99992 + primarygroup = 99990 + passsha256 = "{{ .GLAUTH_HASS_PASSWORD_SHA256 }}" + [[users.customattributes]] + mqttPublishTopic = ["homeassistant/pub/#", "zigbee2mqtt/pub/#"] + mqttSubscriptionTopic = ["homeassistant/sub/#", "zigbee2mqtt/sub/#"] + mqttPubSubTopic = ["homeassistant/pubsub/#", "zigbee2mqtt/pubsub/#"] + [[groups]] + name = "emqx" + gidnumber = 99990 diff --git a/kube/deploy/core/db/emqx/cluster/glauth.yaml b/kube/deploy/core/db/emqx/cluster/glauth.yaml new file mode 100644 index 00000000..804e9b58 --- /dev/null +++ b/kube/deploy/core/db/emqx/cluster/glauth.yaml @@ -0,0 +1,93 @@ +--- +apiVersion: helm.toolkit.fluxcd.io/v2beta2 +kind: HelmRelease +metadata: + name: &app glauth + namespace: emqx +spec: + interval: 5m + chart: + spec: + chart: app-template + version: 3.1.0 + sourceRef: + name: bjw-s + kind: HelmRepository + namespace: flux-system + values: + controllers: + glauth: + type: deployment + replicas: 2 + containers: + main: + image: &img + repository: docker.io/glauth/glauth + tag: v2.3.2@sha256:5112abbb2b5145dadb1a2fed57242ad3718e4af11062d0bb812b50cda6c708ab + env: &env + TZ: "${CONFIG_TZ}" + securityContext: &sc + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: ["ALL"] + resources: + requests: + cpu: "10m" + limits: + memory: "128Mi" + probes: + liveness: + enabled: true + readiness: + enabled: true + service: + glauth: + controller: glauth + ports: + ldap-tcp: + port: 636 + targetPort: 6636 + protocol: TCP + ldap-udp: + port: 636 + targetPort: 6636 + protocol: UDP + persistence: + config: + type: secret + name: emqx-secrets + globalMounts: + - subPath: glauth.toml + path: /config/glauth.toml + tls: + type: secret + name: short-domain-tls + defaultMode: 0400 + globalMounts: + - path: /tls + readOnly: true + defaultPodOptions: + automountServiceAccountToken: false + enableServiceLinks: false + securityContext: + runAsNonRoot: true + runAsUser: &uid 1000 + runAsGroup: *uid + fsGroup: *uid + fsGroupChangePolicy: Always + seccompProfile: { type: "RuntimeDefault" } + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: fuckoff.home.arpa/emqx + operator: DoesNotExist + networkpolicies: + same-ns: + controller: glauth + policyTypes: [Ingress, Egress] + rules: + ingress: [from: [{podSelector: {}}]] + egress: [to: [{podSelector: {}}]] diff --git a/kube/deploy/core/db/emqx/ks.yaml b/kube/deploy/core/db/emqx/ks.yaml new file mode 100644 index 00000000..2b0a8c35 --- /dev/null +++ b/kube/deploy/core/db/emqx/ks.yaml @@ -0,0 +1,29 @@ +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: emqx-app + namespace: flux-system + labels: &l + app.kubernetes.io/name: "emqx" +spec: + commonMetadata: + labels: *l + path: ./kube/deploy/core/db/emqx/app + targetNamespace: "emqx" + dependsOn: [] +--- +apiVersion: kustomize.toolkit.fluxcd.io/v1 +kind: Kustomization +metadata: + name: emqx-cluster + namespace: flux-system + labels: &l + app.kubernetes.io/name: "emqx" +spec: + commonMetadata: + labels: *l + path: ./kube/deploy/core/db/emqx/cluster + targetNamespace: "emqx" + dependsOn: + - name: emqx-app diff --git a/kube/deploy/core/db/emqx/kustomization.yaml b/kube/deploy/core/db/emqx/kustomization.yaml new file mode 100644 index 00000000..5eeb2657 --- /dev/null +++ b/kube/deploy/core/db/emqx/kustomization.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ns.yaml + - ks.yaml diff --git a/kube/deploy/core/db/emqx/ns.yaml b/kube/deploy/core/db/emqx/ns.yaml new file mode 100644 index 00000000..0ef880fb --- /dev/null +++ b/kube/deploy/core/db/emqx/ns.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: emqx + labels: + kustomize.toolkit.fluxcd.io/prune: disabled + pod-security.kubernetes.io/enforce: &ps restricted + pod-security.kubernetes.io/audit: *ps + pod-security.kubernetes.io/warn: *ps diff --git a/kube/repos/flux/helm/emqx.yaml b/kube/repos/flux/helm/emqx.yaml new file mode 100644 index 00000000..bfdac64d --- /dev/null +++ b/kube/repos/flux/helm/emqx.yaml @@ -0,0 +1,10 @@ +--- +apiVersion: source.toolkit.fluxcd.io/v1beta2 +kind: HelmRepository +metadata: + name: emqx + namespace: flux-system +spec: + interval: 1h + timeout: 3m0s + url: https://repos.emqx.io/charts