diff --git a/explorer/property.go b/explorer/property.go index 398981975d..faecc8458a 100644 --- a/explorer/property.go +++ b/explorer/property.go @@ -4,7 +4,6 @@ package explorer import ( - "context" "errors" "github.com/rs/zerolog/log" @@ -26,9 +25,20 @@ func (p *Property) RefreshMRN(ownerMRN string) error { log.Error().Err(err).Str("owner", ownerMRN).Str("uid", p.Uid).Msg("failed to refresh mrn") return multierr.Wrap(err, "failed to refresh mrn for query "+p.Title) } - p.Mrn = nu p.Uid = "" + + for i := range p.For { + pfor := p.For[i] + pforNu, err := RefreshMRN(ownerMRN, pfor.Mrn, MRN_RESOURCE_QUERY, pfor.Uid) + if err != nil { + log.Error().Err(err).Str("owner", ownerMRN).Str("uid", p.Uid).Msg("failed to refresh mrn") + return multierr.Wrap(err, "failed to refresh mrn for query "+p.Title) + } + pfor.Mrn = pforNu + pfor.Uid = "" + } + return nil } @@ -125,26 +135,50 @@ func NewPropsCache() PropsCache { func (c PropsCache) Add(props ...*Property) { for i := range props { base := props[i] + if base.Uid != "" && base.Mrn == "" { // keep track of properties that were specified by uid only. // we will merge them in later if we find a matching mrn c.uidOnlyProps[base.Uid] = base continue } + // All properties at this point should have a mrn + merged := base + if base.Mrn != "" { + name, _ := mrn.GetResource(base.Mrn, MRN_RESOURCE_QUERY) + if uidProp, ok := c.uidOnlyProps[name]; ok { + p := proto.Clone(uidProp).(*Property) + p.Merge(base) + base = p + merged = p + } + if existingProp, ok := c.cache[base.Mrn]; ok { existingProp.Merge(base) + merged = existingProp } else { c.cache[base.Mrn] = base } } + + for i := range base.For { + pfor := base.For[i] + if pfor.Mrn != "" { + if existingProp, ok := c.cache[pfor.Mrn]; ok { + existingProp.Merge(merged) + } else { + c.cache[pfor.Mrn] = merged + } + } + } } } // try to Get the mrn, will also return uid-based // properties if they exist first -func (c PropsCache) Get(ctx context.Context, propMrn string) (*Property, string, error) { +func (c PropsCache) Get(propMrn string) (*Property, string, error) { if res, ok := c.cache[propMrn]; ok { name, err := mrn.GetResource(propMrn, MRN_RESOURCE_QUERY) if err != nil { diff --git a/explorer/property_test.go b/explorer/property_test.go new file mode 100644 index 0000000000..9fb3a80c82 --- /dev/null +++ b/explorer/property_test.go @@ -0,0 +1,28 @@ +// Copyright (c) Mondoo, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package explorer + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestProperty_RefreshMrn(t *testing.T) { + in := &Property{ + Uid: "uid1", + For: []*ObjectRef{{ + Uid: "uid2", + }}, + } + + err := in.RefreshMRN("//my.owner") + require.NoError(t, err) + + assert.Equal(t, "", in.Uid) + assert.Equal(t, "//my.owner/queries/uid1", in.Mrn) + assert.Equal(t, "", in.For[0].Uid) + assert.Equal(t, "//my.owner/queries/uid2", in.For[0].Mrn) +} diff --git a/explorer/query_conductor.go b/explorer/query_conductor.go index 99486912ea..9f0abb9126 100644 --- a/explorer/query_conductor.go +++ b/explorer/query_conductor.go @@ -201,7 +201,7 @@ func (s *LocalServices) addQueryToJob(ctx context.Context, query *Mquery, job *E for i := range query.Props { prop := query.Props[i] - override, name, _ := propsCache.Get(ctx, prop.Mrn) + override, name, _ := propsCache.Get(prop.Mrn) if override != nil { prop = override }