-
Notifications
You must be signed in to change notification settings - Fork 26
/
firewall.go
226 lines (191 loc) · 6.54 KB
/
firewall.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
package civogo
import (
"bytes"
"encoding/json"
"fmt"
"strings"
)
// Firewall represents list of rule in Civo's infrastructure
type Firewall struct {
ID string `json:"id"`
Name string `json:"name,omitempty"`
RulesCount int `json:"rules_count,omitempty"`
InstanceCount int `json:"instance_count"`
ClusterCount int `json:"cluster_count"`
LoadBalancerCount int `json:"loadbalancer_count"`
NetworkID string `json:"network_id,omitempty"`
Rules []FirewallRule `json:"rules,omitempty"`
}
// FirewallResult is the response from the Civo Firewall APIs
type FirewallResult struct {
ID string `json:"id"`
Name string `json:"name"`
Result string `json:"result"`
}
// FirewallRule represents a single rule for a given firewall, regarding
// which ports to open and which protocol, to which CIDR
type FirewallRule struct {
ID string `json:"id,omitempty"`
FirewallID string `json:"firewall_id,omitempty"`
Protocol string `json:"protocol"`
StartPort string `json:"start_port"`
EndPort string `json:"end_port"`
Cidr []string `json:"cidr"`
Direction string `json:"direction"`
Action string `json:"action"`
Label string `json:"label,omitempty"`
Ports string `json:"ports,omitempty"`
}
// FirewallRuleConfig is how you specify the details when creating a new rule
type FirewallRuleConfig struct {
FirewallID string `json:"firewall_id"`
Region string `json:"region"`
Protocol string `json:"protocol"`
StartPort string `json:"start_port"`
EndPort string `json:"end_port"`
Cidr []string `json:"cidr"`
Direction string `json:"direction"`
Action string `json:"action"`
Label string `json:"label,omitempty"`
// Ports will be chosen over StartPort,EndPort if both are provided
Ports string `json:"ports,omitempty"`
}
// FirewallConfig is how you specify the details when creating a new firewall
type FirewallConfig struct {
Name string `json:"name"`
Region string `json:"region"`
NetworkID string `json:"network_id"`
// CreateRules if not send the value will be nil, that mean the default rules will be created
CreateRules *bool `json:"create_rules,omitempty"`
Rules []FirewallRule `json:"rules,omitempty"`
}
// ListFirewalls returns all firewall owned by the calling API account
func (c *Client) ListFirewalls() ([]Firewall, error) {
resp, err := c.SendGetRequest("/v2/firewalls")
if err != nil {
return nil, decodeError(err)
}
firewall := make([]Firewall, 0)
if err := json.NewDecoder(bytes.NewReader(resp)).Decode(&firewall); err != nil {
return nil, err
}
return firewall, nil
}
// FindFirewall finds a firewall by either part of the ID or part of the name
func (c *Client) FindFirewall(search string) (*Firewall, error) {
firewalls, err := c.ListFirewalls()
if err != nil {
return nil, decodeError(err)
}
exactMatch := false
partialMatchesCount := 0
result := Firewall{}
for _, value := range firewalls {
if value.Name == search || value.ID == search {
exactMatch = true
result = value
} else if strings.Contains(value.Name, search) || strings.Contains(value.ID, search) {
if !exactMatch {
result = value
partialMatchesCount++
}
}
}
if exactMatch || partialMatchesCount == 1 {
return &result, nil
} else if partialMatchesCount > 1 {
err := fmt.Errorf("unable to find %s because there were multiple matches", search)
return nil, MultipleMatchesError.wrap(err)
} else {
err := fmt.Errorf("unable to find %s, zero matches", search)
return nil, ZeroMatchesError.wrap(err)
}
}
// NewFirewall creates a new firewall record
func (c *Client) NewFirewall(firewall *FirewallConfig) (*FirewallResult, error) {
body, err := c.SendPostRequest("/v2/firewalls", firewall)
if err != nil {
return nil, decodeError(err)
}
result := &FirewallResult{}
if err := json.NewDecoder(bytes.NewReader(body)).Decode(result); err != nil {
return nil, err
}
return result, nil
}
// RenameFirewall rename firewall
func (c *Client) RenameFirewall(id string, f *FirewallConfig) (*SimpleResponse, error) {
f.Region = c.Region
resp, err := c.SendPutRequest(fmt.Sprintf("/v2/firewalls/%s", id), f)
if err != nil {
return nil, decodeError(err)
}
return c.DecodeSimpleResponse(resp)
}
// DeleteFirewall deletes an firewall
func (c *Client) DeleteFirewall(id string) (*SimpleResponse, error) {
resp, err := c.SendDeleteRequest("/v2/firewalls/" + id)
if err != nil {
return nil, decodeError(err)
}
return c.DecodeSimpleResponse(resp)
}
// NewFirewallRule creates a new rule within a firewall
func (c *Client) NewFirewallRule(r *FirewallRuleConfig) (*FirewallRule, error) {
if len(r.FirewallID) == 0 {
err := fmt.Errorf("the firewall ID is empty")
return nil, IDisEmptyError.wrap(err)
}
r.Region = c.Region
resp, err := c.SendPostRequest(fmt.Sprintf("/v2/firewalls/%s/rules", r.FirewallID), r)
if err != nil {
return nil, decodeError(err)
}
rule := &FirewallRule{}
if err := json.NewDecoder(bytes.NewReader(resp)).Decode(rule); err != nil {
return nil, err
}
return rule, nil
}
// ListFirewallRules get all rules for a firewall
func (c *Client) ListFirewallRules(id string) ([]FirewallRule, error) {
resp, err := c.SendGetRequest(fmt.Sprintf("/v2/firewalls/%s/rules", id))
if err != nil {
return nil, decodeError(err)
}
firewallRule := make([]FirewallRule, 0)
if err := json.NewDecoder(bytes.NewReader(resp)).Decode(&firewallRule); err != nil {
return nil, err
}
return firewallRule, nil
}
// FindFirewallRule finds a firewall Rule by ID or part of the same
func (c *Client) FindFirewallRule(firewallID string, search string) (*FirewallRule, error) {
firewallsRules, err := c.ListFirewallRules(firewallID)
if err != nil {
return nil, decodeError(err)
}
found := -1
for i, firewallRule := range firewallsRules {
if strings.Contains(firewallRule.ID, search) {
if found != -1 {
err := fmt.Errorf("unable to find %s because there were multiple matches", search)
return nil, MultipleMatchesError.wrap(err)
}
found = i
}
}
if found == -1 {
err := fmt.Errorf("unable to find %s, zero matches", search)
return nil, ZeroMatchesError.wrap(err)
}
return &firewallsRules[found], nil
}
// DeleteFirewallRule deletes an firewall
func (c *Client) DeleteFirewallRule(id string, ruleID string) (*SimpleResponse, error) {
resp, err := c.SendDeleteRequest(fmt.Sprintf("/v2/firewalls/%s/rules/%s", id, ruleID))
if err != nil {
return nil, decodeError(err)
}
return c.DecodeSimpleResponse(resp)
}