ALL

Solo para leer y verificar. No puedes copiar, usar, modificar ni redistribuir este código. Aviso completo en la página principal.

tunnel/backend_prod.go

SHA-256: 96afc5f517b01869f7ce3f6d3e4c94e842911a59442a7d760d10290c418a4012
71 líneas · 2986 bytes · Ver en GitHub

1//go:build !testnode && !testcp
2
3package main
4
5import (
6 "flag"
7 "fmt"
8 "io"
9)
10
11// The production backend: the node's real control-plane client, JWKS cache and feed. The node holds exactly one secret, its own Ed25519 signing key
12// (-node-key-file, mode 0600); the control plane holds the public half in TUNNEL_NODE_KEYS and a node that is taken over is revoked by removing its
13// kid there. There is no shared secret to configure, and the control plane's address is the issuer the policy pins unless an operator points a
14// staging node somewhere else on purpose.
15
16func init() {
17 theBackend = &backend{flags: prodFlags}
18 defaultMetricsAddr = "127.0.0.1:9101"
19 defaultOpenAIPrefixesURL = "https://openai.com/chatgpt-connectors.json"
20}
21
22func prodFlags(fs *flag.FlagSet, stdout io.Writer) func(*Config) error {
23 controlURL := fs.String("control-url", envStr("TUNNEL_CONTROL_URL", policyData.Identity.Issuer), "the control plane (https://host[:port]): authorize, the feed and the published keys come from here only [TUNNEL_CONTROL_URL]")
24 keyFile := fs.String("node-key-file", envStr("TUNNEL_NODE_KEY_FILE", ""), "this node's Ed25519 signing key (PKCS#8 PEM, mode 0600): the one credential this node has [TUNNEL_NODE_KEY_FILE]")
25 kid := fs.String("node-kid", envStr("TUNNEL_NODE_KID", ""), "the kid of this node's public key in the control plane's TUNNEL_NODE_KEYS [TUNNEL_NODE_KID]")
26 initKey := fs.Bool("node-key-init", false, "create the signing key at -node-key-file (never over an existing one), print the TUNNEL_NODE_KEYS entry that registers it, and exit")
27 printKey := fs.Bool("node-key-print", false, "print the TUNNEL_NODE_KEYS entry of the key at -node-key-file and exit")
28 return func(cfg *Config) error {
29 if *keyFile == "" {
30 return fmt.Errorf("the node needs its signing key: -node-key-file (create it once with -node-key-init)")
31 }
32 if (*initKey || *printKey) && (!reNodeID.MatchString(cfg.NodeID) || !reKID.MatchString(*kid)) {
33 return fmt.Errorf("the TUNNEL_NODE_KEYS entry needs -node-id and -node-kid")
34 }
35 if *initKey {
36 key, err := GenerateNodeKey(*keyFile)
37 if err != nil {
38 return err
39 }
40 fmt.Fprintln(stdout, NodeKeysEntry(cfg.NodeID, *kid, key))
41 return errDone
42 }
43 key, err := LoadNodeKey(*keyFile)
44 if err != nil {
45 return err
46 }
47 if *printKey {
48 fmt.Fprintln(stdout, NodeKeysEntry(cfg.NodeID, *kid, key))
49 return errDone
50 }
51 control, err := NewHTTPControl(HTTPControlConfig{BaseURL: *controlURL, NodeID: cfg.NodeID, KID: *kid, Key: key, Version: version})
52 if err != nil {
53 return err
54 }
55 clk := newClock(cfg.Now, cfg.AfterFunc)
56 health := &cpHealth{}
57 jwks := NewJWKSCache(JWKSConfig{
58 Fetch: control.FetchJWKS, Clock: clk, Log: cfg.Logger,
59 Observe: func(ok bool) {
60 if ok {
61 health.good(clk.Now())
62 } else {
63 health.bad(clk.Now())
64 }
65 },
66 })
67 cfg.Keys, cfg.Control, cfg.Feed, cfg.Health = jwks, control, control, health
68 cfg.Background = append(cfg.Background, jwks.Run)
69 return nil
70 }
71}