[management] Parse resource addr before db write (#3061)

This commit is contained in:
Pascal Fischer
2024-12-17 12:21:28 +01:00
committed by GitHub
parent 712341e73d
commit 228672aed2
6 changed files with 73 additions and 49 deletions

View File

@@ -142,13 +142,14 @@ func (m *managerImpl) UpdateResource(ctx context.Context, userID string, resourc
return nil, status.NewPermissionDeniedError()
}
resourceType, addr, err := types.GetResourceType(resource.Address)
resourceType, domain, prefix, err := types.GetResourceType(resource.Address)
if err != nil {
return nil, fmt.Errorf("failed to get resource type: %w", err)
}
resource.Type = resourceType
resource.Address = addr
resource.Domain = domain
resource.Prefix = prefix
_, err = m.store.GetNetworkResourceByID(ctx, store.LockingStrengthShare, resource.AccountID, resource.ID)
if err != nil {

View File

@@ -3,9 +3,8 @@ package types
import (
"errors"
"fmt"
"net"
"net/netip"
"regexp"
"strings"
"github.com/rs/xid"
@@ -31,11 +30,13 @@ type NetworkResource struct {
Name string
Description string
Type NetworkResourceType
Address string
Address string `gorm:"-"`
Domain string
Prefix netip.Prefix `gorm:"serializer:json"`
}
func NewNetworkResource(accountID, networkID, name, description, address string) (*NetworkResource, error) {
resourceType, address, err := GetResourceType(address)
resourceType, domain, prefix, err := GetResourceType(address)
if err != nil {
return nil, fmt.Errorf("invalid address: %w", err)
}
@@ -48,6 +49,8 @@ func NewNetworkResource(accountID, networkID, name, description, address string)
Description: description,
Type: resourceType,
Address: address,
Domain: domain,
Prefix: prefix,
}, nil
}
@@ -57,7 +60,8 @@ func (n *NetworkResource) ToAPIResponse(groups []api.GroupMinimum) *api.NetworkR
Name: n.Name,
Description: &n.Description,
Type: api.NetworkResourceType(n.Type.String()),
Address: n.Address,
Domain: n.Domain,
Prefix: n.Prefix.String(),
Groups: groups,
}
}
@@ -84,26 +88,22 @@ func (n *NetworkResource) Copy() *NetworkResource {
}
// GetResourceType returns the type of the resource based on the address
func GetResourceType(address string) (NetworkResourceType, string, error) {
if ip, cidr, err := net.ParseCIDR(address); err == nil {
ones, _ := cidr.Mask.Size()
if strings.HasSuffix(address, "/32") {
return host, address, nil
func GetResourceType(address string) (NetworkResourceType, string, netip.Prefix, error) {
if prefix, err := netip.ParsePrefix(address); err == nil {
if prefix.Bits() == 32 || prefix.Bits() == 128 {
return host, "", prefix, nil
}
if ip != nil && ones == 32 {
return host, address + "/32", nil
}
return subnet, address, nil
return subnet, "", prefix, nil
}
if net.ParseIP(address) != nil {
return host, address + "/32", nil
if ip, err := netip.ParseAddr(address); err == nil {
return host, "", netip.PrefixFrom(ip, ip.BitLen()), nil
}
domainRegex := regexp.MustCompile(`^(\*\.)?([a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}$`)
if domainRegex.MatchString(address) {
return domain, address, nil
return domain, address, netip.Prefix{}, nil
}
return "", "", errors.New("not a host, subnet, or domain")
return "", "", netip.Prefix{}, errors.New("not a valid host, subnet, or domain")
}

View File

@@ -1,35 +1,38 @@
package types
import (
"net/netip"
"testing"
)
func TestGetResourceType(t *testing.T) {
tests := []struct {
input string
expectedType NetworkResourceType
expectedErr bool
expectedAddr string
input string
expectedType NetworkResourceType
expectedErr bool
expectedDomain string
expectedPrefix netip.Prefix
}{
// Valid host IPs
{"1.1.1.1", host, false, "1.1.1.1/32"},
{"1.1.1.1/32", host, false, "1.1.1.1/32"},
{"1.1.1.1", host, false, "", netip.MustParsePrefix("1.1.1.1/32")},
{"1.1.1.1/32", host, false, "", netip.MustParsePrefix("1.1.1.1/32")},
// Valid subnets
{"192.168.1.0/24", subnet, false, "192.168.1.0/24"},
{"10.0.0.0/16", subnet, false, "10.0.0.0/16"},
{"192.168.1.0/24", subnet, false, "", netip.MustParsePrefix("192.168.1.0/24")},
{"10.0.0.0/16", subnet, false, "", netip.MustParsePrefix("10.0.0.0/16")},
// Valid domains
{"example.com", domain, false, "example.com"},
{"*.example.com", domain, false, "*.example.com"},
{"sub.example.com", domain, false, "sub.example.com"},
{"example.com", domain, false, "example.com", netip.Prefix{}},
{"*.example.com", domain, false, "*.example.com", netip.Prefix{}},
{"sub.example.com", domain, false, "sub.example.com", netip.Prefix{}},
// Invalid inputs
{"invalid", "", true, ""},
{"1.1.1.1/abc", "", true, ""},
{"1234", "", true, ""},
{"invalid", "", true, "", netip.Prefix{}},
{"1.1.1.1/abc", "", true, "", netip.Prefix{}},
{"1234", "", true, "", netip.Prefix{}},
}
for _, tt := range tests {
t.Run(tt.input, func(t *testing.T) {
result, addr, err := GetResourceType(tt.input)
result, domain, prefix, err := GetResourceType(tt.input)
if result != tt.expectedType {
t.Errorf("Expected type %v, got %v", tt.expectedType, result)
}
@@ -38,8 +41,12 @@ func TestGetResourceType(t *testing.T) {
t.Errorf("Expected error, got nil")
}
if addr != tt.expectedAddr {
t.Errorf("Expected address %v, got %v", tt.expectedAddr, addr)
if prefix != tt.expectedPrefix {
t.Errorf("Expected address %v, got %v", tt.expectedPrefix, prefix)
}
if domain != tt.expectedDomain {
t.Errorf("Expected domain %v, got %v", tt.expectedDomain, domain)
}
})
}