github.com/cilium/cilium@v1.16.2/pkg/azure/api/metadata.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package api 5 6 import ( 7 "context" 8 "fmt" 9 "net/http" 10 "time" 11 12 "github.com/cilium/cilium/pkg/safeio" 13 ) 14 15 const ( 16 metadataURL = "http://169.254.169.254/metadata" 17 // current version of the metadata/instance service 18 metadataAPIVersion = "2019-06-01" 19 ) 20 21 // GetSubscriptionID retrieves the Azure subscriptionID from the Azure Instance Metadata Service 22 func GetSubscriptionID(ctx context.Context) (string, error) { 23 return getMetadataString(ctx, "instance/compute/subscriptionId") 24 } 25 26 // GetResourceGroupName retrieves the current resource group name in which the host running the Cilium Operator is located 27 // This is retrieved via the Azure Instance Metadata Service 28 func GetResourceGroupName(ctx context.Context) (string, error) { 29 return getMetadataString(ctx, "instance/compute/resourceGroupName") 30 } 31 32 // GetAzureCloudName retrieves the current Azure cloud name in which the host running the Cilium Operator is located 33 // This is retrieved via the Azure Instance Metadata Service 34 func GetAzureCloudName(ctx context.Context) (string, error) { 35 return getMetadataString(ctx, "instance/compute/azEnvironment") 36 } 37 38 // getMetadataString returns the text representation of a field from the Azure IMS (instance metadata service) 39 // more can be found at https://docs.microsoft.com/en-us/azure/virtual-machines/windows/instance-metadata-service#instance-api 40 func getMetadataString(ctx context.Context, path string) (string, error) { 41 client := &http.Client{ 42 Timeout: time.Second * 10, 43 } 44 url := fmt.Sprintf("%s/%s", metadataURL, path) 45 req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) 46 if err != nil { 47 return "", nil 48 } 49 50 query := req.URL.Query() 51 query.Add("api-version", metadataAPIVersion) 52 query.Add("format", "text") 53 54 req.URL.RawQuery = query.Encode() 55 req.Header.Add("Metadata", "true") 56 57 resp, err := client.Do(req) 58 if err != nil { 59 return "", err 60 } 61 defer func() { 62 if err := resp.Body.Close(); err != nil { 63 log.WithError(err).Errorf("Failed to close body for request %s", url) 64 } 65 }() 66 67 respBytes, err := safeio.ReadAllLimit(resp.Body, safeio.MB) 68 if err != nil { 69 return "", err 70 } 71 72 return string(respBytes), nil 73 }