blob: fb3047d4d83e6c871c4fac8d47cc5f185b9791ad [file] [log] [blame]
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +04001package tasks
2
3import (
4 "fmt"
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +04005 "net"
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +04006 "net/netip"
Giorgi Lekveishvilid542b732024-03-25 18:17:39 +04007 "strings"
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +04008
9 "github.com/miekg/dns"
10
11 "github.com/giolekva/pcloud/core/installer"
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040012)
13
Giorgi Lekveishvilid542b732024-03-25 18:17:39 +040014var initGroups = []string{"admin"}
15
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040016func CreateRepoClient(env Env, st *state) Task {
17 t := newLeafTask("Create repo client", func() error {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040018 repo, err := st.ssClient.GetRepo("config")
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040019 if err != nil {
20 return err
21 }
gio3af43942024-04-16 08:13:50 +040022 r, err := installer.NewRepoIO(repo, st.ssClient.Signer)
23 if err != nil {
24 return err
25 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040026 appManager, err := installer.NewAppManager(r, st.nsCreator)
27 if err != nil {
28 return err
29 }
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040030 st.appManager = appManager
31 st.appsRepo = installer.NewInMemoryAppRepository(installer.CreateAllApps())
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040032 return nil
33 })
Giorgi Lekveishviliab7ff6e2024-03-29 13:11:30 +040034 t.beforeStart = func() {
35 st.infoListener("Setting up core infrastructure services.")
36 }
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040037 return &t
38}
39
40func SetupInfra(env Env, startIP net.IP, st *state) Task {
41 return newConcurrentParentTask(
42 "Setup core services",
43 true,
44 SetupNetwork(env, startIP, st),
45 SetupCertificateIssuers(env, st),
46 SetupAuth(env, st),
47 SetupGroupMemberships(env, st),
48 SetupHeadscale(env, startIP, st),
49 SetupWelcome(env, st),
50 SetupAppStore(env, st),
51 )
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040052}
53
54func CommitEnvironmentConfiguration(env Env, st *state) Task {
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +040055 t := newLeafTask("commit config", func() error {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040056 repo, err := st.ssClient.GetRepo("config")
57 if err != nil {
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040058 return err
59 }
gio3af43942024-04-16 08:13:50 +040060 r, err := installer.NewRepoIO(repo, st.ssClient.Signer)
61 if err != nil {
62 return err
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +040063 }
gio3af43942024-04-16 08:13:50 +040064 r.Atomic(func(r installer.RepoFS) (string, error) {
65 {
66 // TODO(giolekva): private domain can be configurable as well
gio3cdee592024-04-17 10:15:56 +040067 config := installer.AppEnvConfig{
68 Id: env.Name,
69 InfraName: env.PCloudEnvName,
70 Domain: env.Domain,
71 PrivateDomain: fmt.Sprintf("p.%s", env.Domain),
72 ContactEmail: env.ContactEmail,
73 PublicIP: st.publicIPs,
74 NamespacePrefix: fmt.Sprintf("%s-", env.Name),
gio3af43942024-04-16 08:13:50 +040075 }
76 if err := installer.WriteYaml(r, "config.yaml", config); err != nil {
77 return "", err
78 }
79 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040080 out, err := r.Writer("pcloud-charts.yaml")
81 if err != nil {
gio3af43942024-04-16 08:13:50 +040082 return "", err
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040083 }
84 defer out.Close()
85 _, err = fmt.Fprintf(out, `
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +040086apiVersion: source.toolkit.fluxcd.io/v1
87kind: GitRepository
88metadata:
89 name: pcloud
90 namespace: %s
91spec:
92 interval: 1m0s
93 url: https://github.com/giolekva/pcloud
94 ref:
gio3cdee592024-04-17 10:15:56 +040095 branch: main
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040096`, env.Name)
97 if err != nil {
gio3af43942024-04-16 08:13:50 +040098 return "", err
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +040099 }
gio3af43942024-04-16 08:13:50 +0400100 rootKust, err := installer.ReadKustomization(r, "kustomization.yaml")
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400101 if err != nil {
gio3af43942024-04-16 08:13:50 +0400102 return "", err
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400103 }
104 rootKust.AddResources("pcloud-charts.yaml")
gio3af43942024-04-16 08:13:50 +0400105 if err := installer.WriteYaml(r, "kustomization.yaml", rootKust); err != nil {
106 return "", err
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400107 }
gio3af43942024-04-16 08:13:50 +0400108 return "configure charts repo", nil
109 })
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400110 return nil
111 })
112 return &t
113}
114
Giorgi Lekveishvilid542b732024-03-25 18:17:39 +0400115type firstAccount struct {
116 Created bool `json:"created"`
117 Groups []string `json:"groups"`
118}
119
120func ConfigureFirstAccount(env Env, st *state) Task {
121 t := newLeafTask("Configure first account settings", func() error {
122 repo, err := st.ssClient.GetRepo("config")
123 if err != nil {
124 return err
125 }
gio3af43942024-04-16 08:13:50 +0400126 r, err := installer.NewRepoIO(repo, st.ssClient.Signer)
127 if err != nil {
Giorgi Lekveishvilid542b732024-03-25 18:17:39 +0400128 return err
129 }
gio3af43942024-04-16 08:13:50 +0400130 return r.Atomic(func(r installer.RepoFS) (string, error) {
131 fa := firstAccount{false, initGroups}
132 if err := installer.WriteYaml(r, "first-account.yaml", fa); err != nil {
133 return "", err
134 }
135 return "first account membership configuration", nil
136 })
Giorgi Lekveishvilid542b732024-03-25 18:17:39 +0400137 })
138 return &t
139}
140
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +0400141func SetupNetwork(env Env, startIP net.IP, st *state) Task {
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400142 t := newLeafTask("Setup private and public networks", func() error {
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +0400143 startAddr, err := netip.ParseAddr(startIP.String())
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400144 if err != nil {
145 return err
146 }
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +0400147 if !startAddr.Is4() {
148 return fmt.Errorf("Expected IPv4, got %s instead", startAddr)
149 }
150 addr := startAddr.AsSlice()
151 if addr[3] != 0 {
152 return fmt.Errorf("Expected last byte to be zero, got %d instead", addr[3])
153 }
154 addr[3] = 10
155 fromIP, ok := netip.AddrFromSlice(addr)
156 if !ok {
157 return fmt.Errorf("Must not reach")
158 }
159 addr[3] = 254
160 toIP, ok := netip.AddrFromSlice(addr)
161 if !ok {
162 return fmt.Errorf("Must not reach")
163 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400164 {
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +0400165 ingressPrivateIP := startAddr
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400166 headscaleIP := ingressPrivateIP.Next()
gio3cdee592024-04-17 10:15:56 +0400167 app, err := installer.FindEnvApp(st.appsRepo, "metallb-ipaddresspool")
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400168 if err != nil {
169 return err
170 }
gio3af43942024-04-16 08:13:50 +0400171 {
gio3cdee592024-04-17 10:15:56 +0400172 instanceId := fmt.Sprintf("%s-ingress-private", app.Name())
173 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400174 namespace := fmt.Sprintf("%s%s-ingress-private", env.NamespacePrefix, app.Namespace())
gio3cdee592024-04-17 10:15:56 +0400175 if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
gio3af43942024-04-16 08:13:50 +0400176 "name": fmt.Sprintf("%s-ingress-private", env.Name),
177 "from": ingressPrivateIP.String(),
178 "to": ingressPrivateIP.String(),
179 "autoAssign": false,
180 "namespace": "metallb-system",
181 }); err != nil {
182 return err
183 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400184 }
gio3af43942024-04-16 08:13:50 +0400185 {
gio3cdee592024-04-17 10:15:56 +0400186 instanceId := fmt.Sprintf("%s-headscale", app.Name())
187 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400188 namespace := fmt.Sprintf("%s%s-ingress-private", env.NamespacePrefix, app.Namespace())
gio3cdee592024-04-17 10:15:56 +0400189 if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
gio3af43942024-04-16 08:13:50 +0400190 "name": fmt.Sprintf("%s-headscale", env.Name),
191 "from": headscaleIP.String(),
192 "to": headscaleIP.String(),
193 "autoAssign": false,
194 "namespace": "metallb-system",
195 }); err != nil {
196 return err
197 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400198 }
gio3af43942024-04-16 08:13:50 +0400199 {
gio3cdee592024-04-17 10:15:56 +0400200 instanceId := app.Name()
201 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400202 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio3cdee592024-04-17 10:15:56 +0400203 if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
gio3af43942024-04-16 08:13:50 +0400204 "name": env.Name,
205 "from": fromIP.String(),
206 "to": toIP.String(),
207 "autoAssign": false,
208 "namespace": "metallb-system",
209 }); err != nil {
210 return err
211 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400212 }
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400213 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400214 {
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +0400215 keys, err := installer.NewSSHKeyPair("port-allocator")
216 if err != nil {
217 return err
218 }
219 user := fmt.Sprintf("%s-port-allocator", env.Name)
220 if err := st.ssClient.AddUser(user, keys.AuthorizedKey()); err != nil {
221 return err
222 }
223 if err := st.ssClient.AddReadWriteCollaborator("config", user); err != nil {
224 return err
225 }
gio3cdee592024-04-17 10:15:56 +0400226 app, err := installer.FindEnvApp(st.appsRepo, "private-network")
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400227 if err != nil {
228 return err
229 }
gio3cdee592024-04-17 10:15:56 +0400230 instanceId := app.Name()
231 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400232 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio3cdee592024-04-17 10:15:56 +0400233 if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400234 "privateNetwork": map[string]any{
235 "hostname": "private-network-proxy",
236 "username": "private-network-proxy",
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +0400237 "ipSubnet": fmt.Sprintf("%s/24", startIP.String()),
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400238 },
Giorgi Lekveishvilib59b7c22024-04-03 22:17:50 +0400239 "sshPrivateKey": string(keys.RawPrivateKey()),
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400240 }); err != nil {
241 return err
242 }
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400243 }
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400244 return nil
245 })
246 return &t
247}
248
249func SetupCertificateIssuers(env Env, st *state) Task {
250 pub := newLeafTask(fmt.Sprintf("Public %s", env.Domain), func() error {
gio3cdee592024-04-17 10:15:56 +0400251 app, err := installer.FindEnvApp(st.appsRepo, "certificate-issuer-public")
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400252 if err != nil {
253 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400254 }
gio3cdee592024-04-17 10:15:56 +0400255 instanceId := app.Name()
256 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400257 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio3cdee592024-04-17 10:15:56 +0400258 if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{}); err != nil {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400259 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400260 }
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400261 return nil
262 })
263 priv := newLeafTask(fmt.Sprintf("Private p.%s", env.Domain), func() error {
gio3cdee592024-04-17 10:15:56 +0400264 app, err := installer.FindEnvApp(st.appsRepo, "certificate-issuer-private")
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400265 if err != nil {
266 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400267 }
gio3cdee592024-04-17 10:15:56 +0400268 instanceId := app.Name()
269 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400270 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio3cdee592024-04-17 10:15:56 +0400271 if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400272 "apiConfigMap": map[string]any{
273 "name": "api-config", // TODO(gio): take from global pcloud config
274 "namespace": fmt.Sprintf("%s-dns-zone-manager", env.PCloudEnvName),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400275 },
276 }); err != nil {
277 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400278 }
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400279 return nil
280 })
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400281 return newSequentialParentTask("Configure TLS certificate issuers", false, &pub, &priv)
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400282}
283
284func SetupAuth(env Env, st *state) Task {
285 t := newLeafTask("Setup", func() error {
gio3cdee592024-04-17 10:15:56 +0400286 app, err := installer.FindEnvApp(st.appsRepo, "core-auth")
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400287 if err != nil {
288 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400289 }
gio3cdee592024-04-17 10:15:56 +0400290 instanceId := app.Name()
291 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400292 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio3cdee592024-04-17 10:15:56 +0400293 if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400294 "subdomain": "test", // TODO(giolekva): make core-auth chart actually use this
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400295 }); err != nil {
296 return err
297 }
298 return nil
299 })
300 return newSequentialParentTask(
301 "Authentication services",
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400302 false,
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400303 &t,
304 waitForAddr(fmt.Sprintf("https://accounts-ui.%s", env.Domain)),
305 )
306}
307
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400308func SetupGroupMemberships(env Env, st *state) Task {
309 t := newLeafTask("Setup", func() error {
gio3cdee592024-04-17 10:15:56 +0400310 app, err := installer.FindEnvApp(st.appsRepo, "memberships")
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400311 if err != nil {
312 return err
313 }
gio3cdee592024-04-17 10:15:56 +0400314 instanceId := app.Name()
315 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400316 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio3cdee592024-04-17 10:15:56 +0400317 if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
Giorgi Lekveishvilid542b732024-03-25 18:17:39 +0400318 "authGroups": strings.Join(initGroups, ","),
319 }); err != nil {
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400320 return err
321 }
322 return nil
323 })
324 return newSequentialParentTask(
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400325 "Group membership",
326 false,
Giorgi Lekveishvilia09fad72024-03-21 15:24:35 +0400327 &t,
328 waitForAddr(fmt.Sprintf("https://memberships.p.%s", env.Domain)),
329 )
330}
331
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +0400332func SetupHeadscale(env Env, startIP net.IP, st *state) Task {
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400333 t := newLeafTask("Setup", func() error {
gio3cdee592024-04-17 10:15:56 +0400334 app, err := installer.FindEnvApp(st.appsRepo, "headscale")
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400335 if err != nil {
336 return err
337 }
gio3cdee592024-04-17 10:15:56 +0400338 instanceId := app.Name()
339 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400340 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio3cdee592024-04-17 10:15:56 +0400341 if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400342 "subdomain": "headscale",
Giorgi Lekveishvili9d5e3f52024-03-13 15:02:50 +0400343 "ipSubnet": fmt.Sprintf("%s/24", startIP),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400344 }); err != nil {
345 return err
346 }
347 return nil
348 })
349 return newSequentialParentTask(
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400350 "Setup mesh VPN",
351 false,
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400352 &t,
353 waitForAddr(fmt.Sprintf("https://headscale.%s/apple", env.Domain)),
354 )
355}
356
357func SetupWelcome(env Env, st *state) Task {
358 t := newLeafTask("Setup", func() error {
359 keys, err := installer.NewSSHKeyPair("welcome")
360 if err != nil {
361 return err
362 }
363 user := fmt.Sprintf("%s-welcome", env.Name)
364 if err := st.ssClient.AddUser(user, keys.AuthorizedKey()); err != nil {
365 return err
366 }
367 if err := st.ssClient.AddReadWriteCollaborator("config", user); err != nil {
368 return err
369 }
gio3cdee592024-04-17 10:15:56 +0400370 app, err := installer.FindEnvApp(st.appsRepo, "welcome")
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400371 if err != nil {
372 return err
373 }
gio3cdee592024-04-17 10:15:56 +0400374 instanceId := app.Name()
375 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400376 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio3cdee592024-04-17 10:15:56 +0400377 if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400378 "repoAddr": st.ssClient.GetRepoAddress("config"),
379 "sshPrivateKey": string(keys.RawPrivateKey()),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400380 }); err != nil {
381 return err
382 }
383 return nil
384 })
385 return newSequentialParentTask(
386 "Welcome service",
Giorgi Lekveishvili5c1b06e2024-03-28 15:19:44 +0400387 false,
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400388 &t,
389 waitForAddr(fmt.Sprintf("https://welcome.%s", env.Domain)),
390 )
391}
392
393func SetupAppStore(env Env, st *state) Task {
394 t := newLeafTask("Application marketplace", func() error {
395 user := fmt.Sprintf("%s-appmanager", env.Name)
396 keys, err := installer.NewSSHKeyPair(user)
397 if err != nil {
398 return err
399 }
400 if err := st.ssClient.AddUser(user, keys.AuthorizedKey()); err != nil {
401 return err
402 }
403 if err := st.ssClient.AddReadWriteCollaborator("config", user); err != nil {
404 return err
405 }
gio3cdee592024-04-17 10:15:56 +0400406 app, err := installer.FindEnvApp(st.appsRepo, "app-manager") // TODO(giolekva): configure
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400407 if err != nil {
408 return err
409 }
gio3cdee592024-04-17 10:15:56 +0400410 instanceId := app.Name()
411 appDir := fmt.Sprintf("/apps/%s", instanceId)
gio3af43942024-04-16 08:13:50 +0400412 namespace := fmt.Sprintf("%s%s", env.NamespacePrefix, app.Namespace())
gio3cdee592024-04-17 10:15:56 +0400413 if err := st.appManager.Install(app, instanceId, appDir, namespace, map[string]any{
Giorgi Lekveishvilie009a5d2024-01-05 14:10:11 +0400414 "repoAddr": st.ssClient.GetRepoAddress("config"),
415 "sshPrivateKey": string(keys.RawPrivateKey()),
Giorgi Lekveishvili3c91e8b2024-03-25 20:20:14 +0400416 "authGroups": strings.Join(initGroups, ","),
Giorgi Lekveishvili378ea882023-12-12 13:59:18 +0400417 }); err != nil {
418 return err
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400419 }
Giorgi Lekveishvili77ee2dc2023-12-11 16:51:10 +0400420 return nil
421 })
422 return &t
Giorgi Lekveishvili46743d42023-12-10 15:47:23 +0400423}
424
425type DNSSecKey struct {
426 Basename string `json:"basename,omitempty"`
427 Key []byte `json:"key,omitempty"`
428 Private []byte `json:"private,omitempty"`
429 DS []byte `json:"ds,omitempty"`
430}
431
432func newDNSSecKey(zone string) (DNSSecKey, error) {
433 key := &dns.DNSKEY{
434 Hdr: dns.RR_Header{Name: dns.Fqdn(zone), Class: dns.ClassINET, Ttl: 3600, Rrtype: dns.TypeDNSKEY},
435 Algorithm: dns.ECDSAP256SHA256, Flags: 257, Protocol: 3,
436 }
437 priv, err := key.Generate(256)
438 if err != nil {
439 return DNSSecKey{}, err
440 }
441 return DNSSecKey{
442 Basename: fmt.Sprintf("K%s+%03d+%05d", key.Header().Name, key.Algorithm, key.KeyTag()),
443 Key: []byte(key.String()),
444 Private: []byte(key.PrivateKeyString(priv)),
445 DS: []byte(key.ToDS(dns.SHA256).String()),
446 }, nil
447}