diff --git a/go.mod b/go.mod index c9474aae76..774bbd81af 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.4.0 github.com/anchore/syft v1.32.0 github.com/aquilax/truncate v1.0.0 - github.com/armosec/armoapi-go v0.0.667 + github.com/armosec/armoapi-go v0.0.670 github.com/armosec/utils-k8s-go v0.0.35 github.com/cenkalti/backoff v2.2.1+incompatible github.com/cenkalti/backoff/v4 v4.3.0 diff --git a/go.sum b/go.sum index 7950178111..ace48d5f72 100644 --- a/go.sum +++ b/go.sum @@ -761,8 +761,8 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/armosec/armoapi-go v0.0.667 h1:LrFowKvthnL676Gx+hjhvqP4pQ2+CjykFO9SdIYDc/c= -github.com/armosec/armoapi-go v0.0.667/go.mod h1:9jAH0g8ZsryhiBDd/aNMX4+n10bGwTx/doWCyyjSxts= +github.com/armosec/armoapi-go v0.0.670 h1:hN2O4ZSGFHAczvO5ko2ZbbdplrcqyJgt/+JR83kLTIE= +github.com/armosec/armoapi-go v0.0.670/go.mod h1:9jAH0g8ZsryhiBDd/aNMX4+n10bGwTx/doWCyyjSxts= github.com/armosec/gojay v1.2.17 h1:VSkLBQzD1c2V+FMtlGFKqWXNsdNvIKygTKJI9ysY8eM= github.com/armosec/gojay v1.2.17/go.mod h1:vuvX3DlY0nbVrJ0qCklSS733AWMoQboq3cFyuQW9ybc= github.com/armosec/utils-go v0.0.58 h1:g9RnRkxZAmzTfPe2ruMo2OXSYLwVSegQSkSavOfmaIE= diff --git a/pkg/cloudmetadata/metadata.go b/pkg/cloudmetadata/metadata.go index d0469c68c3..3d31c01a4a 100644 --- a/pkg/cloudmetadata/metadata.go +++ b/pkg/cloudmetadata/metadata.go @@ -13,6 +13,7 @@ import ( "github.com/kubescape/go-logger/helpers" k8sInterfaceCloudMetadata "github.com/kubescape/k8s-interface/cloudmetadata" "github.com/kubescape/k8s-interface/k8sinterface" + corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -35,6 +36,8 @@ func GetCloudMetadata(ctx context.Context, client *k8sinterface.KubernetesApi, n // special case for AWS, if the account ID is not found in the node metadata, we need to get it from ConfigMap enrichCloudMetadataForAWS(ctx, client, cMetadata) + // special case for Azure, enrich ResourceGroup from node providerID + enrichCloudMetadataForAzure(node, cMetadata) return cMetadata, nil } @@ -57,6 +60,36 @@ func enrichCloudMetadataForAWS(ctx context.Context, client *k8sinterface.Kuberne logger.L().Debug("enriched cloud metadata from aws-auth ConfigMap") } +func enrichCloudMetadataForAzure(node *corev1.Node, cMetadata *armotypes.CloudMetadata) { + if cMetadata == nil || cMetadata.Provider != armotypes.ProviderAzure || cMetadata.ResourceGroup != "" { + return + } + + // Parse ResourceGroup from node's providerID + // Format: azure:///subscriptions/{sub}/resourceGroups/{rg}/providers/... + providerID := node.Spec.ProviderID + if rg := parseAzureResourceGroup(providerID); rg != "" { + cMetadata.ResourceGroup = rg + logger.L().Debug("enriched cloud metadata with Azure ResourceGroup from node providerID", helpers.String("resourceGroup", rg)) + } +} + +func parseAzureResourceGroup(providerID string) string { + // providerID format: azure:///subscriptions/.../resourceGroups/{resourceGroup}/providers/... + const marker = "/resourceGroups/" + idx := strings.Index(strings.ToLower(providerID), strings.ToLower(marker)) + if idx == -1 { + return "" + } + start := idx + len(marker) + rest := providerID[start:] + end := strings.Index(rest, "/") + if end == -1 { + return rest + } + return rest[:end] +} + // GetCloudMetadataWithIMDS retrieves cloud metadata for a given node using IMDS func GetCloudMetadataWithIMDS(ctx context.Context) (*armotypes.CloudMetadata, error) { cMetadataClient := k8sInterfaceCloudMetadata.NewMetadataClient(true) @@ -234,18 +267,19 @@ func fetchAzureMetadata(ctx context.Context) (*armotypes.CloudMetadata, error) { } meta := &armotypes.CloudMetadata{ - Provider: armotypes.ProviderAzure, - HostType: armotypes.HostTypeAzureVm, - AccountID: get("subscriptionId"), - InstanceID: get("vmId"), - InstanceType: vmSize, - Region: get("location"), - Zone: get("zone"), - Hostname: get("name"), + Provider: armotypes.ProviderAzure, + HostType: armotypes.HostTypeAzureVm, + AccountID: get("subscriptionId"), + InstanceID: get("vmId"), + InstanceType: vmSize, + Region: get("location"), + Zone: get("zone"), + Hostname: get("name"), + ResourceGroup: get("resourceGroupName"), } // Detect AKS (heuristic: check for resource group or vmss tags common in AKS) - if strings.Contains(strings.ToLower(get("resourceGroupName")), "aks") { + if strings.Contains(strings.ToLower(meta.ResourceGroup), "aks") { meta.HostType = armotypes.HostTypeAks }