go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/id/azcompute/azcompute.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package azcompute
     5  
     6  import (
     7  	"encoding/json"
     8  	"errors"
     9  	"io"
    10  	"strings"
    11  
    12  	"go.mondoo.com/cnquery/providers-sdk/v1/inventory"
    13  	"go.mondoo.com/cnquery/providers-sdk/v1/plugin"
    14  	"go.mondoo.com/cnquery/providers/os/connection/shared"
    15  	"go.mondoo.com/cnquery/providers/os/resources/powershell"
    16  	"go.mondoo.com/cnquery/utils/multierr"
    17  )
    18  
    19  const (
    20  	identityUrl                   = "http://169.254.169.254/metadata/instance?api-version=2021-02-01"
    21  	metadataIdentityScriptWindows = `Invoke-RestMethod -TimeoutSec 1 -Headers @{"Metadata"="true"} -Method GET -URI http://169.254.169.254/metadata/instance?api-version=2021-02-01 -UseBasicParsing | ConvertTo-Json`
    22  )
    23  
    24  type instanceMetadata struct {
    25  	Compute struct {
    26  		ResourceID     string `json:"resourceID"`
    27  		SubscriptionID string `json:"subscriptionId"`
    28  		Tags           string `json:"tags"`
    29  	} `json:"compute"`
    30  }
    31  
    32  type Identity struct {
    33  	InstanceID string
    34  	AccountID  string
    35  }
    36  
    37  type InstanceIdentifier interface {
    38  	Identify() (Identity, error)
    39  }
    40  
    41  func Resolve(conn shared.Connection, pf *inventory.Platform) (InstanceIdentifier, error) {
    42  	if pf.IsFamily(inventory.FAMILY_UNIX) || pf.IsFamily(inventory.FAMILY_WINDOWS) {
    43  		return &commandInstanceMetadata{conn, pf}, nil
    44  	}
    45  	return nil, errors.New("azure compute id detector is not supported for your asset: " + pf.Name + " " + pf.Version)
    46  }
    47  
    48  type commandInstanceMetadata struct {
    49  	conn     shared.Connection
    50  	platform *inventory.Platform
    51  }
    52  
    53  func (m *commandInstanceMetadata) Identify() (Identity, error) {
    54  	var instanceDocument string
    55  	switch {
    56  	case m.platform.IsFamily(inventory.FAMILY_UNIX):
    57  		cmd, err := m.conn.RunCommand("curl --noproxy '*' -H Metadata:true " + identityUrl)
    58  		if err != nil {
    59  			return Identity{}, err
    60  		}
    61  		data, err := io.ReadAll(cmd.Stdout)
    62  		if err != nil {
    63  			return Identity{}, err
    64  		}
    65  
    66  		instanceDocument = strings.TrimSpace(string(data))
    67  	case m.platform.IsFamily(inventory.FAMILY_WINDOWS):
    68  		cmd, err := m.conn.RunCommand(powershell.Encode(metadataIdentityScriptWindows))
    69  		if err != nil {
    70  			return Identity{}, err
    71  		}
    72  		data, err := io.ReadAll(cmd.Stdout)
    73  		if err != nil {
    74  			return Identity{}, err
    75  		}
    76  
    77  		instanceDocument = strings.TrimSpace(string(data))
    78  	default:
    79  		return Identity{}, errors.New("your platform is not supported by azure metadata identifier resource")
    80  	}
    81  
    82  	// parse into struct
    83  	md := instanceMetadata{}
    84  	if err := json.NewDecoder(strings.NewReader(instanceDocument)).Decode(&md); err != nil {
    85  		return Identity{}, multierr.Wrap(err, "failed to decode Azure Instance Metadata")
    86  	}
    87  
    88  	return Identity{
    89  		InstanceID: plugin.MondooAzureInstanceID(md.Compute.ResourceID),
    90  		AccountID:  "//platformid.api.mondoo.app/runtime/azure/subscriptions/" + md.Compute.SubscriptionID,
    91  	}, nil
    92  }