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/tasks/infra.go b/core/installer/tasks/infra.go
index 59bc986..c7e6f9e 100644
--- a/core/installer/tasks/infra.go
+++ b/core/installer/tasks/infra.go
@@ -35,6 +35,7 @@
 			SetupNetwork(env, startIP, st),
 			SetupCertificateIssuers(env, st),
 			SetupAuth(env, st),
+			SetupGroupMemberships(env, st),
 			SetupHeadscale(env, startIP, st),
 			SetupWelcome(env, st),
 			SetupAppStore(env, st),
@@ -229,6 +230,24 @@
 	)
 }
 
+func SetupGroupMemberships(env Env, st *state) Task {
+	t := newLeafTask("Setup", func() error {
+		app, err := st.appsRepo.Find("memberships")
+		if err != nil {
+			return err
+		}
+		if err := st.appManager.Install(app, st.nsGen, st.emptySuffixGen, map[string]any{}); err != nil {
+			return err
+		}
+		return nil
+	})
+	return newSequentialParentTask(
+		"Group Membership",
+		&t,
+		waitForAddr(fmt.Sprintf("https://memberships.p.%s", env.Domain)),
+	)
+}
+
 func SetupHeadscale(env Env, startIP net.IP, st *state) Task {
 	t := newLeafTask("Setup", func() error {
 		app, err := st.appsRepo.Find("headscale")