...
1 package client
2
3 import (
4 "context"
5 "flag"
6 "fmt"
7 "strings"
8 "sync"
9 "time"
10
11 apb "golang.conradwood.net/apis/auth"
12 "golang.conradwood.net/apis/common"
13 "golang.conradwood.net/go-easyops/cmdline"
14 cm "golang.conradwood.net/go-easyops/common"
15 "golang.conradwood.net/go-easyops/ctx"
16 "golang.conradwood.net/go-easyops/tokens"
17 "golang.conradwood.net/go-easyops/utils"
18 )
19
20
23 var (
24 last_registry string
25 pubkeylock sync.Mutex
26 retrieve_sig_lock = utils.NewTimeoutLock("retrieve_sig_lock")
27 retrieved_sig = false
28 retrieving = false
29 no_retrieve = flag.Bool("ge_disable_dynamic_pubkey", false, "if true, disable the lookup of the public key from authservice on startup")
30 crash_on_race_condition = flag.Bool("ge_development_signature", false, "crash and burn if getsignaturefromauth detects a race condition")
31 )
32
33
34
39 func GotSig() bool {
40 cur := cmdline.GetClientRegistryAddress()
41 if cur != last_registry {
42 return false
43 }
44 return retrieved_sig
45 }
46 func init() {
47 cm.AddRegistryChangeReceiver(GetSignatureFromAuth)
48 }
49 func GetSignatureFromAuth() {
50 if *crash_on_race_condition {
51 if stack_includes("GetSignatureFromAuth", 2) {
52 utils.PrintStack("reentry")
53 panic("re-entry issue")
54 }
55 }
56 if cmdline.IsStandalone() {
57
58 retrieved_sig = true
59 retrieving = false
60 last_registry = cmdline.GetClientRegistryAddress()
61 return
62 }
63 if GotSig() {
64 return
65 }
66 if *no_retrieve {
67 return
68 }
69 if retrieving {
70 b := retrieve_sig_lock.LockWithTimeout(time.Duration(10) * time.Second)
71 if b {
72 retrieve_sig_lock.Unlock()
73 return
74 }
75
76 fmt.Printf("[go-easyops] WARNING Signature retrieving seems to be stuck\n")
77 return
78 }
79 pubkeylock.Lock()
80 if retrieving {
81 pubkeylock.Unlock()
82 return
83 }
84
85 retrieve_sig_lock.Lock()
86 defer retrieve_sig_lock.Unlock()
87 retrieving = true
88
89 pubkeylock.Unlock()
90 if GotSig() {
91 return
92 }
93 started_sig := time.Now()
94 if cmdline.DebugSignature() {
95 fmt.Printf("[go-easyops] Retrieving signature and cloudname...\n")
96 }
97 cb := ctx.NewContextBuilder()
98 cctx := cb.ContextWithAutoCancel()
99 cctx = context.Background()
100 rega := cmdline.GetClientRegistryAddress()
101 cn := ConnectAtNoAuth(rega, "auth.AuthenticationService")
102 authServer := apb.NewAuthenticationServiceClient(cn)
103 pk, err := authServer.GetPublicSigningKey(cctx, &common.Void{})
104 if err != nil {
105 fmt.Printf("[go-easyops] failed to get public auth key (%s)\n", err)
106 cn.Close()
107 retrieving = false
108 return
109 }
110 if cmdline.DebugSignature() {
111 fmt.Printf("[go-easyops] CloudName=\"%s\" (after %0.1fs) \n", pk.CloudName, time.Since(started_sig).Seconds())
112 }
113 tokens.SetCloudName(pk.CloudName)
114 cm.SetPublicSigningKey(pk)
115 cn.Close()
116 retrieved_sig = true
117 retrieving = false
118 last_registry = cmdline.GetClientRegistryAddress()
119 if cmdline.DebugSignature() {
120 fmt.Printf("[go-easyops] got Signature and cloudname (%s) from registry %s (after %0.1fs)\n", pk.CloudName, last_registry, time.Since(started_sig).Seconds())
121 }
122 }
123
124 func stack_includes(pat string, min int) bool {
125 s := utils.GetStack("")
126 if strings.Count(s, pat) >= min {
127 return true
128 }
129 return false
130 }
131
View as plain text