1package diagnose 2 3import ( 4 "context" 5 "fmt" 6 "strings" 7 "time" 8 9 "github.com/hashicorp/vault/sdk/physical" 10) 11 12const ( 13 success string = "success" 14 secretVal string = "diagnoseSecret" 15 16 LatencyWarning string = "Latency above 100 ms: " 17 DirAccessErr string = "Vault storage is directly connected to a Consul server." 18 DirAccessAdvice string = "We recommend connecting to a local agent." 19 AddrDNExistErr string = "Storage config address does not exist: 127.0.0.1:8500 will be used." 20 wrongRWValsPrefix string = "Storage get and put gave wrong values: " 21 latencyThreshold time.Duration = time.Millisecond * 100 22) 23 24func EndToEndLatencyCheckWrite(ctx context.Context, uuid string, b physical.Backend) (time.Duration, error) { 25 start := time.Now() 26 err := b.Put(context.Background(), &physical.Entry{Key: uuid, Value: []byte(secretVal)}) 27 duration := time.Since(start) 28 if err != nil { 29 return time.Duration(0), err 30 } 31 if duration > latencyThreshold { 32 return duration, nil 33 } 34 return time.Duration(0), nil 35} 36 37func EndToEndLatencyCheckRead(ctx context.Context, uuid string, b physical.Backend) (time.Duration, error) { 38 39 start := time.Now() 40 val, err := b.Get(context.Background(), uuid) 41 duration := time.Since(start) 42 if err != nil { 43 return time.Duration(0), err 44 } 45 if val == nil { 46 return time.Duration(0), fmt.Errorf("No value found when reading generated data.") 47 } 48 if val.Key != uuid && string(val.Value) != secretVal { 49 return time.Duration(0), fmt.Errorf(wrongRWValsPrefix+"expecting %s as key and diagnose for value, but got %s, %s.", uuid, val.Key, val.Value) 50 } 51 if duration > latencyThreshold { 52 return duration, nil 53 } 54 return time.Duration(0), nil 55} 56func EndToEndLatencyCheckDelete(ctx context.Context, uuid string, b physical.Backend) (time.Duration, error) { 57 58 start := time.Now() 59 err := b.Delete(context.Background(), uuid) 60 duration := time.Since(start) 61 if err != nil { 62 return time.Duration(0), err 63 } 64 if duration > latencyThreshold { 65 return duration, nil 66 } 67 return time.Duration(0), nil 68} 69 70// ConsulDirectAccess verifies that consul is connecting to local agent, 71// versus directly to a remote server. We can only assume that the local address 72// is a server, not a client. 73func ConsulDirectAccess(config map[string]string) string { 74 configAddr, ok := config["address"] 75 if !ok { 76 return AddrDNExistErr 77 } 78 if !strings.Contains(configAddr, "localhost") && !strings.Contains(configAddr, "127.0.0.1") { 79 return DirAccessErr 80 } 81 return "" 82} 83