From 5caf07bd00c94aff9f7545e6554e72e5f133d7a5 Mon Sep 17 00:00:00 2001 From: Dominik Richter Date: Thu, 29 Sep 2022 18:19:48 -0700 Subject: [PATCH] =?UTF-8?q?=E2=AD=90=20add=20structure=20for=20explorer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Dominik Richter --- Makefile | 5 +- README.md | 1 - explorer/bundle.go | 258 ++++ explorer/datalake.go | 27 + explorer/explorer.go | 3 + explorer/explorer.pb.go | 2248 +++++++++++++++++++++++++++++++++++ explorer/explorer.proto | 217 ++++ explorer/explorer.ranger.go | 612 ++++++++++ explorer/mquery.go | 184 +++ explorer/query_hub.go | 239 ++++ explorer/querypack.go | 105 ++ explorer/services.go | 35 + go.mod | 5 + go.sum | 6 + 14 files changed, 3943 insertions(+), 2 deletions(-) create mode 100644 explorer/bundle.go create mode 100644 explorer/datalake.go create mode 100644 explorer/explorer.go create mode 100644 explorer/explorer.pb.go create mode 100644 explorer/explorer.proto create mode 100644 explorer/explorer.ranger.go create mode 100644 explorer/mquery.go create mode 100644 explorer/query_hub.go create mode 100644 explorer/querypack.go create mode 100644 explorer/services.go diff --git a/Makefile b/Makefile index 6cf07c0122..98f260ad11 100644 --- a/Makefile +++ b/Makefile @@ -58,7 +58,7 @@ prep/tools: # 🌙 MQL/MOTOR # -cnquery/generate: clean/proto motor/generate resources/generate llx/generate lr shared/generate +cnquery/generate: clean/proto motor/generate resources/generate llx/generate lr shared/generate explorer/generate motor/generate: go generate . @@ -199,6 +199,9 @@ mqlc: | llx mqlc/test mqlc/test: go test -timeout 5s $(shell go list ./mqlc/... | grep -v '/vendor/') +explorer/generate: + go generate ./explorer + # 🏗 Binary / Build # .PHONY: cnquery/install diff --git a/README.md b/README.md index a61929b378..668667b283 100644 --- a/README.md +++ b/README.md @@ -156,7 +156,6 @@ There are so many things cnquery can do! Gather information about your fleet, fi Explore: - The Query Hub -- [Policy as Code](https://mondoo.com/docs/tutorials/mondoo/policy-as-code/) - [MQL introduction](https://mondoohq.github.io/mql-intro/index.html) - [MQL resource packs](https://mondoo.com/docs/references/mql/) - [cnspec](https://github.com/mondoohq/cnspec), our open source, cloud-native security scanner diff --git a/explorer/bundle.go b/explorer/bundle.go new file mode 100644 index 0000000000..587fbf9e11 --- /dev/null +++ b/explorer/bundle.go @@ -0,0 +1,258 @@ +package explorer + +import ( + "context" + "io/fs" + "os" + "path/filepath" + "strings" + + "github.com/pkg/errors" + "github.com/rs/zerolog/log" + "go.mondoo.com/cnquery/checksums" + llx "go.mondoo.com/cnquery/llx" + "sigs.k8s.io/yaml" +) + +const ( + MRN_RESOURCE_QUERY = "queries" + MRN_RESOURCE_QUERYPACK = "querypack" + MRN_RESOURCE_ASSET = "assets" +) + +// BundleMap is a Bundle with easier access to its data +type BundleMap struct { + OwnerMrn string `json:"owner_mrn,omitempty"` + Packs map[string]*QueryPack `json:"packs,omitempty"` + Queries map[string]*Mquery `json:"queries,omitempty"` + Code map[string]*llx.CodeBundle `json:"code,omitempty"` +} + +// NewBundleMap creates a new empty initialized map +// dataLake (optional) connects an additional data layer which may provide queries/packs +func NewBundleMap(ownerMrn string) *BundleMap { + return &BundleMap{ + OwnerMrn: ownerMrn, + Packs: make(map[string]*QueryPack), + Queries: make(map[string]*Mquery), + Code: make(map[string]*llx.CodeBundle), + } +} + +// BundleFromPaths loads a single bundle file or a bundle that +// was split into multiple files into a single Bundle struct +func BundleFromPaths(paths ...string) (*Bundle, error) { + // load all the source files + resolvedFilenames, err := walkBundleFiles(paths) + if err != nil { + log.Error().Err(err).Msg("could not resolve bundle files") + return nil, err + } + + // aggregate all files into a single bundle + aggregatedBundle, err := aggregateFilesToBundle(resolvedFilenames) + if err != nil { + log.Error().Err(err).Msg("could merge bundle files") + return nil, err + } + return aggregatedBundle, nil +} + +// walkBundleFiles iterates over all provided filenames and +// checks if the name is a file or a directory. If the filename +// is a directory, it walks the directory recursively +func walkBundleFiles(filenames []string) ([]string, error) { + // resolve file names + resolvedFilenames := []string{} + for i := range filenames { + filename := filenames[i] + fi, err := os.Stat(filename) + if err != nil { + return nil, errors.Wrap(err, "could not load bundle file: "+filename) + } + + if fi.IsDir() { + filepath.WalkDir(filename, func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + // we ignore nested directories + if d.IsDir() { + return nil + } + + // only consider .yaml|.yml files + if strings.HasSuffix(d.Name(), ".yaml") || strings.HasSuffix(d.Name(), ".yml") { + resolvedFilenames = append(resolvedFilenames, path) + } + + return nil + }) + } else { + resolvedFilenames = append(resolvedFilenames, filename) + } + } + + return resolvedFilenames, nil +} + +// aggregateFilesToBundle iterates over all provided files and loads its content. +// It assumes that all provided files are checked upfront and are not a directory +func aggregateFilesToBundle(paths []string) (*Bundle, error) { + // iterate over all files, load them and merge them + mergedBundle := &Bundle{} + + for i := range paths { + path := paths[i] + bundle, err := bundleFromSingleFile(path) + if err != nil { + return nil, errors.Wrap(err, "could not load file: "+path) + } + + mergedBundle.AddBundle(bundle) + } + + return mergedBundle, nil +} + +// bundleFromSingleFile loads a bundle from a single file +func bundleFromSingleFile(path string) (*Bundle, error) { + bundleData, err := os.ReadFile(path) + if err != nil { + return nil, err + } + + return BundleFromYAML(bundleData) +} + +// BundleFromYAML create a bundle from yaml contents +func BundleFromYAML(data []byte) (*Bundle, error) { + var res Bundle + err := yaml.Unmarshal(data, &res) + return &res, err +} + +// ToYAML returns the bundle as yaml +func (p *Bundle) ToYAML() ([]byte, error) { + return yaml.Marshal(p) +} + +func (p *Bundle) SourceHash() (string, error) { + raw, err := p.ToYAML() + if err != nil { + return "", err + } + c := checksums.New + c = c.Add(string(raw)) + return c.String(), nil +} + +// ToMap turns the Bundle into a BundleMap +// dataLake (optional) may be used to provide queries/packs not found in the bundle +func (p *Bundle) ToMap() *BundleMap { + res := NewBundleMap(p.OwnerMrn) + + for i := range p.Packs { + c := p.Packs[i] + res.Packs[c.Mrn] = c + for j := range c.Queries { + cq := c.Queries[j] + res.Queries[cq.Mrn] = cq + } + } + + return res +} + +// Add another bundle into this. No duplicate packs, queries, or +// properties are allowed and will lead to an error. Both bundles must have +// MRNs for everything. OwnerMRNs must be identical as well. +func (p *Bundle) AddBundle(other *Bundle) error { + if p.OwnerMrn == "" { + p.OwnerMrn = other.OwnerMrn + } else if p.OwnerMrn != other.OwnerMrn { + return errors.New("when combining bundles the owner MRNs must be identical") + } + + for i := range other.Packs { + c := other.Packs[i] + if c.Mrn == "" { + return errors.New("source bundle that is added has missing query pack MRNs") + } + + for j := range p.Packs { + if p.Packs[j].Mrn == c.Mrn { + return errors.New("cannot combine query packs, duplicate query packs: " + c.Mrn) + } + } + + p.Packs = append(p.Packs, c) + } + + return nil +} + +// Compile a bundle +// Does 4 things: +// 1. turns it into a map for easier access +// 2. compile all queries. store code in the bundle map +// 3. validation of all contents +// 4. generate MRNs for all packs, queries, and updates referencing local fields +func (p *Bundle) Compile(ctx context.Context) (*BundleMap, error) { + ownerMrn := p.OwnerMrn + if ownerMrn == "" { + return nil, errors.New("failed to compile bundle, the owner MRN is empty") + } + + var warnings []error + + code := map[string]*llx.CodeBundle{} + + // Index packs + update MRNs and checksums, link properties via MRNs + for i := range p.Packs { + querypack := p.Packs[i] + + // !this is very important to prevent user overrides! vv + querypack.InvalidateAllChecksums() + + err := querypack.RefreshMRN(ownerMrn) + if err != nil { + return nil, errors.New("failed to refresh query pack " + querypack.Mrn + ": " + err.Error()) + } + + for i := range querypack.Queries { + query := querypack.Queries[i] + + // remove leading and trailing whitespace of docs, refs and tags + query.Sanitize() + + // ensure the correct mrn is set + if err = query.RefreshMRN(ownerMrn); err != nil { + return nil, err + } + + // recalculate the checksums + codeBundle, err := query.RefreshChecksumAndType(nil) + if err != nil { + log.Error().Err(err).Msg("could not compile the query") + warnings = append(warnings, errors.Wrap(err, "failed to validate query '"+query.Mrn+"'")) + } + + code[query.Mrn] = codeBundle + } + } + + res := p.ToMap() + res.Code = code + + if len(warnings) != 0 { + var msg strings.Builder + for i := range warnings { + msg.WriteString(warnings[i].Error()) + msg.WriteString("\n") + } + return res, errors.New(msg.String()) + } + + return res, nil +} diff --git a/explorer/datalake.go b/explorer/datalake.go new file mode 100644 index 0000000000..eaafea2e99 --- /dev/null +++ b/explorer/datalake.go @@ -0,0 +1,27 @@ +package explorer + +import "context" + +// DataLake provides a shared database access layer +type DataLake interface { + // GetQuery retrieves a given query + GetQuery(ctx context.Context, mrn string) (*Mquery, error) + // SetQuery stores a given query + // Note: the query must be defined, it cannot be nil + SetQuery(ctx context.Context, mrn string, query *Mquery) error + + // SetQueryPack stores a given pack in the data lake + SetQueryPack(ctx context.Context, querypack *QueryPack, filters []*Mquery) error + // GetQueryPack retrieves and if necessary updates the pack + GetQueryPack(ctx context.Context, mrn string) (*QueryPack, error) + // DeleteQueryPack removes a given pack + // Note: the MRN has to be valid + DeleteQueryPack(ctx context.Context, mrn string) error + // GetBundle retrieves and if necessary updates the bundle + GetBundle(ctx context.Context, mrn string) (*Bundle, error) + // List all packs for a given owner + // Note: Owner MRN is required + ListQueryPacks(ctx context.Context, ownerMrn string, name string) ([]*QueryPack, error) + // GetQueryPackFilters retrieves the list of asset filters for a pack (fast) + GetQueryPackFilters(ctx context.Context, mrn string) ([]*Mquery, error) +} diff --git a/explorer/explorer.go b/explorer/explorer.go new file mode 100644 index 0000000000..42ef5651f8 --- /dev/null +++ b/explorer/explorer.go @@ -0,0 +1,3 @@ +package explorer + +//go:generate protoc --proto_path=../:. --go_out=. --go_opt=paths=source_relative --rangerrpc_out=. explorer.proto diff --git a/explorer/explorer.pb.go b/explorer/explorer.pb.go new file mode 100644 index 0000000000..66bd7eac45 --- /dev/null +++ b/explorer/explorer.pb.go @@ -0,0 +1,2248 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.21.6 +// source: explorer.proto + +package explorer + +import ( + llx "go.mondoo.com/cnquery/llx" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Bundle struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OwnerMrn string `protobuf:"bytes,1,opt,name=owner_mrn,json=ownerMrn,proto3" json:"owner_mrn,omitempty"` + Packs []*QueryPack `protobuf:"bytes,2,rep,name=packs,proto3" json:"packs,omitempty"` +} + +func (x *Bundle) Reset() { + *x = Bundle{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Bundle) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Bundle) ProtoMessage() {} + +func (x *Bundle) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Bundle.ProtoReflect.Descriptor instead. +func (*Bundle) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{0} +} + +func (x *Bundle) GetOwnerMrn() string { + if x != nil { + return x.OwnerMrn + } + return "" +} + +func (x *Bundle) GetPacks() []*QueryPack { + if x != nil { + return x.Packs + } + return nil +} + +type QueryPack struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // user-defined UID, which is used to generate the MRN + Uid string `protobuf:"bytes,36,opt,name=uid,proto3" json:"uid,omitempty"` + // MRN to universally identify this query. + // UIDs are local to QueryPacks, MRNs are global + Mrn string `protobuf:"bytes,1,opt,name=mrn,proto3" json:"mrn,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Version string `protobuf:"bytes,3,opt,name=version,proto3" json:"version,omitempty"` + OwnerMrn string `protobuf:"bytes,4,opt,name=owner_mrn,json=ownerMrn,proto3" json:"owner_mrn,omitempty"` // auto-generated + Queries []*Mquery `protobuf:"bytes,6,rep,name=queries,proto3" json:"queries,omitempty"` + Filters []string `protobuf:"bytes,7,rep,name=filters,proto3" json:"filters,omitempty"` + Context string `protobuf:"bytes,8,opt,name=context,proto3" json:"context,omitempty"` + IsPublic bool `protobuf:"varint,20,opt,name=is_public,json=isPublic,proto3" json:"is_public,omitempty"` + License string `protobuf:"bytes,21,opt,name=license,proto3" json:"license,omitempty"` + Docs *QueryPackDocs `protobuf:"bytes,22,opt,name=docs,proto3" json:"docs,omitempty"` + Authors []*Author `protobuf:"bytes,30,rep,name=authors,proto3" json:"authors,omitempty"` + Created int64 `protobuf:"varint,32,opt,name=created,proto3" json:"created,omitempty"` + Modified int64 `protobuf:"varint,33,opt,name=modified,proto3" json:"modified,omitempty"` + Tags map[string]string `protobuf:"bytes,34,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + LocalContentChecksum string `protobuf:"bytes,23,opt,name=local_content_checksum,json=localContentChecksum,proto3" json:"local_content_checksum,omitempty"` + LocalExecutionChecksum string `protobuf:"bytes,24,opt,name=local_execution_checksum,json=localExecutionChecksum,proto3" json:"local_execution_checksum,omitempty"` +} + +func (x *QueryPack) Reset() { + *x = QueryPack{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryPack) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryPack) ProtoMessage() {} + +func (x *QueryPack) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryPack.ProtoReflect.Descriptor instead. +func (*QueryPack) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{1} +} + +func (x *QueryPack) GetUid() string { + if x != nil { + return x.Uid + } + return "" +} + +func (x *QueryPack) GetMrn() string { + if x != nil { + return x.Mrn + } + return "" +} + +func (x *QueryPack) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *QueryPack) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *QueryPack) GetOwnerMrn() string { + if x != nil { + return x.OwnerMrn + } + return "" +} + +func (x *QueryPack) GetQueries() []*Mquery { + if x != nil { + return x.Queries + } + return nil +} + +func (x *QueryPack) GetFilters() []string { + if x != nil { + return x.Filters + } + return nil +} + +func (x *QueryPack) GetContext() string { + if x != nil { + return x.Context + } + return "" +} + +func (x *QueryPack) GetIsPublic() bool { + if x != nil { + return x.IsPublic + } + return false +} + +func (x *QueryPack) GetLicense() string { + if x != nil { + return x.License + } + return "" +} + +func (x *QueryPack) GetDocs() *QueryPackDocs { + if x != nil { + return x.Docs + } + return nil +} + +func (x *QueryPack) GetAuthors() []*Author { + if x != nil { + return x.Authors + } + return nil +} + +func (x *QueryPack) GetCreated() int64 { + if x != nil { + return x.Created + } + return 0 +} + +func (x *QueryPack) GetModified() int64 { + if x != nil { + return x.Modified + } + return 0 +} + +func (x *QueryPack) GetTags() map[string]string { + if x != nil { + return x.Tags + } + return nil +} + +func (x *QueryPack) GetLocalContentChecksum() string { + if x != nil { + return x.LocalContentChecksum + } + return "" +} + +func (x *QueryPack) GetLocalExecutionChecksum() string { + if x != nil { + return x.LocalExecutionChecksum + } + return "" +} + +type QueryPacks struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Items []*QueryPack `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` +} + +func (x *QueryPacks) Reset() { + *x = QueryPacks{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryPacks) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryPacks) ProtoMessage() {} + +func (x *QueryPacks) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryPacks.ProtoReflect.Descriptor instead. +func (*QueryPacks) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{2} +} + +func (x *QueryPacks) GetItems() []*QueryPack { + if x != nil { + return x.Items + } + return nil +} + +type Docs struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Desc string `protobuf:"bytes,1,opt,name=desc,proto3" json:"desc,omitempty"` + Refs []*Reference `protobuf:"bytes,2,rep,name=refs,proto3" json:"refs,omitempty"` +} + +func (x *Docs) Reset() { + *x = Docs{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Docs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Docs) ProtoMessage() {} + +func (x *Docs) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Docs.ProtoReflect.Descriptor instead. +func (*Docs) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{3} +} + +func (x *Docs) GetDesc() string { + if x != nil { + return x.Desc + } + return "" +} + +func (x *Docs) GetRefs() []*Reference { + if x != nil { + return x.Refs + } + return nil +} + +type Reference struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` +} + +func (x *Reference) Reset() { + *x = Reference{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Reference) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Reference) ProtoMessage() {} + +func (x *Reference) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Reference.ProtoReflect.Descriptor instead. +func (*Reference) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{4} +} + +func (x *Reference) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *Reference) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +// Mquery is an MQL query representation +type Mquery struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` + CodeId string `protobuf:"bytes,2,opt,name=code_id,json=codeId,proto3" json:"code_id,omitempty"` + Checksum string `protobuf:"bytes,3,opt,name=checksum,proto3" json:"checksum,omitempty"` + Mrn string `protobuf:"bytes,4,opt,name=mrn,proto3" json:"mrn,omitempty"` + // UID is only needed on Mquery upload, when the MRN is computed. + // It will not be persisted. + Uid string `protobuf:"bytes,5,opt,name=uid,proto3" json:"uid,omitempty"` + Type string `protobuf:"bytes,6,opt,name=type,proto3" json:"type,omitempty"` + Context string `protobuf:"bytes,7,opt,name=context,proto3" json:"context,omitempty"` + Title string `protobuf:"bytes,20,opt,name=title,proto3" json:"title,omitempty"` + Docs *MqueryDocs `protobuf:"bytes,21,opt,name=docs,proto3" json:"docs,omitempty"` + Desc string `protobuf:"bytes,35,opt,name=desc,proto3" json:"desc,omitempty"` // only used if docs.desc is not defined + Refs []*MqueryRef `protobuf:"bytes,22,rep,name=refs,proto3" json:"refs,omitempty"` + Tags map[string]string `protobuf:"bytes,34,rep,name=tags,proto3" json:"tags,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *Mquery) Reset() { + *x = Mquery{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Mquery) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Mquery) ProtoMessage() {} + +func (x *Mquery) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Mquery.ProtoReflect.Descriptor instead. +func (*Mquery) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{5} +} + +func (x *Mquery) GetQuery() string { + if x != nil { + return x.Query + } + return "" +} + +func (x *Mquery) GetCodeId() string { + if x != nil { + return x.CodeId + } + return "" +} + +func (x *Mquery) GetChecksum() string { + if x != nil { + return x.Checksum + } + return "" +} + +func (x *Mquery) GetMrn() string { + if x != nil { + return x.Mrn + } + return "" +} + +func (x *Mquery) GetUid() string { + if x != nil { + return x.Uid + } + return "" +} + +func (x *Mquery) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *Mquery) GetContext() string { + if x != nil { + return x.Context + } + return "" +} + +func (x *Mquery) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *Mquery) GetDocs() *MqueryDocs { + if x != nil { + return x.Docs + } + return nil +} + +func (x *Mquery) GetDesc() string { + if x != nil { + return x.Desc + } + return "" +} + +func (x *Mquery) GetRefs() []*MqueryRef { + if x != nil { + return x.Refs + } + return nil +} + +func (x *Mquery) GetTags() map[string]string { + if x != nil { + return x.Tags + } + return nil +} + +type QueryPackDocs struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Desc string `protobuf:"bytes,1,opt,name=desc,proto3" json:"desc,omitempty"` +} + +func (x *QueryPackDocs) Reset() { + *x = QueryPackDocs{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *QueryPackDocs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*QueryPackDocs) ProtoMessage() {} + +func (x *QueryPackDocs) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use QueryPackDocs.ProtoReflect.Descriptor instead. +func (*QueryPackDocs) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{6} +} + +func (x *QueryPackDocs) GetDesc() string { + if x != nil { + return x.Desc + } + return "" +} + +type MqueryDocs struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Desc string `protobuf:"bytes,1,opt,name=desc,proto3" json:"desc,omitempty"` + Audit string `protobuf:"bytes,2,opt,name=audit,proto3" json:"audit,omitempty"` + Remediation string `protobuf:"bytes,3,opt,name=remediation,proto3" json:"remediation,omitempty"` +} + +func (x *MqueryDocs) Reset() { + *x = MqueryDocs{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MqueryDocs) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MqueryDocs) ProtoMessage() {} + +func (x *MqueryDocs) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MqueryDocs.ProtoReflect.Descriptor instead. +func (*MqueryDocs) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{7} +} + +func (x *MqueryDocs) GetDesc() string { + if x != nil { + return x.Desc + } + return "" +} + +func (x *MqueryDocs) GetAudit() string { + if x != nil { + return x.Audit + } + return "" +} + +func (x *MqueryDocs) GetRemediation() string { + if x != nil { + return x.Remediation + } + return "" +} + +type Author struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` +} + +func (x *Author) Reset() { + *x = Author{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Author) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Author) ProtoMessage() {} + +func (x *Author) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Author.ProtoReflect.Descriptor instead. +func (*Author) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{8} +} + +func (x *Author) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Author) GetEmail() string { + if x != nil { + return x.Email + } + return "" +} + +type MqueryRef struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Title string `protobuf:"bytes,1,opt,name=title,proto3" json:"title,omitempty"` + Url string `protobuf:"bytes,2,opt,name=url,proto3" json:"url,omitempty"` +} + +func (x *MqueryRef) Reset() { + *x = MqueryRef{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MqueryRef) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MqueryRef) ProtoMessage() {} + +func (x *MqueryRef) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use MqueryRef.ProtoReflect.Descriptor instead. +func (*MqueryRef) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{9} +} + +func (x *MqueryRef) GetTitle() string { + if x != nil { + return x.Title + } + return "" +} + +func (x *MqueryRef) GetUrl() string { + if x != nil { + return x.Url + } + return "" +} + +// The list of queries that an asset needs to execute +// May be identical amongst multiple individual policies +// - Checksum helps deduplicate this job +// - Queries have a map from query checksum to query query contents +type ExecutionJob struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Checksum string `protobuf:"bytes,1,opt,name=checksum,proto3" json:"checksum,omitempty"` + // map of all queries that should be executed, checksum => query + Queries map[string]*ExecutionQuery `protobuf:"bytes,2,rep,name=queries,proto3" json:"queries,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *ExecutionJob) Reset() { + *x = ExecutionJob{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecutionJob) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecutionJob) ProtoMessage() {} + +func (x *ExecutionJob) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecutionJob.ProtoReflect.Descriptor instead. +func (*ExecutionJob) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{10} +} + +func (x *ExecutionJob) GetChecksum() string { + if x != nil { + return x.Checksum + } + return "" +} + +func (x *ExecutionJob) GetQueries() map[string]*ExecutionQuery { + if x != nil { + return x.Queries + } + return nil +} + +// A query which is part of an ExecutionJob +// Reduced to the bare minimum for the execution +type ExecutionQuery struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Query string `protobuf:"bytes,1,opt,name=query,proto3" json:"query,omitempty"` + Checksum string `protobuf:"bytes,2,opt,name=checksum,proto3" json:"checksum,omitempty"` + // mapping from name => checksum, which is in the execution job + Properties map[string]string `protobuf:"bytes,3,rep,name=properties,proto3" json:"properties,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + // list of checksums that we collect as data points + Datapoints []string `protobuf:"bytes,4,rep,name=datapoints,proto3" json:"datapoints,omitempty"` + Code *llx.CodeBundle `protobuf:"bytes,5,opt,name=code,proto3" json:"code,omitempty"` +} + +func (x *ExecutionQuery) Reset() { + *x = ExecutionQuery{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExecutionQuery) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExecutionQuery) ProtoMessage() {} + +func (x *ExecutionQuery) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExecutionQuery.ProtoReflect.Descriptor instead. +func (*ExecutionQuery) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{11} +} + +func (x *ExecutionQuery) GetQuery() string { + if x != nil { + return x.Query + } + return "" +} + +func (x *ExecutionQuery) GetChecksum() string { + if x != nil { + return x.Checksum + } + return "" +} + +func (x *ExecutionQuery) GetProperties() map[string]string { + if x != nil { + return x.Properties + } + return nil +} + +func (x *ExecutionQuery) GetDatapoints() []string { + if x != nil { + return x.Datapoints + } + return nil +} + +func (x *ExecutionQuery) GetCode() *llx.CodeBundle { + if x != nil { + return x.Code + } + return nil +} + +type Empty struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *Empty) Reset() { + *x = Empty{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Empty) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Empty) ProtoMessage() {} + +func (x *Empty) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Empty.ProtoReflect.Descriptor instead. +func (*Empty) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{12} +} + +// MRNs are used to uniquely identify resources. They are globally unique. +type Mrn struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Mrn string `protobuf:"bytes,1,opt,name=mrn,proto3" json:"mrn,omitempty"` +} + +func (x *Mrn) Reset() { + *x = Mrn{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Mrn) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Mrn) ProtoMessage() {} + +func (x *Mrn) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Mrn.ProtoReflect.Descriptor instead. +func (*Mrn) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{13} +} + +func (x *Mrn) GetMrn() string { + if x != nil { + return x.Mrn + } + return "" +} + +type Mqueries struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Items []*Mquery `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"` +} + +func (x *Mqueries) Reset() { + *x = Mqueries{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Mqueries) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Mqueries) ProtoMessage() {} + +func (x *Mqueries) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Mqueries.ProtoReflect.Descriptor instead. +func (*Mqueries) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{14} +} + +func (x *Mqueries) GetItems() []*Mquery { + if x != nil { + return x.Items + } + return nil +} + +type ListReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + OwnerMrn string `protobuf:"bytes,1,opt,name=owner_mrn,json=ownerMrn,proto3" json:"owner_mrn,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` +} + +func (x *ListReq) Reset() { + *x = ListReq{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[15] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ListReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListReq) ProtoMessage() {} + +func (x *ListReq) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[15] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ListReq.ProtoReflect.Descriptor instead. +func (*ListReq) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{15} +} + +func (x *ListReq) GetOwnerMrn() string { + if x != nil { + return x.OwnerMrn + } + return "" +} + +func (x *ListReq) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +// Assign a number of packs to an asset. All of these are identified by MRN. +// Generally query packs are assigned (via MRN). +type Assignment struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AssetMrn string `protobuf:"bytes,1,opt,name=asset_mrn,json=assetMrn,proto3" json:"asset_mrn,omitempty"` + PackMrns []string `protobuf:"bytes,2,rep,name=pack_mrns,json=packMrns,proto3" json:"pack_mrns,omitempty"` +} + +func (x *Assignment) Reset() { + *x = Assignment{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[16] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Assignment) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Assignment) ProtoMessage() {} + +func (x *Assignment) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[16] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Assignment.ProtoReflect.Descriptor instead. +func (*Assignment) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{16} +} + +func (x *Assignment) GetAssetMrn() string { + if x != nil { + return x.AssetMrn + } + return "" +} + +func (x *Assignment) GetPackMrns() []string { + if x != nil { + return x.PackMrns + } + return nil +} + +// Resolve a given entity via its MRN. Typically used to resolve assets. +// Can also be used to resolve query packs. +type ResolveReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EntityMrn string `protobuf:"bytes,1,opt,name=entity_mrn,json=entityMrn,proto3" json:"entity_mrn,omitempty"` + AssetFilters []*Mquery `protobuf:"bytes,2,rep,name=asset_filters,json=assetFilters,proto3" json:"asset_filters,omitempty"` +} + +func (x *ResolveReq) Reset() { + *x = ResolveReq{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[17] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResolveReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResolveReq) ProtoMessage() {} + +func (x *ResolveReq) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[17] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResolveReq.ProtoReflect.Descriptor instead. +func (*ResolveReq) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{17} +} + +func (x *ResolveReq) GetEntityMrn() string { + if x != nil { + return x.EntityMrn + } + return "" +} + +func (x *ResolveReq) GetAssetFilters() []*Mquery { + if x != nil { + return x.AssetFilters + } + return nil +} + +// ResolvedPack is returned from a resolve request. It includes the execution job +// with all things that need to be run. +type ResolvedPack struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + ExecutionJob *ExecutionJob `protobuf:"bytes,2,opt,name=execution_job,json=executionJob,proto3" json:"execution_job,omitempty"` + Filters []*Mquery `protobuf:"bytes,4,rep,name=filters,proto3" json:"filters,omitempty"` + GraphExecutionChecksum string `protobuf:"bytes,7,opt,name=graph_execution_checksum,json=graphExecutionChecksum,proto3" json:"graph_execution_checksum,omitempty"` + FiltersChecksum string `protobuf:"bytes,20,opt,name=filters_checksum,json=filtersChecksum,proto3" json:"filters_checksum,omitempty"` +} + +func (x *ResolvedPack) Reset() { + *x = ResolvedPack{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResolvedPack) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResolvedPack) ProtoMessage() {} + +func (x *ResolvedPack) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResolvedPack.ProtoReflect.Descriptor instead. +func (*ResolvedPack) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{18} +} + +func (x *ResolvedPack) GetExecutionJob() *ExecutionJob { + if x != nil { + return x.ExecutionJob + } + return nil +} + +func (x *ResolvedPack) GetFilters() []*Mquery { + if x != nil { + return x.Filters + } + return nil +} + +func (x *ResolvedPack) GetGraphExecutionChecksum() string { + if x != nil { + return x.GraphExecutionChecksum + } + return "" +} + +func (x *ResolvedPack) GetFiltersChecksum() string { + if x != nil { + return x.FiltersChecksum + } + return "" +} + +// Update asset jobs forces all jobs for a given asset to get refreshed. +type UpdateAssetJobsReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AssetMrn string `protobuf:"bytes,1,opt,name=asset_mrn,json=assetMrn,proto3" json:"asset_mrn,omitempty"` + AssetFilters []*Mquery `protobuf:"bytes,2,rep,name=asset_filters,json=assetFilters,proto3" json:"asset_filters,omitempty"` +} + +func (x *UpdateAssetJobsReq) Reset() { + *x = UpdateAssetJobsReq{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateAssetJobsReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateAssetJobsReq) ProtoMessage() {} + +func (x *UpdateAssetJobsReq) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateAssetJobsReq.ProtoReflect.Descriptor instead. +func (*UpdateAssetJobsReq) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{19} +} + +func (x *UpdateAssetJobsReq) GetAssetMrn() string { + if x != nil { + return x.AssetMrn + } + return "" +} + +func (x *UpdateAssetJobsReq) GetAssetFilters() []*Mquery { + if x != nil { + return x.AssetFilters + } + return nil +} + +// Store results for a given asset +type StoreResultsReq struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + AssetMrn string `protobuf:"bytes,1,opt,name=asset_mrn,json=assetMrn,proto3" json:"asset_mrn,omitempty"` + Data map[string]*llx.Result `protobuf:"bytes,3,rep,name=data,proto3" json:"data,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` +} + +func (x *StoreResultsReq) Reset() { + *x = StoreResultsReq{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *StoreResultsReq) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*StoreResultsReq) ProtoMessage() {} + +func (x *StoreResultsReq) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use StoreResultsReq.ProtoReflect.Descriptor instead. +func (*StoreResultsReq) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{20} +} + +func (x *StoreResultsReq) GetAssetMrn() string { + if x != nil { + return x.AssetMrn + } + return "" +} + +func (x *StoreResultsReq) GetData() map[string]*llx.Result { + if x != nil { + return x.Data + } + return nil +} + +// Retrieve data for a given set of entities which was previously stored +type EntityDataRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + EntityMrns []string `protobuf:"bytes,1,rep,name=entity_mrns,json=entityMrns,proto3" json:"entity_mrns,omitempty"` + DataMrns []string `protobuf:"bytes,2,rep,name=data_mrns,json=dataMrns,proto3" json:"data_mrns,omitempty"` +} + +func (x *EntityDataRequest) Reset() { + *x = EntityDataRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[21] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *EntityDataRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*EntityDataRequest) ProtoMessage() {} + +func (x *EntityDataRequest) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[21] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use EntityDataRequest.ProtoReflect.Descriptor instead. +func (*EntityDataRequest) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{21} +} + +func (x *EntityDataRequest) GetEntityMrns() []string { + if x != nil { + return x.EntityMrns + } + return nil +} + +func (x *EntityDataRequest) GetDataMrns() []string { + if x != nil { + return x.DataMrns + } + return nil +} + +// The report of all the things collected for an entity (typically asset). +// The provided pack is used as the root to decide what data fields will be returned. +type Report struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + PackMrn string `protobuf:"bytes,1,opt,name=pack_mrn,json=packMrn,proto3" json:"pack_mrn,omitempty"` + EntityMrn string `protobuf:"bytes,2,opt,name=entity_mrn,json=entityMrn,proto3" json:"entity_mrn,omitempty"` + Data map[string]*llx.Result `protobuf:"bytes,5,rep,name=data,proto3" json:"data,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Created int64 `protobuf:"varint,20,opt,name=created,proto3" json:"created,omitempty"` + Modified int64 `protobuf:"varint,21,opt,name=modified,proto3" json:"modified,omitempty"` + ResolvedVersion string `protobuf:"bytes,33,opt,name=resolved_version,json=resolvedVersion,proto3" json:"resolved_version,omitempty"` +} + +func (x *Report) Reset() { + *x = Report{} + if protoimpl.UnsafeEnabled { + mi := &file_explorer_proto_msgTypes[22] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Report) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Report) ProtoMessage() {} + +func (x *Report) ProtoReflect() protoreflect.Message { + mi := &file_explorer_proto_msgTypes[22] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Report.ProtoReflect.Descriptor instead. +func (*Report) Descriptor() ([]byte, []int) { + return file_explorer_proto_rawDescGZIP(), []int{22} +} + +func (x *Report) GetPackMrn() string { + if x != nil { + return x.PackMrn + } + return "" +} + +func (x *Report) GetEntityMrn() string { + if x != nil { + return x.EntityMrn + } + return "" +} + +func (x *Report) GetData() map[string]*llx.Result { + if x != nil { + return x.Data + } + return nil +} + +func (x *Report) GetCreated() int64 { + if x != nil { + return x.Created + } + return 0 +} + +func (x *Report) GetModified() int64 { + if x != nil { + return x.Modified + } + return 0 +} + +func (x *Report) GetResolvedVersion() string { + if x != nil { + return x.ResolvedVersion + } + return "" +} + +var File_explorer_proto protoreflect.FileDescriptor + +var file_explorer_proto_rawDesc = []byte{ + 0x0a, 0x0e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x12, 0x10, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, + 0x65, 0x72, 0x1a, 0x0d, 0x6c, 0x6c, 0x78, 0x2f, 0x6c, 0x6c, 0x78, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x22, 0x58, 0x0a, 0x06, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6d, 0x72, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4d, 0x72, 0x6e, 0x12, 0x31, 0x0a, 0x05, 0x70, 0x61, 0x63, 0x6b, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x50, 0x61, 0x63, 0x6b, 0x52, 0x05, 0x70, 0x61, 0x63, 0x6b, 0x73, 0x22, 0x9c, 0x05, 0x0a, 0x09, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, + 0x18, 0x24, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x6d, + 0x72, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x72, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x6f, + 0x77, 0x6e, 0x65, 0x72, 0x5f, 0x6d, 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x4d, 0x72, 0x6e, 0x12, 0x32, 0x0a, 0x07, 0x71, 0x75, 0x65, 0x72, + 0x69, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x4d, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x52, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, + 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x66, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, + 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, + 0x12, 0x1b, 0x0a, 0x09, 0x69, 0x73, 0x5f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x18, 0x14, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x08, 0x69, 0x73, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x12, 0x18, 0x0a, + 0x07, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, + 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x04, 0x64, 0x6f, 0x63, 0x73, 0x18, + 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, + 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, + 0x63, 0x6b, 0x44, 0x6f, 0x63, 0x73, 0x52, 0x04, 0x64, 0x6f, 0x63, 0x73, 0x12, 0x32, 0x0a, 0x07, + 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x73, 0x18, 0x1e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, + 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, + 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x52, 0x07, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x73, + 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x20, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x6f, + 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x21, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x6f, + 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x39, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x22, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, + 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x63, + 0x6b, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, + 0x73, 0x12, 0x34, 0x0a, 0x16, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x65, + 0x6e, 0x74, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x17, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x14, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x38, 0x0a, 0x18, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x73, 0x75, 0x6d, 0x18, 0x18, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x6c, 0x6f, 0x63, 0x61, 0x6c, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, + 0x6d, 0x1a, 0x37, 0x0a, 0x09, 0x54, 0x61, 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x3f, 0x0a, 0x0a, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x73, 0x12, 0x31, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x50, 0x61, 0x63, 0x6b, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x4b, 0x0a, 0x04, 0x44, + 0x6f, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x65, 0x66, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, + 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, + 0x63, 0x65, 0x52, 0x04, 0x72, 0x65, 0x66, 0x73, 0x22, 0x33, 0x0a, 0x09, 0x52, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, + 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xa3, 0x03, + 0x0a, 0x06, 0x4d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x17, + 0x0a, 0x07, 0x63, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x63, 0x6f, 0x64, 0x65, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x73, 0x75, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x73, 0x75, 0x6d, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x6d, 0x72, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x03, 0x75, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, + 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, + 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x14, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x04, 0x64, + 0x6f, 0x63, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x63, 0x6e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x4d, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x44, 0x6f, 0x63, 0x73, 0x52, 0x04, 0x64, 0x6f, 0x63, 0x73, 0x12, 0x12, 0x0a, + 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x23, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, + 0x63, 0x12, 0x2f, 0x0a, 0x04, 0x72, 0x65, 0x66, 0x73, 0x18, 0x16, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1b, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, + 0x65, 0x72, 0x2e, 0x4d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x66, 0x52, 0x04, 0x72, 0x65, + 0x66, 0x73, 0x12, 0x36, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x22, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x22, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, + 0x72, 0x65, 0x72, 0x2e, 0x4d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x54, 0x61, 0x67, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x54, 0x61, + 0x67, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, + 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, + 0x02, 0x38, 0x01, 0x22, 0x23, 0x0a, 0x0d, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x63, 0x6b, + 0x44, 0x6f, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 0x22, 0x58, 0x0a, 0x0a, 0x4d, 0x71, 0x75, 0x65, + 0x72, 0x79, 0x44, 0x6f, 0x63, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x63, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x63, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x75, + 0x64, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x75, 0x64, 0x69, 0x74, + 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x6d, 0x65, 0x64, 0x69, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x22, 0x32, 0x0a, 0x06, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x12, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x22, 0x33, 0x0a, 0x09, 0x4d, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x52, 0x65, 0x66, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x22, 0xcf, 0x01, 0x0a, 0x0c, + 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x12, 0x1a, 0x0a, 0x08, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x45, 0x0a, 0x07, 0x71, 0x75, 0x65, 0x72, + 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x6e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, + 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x1a, + 0x5c, 0x0a, 0x0c, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x36, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x20, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, + 0x72, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, + 0x72, 0x79, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xa0, 0x02, + 0x0a, 0x0e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, + 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, + 0x75, 0x6d, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, + 0x75, 0x6d, 0x12, 0x50, 0x0a, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, + 0x69, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x70, 0x65, 0x72, + 0x74, 0x69, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, + 0x69, 0x6e, 0x74, 0x73, 0x12, 0x2b, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x6c, 0x6c, 0x78, + 0x2e, 0x43, 0x6f, 0x64, 0x65, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, + 0x65, 0x1a, 0x3d, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x70, 0x65, 0x72, 0x74, 0x69, 0x65, 0x73, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, + 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x17, 0x0a, 0x03, 0x4d, 0x72, 0x6e, + 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x72, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, + 0x72, 0x6e, 0x22, 0x3a, 0x0a, 0x08, 0x4d, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x2e, + 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, + 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, + 0x2e, 0x4d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x3a, + 0x0a, 0x07, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x12, 0x1b, 0x0a, 0x09, 0x6f, 0x77, 0x6e, + 0x65, 0x72, 0x5f, 0x6d, 0x72, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6f, 0x77, + 0x6e, 0x65, 0x72, 0x4d, 0x72, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x46, 0x0a, 0x0a, 0x41, 0x73, + 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, + 0x74, 0x5f, 0x6d, 0x72, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x73, 0x73, + 0x65, 0x74, 0x4d, 0x72, 0x6e, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x6d, 0x72, + 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x63, 0x6b, 0x4d, 0x72, + 0x6e, 0x73, 0x22, 0x6a, 0x0a, 0x0a, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x65, 0x71, + 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6d, 0x72, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x4d, 0x72, 0x6e, 0x12, + 0x3d, 0x0a, 0x0d, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x4d, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x52, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, 0xec, + 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x12, + 0x43, 0x0a, 0x0d, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6a, 0x6f, 0x62, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x69, 0x6f, 0x6e, 0x4a, 0x6f, 0x62, 0x52, 0x0c, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, + 0x6e, 0x4a, 0x6f, 0x62, 0x12, 0x32, 0x0a, 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, + 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x4d, 0x71, 0x75, 0x65, 0x72, 0x79, 0x52, + 0x07, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x38, 0x0a, 0x18, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x68, 0x65, 0x63, + 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x16, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, + 0x75, 0x6d, 0x12, 0x29, 0x0a, 0x10, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x5f, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x66, 0x69, + 0x6c, 0x74, 0x65, 0x72, 0x73, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x22, 0x70, 0x0a, + 0x12, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x73, + 0x52, 0x65, 0x71, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x72, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x72, 0x6e, + 0x12, 0x3d, 0x0a, 0x0d, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, + 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x4d, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x52, 0x0c, 0x61, 0x73, 0x73, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x22, + 0xbd, 0x01, 0x0a, 0x0f, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, + 0x52, 0x65, 0x71, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x6d, 0x72, 0x6e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x73, 0x73, 0x65, 0x74, 0x4d, 0x72, 0x6e, + 0x12, 0x3f, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, + 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, + 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x64, 0x61, 0x74, + 0x61, 0x1a, 0x4c, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, + 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, + 0x12, 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x13, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x6c, 0x6c, 0x78, 0x2e, 0x52, 0x65, + 0x73, 0x75, 0x6c, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, + 0x51, 0x0a, 0x11, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x5f, 0x6d, + 0x72, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x4d, 0x72, 0x6e, 0x73, 0x12, 0x1b, 0x0a, 0x09, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x6d, 0x72, + 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x64, 0x61, 0x74, 0x61, 0x4d, 0x72, + 0x6e, 0x73, 0x22, 0xa9, 0x02, 0x0a, 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x19, 0x0a, + 0x08, 0x70, 0x61, 0x63, 0x6b, 0x5f, 0x6d, 0x72, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x70, 0x61, 0x63, 0x6b, 0x4d, 0x72, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x6e, 0x74, 0x69, + 0x74, 0x79, 0x5f, 0x6d, 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x4d, 0x72, 0x6e, 0x12, 0x36, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, + 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, + 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x6f, 0x64, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x18, 0x15, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x6d, 0x6f, 0x64, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, + 0x64, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x21, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x1a, 0x4c, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x29, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, + 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x6c, 0x6c, 0x78, 0x2e, 0x52, 0x65, 0x73, + 0x75, 0x6c, 0x74, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x32, 0xe4, + 0x03, 0x0a, 0x08, 0x51, 0x75, 0x65, 0x72, 0x79, 0x48, 0x75, 0x62, 0x12, 0x40, 0x0a, 0x09, 0x53, + 0x65, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x18, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, + 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x42, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x1a, 0x17, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, + 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x43, 0x0a, + 0x0f, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x63, 0x6b, + 0x12, 0x15, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, + 0x72, 0x65, 0x72, 0x2e, 0x4d, 0x72, 0x6e, 0x1a, 0x17, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x42, 0x75, + 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x18, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, + 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x1a, 0x17, + 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, + 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x44, 0x0a, 0x0c, 0x47, 0x65, 0x74, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x12, 0x15, 0x2e, 0x63, 0x6e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x4d, 0x72, 0x6e, + 0x1a, 0x1b, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, + 0x72, 0x65, 0x72, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, 0x63, 0x6b, 0x22, 0x00, 0x12, + 0x3e, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x15, 0x2e, 0x63, + 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, + 0x4d, 0x72, 0x6e, 0x1a, 0x18, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, + 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x00, 0x12, + 0x41, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x73, 0x12, 0x15, 0x2e, + 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, + 0x2e, 0x4d, 0x72, 0x6e, 0x1a, 0x1a, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, + 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x4d, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, + 0x22, 0x00, 0x12, 0x41, 0x0a, 0x04, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x19, 0x2e, 0x63, 0x6e, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, + 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x50, 0x61, + 0x63, 0x6b, 0x73, 0x22, 0x00, 0x32, 0xff, 0x04, 0x0a, 0x0e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x43, + 0x6f, 0x6e, 0x64, 0x75, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x41, 0x0a, 0x06, 0x41, 0x73, 0x73, 0x69, + 0x67, 0x6e, 0x12, 0x1c, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, + 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, + 0x1a, 0x17, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, + 0x72, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x08, 0x55, + 0x6e, 0x61, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x12, 0x1c, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, + 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, + 0x12, 0x49, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x12, 0x1c, 0x2e, 0x63, 0x6e, + 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x1e, 0x2e, 0x63, 0x6e, 0x71, 0x75, + 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, + 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x52, 0x0a, 0x0f, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x12, 0x24, + 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, + 0x72, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4a, 0x6f, 0x62, + 0x73, 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, + 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, + 0x5e, 0x0a, 0x14, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x41, 0x6e, 0x64, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4a, 0x6f, 0x62, 0x73, 0x12, 0x24, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x4a, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1e, 0x2e, + 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, 0x64, 0x50, 0x61, 0x63, 0x6b, 0x22, 0x00, 0x12, + 0x4c, 0x0a, 0x0c, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x12, + 0x21, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, + 0x65, 0x72, 0x2e, 0x53, 0x74, 0x6f, 0x72, 0x65, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x52, + 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, + 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x4c, 0x0a, + 0x09, 0x47, 0x65, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x23, 0x2e, 0x63, 0x6e, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x45, 0x6e, + 0x74, 0x69, 0x74, 0x79, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x18, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, + 0x65, 0x72, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x00, 0x12, 0x4a, 0x0a, 0x07, 0x47, + 0x65, 0x74, 0x44, 0x61, 0x74, 0x61, 0x12, 0x23, 0x2e, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, + 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x6e, + 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x2e, 0x52, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x22, 0x00, 0x42, 0x20, 0x5a, 0x1e, 0x67, 0x6f, 0x2e, 0x6d, 0x6f, + 0x6e, 0x64, 0x6f, 0x6f, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6e, 0x71, 0x75, 0x65, 0x72, 0x79, + 0x2f, 0x65, 0x78, 0x70, 0x6c, 0x6f, 0x72, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x33, +} + +var ( + file_explorer_proto_rawDescOnce sync.Once + file_explorer_proto_rawDescData = file_explorer_proto_rawDesc +) + +func file_explorer_proto_rawDescGZIP() []byte { + file_explorer_proto_rawDescOnce.Do(func() { + file_explorer_proto_rawDescData = protoimpl.X.CompressGZIP(file_explorer_proto_rawDescData) + }) + return file_explorer_proto_rawDescData +} + +var file_explorer_proto_msgTypes = make([]protoimpl.MessageInfo, 29) +var file_explorer_proto_goTypes = []interface{}{ + (*Bundle)(nil), // 0: cnquery.explorer.Bundle + (*QueryPack)(nil), // 1: cnquery.explorer.QueryPack + (*QueryPacks)(nil), // 2: cnquery.explorer.QueryPacks + (*Docs)(nil), // 3: cnquery.explorer.Docs + (*Reference)(nil), // 4: cnquery.explorer.Reference + (*Mquery)(nil), // 5: cnquery.explorer.Mquery + (*QueryPackDocs)(nil), // 6: cnquery.explorer.QueryPackDocs + (*MqueryDocs)(nil), // 7: cnquery.explorer.MqueryDocs + (*Author)(nil), // 8: cnquery.explorer.Author + (*MqueryRef)(nil), // 9: cnquery.explorer.MqueryRef + (*ExecutionJob)(nil), // 10: cnquery.explorer.ExecutionJob + (*ExecutionQuery)(nil), // 11: cnquery.explorer.ExecutionQuery + (*Empty)(nil), // 12: cnquery.explorer.Empty + (*Mrn)(nil), // 13: cnquery.explorer.Mrn + (*Mqueries)(nil), // 14: cnquery.explorer.Mqueries + (*ListReq)(nil), // 15: cnquery.explorer.ListReq + (*Assignment)(nil), // 16: cnquery.explorer.Assignment + (*ResolveReq)(nil), // 17: cnquery.explorer.ResolveReq + (*ResolvedPack)(nil), // 18: cnquery.explorer.ResolvedPack + (*UpdateAssetJobsReq)(nil), // 19: cnquery.explorer.UpdateAssetJobsReq + (*StoreResultsReq)(nil), // 20: cnquery.explorer.StoreResultsReq + (*EntityDataRequest)(nil), // 21: cnquery.explorer.EntityDataRequest + (*Report)(nil), // 22: cnquery.explorer.Report + nil, // 23: cnquery.explorer.QueryPack.TagsEntry + nil, // 24: cnquery.explorer.Mquery.TagsEntry + nil, // 25: cnquery.explorer.ExecutionJob.QueriesEntry + nil, // 26: cnquery.explorer.ExecutionQuery.PropertiesEntry + nil, // 27: cnquery.explorer.StoreResultsReq.DataEntry + nil, // 28: cnquery.explorer.Report.DataEntry + (*llx.CodeBundle)(nil), // 29: cnquery.llx.CodeBundle + (*llx.Result)(nil), // 30: cnquery.llx.Result +} +var file_explorer_proto_depIdxs = []int32{ + 1, // 0: cnquery.explorer.Bundle.packs:type_name -> cnquery.explorer.QueryPack + 5, // 1: cnquery.explorer.QueryPack.queries:type_name -> cnquery.explorer.Mquery + 6, // 2: cnquery.explorer.QueryPack.docs:type_name -> cnquery.explorer.QueryPackDocs + 8, // 3: cnquery.explorer.QueryPack.authors:type_name -> cnquery.explorer.Author + 23, // 4: cnquery.explorer.QueryPack.tags:type_name -> cnquery.explorer.QueryPack.TagsEntry + 1, // 5: cnquery.explorer.QueryPacks.items:type_name -> cnquery.explorer.QueryPack + 4, // 6: cnquery.explorer.Docs.refs:type_name -> cnquery.explorer.Reference + 7, // 7: cnquery.explorer.Mquery.docs:type_name -> cnquery.explorer.MqueryDocs + 9, // 8: cnquery.explorer.Mquery.refs:type_name -> cnquery.explorer.MqueryRef + 24, // 9: cnquery.explorer.Mquery.tags:type_name -> cnquery.explorer.Mquery.TagsEntry + 25, // 10: cnquery.explorer.ExecutionJob.queries:type_name -> cnquery.explorer.ExecutionJob.QueriesEntry + 26, // 11: cnquery.explorer.ExecutionQuery.properties:type_name -> cnquery.explorer.ExecutionQuery.PropertiesEntry + 29, // 12: cnquery.explorer.ExecutionQuery.code:type_name -> cnquery.llx.CodeBundle + 5, // 13: cnquery.explorer.Mqueries.items:type_name -> cnquery.explorer.Mquery + 5, // 14: cnquery.explorer.ResolveReq.asset_filters:type_name -> cnquery.explorer.Mquery + 10, // 15: cnquery.explorer.ResolvedPack.execution_job:type_name -> cnquery.explorer.ExecutionJob + 5, // 16: cnquery.explorer.ResolvedPack.filters:type_name -> cnquery.explorer.Mquery + 5, // 17: cnquery.explorer.UpdateAssetJobsReq.asset_filters:type_name -> cnquery.explorer.Mquery + 27, // 18: cnquery.explorer.StoreResultsReq.data:type_name -> cnquery.explorer.StoreResultsReq.DataEntry + 28, // 19: cnquery.explorer.Report.data:type_name -> cnquery.explorer.Report.DataEntry + 11, // 20: cnquery.explorer.ExecutionJob.QueriesEntry.value:type_name -> cnquery.explorer.ExecutionQuery + 30, // 21: cnquery.explorer.StoreResultsReq.DataEntry.value:type_name -> cnquery.llx.Result + 30, // 22: cnquery.explorer.Report.DataEntry.value:type_name -> cnquery.llx.Result + 0, // 23: cnquery.explorer.QueryHub.SetBundle:input_type -> cnquery.explorer.Bundle + 13, // 24: cnquery.explorer.QueryHub.DeleteQueryPack:input_type -> cnquery.explorer.Mrn + 0, // 25: cnquery.explorer.QueryHub.ValidateBundle:input_type -> cnquery.explorer.Bundle + 13, // 26: cnquery.explorer.QueryHub.GetQueryPack:input_type -> cnquery.explorer.Mrn + 13, // 27: cnquery.explorer.QueryHub.GetBundle:input_type -> cnquery.explorer.Mrn + 13, // 28: cnquery.explorer.QueryHub.GetFilters:input_type -> cnquery.explorer.Mrn + 15, // 29: cnquery.explorer.QueryHub.List:input_type -> cnquery.explorer.ListReq + 16, // 30: cnquery.explorer.QueryConductor.Assign:input_type -> cnquery.explorer.Assignment + 16, // 31: cnquery.explorer.QueryConductor.Unassign:input_type -> cnquery.explorer.Assignment + 17, // 32: cnquery.explorer.QueryConductor.Resolve:input_type -> cnquery.explorer.ResolveReq + 19, // 33: cnquery.explorer.QueryConductor.UpdateAssetJobs:input_type -> cnquery.explorer.UpdateAssetJobsReq + 19, // 34: cnquery.explorer.QueryConductor.ResolveAndUpdateJobs:input_type -> cnquery.explorer.UpdateAssetJobsReq + 20, // 35: cnquery.explorer.QueryConductor.StoreResults:input_type -> cnquery.explorer.StoreResultsReq + 21, // 36: cnquery.explorer.QueryConductor.GetReport:input_type -> cnquery.explorer.EntityDataRequest + 21, // 37: cnquery.explorer.QueryConductor.GetData:input_type -> cnquery.explorer.EntityDataRequest + 12, // 38: cnquery.explorer.QueryHub.SetBundle:output_type -> cnquery.explorer.Empty + 12, // 39: cnquery.explorer.QueryHub.DeleteQueryPack:output_type -> cnquery.explorer.Empty + 12, // 40: cnquery.explorer.QueryHub.ValidateBundle:output_type -> cnquery.explorer.Empty + 1, // 41: cnquery.explorer.QueryHub.GetQueryPack:output_type -> cnquery.explorer.QueryPack + 0, // 42: cnquery.explorer.QueryHub.GetBundle:output_type -> cnquery.explorer.Bundle + 14, // 43: cnquery.explorer.QueryHub.GetFilters:output_type -> cnquery.explorer.Mqueries + 2, // 44: cnquery.explorer.QueryHub.List:output_type -> cnquery.explorer.QueryPacks + 12, // 45: cnquery.explorer.QueryConductor.Assign:output_type -> cnquery.explorer.Empty + 12, // 46: cnquery.explorer.QueryConductor.Unassign:output_type -> cnquery.explorer.Empty + 18, // 47: cnquery.explorer.QueryConductor.Resolve:output_type -> cnquery.explorer.ResolvedPack + 12, // 48: cnquery.explorer.QueryConductor.UpdateAssetJobs:output_type -> cnquery.explorer.Empty + 18, // 49: cnquery.explorer.QueryConductor.ResolveAndUpdateJobs:output_type -> cnquery.explorer.ResolvedPack + 12, // 50: cnquery.explorer.QueryConductor.StoreResults:output_type -> cnquery.explorer.Empty + 22, // 51: cnquery.explorer.QueryConductor.GetReport:output_type -> cnquery.explorer.Report + 22, // 52: cnquery.explorer.QueryConductor.GetData:output_type -> cnquery.explorer.Report + 38, // [38:53] is the sub-list for method output_type + 23, // [23:38] is the sub-list for method input_type + 23, // [23:23] is the sub-list for extension type_name + 23, // [23:23] is the sub-list for extension extendee + 0, // [0:23] is the sub-list for field type_name +} + +func init() { file_explorer_proto_init() } +func file_explorer_proto_init() { + if File_explorer_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_explorer_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Bundle); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryPack); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryPacks); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Docs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Reference); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Mquery); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*QueryPackDocs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MqueryDocs); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Author); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*MqueryRef); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecutionJob); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExecutionQuery); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Empty); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Mrn); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Mqueries); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ListReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Assignment); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResolveReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResolvedPack); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UpdateAssetJobsReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StoreResultsReq); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*EntityDataRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_explorer_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Report); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_explorer_proto_rawDesc, + NumEnums: 0, + NumMessages: 29, + NumExtensions: 0, + NumServices: 2, + }, + GoTypes: file_explorer_proto_goTypes, + DependencyIndexes: file_explorer_proto_depIdxs, + MessageInfos: file_explorer_proto_msgTypes, + }.Build() + File_explorer_proto = out.File + file_explorer_proto_rawDesc = nil + file_explorer_proto_goTypes = nil + file_explorer_proto_depIdxs = nil +} diff --git a/explorer/explorer.proto b/explorer/explorer.proto new file mode 100644 index 0000000000..32278e8b8a --- /dev/null +++ b/explorer/explorer.proto @@ -0,0 +1,217 @@ +syntax = "proto3"; + +package cnquery.explorer; +option go_package = "go.mondoo.com/cnquery/explorer"; + +import "llx/llx.proto"; + +message Bundle { + string owner_mrn = 1; + repeated QueryPack packs = 2; +} + +message QueryPack { + // user-defined UID, which is used to generate the MRN + string uid = 36; + // MRN to universally identify this query. + // UIDs are local to QueryPacks, MRNs are global + string mrn = 1; + + string name = 2; + string version = 3; + string owner_mrn = 4; // auto-generated + + repeated Mquery queries = 6; + repeated string filters = 7; + string context = 8; + + bool is_public = 20; + string license = 21; + QueryPackDocs docs = 22; + + repeated Author authors = 30; + int64 created = 32; + int64 modified = 33; + map tags = 34; + + string local_content_checksum = 23; + string local_execution_checksum = 24; +} + +message QueryPacks { + repeated QueryPack items = 1; +} + +message Docs { + string desc = 1; + repeated Reference refs = 2; +} + +message Reference { + string title = 1; + string url = 2; +} + +// Mquery is an MQL query representation +message Mquery { + string query = 1; + string code_id = 2; + string checksum = 3; + string mrn = 4; + // UID is only needed on Mquery upload, when the MRN is computed. + // It will not be persisted. + string uid = 5; + string type = 6; + string context = 7; + string title = 20; + MqueryDocs docs = 21; + string desc = 35; // only used if docs.desc is not defined + repeated MqueryRef refs = 22; + map tags = 34; +} + +message QueryPackDocs { + string desc = 1; +} + +message MqueryDocs { + string desc = 1; + string audit = 2; + string remediation = 3; +} + +message Author { + string name = 1; + string email = 2; +} + +message MqueryRef { + string title = 1; + string url = 2; +} + +// ********** Resolution / Execution ************** + +/* + The list of queries that an asset needs to execute + May be identical amongst multiple packs +*/ +message ExecutionJob { + string checksum = 1; + // map of all queries that should be executed, checksum => query + map queries = 2; +} + +/* + A query which is part of an ExecutionJob + Reduced to the bare minimum for the execution +*/ +message ExecutionQuery { + string query = 1; + string checksum = 2; + // mapping from name => checksum, which is in the execution job + map properties = 3; + // list of checksums that we collect as data points + repeated string datapoints = 4; + cnquery.llx.CodeBundle code = 5; +} + +// ********** Query Hub ************** + +service QueryHub { + rpc SetBundle(Bundle) returns (Empty) {} + rpc DeleteQueryPack(Mrn) returns (Empty) {} + rpc ValidateBundle(Bundle) returns (Empty) {} + rpc GetQueryPack(Mrn) returns (QueryPack) {} + rpc GetBundle(Mrn) returns (Bundle) {} + rpc GetFilters(Mrn) returns (Mqueries) {} + rpc List(ListReq) returns (QueryPacks) {} +} + +message Empty {} + +// MRNs are used to uniquely identify resources. They are globally unique. +message Mrn { + string mrn = 1; +} + +message Mqueries { + repeated Mquery items = 1; +} + +message ListReq { + string owner_mrn = 1; + string name = 2; +} + +// ********** Query Conductor ************** + +service QueryConductor { + rpc Assign(Assignment) returns (Empty) {} + rpc Unassign(Assignment) returns (Empty) {} + + rpc Resolve(ResolveReq) returns (ResolvedPack) {} + // UpdateAssetJobs is used to update the jobs of an asset + rpc UpdateAssetJobs(UpdateAssetJobsReq) returns (Empty) {} + // ResolveAndUpdate is used to update the jobs of an asset and return it + rpc ResolveAndUpdateJobs(UpdateAssetJobsReq) returns (ResolvedPack) {} + + rpc StoreResults(StoreResultsReq) returns (Empty) {} + + rpc GetReport(EntityDataRequest) returns (Report) {} + rpc GetData(EntityDataRequest) returns (Report) {} +} + +// Assign a number of packs to an asset. All of these are identified by MRN. +// Generally query packs are assigned (via MRN). +message Assignment { + string asset_mrn = 1; + repeated string pack_mrns = 2; +} + +// Resolve a given entity via its MRN. Typically used to resolve assets. +// Can also be used to resolve query packs. +message ResolveReq { + string entity_mrn = 1; + repeated Mquery asset_filters = 2; +} + +// ResolvedPack is returned from a resolve request. It includes the execution job +// with all things that need to be run. +message ResolvedPack { + ExecutionJob execution_job = 2; + repeated Mquery filters = 4; + string graph_execution_checksum = 7; + string filters_checksum = 20; +} + +// Update asset jobs forces all jobs for a given asset to get refreshed. +message UpdateAssetJobsReq { + string asset_mrn = 1; + repeated Mquery asset_filters = 2; +} + +// Store results for a given asset +message StoreResultsReq { + string asset_mrn = 1; + map data = 3; +} + +// Retrieve data for a given set of entities which was previously stored +message EntityDataRequest { + repeated string entity_mrns = 1; + repeated string data_mrns = 2; +} + +// The report of all the things collected for an entity (typically asset). +// The provided pack is used as the root to decide what data fields will be returned. +message Report { + string pack_mrn = 1; + string entity_mrn = 2; + map data = 5; + + int64 created = 20; + int64 modified = 21; + + string resolved_version = 33; +} diff --git a/explorer/explorer.ranger.go b/explorer/explorer.ranger.go new file mode 100644 index 0000000000..cc19bbd2e7 --- /dev/null +++ b/explorer/explorer.ranger.go @@ -0,0 +1,612 @@ +// Code generated by protoc-gen-rangerrpc version DO NOT EDIT. +// source: explorer.proto + +package explorer + +import ( + "context" + "errors" + "net/http" + "net/url" + "strings" + + ranger "go.mondoo.com/ranger-rpc" + "go.mondoo.com/ranger-rpc/metadata" + jsonpb "google.golang.org/protobuf/encoding/protojson" + pb "google.golang.org/protobuf/proto" +) + +// service interface definition + +type QueryHub interface { + SetBundle(context.Context, *Bundle) (*Empty, error) + DeleteQueryPack(context.Context, *Mrn) (*Empty, error) + ValidateBundle(context.Context, *Bundle) (*Empty, error) + GetQueryPack(context.Context, *Mrn) (*QueryPack, error) + GetBundle(context.Context, *Mrn) (*Bundle, error) + GetFilters(context.Context, *Mrn) (*Mqueries, error) + List(context.Context, *ListReq) (*QueryPacks, error) +} + +// client implementation + +type QueryHubClient struct { + ranger.Client + httpclient ranger.HTTPClient + prefix string +} + +func NewQueryHubClient(addr string, client ranger.HTTPClient, plugins ...ranger.ClientPlugin) (*QueryHubClient, error) { + base, err := url.Parse(ranger.SanitizeUrl(addr)) + if err != nil { + return nil, err + } + + u, err := url.Parse("./QueryHub") + if err != nil { + return nil, err + } + + serviceClient := &QueryHubClient{ + httpclient: client, + prefix: base.ResolveReference(u).String(), + } + serviceClient.AddPlugins(plugins...) + return serviceClient, nil +} +func (c *QueryHubClient) SetBundle(ctx context.Context, in *Bundle) (*Empty, error) { + out := new(Empty) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/SetBundle"}, ""), in, out) + return out, err +} +func (c *QueryHubClient) DeleteQueryPack(ctx context.Context, in *Mrn) (*Empty, error) { + out := new(Empty) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/DeleteQueryPack"}, ""), in, out) + return out, err +} +func (c *QueryHubClient) ValidateBundle(ctx context.Context, in *Bundle) (*Empty, error) { + out := new(Empty) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/ValidateBundle"}, ""), in, out) + return out, err +} +func (c *QueryHubClient) GetQueryPack(ctx context.Context, in *Mrn) (*QueryPack, error) { + out := new(QueryPack) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/GetQueryPack"}, ""), in, out) + return out, err +} +func (c *QueryHubClient) GetBundle(ctx context.Context, in *Mrn) (*Bundle, error) { + out := new(Bundle) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/GetBundle"}, ""), in, out) + return out, err +} +func (c *QueryHubClient) GetFilters(ctx context.Context, in *Mrn) (*Mqueries, error) { + out := new(Mqueries) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/GetFilters"}, ""), in, out) + return out, err +} +func (c *QueryHubClient) List(ctx context.Context, in *ListReq) (*QueryPacks, error) { + out := new(QueryPacks) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/List"}, ""), in, out) + return out, err +} + +// server implementation + +type QueryHubServerOption func(s *QueryHubServer) + +func WithUnknownFieldsForQueryHubServer() QueryHubServerOption { + return func(s *QueryHubServer) { + s.allowUnknownFields = true + } +} + +func NewQueryHubServer(handler QueryHub, opts ...QueryHubServerOption) http.Handler { + srv := &QueryHubServer{ + handler: handler, + } + + for i := range opts { + opts[i](srv) + } + + service := ranger.Service{ + Name: "QueryHub", + Methods: map[string]ranger.Method{ + "SetBundle": srv.SetBundle, + "DeleteQueryPack": srv.DeleteQueryPack, + "ValidateBundle": srv.ValidateBundle, + "GetQueryPack": srv.GetQueryPack, + "GetBundle": srv.GetBundle, + "GetFilters": srv.GetFilters, + "List": srv.List, + }, + } + return ranger.NewRPCServer(&service) +} + +type QueryHubServer struct { + handler QueryHub + allowUnknownFields bool +} + +func (p *QueryHubServer) SetBundle(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req Bundle + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.SetBundle(ctx, &req) +} +func (p *QueryHubServer) DeleteQueryPack(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req Mrn + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.DeleteQueryPack(ctx, &req) +} +func (p *QueryHubServer) ValidateBundle(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req Bundle + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.ValidateBundle(ctx, &req) +} +func (p *QueryHubServer) GetQueryPack(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req Mrn + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.GetQueryPack(ctx, &req) +} +func (p *QueryHubServer) GetBundle(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req Mrn + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.GetBundle(ctx, &req) +} +func (p *QueryHubServer) GetFilters(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req Mrn + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.GetFilters(ctx, &req) +} +func (p *QueryHubServer) List(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req ListReq + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.List(ctx, &req) +} + +// service interface definition + +type QueryConductor interface { + Assign(context.Context, *Assignment) (*Empty, error) + Unassign(context.Context, *Assignment) (*Empty, error) + Resolve(context.Context, *ResolveReq) (*ResolvedPack, error) + UpdateAssetJobs(context.Context, *UpdateAssetJobsReq) (*Empty, error) + ResolveAndUpdateJobs(context.Context, *UpdateAssetJobsReq) (*ResolvedPack, error) + StoreResults(context.Context, *StoreResultsReq) (*Empty, error) + GetReport(context.Context, *EntityDataRequest) (*Report, error) + GetData(context.Context, *EntityDataRequest) (*Report, error) +} + +// client implementation + +type QueryConductorClient struct { + ranger.Client + httpclient ranger.HTTPClient + prefix string +} + +func NewQueryConductorClient(addr string, client ranger.HTTPClient, plugins ...ranger.ClientPlugin) (*QueryConductorClient, error) { + base, err := url.Parse(ranger.SanitizeUrl(addr)) + if err != nil { + return nil, err + } + + u, err := url.Parse("./QueryConductor") + if err != nil { + return nil, err + } + + serviceClient := &QueryConductorClient{ + httpclient: client, + prefix: base.ResolveReference(u).String(), + } + serviceClient.AddPlugins(plugins...) + return serviceClient, nil +} +func (c *QueryConductorClient) Assign(ctx context.Context, in *Assignment) (*Empty, error) { + out := new(Empty) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/Assign"}, ""), in, out) + return out, err +} +func (c *QueryConductorClient) Unassign(ctx context.Context, in *Assignment) (*Empty, error) { + out := new(Empty) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/Unassign"}, ""), in, out) + return out, err +} +func (c *QueryConductorClient) Resolve(ctx context.Context, in *ResolveReq) (*ResolvedPack, error) { + out := new(ResolvedPack) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/Resolve"}, ""), in, out) + return out, err +} +func (c *QueryConductorClient) UpdateAssetJobs(ctx context.Context, in *UpdateAssetJobsReq) (*Empty, error) { + out := new(Empty) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/UpdateAssetJobs"}, ""), in, out) + return out, err +} +func (c *QueryConductorClient) ResolveAndUpdateJobs(ctx context.Context, in *UpdateAssetJobsReq) (*ResolvedPack, error) { + out := new(ResolvedPack) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/ResolveAndUpdateJobs"}, ""), in, out) + return out, err +} +func (c *QueryConductorClient) StoreResults(ctx context.Context, in *StoreResultsReq) (*Empty, error) { + out := new(Empty) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/StoreResults"}, ""), in, out) + return out, err +} +func (c *QueryConductorClient) GetReport(ctx context.Context, in *EntityDataRequest) (*Report, error) { + out := new(Report) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/GetReport"}, ""), in, out) + return out, err +} +func (c *QueryConductorClient) GetData(ctx context.Context, in *EntityDataRequest) (*Report, error) { + out := new(Report) + err := c.DoClientRequest(ctx, c.httpclient, strings.Join([]string{c.prefix, "/GetData"}, ""), in, out) + return out, err +} + +// server implementation + +type QueryConductorServerOption func(s *QueryConductorServer) + +func WithUnknownFieldsForQueryConductorServer() QueryConductorServerOption { + return func(s *QueryConductorServer) { + s.allowUnknownFields = true + } +} + +func NewQueryConductorServer(handler QueryConductor, opts ...QueryConductorServerOption) http.Handler { + srv := &QueryConductorServer{ + handler: handler, + } + + for i := range opts { + opts[i](srv) + } + + service := ranger.Service{ + Name: "QueryConductor", + Methods: map[string]ranger.Method{ + "Assign": srv.Assign, + "Unassign": srv.Unassign, + "Resolve": srv.Resolve, + "UpdateAssetJobs": srv.UpdateAssetJobs, + "ResolveAndUpdateJobs": srv.ResolveAndUpdateJobs, + "StoreResults": srv.StoreResults, + "GetReport": srv.GetReport, + "GetData": srv.GetData, + }, + } + return ranger.NewRPCServer(&service) +} + +type QueryConductorServer struct { + handler QueryConductor + allowUnknownFields bool +} + +func (p *QueryConductorServer) Assign(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req Assignment + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.Assign(ctx, &req) +} +func (p *QueryConductorServer) Unassign(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req Assignment + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.Unassign(ctx, &req) +} +func (p *QueryConductorServer) Resolve(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req ResolveReq + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.Resolve(ctx, &req) +} +func (p *QueryConductorServer) UpdateAssetJobs(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req UpdateAssetJobsReq + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.UpdateAssetJobs(ctx, &req) +} +func (p *QueryConductorServer) ResolveAndUpdateJobs(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req UpdateAssetJobsReq + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.ResolveAndUpdateJobs(ctx, &req) +} +func (p *QueryConductorServer) StoreResults(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req StoreResultsReq + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.StoreResults(ctx, &req) +} +func (p *QueryConductorServer) GetReport(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req EntityDataRequest + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.GetReport(ctx, &req) +} +func (p *QueryConductorServer) GetData(ctx context.Context, reqBytes *[]byte) (pb.Message, error) { + var req EntityDataRequest + var err error + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return nil, errors.New("could not access header") + } + + switch md.First("Content-Type") { + case "application/protobuf", "application/octet-stream", "application/grpc+proto": + err = pb.Unmarshal(*reqBytes, &req) + default: + // handle case of empty object + if len(*reqBytes) > 0 { + err = jsonpb.UnmarshalOptions{DiscardUnknown: true}.Unmarshal(*reqBytes, &req) + } + } + + if err != nil { + return nil, err + } + return p.handler.GetData(ctx, &req) +} diff --git a/explorer/mquery.go b/explorer/mquery.go new file mode 100644 index 0000000000..a86b44431e --- /dev/null +++ b/explorer/mquery.go @@ -0,0 +1,184 @@ +package explorer + +import ( + "sort" + "strings" + + "github.com/pkg/errors" + "github.com/rs/zerolog/log" + "go.mondoo.com/cnquery" + "go.mondoo.com/cnquery/checksums" + llx "go.mondoo.com/cnquery/llx" + "go.mondoo.com/cnquery/mqlc" + "go.mondoo.com/cnquery/mrn" + "go.mondoo.com/cnquery/resources/packs/all/info" + "go.mondoo.com/cnquery/types" +) + +// Compile a given query and return the bundle. Both v1 and v2 versions are compiled. +// Both versions will be given the same code id. +func (m *Mquery) Compile(props map[string]*llx.Primitive) (*llx.CodeBundle, error) { + if m.Query == "" { + return nil, errors.New("query is not implemented '" + m.Mrn + "'") + } + + schema := info.Registry.Schema() + + v2Code, err := mqlc.Compile(m.Query, schema, + cnquery.Features{byte(cnquery.PiperCode)}, props) + if err != nil { + return nil, err + } + + return v2Code, nil +} + +func RefreshMRN(ownerMRN string, existingMRN string, resource string, uid string) (string, error) { + // NOTE: asset bundles may not have an owner set, therefore we skip if the query already has an mrn + if existingMRN != "" { + if !mrn.IsValid(existingMRN) { + return "", errors.New("invalid MRN: " + existingMRN) + } + return existingMRN, nil + } + + if ownerMRN == "" { + return "", errors.New("cannot refresh MRN if the owner MRN is empty") + } + + if uid == "" { + return "", errors.New("cannot refresh MRN with an empty UID") + } + + mrn, err := mrn.NewChildMRN(ownerMRN, resource, uid) + if err != nil { + return "", err + } + + return mrn.String(), nil +} + +// RefreshMRN computes a MRN from the UID or validates the existing MRN. +// Both of these need to fit the ownerMRN. It also removes the UID. +func (m *Mquery) RefreshMRN(ownerMRN string) error { + nu, err := RefreshMRN(ownerMRN, m.Mrn, MRN_RESOURCE_QUERY, m.Uid) + if err != nil { + log.Error().Err(err).Str("owner", ownerMRN).Str("uid", m.Uid).Msg("failed to refresh mrn") + return errors.Wrap(err, "failed to refresh mrn for query "+m.Title) + } + + m.Mrn = nu + m.Uid = "" + return nil +} + +// RefreshChecksumAndType by compiling the query and updating the Checksum field +func (m *Mquery) RefreshChecksumAndType(props map[string]*llx.Primitive) (*llx.CodeBundle, error) { + return m.refreshChecksumAndType(props) +} + +func (m *Mquery) refreshChecksumAndType(props map[string]*llx.Primitive) (*llx.CodeBundle, error) { + bundle, err := m.Compile(props) + if err != nil { + return bundle, errors.New("failed to compile query '" + m.Query + "': " + err.Error()) + } + + if bundle.GetCodeV2().GetId() == "" { + return bundle, errors.New("failed to compile query: received empty result values") + } + + // We think its ok to always use the new code id + m.CodeId = bundle.CodeV2.Id + + // the compile step also dedents the code + m.Query = bundle.Source + + // TODO: record multiple entrypoints and types + // TODO(jaym): is it possible that the 2 could produce different types + if bundle.DeprecatedV5Code != nil { + if len(bundle.DeprecatedV5Code.Entrypoints) == 1 { + ep := bundle.DeprecatedV5Code.Entrypoints[0] + chunk := bundle.DeprecatedV5Code.Code[ep-1] + typ := chunk.Type() + m.Type = string(typ) + } else { + m.Type = string(types.Any) + } + } else { + if entrypoints := bundle.CodeV2.Entrypoints(); len(entrypoints) == 1 { + ep := entrypoints[0] + chunk := bundle.CodeV2.Chunk(ep) + typ := chunk.Type() + m.Type = string(typ) + } else { + m.Type = string(types.Any) + } + } + + c := checksums.New. + Add(m.Query). + Add(m.CodeId). + Add(bundle.DeprecatedV5Code.GetId()). + Add(m.Mrn). + Add(m.Type). + Add(m.Title).Add("v2") + + if m.Docs != nil { + c = c. + Add(m.Docs.Desc). + Add(m.Docs.Audit). + Add(m.Docs.Remediation) + } + + for i := range m.Refs { + c = c. + Add(m.Refs[i].Title). + Add(m.Refs[i].Url) + } + + keys := make([]string, len(m.Tags)) + i := 0 + for k := range m.Tags { + keys[i] = k + i++ + } + sort.Strings(keys) + for _, k := range keys { + c = c. + Add(k). + Add(m.Tags[k]) + } + + m.Checksum = c.String() + + return bundle, nil +} + +// Sanitize ensure the content is in good shape and removes leading and trailing whitespace +func (m *Mquery) Sanitize() { + if m == nil { + return + } + + if m.Docs != nil { + m.Docs.Desc = strings.TrimSpace(m.Docs.Desc) + m.Docs.Audit = strings.TrimSpace(m.Docs.Audit) + m.Docs.Remediation = strings.TrimSpace(m.Docs.Remediation) + } + + for i := range m.Refs { + r := m.Refs[i] + r.Title = strings.TrimSpace(r.Title) + r.Url = strings.TrimSpace(r.Url) + } + + if m.Tags != nil { + sanitizedTags := map[string]string{} + for k, v := range m.Tags { + sk := strings.TrimSpace(k) + sv := strings.TrimSpace(v) + sanitizedTags[sk] = sv + } + m.Tags = sanitizedTags + } +} diff --git a/explorer/query_hub.go b/explorer/query_hub.go new file mode 100644 index 0000000000..006d7e8cd8 --- /dev/null +++ b/explorer/query_hub.go @@ -0,0 +1,239 @@ +package explorer + +import ( + "context" + "errors" + + "github.com/gogo/status" + "go.mondoo.com/cnquery/logger" + "go.opentelemetry.io/otel" + "google.golang.org/grpc/codes" +) + +var tracer = otel.Tracer("go.mondoo.com/cnquery/explorer") + +// ValidateBundle and check queries, relationships, MRNs, and versions +func (s *LocalServices) ValidateBundle(ctx context.Context, bundle *Bundle) (*Empty, error) { + _, err := bundle.Compile(ctx) + return globalEmpty, err +} + +// SetBundle stores a bundle of policies and queries in this marketplace +func (s *LocalServices) SetBundle(ctx context.Context, bundle *Bundle) (*Empty, error) { + if len(bundle.OwnerMrn) == 0 { + return globalEmpty, status.Error(codes.InvalidArgument, "owner MRN is required") + } + + bundlemap, err := bundle.Compile(ctx) + if err != nil { + return globalEmpty, err + } + + if err := s.setAllQueryPacks(ctx, bundlemap); err != nil { + return nil, err + } + + return globalEmpty, nil +} + +// PreparePack takes a query pack and an optional bundle and gets it +// ready to be saved in the DB, including asset filters. +// Note1: The bundle must have been pre-compiled and validated! +func (s *LocalServices) PreparePack(ctx context.Context, querypack *QueryPack) (*QueryPack, []*Mquery, error) { + logCtx := logger.FromContext(ctx) + + if querypack == nil || len(querypack.Mrn) == 0 { + return nil, nil, status.Error(codes.InvalidArgument, "mrn is required") + } + + if len(querypack.OwnerMrn) == 0 { + return nil, nil, status.Error(codes.InvalidArgument, "owner mrn is required") + } + + // store all queries + for i := range querypack.Queries { + q := querypack.Queries[i] + if err := s.setQuery(ctx, q.Mrn, q, false); err != nil { + return nil, nil, err + } + } + + if querypack.LocalExecutionChecksum == "" || querypack.LocalContentChecksum == "" { + logCtx.Trace().Str("querypack", querypack.Mrn).Msg("hub> update checksum") + if err := querypack.UpdateChecksums(); err != nil { + return nil, nil, err + } + } + + filters, err := querypack.ComputeAssetFilters(ctx) + if err != nil { + return nil, nil, err + } + + return querypack, filters, nil +} + +func (s *LocalServices) setPack(ctx context.Context, querypack *QueryPack) error { + querypack, filters, err := s.PreparePack(ctx, querypack) + if err != nil { + return err + } + + err = s.DataLake.SetQueryPack(ctx, querypack, filters) + if err != nil { + return err + } + + return nil +} + +func (s *LocalServices) setAllQueryPacks(ctx context.Context, bundle *BundleMap) error { + logCtx := logger.FromContext(ctx) + + var err error + for i := range bundle.Packs { + querypack := bundle.Packs[i] + logCtx.Debug().Str("owner", querypack.OwnerMrn).Str("uid", querypack.Uid).Str("mrn", querypack.Mrn).Msg("store query pack") + querypack.OwnerMrn = bundle.OwnerMrn + + // If this is user generated, it must be non-public + if bundle.OwnerMrn != "//querypack.api.mondoo.app" { + querypack.IsPublic = false + } + + if err = s.setPack(ctx, querypack); err != nil { + return err + } + } + + return nil +} + +func (s *LocalServices) setQuery(ctx context.Context, mrn string, query *Mquery, isScored bool) error { + if query == nil { + return errors.New("cannot set query '" + mrn + "' as it is not defined") + } + + if query.Title == "" { + query.Title = query.Query + } + + return s.DataLake.SetQuery(ctx, mrn, query) +} + +// GetQueryPack for a given MRN +func (s *LocalServices) GetQueryPack(ctx context.Context, in *Mrn) (*QueryPack, error) { + logCtx := logger.FromContext(ctx) + + if in == nil || len(in.Mrn) == 0 { + return nil, status.Error(codes.InvalidArgument, "mrn is required") + } + + b, err := s.DataLake.GetQueryPack(ctx, in.Mrn) + if err == nil { + logCtx.Debug().Str("querypack", in.Mrn).Err(err).Msg("query.hub> get query pack from db") + return b, nil + } + if s.Upstream == nil { + return nil, err + } + + // try upstream; once it's cached, try again + _, err = s.cacheUpstreamQueryPack(ctx, in.Mrn) + if err != nil { + return nil, err + } + return s.DataLake.GetQueryPack(ctx, in.Mrn) +} + +// GetBundle retrieves the given bundle and all its dependencies (policies/queries) +func (s *LocalServices) GetBundle(ctx context.Context, in *Mrn) (*Bundle, error) { + if in == nil || len(in.Mrn) == 0 { + return nil, status.Error(codes.InvalidArgument, "mrn is required") + } + + b, err := s.DataLake.GetBundle(ctx, in.Mrn) + if err == nil { + return b, nil + } + if s.Upstream == nil { + return nil, err + } + + // try upstream + return s.cacheUpstreamQueryPack(ctx, in.Mrn) +} + +// GetFilters retrieves the asset filter queries for a given query pack +func (s *LocalServices) GetFilters(ctx context.Context, mrn *Mrn) (*Mqueries, error) { + if mrn == nil || len(mrn.Mrn) == 0 { + return nil, status.Error(codes.InvalidArgument, "mrn is required") + } + + filters, err := s.DataLake.GetQueryPackFilters(ctx, mrn.Mrn) + if err != nil { + return nil, errors.New("failed to get filters: " + err.Error()) + } + + return &Mqueries{Items: filters}, nil +} + +// List all policies for a given owner +func (s *LocalServices) List(ctx context.Context, filter *ListReq) (*QueryPacks, error) { + if filter == nil { + return nil, status.Error(codes.InvalidArgument, "need to provide a filter object for list") + } + + if len(filter.OwnerMrn) == 0 { + return nil, status.Error(codes.InvalidArgument, "a MRN for the owner is required") + } + + res, err := s.DataLake.ListQueryPacks(ctx, filter.OwnerMrn, filter.Name) + if err != nil { + return nil, err + } + if res == nil { + res = []*QueryPack{} + } + + return &QueryPacks{ + Items: res, + }, nil +} + +// DeleteQueryPack removes a query pack via its given MRN +func (s *LocalServices) DeleteQueryPack(ctx context.Context, in *Mrn) (*Empty, error) { + if in == nil || len(in.Mrn) == 0 { + return nil, status.Error(codes.InvalidArgument, "mrn is required") + } + + return globalEmpty, s.DataLake.DeleteQueryPack(ctx, in.Mrn) +} + +// HELPER METHODS +// ================= + +// cacheUpstreamQueryPack by storing a copy of the upstream bundle in this db +// Note: upstream has to be defined +func (s *LocalServices) cacheUpstreamQueryPack(ctx context.Context, mrn string) (*Bundle, error) { + logCtx := logger.FromContext(ctx) + if s.Upstream == nil { + return nil, errors.New("failed to retrieve upstream query pack " + mrn + " since upstream is not defined") + } + + logCtx.Debug().Str("querypack", mrn).Msg("query.hub> fetch bundle from upstream") + bundle, err := s.Upstream.GetBundle(ctx, &Mrn{Mrn: mrn}) + if err != nil { + logCtx.Error().Err(err).Str("querypack", mrn).Msg("query.hub> failed to retrieve bundle from upstream") + return nil, errors.New("failed to retrieve upstream query pack " + mrn + ": " + err.Error()) + } + + _, err = s.SetBundle(ctx, bundle) + if err != nil { + logCtx.Error().Err(err).Str("querypack", mrn).Msg("query.hub> failed to set bundle retrieved from upstream") + return nil, errors.New("failed to cache upstream query pack " + mrn + ": " + err.Error()) + } + + logCtx.Debug().Str("querypack", mrn).Msg("query.hub> fetched bundle from upstream") + return bundle, nil +} diff --git a/explorer/querypack.go b/explorer/querypack.go new file mode 100644 index 0000000000..766ef4133f --- /dev/null +++ b/explorer/querypack.go @@ -0,0 +1,105 @@ +package explorer + +import ( + "context" + "sort" + + "github.com/pkg/errors" + "github.com/rs/zerolog/log" + "go.mondoo.com/cnquery/checksums" +) + +func (p *QueryPack) InvalidateAllChecksums() { + p.LocalContentChecksum = "" + p.LocalExecutionChecksum = "" +} + +// RefreshMRN computes a MRN from the UID or validates the existing MRN. +// Both of these need to fit the ownerMRN. It also removes the UID. +func (p *QueryPack) RefreshMRN(ownerMRN string) error { + nu, err := RefreshMRN(ownerMRN, p.Mrn, "policies", p.Uid) + if err != nil { + log.Error().Err(err).Str("owner", ownerMRN).Str("uid", p.Uid).Msg("failed to refresh mrn") + return errors.Wrap(err, "failed to refresh mrn for query "+p.Name) + } + + p.Mrn = nu + p.Uid = "" + return nil +} + +func (p *QueryPack) UpdateChecksums() error { + p.LocalContentChecksum = "" + p.LocalExecutionChecksum = "" + + // Note: this relies on the fact that the bundle was compiled before + + var i int + executionChecksum := checksums.New + contentChecksum := checksums.New + + contentChecksum = contentChecksum.Add(p.Mrn).Add(p.Name).Add(p.Version).Add(p.OwnerMrn) + if p.IsPublic { + contentChecksum = contentChecksum.AddUint(1) + } else { + contentChecksum = contentChecksum.AddUint(0) + } + for i := range p.Authors { + author := p.Authors[i] + contentChecksum = contentChecksum.Add(author.Email).Add(author.Name) + } + contentChecksum = contentChecksum.AddUint(uint64(p.Created)).AddUint(uint64(p.Modified)) + + if p.Docs != nil { + contentChecksum = contentChecksum.Add(p.Docs.Desc) + } + + executionChecksum = executionChecksum.Add(p.Mrn) + + // tags + arr := make([]string, len(p.Tags)) + i = 0 + for k := range p.Tags { + arr[i] = k + i++ + } + sort.Strings(arr) + for _, k := range arr { + contentChecksum = contentChecksum.Add(k).Add(p.Tags[k]) + } + + // QUERIES (must be sorted) + queryIDs := make([]string, len(p.Queries)) + queries := make(map[string]*Mquery, len(p.Queries)) + for i := range p.Queries { + query := p.Queries[i] + queryIDs[i] = query.Mrn + queries[query.Mrn] = query + } + sort.Strings(queryIDs) + for _, queryID := range queryIDs { + q, ok := queries[queryID] + if !ok { + return errors.New("cannot find query " + queryID) + } + + // we use the checksum for doc, tag and ref changes + contentChecksum = contentChecksum.Add(q.Checksum) + executionChecksum = executionChecksum.Add(q.CodeId) + } + + return nil +} + +// ComputeAssetFilters into mql +func (p *QueryPack) ComputeAssetFilters(ctx context.Context) ([]*Mquery, error) { + res := make([]*Mquery, len(p.Filters)) + for i := range p.Filters { + code := p.Filters[i] + res[i] = &Mquery{ + Query: code, + } + } + + return res, nil +} diff --git a/explorer/services.go b/explorer/services.go new file mode 100644 index 0000000000..724d211fc6 --- /dev/null +++ b/explorer/services.go @@ -0,0 +1,35 @@ +package explorer + +type ResolvedVersion string + +const ( + PreMassResolved ResolvedVersion = "v0" + MassResolved ResolvedVersion = "v1" + V2Code ResolvedVersion = "v2" +) + +var globalEmpty = &Empty{} + +type Services struct { + QueryHub + QueryConductor +} + +// LocalServices is a bundle of all the services for handling policies. +// It has an optional upstream-handler embedded. If a local service does not +// yield results for a request, and the upstream handler is defined, it will +// be used instead. +type LocalServices struct { + DataLake DataLake + Upstream *Services + Incognito bool +} + +// NewLocalServices initializes a reasonably configured local services struct +func NewLocalServices(datalake DataLake, uuid string) *LocalServices { + return &LocalServices{ + DataLake: datalake, + Upstream: nil, + Incognito: false, + } +} diff --git a/go.mod b/go.mod index 7eb0113691..0683ca210c 100644 --- a/go.mod +++ b/go.mod @@ -71,6 +71,7 @@ require ( github.com/docker/docker v20.10.17+incompatible github.com/gobwas/glob v0.2.3 github.com/gofrs/uuid v4.2.0+incompatible + github.com/gogo/status v1.1.0 github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang/mock v1.6.0 github.com/golangci/golangci-lint v1.49.0 @@ -127,6 +128,7 @@ require ( github.com/xanzy/go-gitlab v0.73.1 github.com/zclconf/go-cty v1.11.0 go.mondoo.com/ranger-rpc v0.5.1-0.20220923135836-9e7732899d34 + go.opentelemetry.io/otel v1.10.0 golang.org/x/crypto v0.0.0-20220919173607-35f4265a4bc0 golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b golang.org/x/oauth2 v0.0.0-20220822191816-0ebed06d0094 @@ -239,6 +241,7 @@ require ( github.com/go-critic/go-critic v0.6.5 // indirect github.com/go-errors/errors v1.1.1 // indirect github.com/go-logr/logr v1.2.3 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.20.0 // indirect @@ -253,6 +256,7 @@ require ( github.com/go-xmlfmt/xmlfmt v1.1.2 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/flock v0.8.1 // indirect + github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt/v4 v4.4.1 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -426,6 +430,7 @@ require ( github.com/yosida95/uritemplate/v3 v3.0.2 // indirect gitlab.com/bosi/decorder v0.2.3 // indirect go.opencensus.io v0.23.0 // indirect + go.opentelemetry.io/otel/trace v1.10.0 // indirect go.uber.org/atomic v1.10.0 // indirect go.uber.org/goleak v1.1.12 // indirect go.uber.org/multierr v1.8.0 // indirect diff --git a/go.sum b/go.sum index 57cfea87a9..692d45bdbd 100644 --- a/go.sum +++ b/go.sum @@ -527,9 +527,11 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= @@ -587,6 +589,7 @@ github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14j github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -595,6 +598,7 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/gogo/status v1.1.0 h1:+eIkrewn5q6b30y+g/BJINVVdi2xH7je5MPJ3ZPK3JA= github.com/gogo/status v1.1.0/go.mod h1:BFv9nrluPLmrS0EmGVvLaPNmRosr9KapBYd5/hpY1WM= github.com/golang-jwt/jwt v3.2.1+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= @@ -1601,7 +1605,9 @@ go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opentelemetry.io/otel v1.10.0 h1:Y7DTJMR6zs1xkS/upamJYk0SxxN4C9AqRd77jmZnyY4= +go.opentelemetry.io/otel v1.10.0/go.mod h1:NbvWjCthWHKBEUMpf0/v8ZRZlni86PpGFEMA9pnQSnQ= go.opentelemetry.io/otel/trace v1.10.0 h1:npQMbR8o7mum8uF95yFbOEJffhs1sbCOfDh8zAJiH5E= +go.opentelemetry.io/otel/trace v1.10.0/go.mod h1:Sij3YYczqAdz+EhmGhE6TpTxUO5/F/AzrK+kxfGqySM= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=