blob: 6f02fa3ba445ec1ea037d023369e2d30370e8022 [file] [log] [blame]
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +04001package tasks
2
3import (
4 "fmt"
Giorgi Lekveishvilid542b732024-03-25 18:17:39 +04005 "strings"
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +04006
7 "github.com/miekg/dns"
8
9 "github.com/giolekva/pcloud/core/installer"
gioe72b54f2024-04-22 10:44:41 +040010 "github.com/giolekva/pcloud/core/installer/soft"
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040011)
12
Giorgi Lekveishvilid542b732024-03-25 18:17:39 +040013var initGroups = []string{"admin"}
14
gioe72b54f2024-04-22 10:44:41 +040015func CreateRepoClient(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040016 t := newLeafTask("Create repo client", func() error {
gioe72b54f2024-04-22 10:44:41 +040017 r, err := st.ssClient.GetRepo("config")
gio3af43942024-04-16 08:13:50 +040018 if err != nil {
19 return err
20 }
giof8843412024-05-22 16:38:05 +040021 appManager, err := installer.NewAppManager(r, st.nsCreator, st.jc, st.hf, "/apps")
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040022 if err != nil {
23 return err
24 }
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040025 st.appManager = appManager
26 st.appsRepo = installer.NewInMemoryAppRepository(installer.CreateAllApps())
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040027 return nil
28 })
Giorgi Lekveishviliab7ff6e2024-03-29 13:11:30 +040029 t.beforeStart = func() {
30 st.infoListener("Setting up core infrastructure services.")
31 }
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040032 return &t
33}
34
gioe72b54f2024-04-22 10:44:41 +040035func SetupInfra(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040036 return newConcurrentParentTask(
37 "Setup core services",
38 true,
gioe72b54f2024-04-22 10:44:41 +040039 SetupNetwork(env, st),
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040040 SetupCertificateIssuers(env, st),
41 SetupAuth(env, st),
42 SetupGroupMemberships(env, st),
gioe72b54f2024-04-22 10:44:41 +040043 SetupHeadscale(env, st),
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040044 SetupWelcome(env, st),
45 SetupAppStore(env, st),
Davit Tabidze56f86a42024-04-09 19:15:25 +040046 SetupLauncher(env, st),
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040047 )
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040048}
49
gioe72b54f2024-04-22 10:44:41 +040050func CommitEnvironmentConfiguration(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040051 t := newLeafTask("commit config", func() error {
gioe72b54f2024-04-22 10:44:41 +040052 r, err := st.ssClient.GetRepo("config")
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040053 if err != nil {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040054 return err
55 }
gioe72b54f2024-04-22 10:44:41 +040056 r.Do(func(r soft.RepoFS) (string, error) {
57 if err := soft.WriteYaml(r, "config.yaml", env); err != nil {
58 return "", err
gio3af43942024-04-16 08:13:50 +040059 }
gioe72b54f2024-04-22 10:44:41 +040060 rootKust, err := soft.ReadKustomization(r, "kustomization.yaml")
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040061 if err != nil {
gio3af43942024-04-16 08:13:50 +040062 return "", err
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040063 }
gioe72b54f2024-04-22 10:44:41 +040064 if err := soft.WriteYaml(r, "kustomization.yaml", rootKust); err != nil {
gio3af43942024-04-16 08:13:50 +040065 return "", err
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040066 }
gio3af43942024-04-16 08:13:50 +040067 return "configure charts repo", nil
68 })
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040069 return nil
70 })
71 return &t
72}
73
Giorgi Lekveishvilid542b732024-03-25 18:17:39 +040074type firstAccount struct {
75 Created bool `json:"created"`
76 Groups []string `json:"groups"`
77}
78
gioe72b54f2024-04-22 10:44:41 +040079func ConfigureFirstAccount(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishvilid542b732024-03-25 18:17:39 +040080 t := newLeafTask("Configure first account settings", func() error {
gioe72b54f2024-04-22 10:44:41 +040081 r, err := st.ssClient.GetRepo("config")
Giorgi Lekveishvilid542b732024-03-25 18:17:39 +040082 if err != nil {
83 return err
84 }
gioe72b54f2024-04-22 10:44:41 +040085 return r.Do(func(r soft.RepoFS) (string, error) {
gio3af43942024-04-16 08:13:50 +040086 fa := firstAccount{false, initGroups}
gioe72b54f2024-04-22 10:44:41 +040087 if err := soft.WriteYaml(r, "first-account.yaml", fa); err != nil {
gio3af43942024-04-16 08:13:50 +040088 return "", err
89 }
90 return "first account membership configuration", nil
91 })
Giorgi Lekveishvilid542b732024-03-25 18:17:39 +040092 })
93 return &t
94}
95
gioe72b54f2024-04-22 10:44:41 +040096func SetupNetwork(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040097 t := newLeafTask("Setup private and public networks", func() error {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040098 {
gio3cdee592024-04-17 10:15:56 +040099 app, err := installer.FindEnvApp(st.appsRepo, "metallb-ipaddresspool")
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400100 if err != nil {
101 return err
102 }
gio3af43942024-04-16 08:13:50 +0400103 {
gio44f621b2024-04-29 09:44:38 +0400104 instanceId := fmt.Sprintf("%s-ingress-private", app.Slug())
gio3cdee592024-04-17 10:15:56 +0400105 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400106 namespace := fmt.Sprintf("%s%s-ingress-private", env.NamespacePrefix, app.Namespace())
gio778577f2024-04-29 09:44:38 +0400107 if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
gioe72b54f2024-04-22 10:44:41 +0400108 "name": fmt.Sprintf("%s-ingress-private", env.Id),
109 "from": env.Network.Ingress.String(),
110 "to": env.Network.Ingress.String(),
gio3af43942024-04-16 08:13:50 +0400111 "autoAssign": false,
112 "namespace": "metallb-system",
113 }); err != nil {
114 return err
115 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400116 }
gio3af43942024-04-16 08:13:50 +0400117 {
gio44f621b2024-04-29 09:44:38 +0400118 instanceId := fmt.Sprintf("%s-headscale", app.Slug())
gio3cdee592024-04-17 10:15:56 +0400119 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400120 namespace := fmt.Sprintf("%s%s-ingress-private", env.NamespacePrefix, app.Namespace())
gio778577f2024-04-29 09:44:38 +0400121 if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
gioe72b54f2024-04-22 10:44:41 +0400122 "name": fmt.Sprintf("%s-headscale", env.Id),
123 "from": env.Network.Headscale.String(),
124 "to": env.Network.Headscale.String(),
gio3af43942024-04-16 08:13:50 +0400125 "autoAssign": false,
126 "namespace": "metallb-system",
127 }); err != nil {
128 return err
129 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400130 }
gio3af43942024-04-16 08:13:50 +0400131 {
gio44f621b2024-04-29 09:44:38 +0400132 instanceId := app.Slug()
gio3cdee592024-04-17 10:15:56 +0400133 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400134 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio778577f2024-04-29 09:44:38 +0400135 if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
gioe72b54f2024-04-22 10:44:41 +0400136 "name": env.Id,
137 "from": env.Network.ServicesFrom.String(),
138 "to": env.Network.ServicesTo.String(),
gio3af43942024-04-16 08:13:50 +0400139 "autoAssign": false,
140 "namespace": "metallb-system",
141 }); err != nil {
142 return err
143 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400144 }
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400145 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400146 {
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +0400147 keys, err := installer.NewSSHKeyPair("port-allocator")
148 if err != nil {
149 return err
150 }
gioe72b54f2024-04-22 10:44:41 +0400151 user := fmt.Sprintf("%s-port-allocator", env.Id)
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +0400152 if err := st.ssClient.AddUser(user, keys.AuthorizedKey()); err != nil {
153 return err
154 }
155 if err := st.ssClient.AddReadWriteCollaborator("config", user); err != nil {
156 return err
157 }
gio3cdee592024-04-17 10:15:56 +0400158 app, err := installer.FindEnvApp(st.appsRepo, "private-network")
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400159 if err != nil {
160 return err
161 }
gio44f621b2024-04-29 09:44:38 +0400162 instanceId := app.Slug()
gio3cdee592024-04-17 10:15:56 +0400163 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400164 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio778577f2024-04-29 09:44:38 +0400165 if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400166 "privateNetwork": map[string]any{
167 "hostname": "private-network-proxy",
168 "username": "private-network-proxy",
gioe72b54f2024-04-22 10:44:41 +0400169 "ipSubnet": fmt.Sprintf("%s.0/24", strings.Join(strings.Split(env.Network.DNS.String(), ".")[:3], ".")),
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400170 },
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +0400171 "sshPrivateKey": string(keys.RawPrivateKey()),
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400172 }); err != nil {
173 return err
174 }
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400175 }
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400176 return nil
177 })
178 return &t
179}
180
gioe72b54f2024-04-22 10:44:41 +0400181func SetupCertificateIssuers(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400182 pub := newLeafTask(fmt.Sprintf("Public %s", env.Domain), func() error {
gio3cdee592024-04-17 10:15:56 +0400183 app, err := installer.FindEnvApp(st.appsRepo, "certificate-issuer-public")
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400184 if err != nil {
185 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400186 }
gio44f621b2024-04-29 09:44:38 +0400187 instanceId := app.Slug()
gio3cdee592024-04-17 10:15:56 +0400188 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400189 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio778577f2024-04-29 09:44:38 +0400190 if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{}); err != nil {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400191 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400192 }
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400193 return nil
194 })
195 priv := newLeafTask(fmt.Sprintf("Private p.%s", env.Domain), func() error {
gio3cdee592024-04-17 10:15:56 +0400196 app, err := installer.FindEnvApp(st.appsRepo, "certificate-issuer-private")
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400197 if err != nil {
198 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400199 }
gio44f621b2024-04-29 09:44:38 +0400200 instanceId := app.Slug()
gio3cdee592024-04-17 10:15:56 +0400201 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400202 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio778577f2024-04-29 09:44:38 +0400203 if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{}); err != nil {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400204 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400205 }
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400206 return nil
207 })
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400208 return newSequentialParentTask("Configure TLS certificate issuers", false, &pub, &priv)
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400209}
210
gioe72b54f2024-04-22 10:44:41 +0400211func SetupAuth(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400212 t := newLeafTask("Setup", func() error {
gio3cdee592024-04-17 10:15:56 +0400213 app, err := installer.FindEnvApp(st.appsRepo, "core-auth")
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400214 if err != nil {
215 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400216 }
gio44f621b2024-04-29 09:44:38 +0400217 instanceId := app.Slug()
gio3cdee592024-04-17 10:15:56 +0400218 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400219 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio778577f2024-04-29 09:44:38 +0400220 if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400221 "subdomain": "test", // TODO(giolekva): make core-auth chart actually use this
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400222 }); err != nil {
223 return err
224 }
225 return nil
226 })
227 return newSequentialParentTask(
228 "Authentication services",
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400229 false,
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400230 &t,
gioe72b54f2024-04-22 10:44:41 +0400231 waitForAddr(st.httpClient, fmt.Sprintf("https://accounts-ui.%s", env.Domain)),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400232 )
233}
234
gioe72b54f2024-04-22 10:44:41 +0400235func SetupGroupMemberships(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400236 t := newLeafTask("Setup", func() error {
gio3cdee592024-04-17 10:15:56 +0400237 app, err := installer.FindEnvApp(st.appsRepo, "memberships")
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400238 if err != nil {
239 return err
240 }
gio44f621b2024-04-29 09:44:38 +0400241 instanceId := app.Slug()
gio3cdee592024-04-17 10:15:56 +0400242 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400243 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio778577f2024-04-29 09:44:38 +0400244 if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
Giorgi Lekveishvilid542b732024-03-25 18:17:39 +0400245 "authGroups": strings.Join(initGroups, ","),
246 }); err != nil {
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400247 return err
248 }
249 return nil
250 })
251 return newSequentialParentTask(
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400252 "Group membership",
253 false,
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400254 &t,
gioe72b54f2024-04-22 10:44:41 +0400255 waitForAddr(st.httpClient, fmt.Sprintf("https://memberships.p.%s", env.Domain)),
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400256 )
257}
258
gio09a3e5b2024-04-26 14:11:06 +0400259func SetupLauncher(env installer.EnvConfig, st *state) Task {
260 t := newLeafTask("Setup", func() error {
261 user := fmt.Sprintf("%s-launcher", env.Id)
262 keys, err := installer.NewSSHKeyPair(user)
263 if err != nil {
264 return err
265 }
266 if err := st.ssClient.AddUser(user, keys.AuthorizedKey()); err != nil {
267 return err
268 }
269 if err := st.ssClient.AddReadWriteCollaborator("config", user); err != nil {
270 return err
271 }
272 app, err := installer.FindEnvApp(st.appsRepo, "launcher")
273 if err != nil {
274 return err
275 }
276 instanceId := app.Slug()
277 appDir := fmt.Sprintf("/apps/%s", instanceId)
278 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
279 if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
280 "repoAddr": st.ssClient.GetRepoAddress("config"),
281 "sshPrivateKey": string(keys.RawPrivateKey()),
282 }); err != nil {
283 return err
284 }
285 return nil
286 })
287 return newSequentialParentTask(
288 "Launcher",
289 false,
290 &t,
291 waitForAddr(st.httpClient, fmt.Sprintf("https://launcher.%s", env.Domain)),
292 )
293}
294
gioe72b54f2024-04-22 10:44:41 +0400295func SetupHeadscale(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400296 t := newLeafTask("Setup", func() error {
gio3cdee592024-04-17 10:15:56 +0400297 app, err := installer.FindEnvApp(st.appsRepo, "headscale")
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400298 if err != nil {
299 return err
300 }
gio44f621b2024-04-29 09:44:38 +0400301 instanceId := app.Slug()
gio3cdee592024-04-17 10:15:56 +0400302 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400303 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio778577f2024-04-29 09:44:38 +0400304 if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400305 "subdomain": "headscale",
gioe72b54f2024-04-22 10:44:41 +0400306 "ipSubnet": fmt.Sprintf("%s/24", env.Network.DNS.String()),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400307 }); err != nil {
308 return err
309 }
310 return nil
311 })
312 return newSequentialParentTask(
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400313 "Setup mesh VPN",
314 false,
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400315 &t,
gioe72b54f2024-04-22 10:44:41 +0400316 waitForAddr(st.httpClient, fmt.Sprintf("https://headscale.%s/apple", env.Domain)),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400317 )
318}
319
gioe72b54f2024-04-22 10:44:41 +0400320func SetupWelcome(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400321 t := newLeafTask("Setup", func() error {
322 keys, err := installer.NewSSHKeyPair("welcome")
323 if err != nil {
324 return err
325 }
gioe72b54f2024-04-22 10:44:41 +0400326 user := fmt.Sprintf("%s-welcome", env.Id)
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400327 if err := st.ssClient.AddUser(user, keys.AuthorizedKey()); err != nil {
328 return err
329 }
330 if err := st.ssClient.AddReadWriteCollaborator("config", user); err != nil {
331 return err
332 }
gio3cdee592024-04-17 10:15:56 +0400333 app, err := installer.FindEnvApp(st.appsRepo, "welcome")
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400334 if err != nil {
335 return err
336 }
gio44f621b2024-04-29 09:44:38 +0400337 instanceId := app.Slug()
gio3cdee592024-04-17 10:15:56 +0400338 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400339 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio778577f2024-04-29 09:44:38 +0400340 if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400341 "repoAddr": st.ssClient.GetRepoAddress("config"),
342 "sshPrivateKey": string(keys.RawPrivateKey()),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400343 }); err != nil {
344 return err
345 }
346 return nil
347 })
348 return newSequentialParentTask(
349 "Welcome service",
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400350 false,
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400351 &t,
gioe72b54f2024-04-22 10:44:41 +0400352 waitForAddr(st.httpClient, fmt.Sprintf("https://welcome.%s", env.Domain)),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400353 )
354}
355
gioe72b54f2024-04-22 10:44:41 +0400356func SetupAppStore(env installer.EnvConfig, st *state) Task {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400357 t := newLeafTask("Application marketplace", func() error {
gioe72b54f2024-04-22 10:44:41 +0400358 user := fmt.Sprintf("%s-appmanager", env.Id)
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400359 keys, err := installer.NewSSHKeyPair(user)
360 if err != nil {
361 return err
362 }
363 if err := st.ssClient.AddUser(user, keys.AuthorizedKey()); err != nil {
364 return err
365 }
366 if err := st.ssClient.AddReadWriteCollaborator("config", user); err != nil {
367 return err
368 }
gio3cdee592024-04-17 10:15:56 +0400369 app, err := installer.FindEnvApp(st.appsRepo, "app-manager") // TODO(giolekva): configure
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400370 if err != nil {
371 return err
372 }
gio44f621b2024-04-29 09:44:38 +0400373 instanceId := app.Slug()
gio3cdee592024-04-17 10:15:56 +0400374 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400375 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio778577f2024-04-29 09:44:38 +0400376 if _, err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400377 "repoAddr": st.ssClient.GetRepoAddress("config"),
378 "sshPrivateKey": string(keys.RawPrivateKey()),
Giorgi Lekveishvili3c91e8b2024-03-25 20:20:14 +0400379 "authGroups": strings.Join(initGroups, ","),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400380 }); err != nil {
381 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400382 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400383 return nil
384 })
385 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400386}
387
gioe72b54f2024-04-22 10:44:41 +0400388// TODO(gio-dns): remove
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400389type DNSSecKey struct {
390 Basename string `json:"basename,omitempty"`
391 Key []byte `json:"key,omitempty"`
392 Private []byte `json:"private,omitempty"`
393 DS []byte `json:"ds,omitempty"`
394}
395
396func newDNSSecKey(zone string) (DNSSecKey, error) {
397 key := &dns.DNSKEY{
398 Hdr: dns.RR_Header{Name: dns.Fqdn(zone), Class: dns.ClassINET, Ttl: 3600, Rrtype: dns.TypeDNSKEY},
399 Algorithm: dns.ECDSAP256SHA256, Flags: 257, Protocol: 3,
400 }
401 priv, err := key.Generate(256)
402 if err != nil {
403 return DNSSecKey{}, err
404 }
405 return DNSSecKey{
406 Basename: fmt.Sprintf("K%s+%03d+%05d", key.Header().Name, key.Algorithm, key.KeyTag()),
407 Key: []byte(key.String()),
408 Private: []byte(key.PrivateKeyString(priv)),
409 DS: []byte(key.ToDS(dns.SHA256).String()),
410 }, nil
411}