-
Notifications
You must be signed in to change notification settings - Fork 48
/
firewall.go
146 lines (130 loc) · 4.04 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
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package cloudtypes
import (
"fmt"
"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork"
ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types"
"golang.org/x/text/cases"
"golang.org/x/text/language"
computepb "google.golang.org/genproto/googleapis/cloud/compute/v1"
"google.golang.org/protobuf/proto"
)
// FirewallRule holds a single firewall rule.
type FirewallRule struct {
Name string
Description string
Protocol string
IPRange string
FromPort int
ToPort int
}
// Firewall contains all firewall rules to be applied for either ingress or egress.
type Firewall []FirewallRule
func (f Firewall) GCP() ([]*computepb.Firewall, error) {
var fw []*computepb.Firewall
for _, rule := range f {
var srcRange []string
if rule.IPRange != "" {
srcRange = []string{rule.IPRange}
}
var ports []string
if rule.FromPort != 0 || rule.ToPort != 0 {
port, err := portOrRange(rule.FromPort, rule.ToPort)
if err != nil {
return nil, err
}
ports = []string{port}
}
fw = append(fw, &computepb.Firewall{
Allowed: []*computepb.Allowed{
{
IPProtocol: proto.String(rule.Protocol),
Ports: ports,
},
},
Description: proto.String(rule.Description),
SourceRanges: srcRange,
Name: proto.String(rule.Name),
})
}
return fw, nil
}
func (f Firewall) Azure() ([]*armnetwork.SecurityRule, error) {
var fw []*armnetwork.SecurityRule
for i, rule := range f {
// format string according to armnetwork.SecurityRuleProtocol specification
protocol := cases.Title(language.English).String(rule.Protocol)
dstPortRange, err := portOrRange(rule.FromPort, rule.ToPort)
if err != nil {
return nil, err
}
fw = append(fw, &armnetwork.SecurityRule{
Name: proto.String(rule.Name),
Properties: &armnetwork.SecurityRulePropertiesFormat{
Description: proto.String(rule.Description),
Protocol: (*armnetwork.SecurityRuleProtocol)(proto.String(protocol)),
SourceAddressPrefix: proto.String(rule.IPRange),
SourcePortRange: proto.String("*"),
DestinationAddressPrefix: proto.String(rule.IPRange),
DestinationPortRange: proto.String(dstPortRange),
Access: to.Ptr(armnetwork.SecurityRuleAccessAllow),
Direction: to.Ptr(armnetwork.SecurityRuleDirectionInbound),
// Each security role needs a unique priority
Priority: proto.Int32(int32(100 * (i + 1))),
},
})
}
return fw, nil
}
func (f Firewall) AWS() []ec2types.IpPermission {
var fw []ec2types.IpPermission
for _, rule := range f {
fw = append(fw, ec2types.IpPermission{
FromPort: proto.Int32(int32(rule.FromPort)),
ToPort: proto.Int32(int32(rule.ToPort)),
IpProtocol: proto.String(rule.Protocol),
IpRanges: []ec2types.IpRange{
{
CidrIp: proto.String(rule.IPRange),
Description: proto.String(rule.Description),
},
},
})
}
return fw
}
const (
MinPort = 0
MaxPort = 65535
)
// PortOutOfRangeError occurs when either FromPort or ToPort are out of range
// of [MinPort-MaxPort].
type PortOutOfRangeError struct {
FromPort int
ToPort int
}
func (p *PortOutOfRangeError) Error() string {
return fmt.Sprintf(
"[%d-%d] not in allowed port range of [%d-%d]",
p.FromPort, p.ToPort, MinPort, MaxPort,
)
}
// portOrRange returns "fromPort" as single port, if toPort is zero.
// If toPort is >0 a port range of form "fromPort-toPort".
// If either value is negative PortOutOfRangeError is returned.
func portOrRange(fromPort, toPort int) (string, error) {
if fromPort < MinPort || toPort < MinPort || fromPort > MaxPort || toPort > MaxPort {
return "", &PortOutOfRangeError{FromPort: fromPort, ToPort: toPort}
}
if toPort == MinPort || fromPort == toPort {
return fmt.Sprintf("%d", fromPort), nil
}
if toPort > MinPort {
return fmt.Sprintf("%d-%d", fromPort, toPort), nil
}
return "", &PortOutOfRangeError{FromPort: fromPort, ToPort: toPort}
}