Commit | Line | Data |
---|---|---|
9a72579f SB |
1 | package main |
2 | ||
3 | import ( | |
4 | "encoding/json" | |
5 | "fmt" | |
6 | "io/ioutil" | |
7 | "net/http" | |
8 | ||
9 | log "github.com/sirupsen/logrus" | |
10 | ) | |
11 | ||
9bce124f SB |
12 | const ( |
13 | HealthEndpointURL = "/v1/sys/health" | |
14 | LeaderEndpointURL = "/v1/sys/leader" | |
15 | ||
16 | // Vault Health Status https://www.vaultproject.io/api/system/health.html | |
17 | VaultActive = http.StatusOK | |
18 | VaultStandby = http.StatusTooManyRequests | |
19 | VaultRecovery = 472 | |
20 | VaultNotReady = http.StatusNotImplemented | |
21 | VaultSealed = http.StatusServiceUnavailable | |
22 | ) | |
23 | ||
9a72579f SB |
24 | type Vault struct { |
25 | URL string | |
26 | ConnectionStatus string | |
27 | ClusterStatus string | |
28 | } | |
29 | ||
9bce124f SB |
30 | type VaultSealedResult struct { |
31 | Sealed bool `json:"sealed"` | |
32 | } | |
33 | ||
9a72579f | 34 | func (v *Vault) CheckHealth() (bool, error) { |
9bce124f | 35 | healthURL := v.URL + HealthEndpointURL |
9a72579f SB |
36 | cnx := NewConnection(healthURL) |
37 | log.Debugf("Vault Connection on %s", healthURL) | |
38 | resp, err := cnx.Head() | |
39 | if err != nil { | |
40 | return false, err | |
41 | } | |
42 | defer resp.Body.Close() | |
43 | ||
44 | log.Debugf("Vault CheckHealth response: %s", resp.Status) | |
45 | ||
9bce124f | 46 | return isHealthy(resp.StatusCode), nil |
9a72579f SB |
47 | } |
48 | ||
49 | func (v *Vault) CheckCluster() (bool, error) { | |
9bce124f SB |
50 | vaultFilter := make(map[string]string) |
51 | vaultFilter["Name"] = "tag:Cluster" | |
52 | vaultFilter["Value"] = "theknowledge" | |
53 | ||
4d747e6f SB |
54 | provider := newEC2Provider() |
55 | vaultNodeIps, err := provider.GetInstancesPrivateIps(vaultFilter) | |
9bce124f SB |
56 | if err != nil { |
57 | return false, err | |
58 | } | |
59 | ||
60 | for _, nodeIp := range vaultNodeIps { | |
61 | healthURL := "https://" + nodeIp + ":8200" + HealthEndpointURL | |
62 | if sealed, err := isSealed(healthURL); sealed { | |
63 | return false, err | |
64 | } | |
65 | } | |
66 | ||
67 | return true, nil | |
68 | } | |
69 | ||
70 | func isHealthy(statusCode int) bool { | |
71 | return statusCode == VaultActive || statusCode == VaultStandby | |
72 | } | |
73 | ||
74 | func isSealed(healthURL string) (bool, error) { | |
75 | cnx := NewConnection(healthURL) | |
76 | log.Debugf("Vault isSealed node connection on %s", healthURL) | |
9a72579f SB |
77 | resp, err := cnx.Get() |
78 | if err != nil { | |
79 | return false, err | |
80 | } | |
81 | defer resp.Body.Close() | |
82 | ||
9bce124f SB |
83 | log.Debugf("Vault isSealed connection response: %s", resp.Status) |
84 | if resp.StatusCode == VaultSealed { | |
85 | return true, nil | |
86 | } | |
9a72579f SB |
87 | |
88 | buf, err := ioutil.ReadAll(resp.Body) | |
89 | if err != nil { | |
90 | return false, err | |
91 | } | |
92 | ||
9bce124f SB |
93 | var result VaultSealedResult |
94 | ||
9a72579f SB |
95 | err = json.Unmarshal(buf, &result) |
96 | if err != nil { | |
97 | return false, err | |
98 | } | |
99 | ||
9bce124f | 100 | log.Debugf("Vault isSealed JSON result: %+v", result) |
9a72579f | 101 | |
9bce124f | 102 | return result.Sealed, nil |
9a72579f SB |
103 | } |
104 | ||
105 | func (v *Vault) Test() (bool, string) { | |
106 | // test health | |
107 | result, err := v.CheckHealth() | |
108 | if err != nil { | |
109 | log.Errorf("Vault CheckHealth error: %s", err) | |
110 | v.ConnectionStatus = "KO" | |
111 | } | |
9bce124f SB |
112 | |
113 | if result == false { | |
114 | v.ConnectionStatus = "KO" | |
115 | } else { | |
116 | v.ConnectionStatus = "OK" | |
117 | } | |
9a72579f SB |
118 | log.Debugf("Vault CheckHealth result: %t", result) |
119 | ||
120 | // test cluster | |
121 | result, err = v.CheckCluster() | |
122 | if err != nil { | |
123 | log.Errorf("Vault CheckCluster error: %s", err) | |
124 | v.ClusterStatus = "KO" | |
125 | } | |
9bce124f SB |
126 | |
127 | if result == false { | |
128 | v.ClusterStatus = "KO" | |
129 | } else { | |
130 | v.ClusterStatus = "OK" | |
131 | } | |
9a72579f SB |
132 | log.Debugf("Vault CheckCluster result: %t", result) |
133 | ||
134 | return result, fmt.Sprintf("> %s `%s` status *%s*. Cluster status *%s*.", v.Name(), v.URL, v.ConnectionStatus, v.ClusterStatus) | |
135 | } | |
136 | ||
137 | func (v *Vault) Name() string { | |
138 | return "Vault" | |
139 | } | |
140 | ||
141 | func NewVault(url string) CheckProvider { | |
142 | return &Vault{URL: url} | |
143 | } |