Add Makefile
[vaultmon/.git] / vault.go
CommitLineData
9a72579f
SB
1package main
2
3import (
4 "encoding/json"
5 "fmt"
6 "io/ioutil"
7 "net/http"
8
9 log "github.com/sirupsen/logrus"
10)
11
9bce124f
SB
12const (
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
24type Vault struct {
25 URL string
26 ConnectionStatus string
27 ClusterStatus string
28}
29
9bce124f
SB
30type VaultSealedResult struct {
31 Sealed bool `json:"sealed"`
32}
33
9a72579f 34func (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
49func (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
70func isHealthy(statusCode int) bool {
71 return statusCode == VaultActive || statusCode == VaultStandby
72}
73
74func 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
105func (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
137func (v *Vault) Name() string {
138 return "Vault"
139}
140
141func NewVault(url string) CheckProvider {
142 return &Vault{URL: url}
143}