Gate shelly-manager behind Authentik passkey step-up #138
@@ -328,6 +328,111 @@ data:
|
||||
kubernetes_ingress_secret_name: "authentik-outpost-tls"
|
||||
kubernetes_json_patches: null
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# shelly-manager gate
|
||||
#
|
||||
# shelly-manager has no authentication of its own: anything that can
|
||||
# reach :8080 can rewrite Shelly device config, push scripts, and read
|
||||
# the stored per-device AdminPassword values. Until now the only
|
||||
# control was reachability of shelly-manager.home.renner.uno.
|
||||
#
|
||||
# Same shape as the vscode-gate above: a dedicated outpost terminates
|
||||
# the request, enforces a passkey step-up, and forwards to the
|
||||
# shelly-manager Service. Traefik only ever routes the hostname to the
|
||||
# outpost; the home-assistant CNP allows ONLY this outpost to reach
|
||||
# :8080 (see home-assistant-ns.yaml + shelly-manager-gate-egress.yaml).
|
||||
# ------------------------------------------------------------------
|
||||
- id: shelly-managers-group
|
||||
model: authentik_core.group
|
||||
identifiers:
|
||||
name: Shelly Managers
|
||||
state: present
|
||||
attrs:
|
||||
is_superuser: false
|
||||
# Git owns membership, as with Home Assistant Config Editors: this
|
||||
# group is the explicit allowlist for who may reconfigure the
|
||||
# Shellies. Add/remove members HERE, not in the UI — blueprint
|
||||
# apply is authoritative for this M2M and reverts UI edits.
|
||||
users:
|
||||
- !Find [authentik_core.user, [username, k.renner]]
|
||||
|
||||
- id: shelly-manager-gate-provider
|
||||
model: authentik_providers_proxy.proxyprovider
|
||||
identifiers:
|
||||
name: shelly-manager-gate
|
||||
state: present
|
||||
attrs:
|
||||
authorization_flow: !Find [authentik_flows.flow, [slug, passkey-stepup-authorization]]
|
||||
invalidation_flow: !Find [authentik_flows.flow, [slug, default-provider-invalidation-flow]]
|
||||
mode: proxy
|
||||
internal_host: http://shelly-manager.home-assistant.svc.cluster.local
|
||||
internal_host_ssl_validation: false
|
||||
external_host: https://shelly-manager.home.renner.uno
|
||||
cookie_domain: renner.uno
|
||||
access_token_validity: hours=24
|
||||
refresh_token_validity: days=30
|
||||
intercept_header_auth: true
|
||||
# No skip_path_regex, deliberately. The music-assistant gate died
|
||||
# on PWA assets fetched with `credentials: 'omit'` (manifest, service
|
||||
# worker), and paperless/vscode carve those out. shelly-manager ships
|
||||
# no manifest and no service worker — wwwroot is app.css, favicon.png
|
||||
# and lib/ only — so every asset is a same-origin credentialed fetch
|
||||
# and nothing needs to bypass the gate. It is a Blazor Web app: the
|
||||
# SignalR circuit at /_blazor upgrades to a websocket carrying the
|
||||
# session cookie, which the proxy outpost forwards. If the UI ever
|
||||
# fails to establish its circuit, look there first, not at static
|
||||
# assets.
|
||||
|
||||
- model: authentik_core.application
|
||||
identifiers:
|
||||
slug: shelly-manager-gate
|
||||
state: present
|
||||
attrs:
|
||||
name: Shelly Manager (Gate)
|
||||
slug: shelly-manager-gate
|
||||
provider: !KeyOf shelly-manager-gate-provider
|
||||
meta_launch_url: https://shelly-manager.home.renner.uno
|
||||
meta_description: "Passkey-gated Shelly device manager"
|
||||
|
||||
# Only the Shelly Managers group passes the gate.
|
||||
- model: authentik_policies.policybinding
|
||||
identifiers:
|
||||
target: !Find [authentik_core.application, [slug, shelly-manager-gate]]
|
||||
group: !KeyOf shelly-managers-group
|
||||
order: 0
|
||||
state: present
|
||||
attrs:
|
||||
enabled: true
|
||||
negate: false
|
||||
failure_result: false
|
||||
|
||||
- model: authentik_outposts.outpost
|
||||
identifiers:
|
||||
name: shelly-manager-gate
|
||||
state: present
|
||||
attrs:
|
||||
type: proxy
|
||||
service_connection: !KeyOf k8s-conn
|
||||
providers:
|
||||
- !KeyOf shelly-manager-gate-provider
|
||||
config:
|
||||
log_level: info
|
||||
authentik_host: "http://authentik-server.authentik.svc.cluster.local"
|
||||
authentik_host_insecure: false
|
||||
authentik_host_browser: "https://auth.renner.uno/"
|
||||
refresh_interval: "minutes=5"
|
||||
container_image: null
|
||||
object_naming_template: "ak-outpost-%(name)s"
|
||||
kubernetes_namespace: authentik
|
||||
kubernetes_replicas: 1
|
||||
kubernetes_service_type: ClusterIP
|
||||
kubernetes_disabled_components: ["ingress"]
|
||||
kubernetes_image_pull_secrets: []
|
||||
kubernetes_ingress_annotations: {}
|
||||
kubernetes_ingress_class_name: null
|
||||
kubernetes_ingress_secret_name: "authentik-outpost-tls"
|
||||
kubernetes_json_patches: null
|
||||
|
||||
- model: authentik_outposts.outpost
|
||||
identifiers:
|
||||
name: authentik Embedded Outpost
|
||||
|
||||
@@ -8,6 +8,7 @@ resources:
|
||||
- paperless-gate-ingress.yaml
|
||||
- paperless-gate-egress.yaml
|
||||
- vscode-gate-egress.yaml
|
||||
- shelly-manager-gate-egress.yaml
|
||||
- outpost-servicemonitors.yaml
|
||||
- ldap-outpost-cert.yaml
|
||||
- ldap-outpost-lb.yaml
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
# Allow the dedicated shelly-manager-gate outpost to egress into the
|
||||
# home-assistant namespace and reach shelly-manager (:8080). Without this,
|
||||
# the authentik-namespace baseline CNP
|
||||
# (kubernetes/infrastructure/network-policies/authentik-ns.yaml) has no
|
||||
# egress rule to home-assistant, so the gate outpost's forwarded requests
|
||||
# are dropped. Scoped to the gate outpost's pod label so no other authentik
|
||||
# component can reach it. Mirrors vscode-gate-egress.yaml.
|
||||
apiVersion: cilium.io/v2
|
||||
kind: CiliumNetworkPolicy
|
||||
metadata:
|
||||
name: shelly-manager-gate-egress
|
||||
namespace: authentik
|
||||
spec:
|
||||
endpointSelector:
|
||||
matchLabels:
|
||||
goauthentik.io/outpost-name: shelly-manager-gate
|
||||
egress:
|
||||
- toEndpoints:
|
||||
- matchLabels:
|
||||
"k8s:io.kubernetes.pod.namespace": home-assistant
|
||||
app.kubernetes.io/name: shelly-manager
|
||||
toPorts:
|
||||
- ports:
|
||||
- port: "8080"
|
||||
protocol: TCP
|
||||
@@ -23,6 +23,7 @@ resources:
|
||||
- shelly-manager-network-attachment.yaml
|
||||
- shelly-manager-deployment.yaml
|
||||
- shelly-manager-service.yaml
|
||||
- shelly-manager-gate-service.yaml
|
||||
- shelly-manager-ingress.yaml
|
||||
configMapGenerator:
|
||||
# nginx config for the reverse-proxy sidecar. Hash suffix disabled so
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
# ExternalName mirror so the home-assistant-namespace shelly-manager Ingress
|
||||
# can backend to the shelly-manager-gate outpost that Authentik deploys into
|
||||
# the authentik namespace (cross-namespace Service refs aren't supported in a
|
||||
# standard Ingress). Mirrors ak-outpost-vscode-gate in
|
||||
# vscode-gate-service.yaml.
|
||||
#
|
||||
# Traffic path:
|
||||
# browser → traefik (shelly-manager.home.renner.uno)
|
||||
# → ak-outpost-shelly-manager-gate (ExternalName → authentik ns)
|
||||
# → outpost validates session + passkey step-up
|
||||
# → http://shelly-manager.home-assistant.svc:80 (shelly-manager :8080)
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: ak-outpost-shelly-manager-gate
|
||||
namespace: home-assistant
|
||||
spec:
|
||||
type: ExternalName
|
||||
externalName: ak-outpost-shelly-manager-gate.authentik.svc.cluster.local
|
||||
ports:
|
||||
- port: 9000
|
||||
targetPort: 9000
|
||||
@@ -12,6 +12,15 @@ spec:
|
||||
# SignalR 15s server-side keepalive keeps alive. If the UI starts
|
||||
# losing scan-progress updates, raise idleTimeout on the websecure
|
||||
# entrypoint in kubernetes/infrastructure/traefik/helmrelease.yaml.
|
||||
#
|
||||
# Traefik no longer routes to shelly-manager directly. The app has no
|
||||
# authentication of its own — anything reaching :8080 can rewrite Shelly
|
||||
# config, push scripts, and read stored device AdminPasswords — so this
|
||||
# Ingress backends the Authentik shelly-manager-gate proxy outpost
|
||||
# (ExternalName → authentik ns), which enforces a passkey step-up and
|
||||
# forwards only after the session is validated. The home-assistant CNP
|
||||
# allows ONLY that outpost to reach :8080 (see home-assistant-ns.yaml).
|
||||
# Pattern mirrors vscode-ingress.yaml.
|
||||
ingressClassName: traefik
|
||||
rules:
|
||||
- host: shelly-manager.home.renner.uno
|
||||
@@ -21,9 +30,9 @@ spec:
|
||||
pathType: Prefix
|
||||
backend:
|
||||
service:
|
||||
name: shelly-manager
|
||||
name: ak-outpost-shelly-manager-gate
|
||||
port:
|
||||
number: 80
|
||||
number: 9000
|
||||
tls:
|
||||
- secretName: shelly-manager-tls
|
||||
hosts:
|
||||
|
||||
@@ -41,6 +41,26 @@ spec:
|
||||
- ports:
|
||||
- port: "8080"
|
||||
protocol: TCP
|
||||
# shelly-manager (:8080) is likewise reached only through its own
|
||||
# Authentik gate outpost. Note this rule and the vscode one are
|
||||
# port-identical: because this CNP's endpointSelector is {}, a
|
||||
# `toPorts: 8080` grant here applies to EVERY pod in the namespace that
|
||||
# listens on 8080, not just the intended one — which is exactly how
|
||||
# shelly-manager silently rode on the old traefik→:8080 allow written
|
||||
# for code-server, and why removing that allow in 760e187 took
|
||||
# shelly-manager's ingress down with it. The `fromEndpoints` selector is
|
||||
# what keeps these two apart: each gate outpost can only reach its own
|
||||
# target, enforced on the egress side by the matching CNPs in the
|
||||
# authentik namespace (vscode-gate-egress.yaml,
|
||||
# shelly-manager-gate-egress.yaml).
|
||||
- fromEndpoints:
|
||||
- matchLabels:
|
||||
"k8s:io.kubernetes.pod.namespace": authentik
|
||||
goauthentik.io/outpost-name: shelly-manager-gate
|
||||
toPorts:
|
||||
- ports:
|
||||
- port: "8080"
|
||||
protocol: TCP
|
||||
# Prometheus scrape: kube-prometheus-stack hits HA's /api/prometheus.
|
||||
- fromEndpoints:
|
||||
- matchLabels:
|
||||
|
||||
Reference in New Issue
Block a user