diff --git a/data-restorer.yaml b/data-restorer.yaml index ea0f123..1026756 100644 --- a/data-restorer.yaml +++ b/data-restorer.yaml @@ -2,16 +2,16 @@ apiVersion: v1 kind: Pod metadata: name: data-restorer - namespace: vault + namespace: default spec: containers: - name: alpine image: alpine:latest - command: ["sleep", "infinity"] + command: ["/bin/sh", "-c", "apk add --no-cache vim && sleep infinity"] volumeMounts: - mountPath: /restore name: target-volume volumes: - name: target-volume persistentVolumeClaim: - claimName: keykeeper-data-pvc + claimName: jellyfin-config-pvc diff --git a/services/foundryvtt/foundry-vtt-account.yaml b/services/foundryvtt/foundry-vtt-account.yaml deleted file mode 100644 index 60fec67..0000000 --- a/services/foundryvtt/foundry-vtt-account.yaml +++ /dev/null @@ -1,19 +0,0 @@ ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: foundry-vtt-sa - namespace: default ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: foundry-vtt-auth-delegator -subjects: -- kind: ServiceAccount - name: foundry-vtt-sa - namespace: default -roleRef: - kind: ClusterRole - name: system:auth-delegator - apiGroup: rbac.authorization.k8s.io diff --git a/services/foundryvtt/foundry-vtt-deployment.yaml b/services/foundryvtt/foundry-vtt-deployment.yaml index 56744be..e4b7401 100644 --- a/services/foundryvtt/foundry-vtt-deployment.yaml +++ b/services/foundryvtt/foundry-vtt-deployment.yaml @@ -2,8 +2,6 @@ apiVersion: apps/v1 kind: Deployment metadata: name: foundry-vtt - annotations: - reloader.stakater.com/auto: "true" spec: replicas: 1 selector: @@ -18,7 +16,7 @@ spec: spec: containers: - name: foundry-vtt - image: felddy/foundryvtt:release + image: felddy/foundryvtt:latest ports: - containerPort: 30000 protocol: TCP diff --git a/services/foundryvtt/foundry-vtt-external-secrets.yaml b/services/foundryvtt/foundry-vtt-external-secrets.yaml index 04af5c6..ec75d4e 100644 --- a/services/foundryvtt/foundry-vtt-external-secrets.yaml +++ b/services/foundryvtt/foundry-vtt-external-secrets.yaml @@ -14,17 +14,17 @@ spec: data: - secretKey: FOUNDRY_ADMIN_KEY remoteRef: - key: foundry-vtt/config - property: admin_key + key: foundryvtt + property: admin-key - secretKey: FOUNDRY_LICENSE_KEY remoteRef: - key: foundry-vtt/config - property: license_key + key: foundryvtt + property: license-key - secretKey: FOUNDRY_PASSWORD remoteRef: - key: foundry-vtt/config + key: foundryvtt property: password - secretKey: FOUNDRY_USERNAME remoteRef: - key: foundry-vtt/config + key: foundryvtt property: username diff --git a/services/foundryvtt/foundry-vtt-ingress.yaml b/services/foundryvtt/foundry-vtt-ingress.yaml index 4cdbf01..dc6a293 100644 --- a/services/foundryvtt/foundry-vtt-ingress.yaml +++ b/services/foundryvtt/foundry-vtt-ingress.yaml @@ -1,27 +1,3 @@ -apiVersion: traefik.io/v1alpha1 -kind: Middleware -metadata: - name: foundry-proxy-headers - namespace: default -spec: - headers: - customRequestHeaders: - X-Forwarded-Proto: "https" ---- -apiVersion: traefik.io/v1alpha1 -kind: Middleware -metadata: - name: foundry-vtt-oauth-auth - namespace: default -spec: - forwardAuth: - address: http://foundry-vtt-oauth2-proxy.default.svc.cluster.local:4180/ - trustForwardHeader: true - authResponseHeaders: - - X-Auth-Request-User - - X-Auth-Request-Email - - X-Auth-Request-Access-Token ---- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: @@ -30,8 +6,7 @@ metadata: annotations: cert-manager.io/cluster-issuer: "letsencrypt-prod" traefik.ingress.kubernetes.io/router.entrypoints: websecure - traefik.ingress.kubernetes.io/router.tls: "true" - traefik.ingress.kubernetes.io/router.middlewares: default-foundry-proxy-headers@kubernetescrd, default-foundry-vtt-oauth-auth@kubernetescrd + traefik.ingress.kubernetes.io/router.middlewares: security-auth-foundryvtt@kubernetescrd spec: ingressClassName: traefik tls: @@ -53,13 +28,11 @@ spec: apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: foundry-oauth-ingress - namespace: default + name: foundry-auth-ingress + namespace: security # MOVED TO SECURITY NAMESPACE annotations: cert-manager.io/cluster-issuer: "letsencrypt-prod" traefik.ingress.kubernetes.io/router.entrypoints: websecure - traefik.ingress.kubernetes.io/router.tls: "true" - traefik.ingress.kubernetes.io/router.middlewares: default-foundry-proxy-headers@kubernetescrd spec: ingressClassName: traefik tls: @@ -74,6 +47,6 @@ spec: pathType: Prefix backend: service: - name: foundry-vtt-oauth2-proxy + name: oauth2-proxy-foundryvtt port: number: 4180 diff --git a/services/foundryvtt/foundry-vtt-oauth2-proxy-deployment.yaml b/services/foundryvtt/foundry-vtt-oauth2-proxy-deployment.yaml deleted file mode 100644 index 3346a1f..0000000 --- a/services/foundryvtt/foundry-vtt-oauth2-proxy-deployment.yaml +++ /dev/null @@ -1,39 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: foundry-vtt-oauth2-proxy - namespace: default -spec: - replicas: 1 - selector: - matchLabels: - app: foundry-vtt-oauth2-proxy - template: - metadata: - labels: - app: foundry-vtt-oauth2-proxy - spec: - containers: - - name: oauth2-proxy - image: quay.io/oauth2-proxy/oauth2-proxy:latest - args: - - --provider=oidc - - --oidc-issuer-url=https://sso.mynest.love/realms/nest - - --redirect-url=https://foundry.mynest.love/oauth2/callback - - --email-domain=* - - --upstream=static://200 - - --http-address=0.0.0.0:4180 - - --pass-authorization-header=true - - --pass-access-token=true - - --set-xauthrequest=true - - --skip-provider-button=true - - --reverse-proxy=true - - --cookie-secure=true - - --cookie-domain=.mynest.love - - --whitelist-domain=.mynest.love - - --cookie-name=_oauth2_proxy_foundry - envFrom: - - secretRef: - name: foundry-vtt-oauth2-proxy-secret - ports: - - containerPort: 4180 diff --git a/services/foundryvtt/foundry-vtt-oauth2-proxy-external-secrets.yaml b/services/foundryvtt/foundry-vtt-oauth2-proxy-external-secrets.yaml deleted file mode 100644 index bcbb785..0000000 --- a/services/foundryvtt/foundry-vtt-oauth2-proxy-external-secrets.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: external-secrets.io/v1 -kind: ExternalSecret -metadata: - name: foundry-vtt-oauth2-proxy-credentials - namespace: default -spec: - refreshInterval: "1h" - secretStoreRef: - name: vault-external-secrets-store - kind: ClusterSecretStore - target: - name: foundry-vtt-oauth2-proxy-secret - creationPolicy: Owner - data: - - secretKey: OAUTH2_PROXY_CLIENT_ID - remoteRef: - key: oauth2-proxy/foundry-vtt - property: client-id - - secretKey: OAUTH2_PROXY_CLIENT_SECRET - remoteRef: - key: oauth2-proxy/foundry-vtt - property: client-secret - - secretKey: OAUTH2_PROXY_COOKIE_SECRET - remoteRef: - key: oauth2-proxy/foundry-vtt - property: cookie-secret diff --git a/services/foundryvtt/foundry-vtt-oauth2-proxy-service.yaml b/services/foundryvtt/foundry-vtt-oauth2-proxy-service.yaml deleted file mode 100644 index da876c8..0000000 --- a/services/foundryvtt/foundry-vtt-oauth2-proxy-service.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: foundry-vtt-oauth2-proxy - namespace: default -spec: - ports: - - port: 4180 - targetPort: 4180 - selector: - app: foundry-vtt-oauth2-proxy diff --git a/services/foundryvtt/foundry-vtt-oauth2-proxy.yaml b/services/foundryvtt/foundry-vtt-oauth2-proxy.yaml new file mode 100644 index 0000000..c7d4c4b --- /dev/null +++ b/services/foundryvtt/foundry-vtt-oauth2-proxy.yaml @@ -0,0 +1,86 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: foundryvtt-proxy-foundryvtt + namespace: security +spec: + replicas: 1 + selector: + matchLabels: + app: oauth2-proxy-foundryvtt + template: + metadata: + labels: + app: oauth2-proxy-foundryvtt + spec: + containers: + - name: oauth2-proxy + image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 + envFrom: + - secretRef: + name: foundry-oauth-secrets + args: + - "--provider=oidc" + - "--oidc-issuer-url=https://sso.mynest.love/realms/nest" + - "--oidc-groups-claim=groups" + - "--redirect-url=https://foundry.mynest.love/oauth2/callback" + - "--email-domain=*" + - "--allowed-group=foundryvtt" + - "--skip-provider-button=true" + - "--cookie-secure=true" + - "--cookie-domain=foundry.mynest.love" + - "--http-address=0.0.0.0:4180" + - "--reverse-proxy=true" + - "--upstream=static://200" + - "--whitelist-domain=foundry.mynest.love" + ports: + - containerPort: 4180 +--- +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: foundry-oauth-secrets + namespace: security +spec: + refreshInterval: "1h" + secretStoreRef: + name: vault-external-secrets-store + kind: ClusterSecretStore + target: + name: foundry-oauth-secrets + creationPolicy: Owner + data: + - secretKey: OAUTH2_PROXY_CLIENT_ID + remoteRef: + key: oauth2-proxy/foundryvtt + property: client-id + - secretKey: OAUTH2_PROXY_CLIENT_SECRET + remoteRef: + key: oauth2-proxy/foundryvtt + property: client-secret + - secretKey: OAUTH2_PROXY_COOKIE_SECRET + remoteRef: + key: oauth2-proxy/foundryvtt + property: cookie-secret +--- +apiVersion: v1 +kind: Service +metadata: + name: oauth2-proxy-foundryvtt + namespace: security +spec: + ports: + - port: 4180 + targetPort: 4180 + selector: + app: oauth2-proxy-foundryvtt +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: auth-foundryvtt + namespace: security +spec: + forwardAuth: + address: "http://oauth2-proxy-foundryvtt.security.svc.cluster.local:4180" + trustForwardHeader: true diff --git a/services/keycloak/keycloak-deployment.yaml b/services/keycloak/keycloak-deployment.yaml index 162ad5c..5ab24f0 100644 --- a/services/keycloak/keycloak-deployment.yaml +++ b/services/keycloak/keycloak-deployment.yaml @@ -15,7 +15,7 @@ spec: spec: containers: - name: keycloak - image: quay.io/keycloak/keycloak:24.0.0 + image: quay.io/keycloak/keycloak:latest command: ["/bin/sh", "-c", "/opt/keycloak/bin/kc.sh start"] envFrom: - secretRef: diff --git a/services/navidrome/navidrome-account.yaml b/services/navidrome/navidrome-account.yaml deleted file mode 100644 index 35424bd..0000000 --- a/services/navidrome/navidrome-account.yaml +++ /dev/null @@ -1,19 +0,0 @@ ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: navidrome-sa - namespace: default ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: navidrome-auth-delegator -subjects: -- kind: ServiceAccount - name: navidrome-sa - namespace: default -roleRef: - kind: ClusterRole - name: system:auth-delegator - apiGroup: rbac.authorization.k8s.io diff --git a/services/navidrome/navidrome-deployment.yaml b/services/navidrome/navidrome-deployment.yaml index a62037c..e70e642 100644 --- a/services/navidrome/navidrome-deployment.yaml +++ b/services/navidrome/navidrome-deployment.yaml @@ -26,6 +26,10 @@ spec: - env: - name: TZ value: America/New_York + - name: ND_REVERSEPROXYUSERHEADER + value: "X-Auth-Request-Preferred-Username" + - name: ND_REVERSEPROXYWHITELIST + value: "10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,10.42.0.0/16,10.43.0.0/16" image: deluan/navidrome:latest name: navidrome ports: diff --git a/services/navidrome/navidrome-ingress.yaml b/services/navidrome/navidrome-ingress.yaml index c2e4e18..b4c3434 100644 --- a/services/navidrome/navidrome-ingress.yaml +++ b/services/navidrome/navidrome-ingress.yaml @@ -1,23 +1,14 @@ -apiVersion: traefik.io/v1alpha1 -kind: Middleware -metadata: - name: navidrome-proxy-headers - namespace: default -spec: - headers: - customRequestHeaders: - X-Forwarded-Proto: "https" ---- +# 1. Main Web UI Ingress - Protected by SSO apiVersion: networking.k8s.io/v1 kind: Ingress metadata: - name: navidrome-ingress + name: navidrome-ingress-web namespace: default annotations: cert-manager.io/cluster-issuer: "letsencrypt-prod" traefik.ingress.kubernetes.io/router.entrypoints: websecure traefik.ingress.kubernetes.io/router.tls: "true" - traefik.ingress.kubernetes.io/router.middlewares: default-navidrome-proxy-headers@kubernetescrd + traefik.ingress.kubernetes.io/router.middlewares: default-navidrome-proxy-headers@kubernetescrd, security-auth-navidrome@kubernetescrd spec: tls: - hosts: @@ -34,3 +25,66 @@ spec: name: navidrome port: name: http-web +--- +# 2. Subsonic API Ingress - Bypasses SSO Middleware for Mobile Clients +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: navidrome-ingress-api + namespace: default + annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.tls: "true" + traefik.ingress.kubernetes.io/router.middlewares: default-navidrome-proxy-headers@kubernetescrd +spec: + ingressClassName: traefik + tls: + - hosts: + - chirp.mynest.love + secretName: navidrome-tls + rules: + - host: chirp.mynest.love + http: + paths: + - path: /rest + pathType: Prefix + backend: + service: + name: navidrome + port: + name: http-web + - path: /share + pathType: Prefix + backend: + service: + name: navidrome + port: + name: http-web +--- +# 3. Auth Callback Ingress - Bypasses SSO to deliver tokens directly to the proxy +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: navidrome-auth-ingress + namespace: security + annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" + traefik.ingress.kubernetes.io/router.entrypoints: websecure +spec: + ingressClassName: traefik + tls: + - hosts: + - chirp.mynest.love + secretName: navidrome-tls + rules: + - host: chirp.mynest.love + http: + paths: + - path: /oauth2 + pathType: Prefix + backend: + service: + name: oauth2-proxy-navidrome + port: + number: 4180 diff --git a/services/navidrome/navidrome-oauth2.yaml b/services/navidrome/navidrome-oauth2.yaml new file mode 100644 index 0000000..174995f --- /dev/null +++ b/services/navidrome/navidrome-oauth2.yaml @@ -0,0 +1,120 @@ +apiVersion: external-secrets.io/v1 +kind: ExternalSecret +metadata: + name: navidrome-oauth-secrets + namespace: security +spec: + refreshInterval: "1h" + secretStoreRef: + name: vault-external-secrets-store + kind: ClusterSecretStore + target: + name: navidrome-oauth-secrets + creationPolicy: Owner + data: + - secretKey: OAUTH2_PROXY_CLIENT_ID + remoteRef: + key: oauth2-proxy/navidrome + property: client-id + - secretKey: OAUTH2_PROXY_CLIENT_SECRET + remoteRef: + key: oauth2-proxy/navidrome + property: client-secret + - secretKey: OAUTH2_PROXY_COOKIE_SECRET + remoteRef: + key: oauth2-proxy/navidrome + property: cookie-secret +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: oauth2-proxy-navidrome + namespace: security +spec: + replicas: 1 + selector: + matchLabels: + app: oauth2-proxy-navidrome + template: + metadata: + labels: + app: oauth2-proxy-navidrome + spec: + containers: + - name: oauth2-proxy + image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 + envFrom: + - secretRef: + name: navidrome-oauth-secrets + args: + - "--provider=oidc" + - "--user-id-claim=preferred_username" + - "--set-xauthrequest=true" + - "--oidc-issuer-url=https://sso.mynest.love/realms/nest" + - "--oidc-groups-claim=groups" + - "--redirect-url=https://chirp.mynest.love/oauth2/callback" + - "--email-domain=*" + - "--allowed-group=navidrome" + - "--skip-provider-button=true" + - "--cookie-secure=true" + - "--cookie-domain=chirp.mynest.love" + - "--http-address=0.0.0.0:4180" + - "--reverse-proxy=true" + - "--upstream=static://200" + - "--whitelist-domain=chirp.mynest.love" + - "--set-xauthrequest=true" + ports: + - containerPort: 4180 +--- +apiVersion: v1 +kind: Service +metadata: + name: oauth2-proxy-navidrome + namespace: security +spec: + ports: + - port: 4180 + targetPort: 4180 + selector: + app: oauth2-proxy-navidrome +--- +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: auth-navidrome + namespace: security +spec: + forwardAuth: + address: http://oauth2-proxy-navidrome.security.svc.cluster.local:4180 + trustForwardHeader: true + authResponseHeaders: + - X-Auth-Request-User + - X-Auth-Request-Email + - X-Auth-Request-Preferred-Username +--- +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: navidrome-auth-ingress + namespace: security + annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" + traefik.ingress.kubernetes.io/router.entrypoints: websecure + traefik.ingress.kubernetes.io/router.tls: "true" +spec: + ingressClassName: traefik + tls: + - hosts: + - chirp.mynest.love + secretName: navidrome-tls + rules: + - host: chirp.mynest.love + http: + paths: + - path: /oauth2 + pathType: Prefix + backend: + service: + name: oauth2-proxy-navidrome + port: + number: 4180