mirror of
https://github.com/edgelesssys/constellation.git
synced 2025-07-30 02:28:48 -04:00
Feat/conformity test (#79)
* Added files required to request conformance with kubernetes * Extended firewall implementation to allow port ranges * Added default nodeport range to vpc network config
This commit is contained in:
parent
51068abc27
commit
2a766a3ab5
14 changed files with 263 additions and 47 deletions
|
@ -33,7 +33,7 @@ func TestCreator(t *testing.T) {
|
|||
GCPCoordinatorInstanceTemplate: "coordinator-template",
|
||||
GCPNetwork: "network",
|
||||
GCPSubnetwork: "subnetwork",
|
||||
GCPFirewalls: []string{"coordinator", "wireguard", "ssh"},
|
||||
GCPFirewalls: []string{"coordinator", "wireguard", "ssh", "nodeport"},
|
||||
}
|
||||
|
||||
wantAzureState := state.ConstellationState{
|
||||
|
|
|
@ -2,7 +2,6 @@ package cloudtypes
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork"
|
||||
|
@ -16,12 +15,13 @@ type FirewallRule struct {
|
|||
Description string
|
||||
Protocol string
|
||||
IPRange string
|
||||
Port int
|
||||
FromPort int
|
||||
ToPort int
|
||||
}
|
||||
|
||||
type Firewall []FirewallRule
|
||||
|
||||
func (f Firewall) GCP() []*computepb.Firewall {
|
||||
func (f Firewall) GCP() ([]*computepb.Firewall, error) {
|
||||
var fw []*computepb.Firewall
|
||||
for _, rule := range f {
|
||||
var destRange []string = nil
|
||||
|
@ -29,11 +29,15 @@ func (f Firewall) GCP() []*computepb.Firewall {
|
|||
destRange = append(destRange, rule.IPRange)
|
||||
}
|
||||
|
||||
ports, err := portOrRange(rule.FromPort, rule.ToPort)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fw = append(fw, &computepb.Firewall{
|
||||
Allowed: []*computepb.Allowed{
|
||||
{
|
||||
IPProtocol: proto.String(rule.Protocol),
|
||||
Ports: []string{fmt.Sprint(rule.Port)},
|
||||
Ports: []string{ports},
|
||||
},
|
||||
},
|
||||
Description: proto.String(rule.Description),
|
||||
|
@ -41,15 +45,19 @@ func (f Firewall) GCP() []*computepb.Firewall {
|
|||
Name: proto.String(rule.Name),
|
||||
})
|
||||
}
|
||||
return fw
|
||||
return fw, nil
|
||||
}
|
||||
|
||||
func (f Firewall) Azure() []*armnetwork.SecurityRule {
|
||||
func (f Firewall) Azure() ([]*armnetwork.SecurityRule, error) {
|
||||
var fw []*armnetwork.SecurityRule
|
||||
for i, rule := range f {
|
||||
// format string according to armnetwork.SecurityRuleProtocol specification
|
||||
protocol := strings.Title(strings.ToLower(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{
|
||||
|
@ -58,7 +66,7 @@ func (f Firewall) Azure() []*armnetwork.SecurityRule {
|
|||
SourceAddressPrefix: proto.String(rule.IPRange),
|
||||
SourcePortRange: proto.String("*"),
|
||||
DestinationAddressPrefix: proto.String(rule.IPRange),
|
||||
DestinationPortRange: proto.String(strconv.Itoa(rule.Port)),
|
||||
DestinationPortRange: proto.String(dstPortRange),
|
||||
Access: armnetwork.SecurityRuleAccessAllow.ToPtr(),
|
||||
Direction: armnetwork.SecurityRuleDirectionInbound.ToPtr(),
|
||||
// Each security role needs a unique priority
|
||||
|
@ -66,15 +74,15 @@ func (f Firewall) Azure() []*armnetwork.SecurityRule {
|
|||
},
|
||||
})
|
||||
}
|
||||
return fw
|
||||
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.Port)),
|
||||
ToPort: proto.Int32(int32(rule.Port)),
|
||||
FromPort: proto.Int32(int32(rule.FromPort)),
|
||||
ToPort: proto.Int32(int32(rule.ToPort)),
|
||||
IpProtocol: proto.String(rule.Protocol),
|
||||
IpRanges: []ec2types.IpRange{
|
||||
{
|
||||
|
@ -86,3 +94,38 @@ func (f Firewall) AWS() []ec2types.IpPermission {
|
|||
}
|
||||
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}
|
||||
}
|
||||
|
|
|
@ -20,18 +20,19 @@ func TestFirewallGCP(t *testing.T) {
|
|||
Description: "This is the Test-1 Permission",
|
||||
Protocol: "tcp",
|
||||
IPRange: "",
|
||||
Port: 9000,
|
||||
FromPort: 9000,
|
||||
},
|
||||
{
|
||||
Name: "test-2",
|
||||
Description: "This is the Test-2 Permission",
|
||||
Protocol: "udp",
|
||||
IPRange: "",
|
||||
Port: 51820,
|
||||
FromPort: 51820,
|
||||
},
|
||||
}
|
||||
|
||||
firewalls := testFw.GCP()
|
||||
firewalls, err := testFw.GCP()
|
||||
assert.NoError(err)
|
||||
assert.Equal(2, len(firewalls))
|
||||
|
||||
// Check permissions
|
||||
|
@ -41,7 +42,7 @@ func TestFirewallGCP(t *testing.T) {
|
|||
|
||||
actualPort, err := strconv.Atoi(actualPermission1.GetPorts()[0])
|
||||
require.NoError(err)
|
||||
assert.Equal(testFw[i].Port, actualPort)
|
||||
assert.Equal(testFw[i].FromPort, actualPort)
|
||||
assert.Equal(testFw[i].Protocol, actualPermission1.GetIPProtocol())
|
||||
|
||||
assert.Equal(testFw[i].Name, firewall1.GetName())
|
||||
|
@ -58,21 +59,21 @@ func TestFirewallAzure(t *testing.T) {
|
|||
Description: "perm1 description",
|
||||
Protocol: "TCP",
|
||||
IPRange: "192.0.2.0/24",
|
||||
Port: 22,
|
||||
FromPort: 22,
|
||||
},
|
||||
{
|
||||
Name: "perm2",
|
||||
Description: "perm2 description",
|
||||
Protocol: "udp",
|
||||
IPRange: "192.0.2.0/24",
|
||||
Port: 4433,
|
||||
FromPort: 4433,
|
||||
},
|
||||
{
|
||||
Name: "perm3",
|
||||
Description: "perm3 description",
|
||||
Protocol: "tcp",
|
||||
IPRange: "192.0.2.0/24",
|
||||
Port: 4433,
|
||||
FromPort: 4433,
|
||||
},
|
||||
}
|
||||
wantOutput := []*armnetwork.SecurityRule{
|
||||
|
@ -120,7 +121,8 @@ func TestFirewallAzure(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
out := input.Azure()
|
||||
out, err := input.Azure()
|
||||
assert.NoError(err)
|
||||
assert.Equal(wantOutput, out)
|
||||
}
|
||||
|
||||
|
@ -132,19 +134,22 @@ func TestIPPermissonsToAWS(t *testing.T) {
|
|||
Description: "perm1",
|
||||
Protocol: "TCP",
|
||||
IPRange: "192.0.2.0/24",
|
||||
Port: 22,
|
||||
FromPort: 22,
|
||||
ToPort: 22,
|
||||
},
|
||||
{
|
||||
Description: "perm2",
|
||||
Protocol: "UDP",
|
||||
IPRange: "192.0.2.0/24",
|
||||
Port: 4433,
|
||||
FromPort: 4433,
|
||||
ToPort: 4433,
|
||||
},
|
||||
{
|
||||
Description: "perm3",
|
||||
Protocol: "TCP",
|
||||
IPRange: "192.0.2.0/24",
|
||||
Port: 4433,
|
||||
FromPort: 4433,
|
||||
ToPort: 4433,
|
||||
},
|
||||
}
|
||||
wantOutput := []ec2types.IpPermission{
|
||||
|
@ -186,3 +191,73 @@ func TestIPPermissonsToAWS(t *testing.T) {
|
|||
out := input.AWS()
|
||||
assert.Equal(wantOutput, out)
|
||||
}
|
||||
|
||||
func TestPortOrRange(t *testing.T) {
|
||||
testCases := map[string]struct {
|
||||
fromPort int
|
||||
toPort int
|
||||
result string
|
||||
wantErr bool
|
||||
}{
|
||||
"ssh": {
|
||||
fromPort: 22,
|
||||
result: "22",
|
||||
},
|
||||
"https": {
|
||||
fromPort: 443,
|
||||
result: "443",
|
||||
},
|
||||
"nodePorts": {
|
||||
fromPort: 30000,
|
||||
toPort: 32767,
|
||||
result: "30000-32767",
|
||||
},
|
||||
"negative fromPort": {
|
||||
fromPort: -1,
|
||||
wantErr: true,
|
||||
},
|
||||
"negative toPort": {
|
||||
toPort: -1,
|
||||
wantErr: true,
|
||||
},
|
||||
"same value no range": {
|
||||
fromPort: 22,
|
||||
toPort: 22,
|
||||
result: "22",
|
||||
},
|
||||
"from zero to ssh": {
|
||||
toPort: 22,
|
||||
result: "0-22",
|
||||
},
|
||||
"from max": {
|
||||
fromPort: MaxPort,
|
||||
result: "65535",
|
||||
},
|
||||
"from max+1": {
|
||||
fromPort: MaxPort + 1,
|
||||
wantErr: true,
|
||||
},
|
||||
"to max": {
|
||||
toPort: MaxPort,
|
||||
result: "0-65535",
|
||||
},
|
||||
"to max+1": {
|
||||
toPort: MaxPort + 1,
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
got, err := portOrRange(tc.fromPort, tc.toPort)
|
||||
if tc.wantErr {
|
||||
assert.Error(err)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
assert.Equal(tc.result, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue