auth-proxy: verify group membership (#105)

* auth-proxy: verify group membership

* memberships: install memberships app and use it in few apps

* app-repo: render auth

* installer: always use external dependencies option in app configs

* installer: fix auth handling

* auth-proxy: configure membership-addr and groups flags in helm chart

* installer: fix indentation

* app-manager: fix how auth block is rendered

---------

Co-authored-by: Giorgi Lekveishvili <lekva@gl-mbp-m1-max.local>
diff --git a/core/installer/values-tmpl/cert-manager.cue b/core/installer/values-tmpl/cert-manager.cue
index 7f4f55a..fdede37 100644
--- a/core/installer/values-tmpl/cert-manager.cue
+++ b/core/installer/values-tmpl/cert-manager.cue
@@ -55,7 +55,7 @@
 helm: {
 	"cert-manager": {
 		chart: charts.certManager
-		dependsOnExternal: [{
+		dependsOn: [{
 			name: "ingress-public"
 			namespace: _ingressPublic
 		}]
@@ -87,7 +87,10 @@
 	}
 	"cert-manager-webhook-pcloud": {
 		chart: charts.dnsChallengeSolver
-		dependsOn: [helm["cert-manager"]]
+		dependsOn: [{
+			name: "cert-manager"
+			namespace: release.namespace
+		}]
 		values: {
 			fullnameOverride: "\(global.pcloudEnvName)-cert-manager-webhook-pcloud"
 			certManager: {
diff --git a/core/installer/values-tmpl/certificate-issuer-private.cue b/core/installer/values-tmpl/certificate-issuer-private.cue
index ca4c7c2..fc490a3 100644
--- a/core/installer/values-tmpl/certificate-issuer-private.cue
+++ b/core/installer/values-tmpl/certificate-issuer-private.cue
@@ -24,7 +24,7 @@
 helm: {
 	"certificate-issuer-private": {
 		chart: charts["certificate-issuer-private"]
-		dependsOnExternal: [{
+		dependsOn: [{
 			name: "ingress-nginx"
 			namespace: "\(global.namespacePrefix)ingress-private"
 		}]
diff --git a/core/installer/values-tmpl/certificate-issuer-public.cue b/core/installer/values-tmpl/certificate-issuer-public.cue
index 33be2a9..58a4bfd 100644
--- a/core/installer/values-tmpl/certificate-issuer-public.cue
+++ b/core/installer/values-tmpl/certificate-issuer-public.cue
@@ -19,7 +19,7 @@
 helm: {
 	"certificate-issuer-public": {
 		chart: charts["certificate-issuer-public"]
-		dependsOnExternal: [{
+		dependsOn: [{
 			name: "ingress-nginx"
 			namespace: "\(global.namespacePrefix)ingress-private"
 		}]
diff --git a/core/installer/values-tmpl/core-auth.cue b/core/installer/values-tmpl/core-auth.cue
index 192f806..0e9f26f 100644
--- a/core/installer/values-tmpl/core-auth.cue
+++ b/core/installer/values-tmpl/core-auth.cue
@@ -128,10 +128,12 @@
 	}
 	auth: {
 		chart: charts.auth
-		dependsOn: [postgres]
-		dependsOnExternal: [{
+		dependsOn: [{
 			name: "ingress-nginx"
 			namespace: "\(global.namespacePrefix)ingress-private"
+		}, {
+			name: "postgres"
+			namespace: release.namespace
 		}]
 		values: {
 			kratos: {
diff --git a/core/installer/values-tmpl/headscale.cue b/core/installer/values-tmpl/headscale.cue
index 1db5eb8..fee75ab 100644
--- a/core/installer/values-tmpl/headscale.cue
+++ b/core/installer/values-tmpl/headscale.cue
@@ -47,7 +47,7 @@
 	"oauth2-client": {
 		chart: charts.oauth2Client
 		// TODO(gio): remove once hydra maester is installed as part of dodo itself
-		dependsOnExternal: [{
+		dependsOn: [{
 			name: "auth"
 			namespace: "\(global.namespacePrefix)core-auth"
 		}]
@@ -63,7 +63,7 @@
 	}
 	headscale: {
 		chart: charts.headscale
-		dependsOnExternal: [{
+		dependsOn: [{
 			name: "auth"
 			namespace: "\(global.namespacePrefix)core-auth"
 		}]
diff --git a/core/installer/values-tmpl/matrix.cue b/core/installer/values-tmpl/matrix.cue
index 9daf2eb..1f32318 100644
--- a/core/installer/values-tmpl/matrix.cue
+++ b/core/installer/values-tmpl/matrix.cue
@@ -69,9 +69,10 @@
 		}
 	}
 	matrix: {
-		dependsOn: [
-			postgres
-	    ]
+		dependsOn: [{
+			name: "postgres"
+			namespace: release.namespace
+		}]
 		chart: charts.matrix
 		values: {
 			domain: global.domain
diff --git a/core/installer/values-tmpl/memberships.cue b/core/installer/values-tmpl/memberships.cue
index 4abd6d6..6790cfd 100644
--- a/core/installer/values-tmpl/memberships.cue
+++ b/core/installer/values-tmpl/memberships.cue
@@ -1,14 +1,10 @@
-input: {
-    network: #Network
-    subdomain: string
-    requireAuth: bool
-}
+input: {}
 
-_domain: "\(input.subdomain).\(input.network.domain)"
+_domain: "memberships.\(global.privateDomain)"
 
 name: "memberships"
-namespace: "app-memberships"
-readme: "Memberships application will be installed on \(input.network.name) network and be accessible at https://\(_domain)"
+namespace: "core-auth-memberships"
+readme: "Memberships application will be installed on Private network and be accessible at https://\(_domain)"
 description: "The application is a membership management system designed to facilitate the organization and administration of groups and memberships. Can be configured to be reachable only from private network or publicly."
 icon: "<svg xmlns='http://www.w3.org/2000/svg' width='50' height='50' viewBox='0 0 24 24'><path fill='currentColor' d='M15.43 15.48c-1.1-.49-2.26-.73-3.43-.73c-1.18 0-2.33.25-3.43.73c-.23.1-.4.29-.49.52h7.85a.978.978 0 0 0-.5-.52m-2.49-6.69C12.86 8.33 12.47 8 12 8s-.86.33-.94.79l-.2 1.21h2.28z' opacity='0.3'/><path fill='currentColor' d='M10.27 12h3.46a1.5 1.5 0 0 0 1.48-1.75l-.3-1.79a2.951 2.951 0 0 0-5.82.01l-.3 1.79c-.15.91.55 1.74 1.48 1.74m.79-3.21c.08-.46.47-.79.94-.79s.86.33.94.79l.2 1.21h-2.28zm-9.4 2.32c-.13.26-.18.57-.1.88c.16.69.76 1.03 1.53 1h1.95c.83 0 1.51-.58 1.51-1.29c0-.14-.03-.27-.07-.4c-.01-.03-.01-.05.01-.08c.09-.16.14-.34.14-.53c0-.31-.14-.6-.36-.82c-.03-.03-.03-.06-.02-.1c.07-.2.07-.43.01-.65a1.12 1.12 0 0 0-.99-.74a.09.09 0 0 1-.07-.03C5.03 8.14 4.72 8 4.37 8c-.3 0-.57.1-.75.26c-.03.03-.06.03-.09.02a1.24 1.24 0 0 0-1.7 1.03c0 .02-.01.04-.03.06c-.29.26-.46.65-.41 1.05c.03.22.12.43.25.6c.03.02.03.06.02.09m14.58 2.54c-1.17-.52-2.61-.9-4.24-.9c-1.63 0-3.07.39-4.24.9A2.988 2.988 0 0 0 6 16.39V18h12v-1.61c0-1.18-.68-2.26-1.76-2.74M8.07 16a.96.96 0 0 1 .49-.52c1.1-.49 2.26-.73 3.43-.73c1.18 0 2.33.25 3.43.73c.23.1.4.29.49.52zm-6.85-1.42A2.01 2.01 0 0 0 0 16.43V18h4.5v-1.61c0-.83.23-1.61.63-2.29c-.37-.06-.74-.1-1.13-.1c-.99 0-1.93.21-2.78.58m21.56 0A6.95 6.95 0 0 0 20 14c-.39 0-.76.04-1.13.1c.4.68.63 1.46.63 2.29V18H24v-1.57c0-.81-.48-1.53-1.22-1.85M22 11v-.5c0-1.1-.9-2-2-2h-2c-.42 0-.65.48-.39.81l.7.63c-.19.31-.31.67-.31 1.06c0 1.1.9 2 2 2s2-.9 2-2'/></svg>"
 
@@ -59,7 +55,7 @@
 _httpPortName: "http"
 
 helm: {
-    "memberships": {
+    memberships: {
         chart: charts.memberships
         values: {
             storage: {
diff --git a/core/installer/values-tmpl/pihole.cue b/core/installer/values-tmpl/pihole.cue
index 35d4c51..ff04fe2 100644
--- a/core/installer/values-tmpl/pihole.cue
+++ b/core/installer/values-tmpl/pihole.cue
@@ -1,7 +1,7 @@
 input: {
 	network: #Network
 	subdomain: string
-	requireAuth: bool
+	auth: #Auth
 }
 
 _domain: "\(input.subdomain).\(input.network.domain)"
@@ -108,7 +108,7 @@
 			}
 		}
 	}
-	if input.requireAuth {
+	if input.auth.enabled {
 		"auth-proxy": {
 			chart: charts.authProxy
 			values: {
@@ -120,6 +120,8 @@
 				upstream: "\(_piholeServiceName).\(release.namespace).svc.cluster.local"
 				whoAmIAddr: "https://accounts.\(global.domain)/sessions/whoami"
 				loginAddr: "https://accounts-ui.\(global.domain)/login"
+				membershipAddr: "http://memberships.\(global.id)-core-auth-memberships.svc.cluster.local/api/user"
+				groups: input.auth.groups
 				portName: _httpPortName
 			}
 		}
@@ -131,11 +133,11 @@
 			ingressClassName: input.network.ingressClass
 			certificateIssuer: input.network.certificateIssuer
 			service: {
-				if input.requireAuth {
+				if input.auth.enabled {
 					name: _authProxyServiceName
 					port: name: _httpPortName
 				}
-				if !input.requireAuth {
+				if !input.auth.enabled {
 					name: _piholeServiceName
 					port: number: _serviceWebPort
 				}
diff --git a/core/installer/values-tmpl/rpuppy.cue b/core/installer/values-tmpl/rpuppy.cue
index ff316a0..4955f81 100644
--- a/core/installer/values-tmpl/rpuppy.cue
+++ b/core/installer/values-tmpl/rpuppy.cue
@@ -1,7 +1,7 @@
 input: {
 	network: #Network
 	subdomain: string
-	requireAuth: bool
+	auth: #Auth
 }
 
 _domain: "\(input.subdomain).\(input.network.domain)"
@@ -70,7 +70,7 @@
 			portName: _httpPortName
 		}
 	}
-	if input.requireAuth {
+	if input.auth.enabled {
 		"auth-proxy": {
 			chart: charts.authProxy
 			values: {
@@ -82,6 +82,8 @@
 				upstream: "\(_rpuppyServiceName).\(release.namespace).svc.cluster.local"
 				whoAmIAddr: "https://accounts.\(global.domain)/sessions/whoami"
 				loginAddr: "https://accounts-ui.\(global.domain)/login"
+				membershipAddr: "http://memberships.\(global.id)-core-auth-memberships.svc.cluster.local/api/user"
+				groups: input.auth.groups
 				portName: _httpPortName
 			}
 		}
@@ -93,10 +95,10 @@
 			ingressClassName: input.network.ingressClass
 			certificateIssuer: input.network.certificateIssuer
 			service: {
-				if input.requireAuth {
+				if input.auth.enabled {
 					name: _authProxyServiceName
 				}
-				if !input.requireAuth {
+				if !input.auth.enabled {
 					name: _rpuppyServiceName
 				}
 				port: name: _httpPortName
diff --git a/core/installer/values-tmpl/url-shortener.cue b/core/installer/values-tmpl/url-shortener.cue
index 7d854e8..42a3ce8 100644
--- a/core/installer/values-tmpl/url-shortener.cue
+++ b/core/installer/values-tmpl/url-shortener.cue
@@ -1,7 +1,7 @@
 input: {
     network: #Network
     subdomain: string
-	requireAuth: bool
+	auth: #Auth
 }
 
 _domain: "\(input.subdomain).\(input.network.domain)"
@@ -73,7 +73,7 @@
             portName: _httpPortName
         }
     }
-	if input.requireAuth {
+	if input.auth.enabled {
 		"auth-proxy": {
 			chart: charts.authProxy
 			values: {
@@ -85,6 +85,8 @@
 				upstream: "\(_urlShortenerServiceName).\(release.namespace).svc.cluster.local"
 				whoAmIAddr: "https://accounts.\(global.domain)/sessions/whoami"
 				loginAddr: "https://accounts-ui.\(global.domain)/login"
+				membershipAddr: "http://memberships.\(global.id)-core-auth-memberships.svc.cluster.local/api/user"
+				groups: input.auth.groups
 				portName: _httpPortName
 			}
 		}
@@ -96,10 +98,10 @@
 			ingressClassName: input.network.ingressClass
 			certificateIssuer: input.network.certificateIssuer
 			service: {
-				if input.requireAuth {
+				if input.auth.enabled {
 					name: _authProxyServiceName
 				}
-				if !input.requireAuth {
+				if !input.auth.enabled {
 					name: _urlShortenerServiceName
 				}
 				port: name: _httpPortName