go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers-sdk/v1/inventory/manager/credentials_query.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package manager
     5  
     6  import (
     7  	"strings"
     8  
     9  	"github.com/cockroachdb/errors"
    10  	"github.com/mitchellh/mapstructure"
    11  	"github.com/rs/zerolog/log"
    12  	"go.mondoo.com/cnquery"
    13  	"go.mondoo.com/cnquery/llx"
    14  	"go.mondoo.com/cnquery/mql"
    15  	"go.mondoo.com/cnquery/providers-sdk/v1/inventory"
    16  	"go.mondoo.com/cnquery/providers-sdk/v1/vault"
    17  	"go.mondoo.com/cnquery/types"
    18  )
    19  
    20  type CredentialQueryResponse struct {
    21  	// maps to credentials
    22  	Type     string `json:"type,omitempty"`
    23  	User     string `json:"user,omitempty"`      // user associated with the secret
    24  	SecretId string `json:"secret_id,omitempty"` // id to use to fetch the secret from the source vault
    25  }
    26  
    27  func NewCredentialQueryRunner(credentialQuery string, runtime llx.Runtime) (*CredentialQueryRunner, error) {
    28  	mqlExecutor := mql.New(runtime, cnquery.DefaultFeatures)
    29  
    30  	// just empty props to ensure we can compile
    31  	props := map[string]*llx.Primitive{
    32  		"mrn":      llx.StringPrimitive(""),
    33  		"name":     llx.StringPrimitive(""),
    34  		"labels":   llx.MapData(map[string]interface{}{}, types.String).Result().Data,
    35  		"platform": llx.MapData(map[string]interface{}{}, types.String).Result().Data,
    36  	}
    37  
    38  	// test query to see if it compiles well
    39  	_, err := mql.Exec(credentialQuery, runtime, nil, props)
    40  	if err != nil {
    41  		return nil, errors.Wrap(err, "could not compile the secret metadata function")
    42  	}
    43  	return &CredentialQueryRunner{
    44  		mqlExecutor:         mqlExecutor,
    45  		secretMetadataQuery: credentialQuery,
    46  	}, nil
    47  }
    48  
    49  type CredentialQueryRunner struct {
    50  	mqlExecutor         *mql.Executor
    51  	secretMetadataQuery string
    52  }
    53  
    54  func (sq *CredentialQueryRunner) Run(a *inventory.Asset) (*vault.Credential, error) {
    55  	// map labels to props
    56  	labelProps := map[string]interface{}{}
    57  	labels := a.GetLabels()
    58  	for k, v := range labels {
    59  		labelProps[k] = v
    60  	}
    61  
    62  	// map platform to props
    63  	var platformProps map[string]interface{}
    64  	if a.Platform != nil {
    65  		platformProps = map[string]interface{}{
    66  			"name":    a.Platform.Name,
    67  			"release": a.Platform.Version,
    68  			"arch":    a.Platform.Arch,
    69  		}
    70  	} else {
    71  		platformProps = map[string]interface{}{}
    72  	}
    73  
    74  	props := map[string]*llx.Primitive{
    75  		"mrn":      llx.StringPrimitive(a.Mrn),
    76  		"name":     llx.StringPrimitive(a.Name),
    77  		"labels":   llx.MapData(labelProps, types.String).Result().Data,
    78  		"platform": llx.MapData(platformProps, types.String).Result().Data,
    79  	}
    80  
    81  	value, err := sq.mqlExecutor.Exec(sq.secretMetadataQuery, props)
    82  	if err != nil {
    83  		return nil, err
    84  	}
    85  
    86  	sMeta := &CredentialQueryResponse{}
    87  	decoder, _ := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
    88  		Metadata: nil,
    89  		Result:   sMeta,
    90  		TagName:  "json",
    91  	})
    92  	err = decoder.Decode(value.Value)
    93  
    94  	code, ok := vault.CredentialType_value[strings.TrimSpace(sMeta.Type)]
    95  	if !ok {
    96  		log.Warn().Str("credential_type", sMeta.Type).Msg("unknown credential type used in credential query")
    97  	}
    98  
    99  	creds := &vault.Credential{
   100  		Type:     vault.CredentialType(code),
   101  		User:     sMeta.User,
   102  		SecretId: sMeta.SecretId,
   103  	}
   104  
   105  	return creds, err
   106  }