Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ RUN [[ $(ls -1 vendor/ | wc -l) -gt 0 ]] || (echo "Expected 'vendor' dependencie
COPY cmd/ cmd/
COPY pkg/ pkg/

COPY test/custom_ranges.json /etc/kubenetmon/custom_ranges.json

# Build
ARG VERSION=dev
ARG GIT_COMMIT=unspecified
ARG TARGETOS TARGETARCH
RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -a -o bin/ ./...
RUN CGO_ENABLED=1 GOOS=linux go test -v -race -coverprofile cover.out -tags '!integration' ./...

# Use distroless as minimal base image to package the kubenetmon binary
# Refer to https://github.com/GoogleContainerTools/distroless for more details
Expand Down
30 changes: 29 additions & 1 deletion pkg/labeler/public_ranges.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,10 +142,23 @@ type AzurePrefixGroupProperties struct {
NetworkFeatures []string `json:"networkFeatures"`
}

/* Custom IP range structs */
type CustomIPRanges struct {
SyncToken string `json:"syncToken"`
CreateDate string `json:"createDate"`
Prefixes []CustomPrefix `json:"prefixes"`
}
type CustomPrefix struct {
IPPrefixStr string `json:"ip_prefix"`
AvailabilityZone string `json:"az"`
Service string `json:"service"`
}

type remoteIPPrefixDetail struct {
cloud Cloud
service string
region string
az string
}

func (d *remoteIPPrefixDetail) Normalize() {
Expand All @@ -167,7 +180,7 @@ var awsServicePriorities map[string]int = map[string]int{
"ec2": 2,
}

func refreshRemoteIPs(aws AWSIPRanges, gcp GCPIPRanges, google GoogleIPRanges, azure AzureIPRanges) (map[ipaddr.IPv4AddressKey]remoteIPPrefixDetail, *ipaddr.IPv4AddressTrie, error) {
func refreshRemoteIPs(aws AWSIPRanges, gcp GCPIPRanges, google GoogleIPRanges, azure AzureIPRanges, custom CustomIPRanges) (map[ipaddr.IPv4AddressKey]remoteIPPrefixDetail, *ipaddr.IPv4AddressTrie, error) {
remoteIPRanges := make(map[ipaddr.IPv4AddressKey]remoteIPPrefixDetail)
trie := ipaddr.NewIPv4AddressTrie()

Expand Down Expand Up @@ -210,6 +223,21 @@ func refreshRemoteIPs(aws AWSIPRanges, gcp GCPIPRanges, google GoogleIPRanges, a
}
}

for _, prefix := range custom.Prefixes {
ip, err := ipaddr.NewIPAddressString(prefix.IPPrefixStr).ToAddress()
if err != nil {
return nil, nil, fmt.Errorf("invalid IPv4 address %s", prefix.IPPrefixStr)
}
trie.Add(ip.ToIPv4())
d := remoteIPPrefixDetail{
cloud: AWS,
service: prefix.Service,
az: prefix.AvailabilityZone,
}
d.Normalize()
remoteIPRanges[ip.ToIPv4().ToKey()] = d
}

// Parse the prefix, we only care about IPv4 right now.
for _, prefix := range gcp.Prefixes {
if prefix.IPv4PrefixStr == "" {
Expand Down
52 changes: 43 additions & 9 deletions pkg/labeler/public_ranges_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ func TestRefreshRemoteIPs(t *testing.T) {
gcp := GCPIPRanges{}
google := GoogleIPRanges{}
azure := AzureIPRanges{}
custom := CustomIPRanges{}

remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure)
remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure, custom)
assert.NoError(t, err)
assert.NotNil(t, remoteIPRanges)
assert.NotNil(t, trie)
Expand Down Expand Up @@ -62,8 +63,9 @@ func TestRefreshRemoteIPs(t *testing.T) {
gcp := GCPIPRanges{}
google := GoogleIPRanges{}
azure := AzureIPRanges{}
custom := CustomIPRanges{}

remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure)
remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure, custom)
assert.Error(t, err)
assert.Nil(t, remoteIPRanges)
assert.Nil(t, trie)
Expand All @@ -78,8 +80,9 @@ func TestRefreshRemoteIPs(t *testing.T) {
}
google := GoogleIPRanges{}
azure := AzureIPRanges{}
custom := CustomIPRanges{}

remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure)
remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure, custom)
assert.NoError(t, err)
assert.NotNil(t, remoteIPRanges)
assert.NotNil(t, trie)
Expand All @@ -103,8 +106,9 @@ func TestRefreshRemoteIPs(t *testing.T) {
}
google := GoogleIPRanges{}
azure := AzureIPRanges{}
custom := CustomIPRanges{}

remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure)
remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure, custom)
assert.Error(t, err)
assert.Nil(t, remoteIPRanges)
assert.Nil(t, trie)
Expand All @@ -119,8 +123,9 @@ func TestRefreshRemoteIPs(t *testing.T) {
},
}
azure := AzureIPRanges{}
custom := CustomIPRanges{}

remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure)
remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure, custom)
assert.NoError(t, err)
assert.NotNil(t, remoteIPRanges)
assert.NotNil(t, trie)
Expand All @@ -144,8 +149,9 @@ func TestRefreshRemoteIPs(t *testing.T) {
},
}
azure := AzureIPRanges{}
custom := CustomIPRanges{}

remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure)
remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure, custom)
assert.Error(t, err)
assert.Nil(t, remoteIPRanges)
assert.Nil(t, trie)
Expand Down Expand Up @@ -195,8 +201,9 @@ func TestRefreshRemoteIPs(t *testing.T) {
},
},
}
custom := CustomIPRanges{}

remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure)
remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure, custom)
assert.NoError(t, err)
assert.NotNil(t, remoteIPRanges)
assert.NotNil(t, trie)
Expand Down Expand Up @@ -234,8 +241,9 @@ func TestRefreshRemoteIPs(t *testing.T) {
},
},
}
custom := CustomIPRanges{}

remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure)
remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure, custom)
assert.Error(t, err)
assert.Nil(t, remoteIPRanges)
assert.Nil(t, trie)
Expand All @@ -256,8 +264,9 @@ func TestRefreshRemoteIPs(t *testing.T) {
gcp := GCPIPRanges{}
google := GoogleIPRanges{}
azure := AzureIPRanges{}
custom := CustomIPRanges{}

remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure)
remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure, custom)
assert.NoError(t, err)
assert.NotNil(t, remoteIPRanges)
assert.NotNil(t, trie)
Expand All @@ -270,6 +279,31 @@ func TestRefreshRemoteIPs(t *testing.T) {
assert.Equal(t, "service1", detail.service)
assert.Equal(t, "us-east-1", detail.region)
})

t.Run("Test Custom az", func(t *testing.T) {
custom := CustomIPRanges{
Prefixes: []CustomPrefix{
{IPPrefixStr: "10.1.1.16/32", Service: "redis", AvailabilityZone: "us-west-2a"},
},
}
aws := AWSIPRanges{}
gcp := GCPIPRanges{}
google := GoogleIPRanges{}
azure := AzureIPRanges{}

remoteIPRanges, trie, err := refreshRemoteIPs(aws, gcp, google, azure, custom)
assert.NoError(t, err)
assert.NotNil(t, remoteIPRanges)
assert.NotNil(t, trie)

assert.Equal(t, 1, len(remoteIPRanges))
ip, err := ipaddr.NewIPAddressString("10.1.1.16/32").ToAddress()
assert.NoError(t, err)
assert.NotNil(t, ip)
detail := remoteIPRanges[ip.ToIPv4().ToKey()]
assert.Equal(t, "redis", detail.service)
assert.Equal(t, "us-west-2a", detail.az)
})
}

func TestNormalizeCloudString(t *testing.T) {
Expand Down
33 changes: 31 additions & 2 deletions pkg/labeler/remote.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package labeler

import (
"encoding/json"
"fmt"
"os"
"sync"
"time"

Expand Down Expand Up @@ -56,7 +58,12 @@ func NewRemoteLabeler(localRegion string, localCloud Cloud, environment Environm
errorCounter.WithLabelValues([]string{"get_cloud_ranges"}...).Inc()
return nil, fmt.Errorf("error fetching cloud ranges: %v", err)
}
remoteIPPrefixes, remoteIPPrefixesTrie, err := refreshRemoteIPs(aws, gcp, google, azure)
custom, err := getCustomRanges()
if err != nil {
errorCounter.WithLabelValues([]string{"get_custom_ranges"}...).Inc()
return nil, fmt.Errorf("error fetching custom ranges: %v", err)
}
remoteIPPrefixes, remoteIPPrefixesTrie, err := refreshRemoteIPs(aws, gcp, google, azure, custom)
if err != nil {
errorCounter.WithLabelValues([]string{"remote_ips_refresh"}...).Inc()
publicIPRefreshCounter.WithLabelValues([]string{"failed"}...).Inc()
Expand Down Expand Up @@ -106,7 +113,14 @@ func NewRemoteLabeler(localRegion string, localCloud Cloud, environment Environm
log.Error().Err(err).Msg("failed to refresh cloud provider IPs")
continue
}
remoteIPPrefixes, remoteIPPrefixesTrie, err := refreshRemoteIPs(aws, gcp, google, azure)
custom, err := getCustomRanges()
if err != nil {
errorCounter.WithLabelValues([]string{"get_custom_ranges"}...).Inc()
publicIPRefreshCounter.WithLabelValues([]string{"failed"}...).Inc()
log.Error().Err(err).Msg("failed to refresh custom provider IPs")
continue
}
remoteIPPrefixes, remoteIPPrefixesTrie, err := refreshRemoteIPs(aws, gcp, google, azure, custom)
if err != nil {
errorCounter.WithLabelValues([]string{"remote_ips_refresh"}...).Inc()
publicIPRefreshCounter.WithLabelValues([]string{"failed"}...).Inc()
Expand Down Expand Up @@ -144,6 +158,7 @@ func (l *RemoteLabeler) labelRemote(remoteEndpoint *endpointInfo, FlowData *Flow
FlowData.RemoteRegion = remoteDetail.region
FlowData.RemoteCloudService = remoteDetail.service
FlowData.RemoteCloud = remoteDetail.cloud
FlowData.RemoteAvailabilityZone = remoteDetail.az

if remoteDetail.cloud == l.cloud {
if remoteDetail.region == "" {
Expand Down Expand Up @@ -208,3 +223,17 @@ func getCloudRanges() (awsIPRanges AWSIPRanges, gcpIPRanges GCPIPRanges, googleI

return
}

func getCustomRanges() (customIPRanges CustomIPRanges, err error) {
body, err := os.ReadFile("/etc/kubenetmon/custom_ranges.json")
if err != nil {
return customIPRanges, err
}

err = json.Unmarshal(body, &customIPRanges)
if err != nil {
return customIPRanges, err
}

return customIPRanges, err
}
12 changes: 12 additions & 0 deletions test/custom_ranges.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"syncToken": "1739569991",
"createDate": "2025-02-14-21-53-11",
"prefixes": [
{
"ip_prefix": "10.16.1.16/32",
"az": "ap-southeast-2b",
"service": "redis"
}
]
}

Loading