From 0617348eeb2a7103583c7d99df287d0c03191522 Mon Sep 17 00:00:00 2001 From: Mike Cohen Date: Wed, 26 May 2021 22:05:54 +1000 Subject: [PATCH] Artifacts can now specify a custom notebook. (#1079) When they are collected in a flow or a hunt, the artifacts can specify a new template to be created in the notebook tab. This allows artifacts to create specialized post processing content using the notebook reporting. --- api/api.go | 148 ----- api/hunts.go | 155 +++++ api/notebooks.go | 260 ++++++-- api/proto/api.pb.gw.go | 10 +- api/proto/notebooks.pb.go | 470 +++++++++---- api/proto/notebooks.proto | 23 + .../Detection/EnvironmentVariables.yaml | 50 +- artifacts/proto/artifact.pb.go | 622 ++++++++++-------- artifacts/proto/artifact.proto | 9 + .../src/components/core/paged-table.js | 9 +- .../src/components/flows/flow-notebook.js | 27 +- .../src/components/hunts/hunt-list.js | 5 +- .../src/components/hunts/hunt-notebook.js | 32 +- .../notebooks/notebook-cell-renderer.js | 11 +- .../components/notebooks/notebook-renderer.js | 3 +- .../notebooks/notebook-report-renderer.js | 38 +- .../notebooks/notebook-table-renderer.js | 2 + reporting/cell_test.go | 49 ++ reporting/cells.go | 72 ++ .../fixtures/VQL2MarkdownConversion.golden | 23 + reporting/gui.go | 5 +- services/repository.go | 3 + services/repository/repository.go | 17 + 23 files changed, 1367 insertions(+), 676 deletions(-) create mode 100644 reporting/cell_test.go create mode 100644 reporting/cells.go create mode 100644 reporting/fixtures/VQL2MarkdownConversion.golden diff --git a/api/api.go b/api/api.go index 10e2aaf55fa..4d546a2e95b 100644 --- a/api/api.go +++ b/api/api.go @@ -241,154 +241,6 @@ func (self *ApiServer) CollectArtifact( return result, nil } -func (self *ApiServer) CreateHunt( - ctx context.Context, - in *api_proto.Hunt) (*api_proto.StartFlowResponse, error) { - - defer Instrument("CreateHunt")() - - // Log this event as an Audit event. - in.Creator = GetGRPCUserInfo(self.config, ctx).Name - in.HuntId = flows.GetNewHuntId() - - acl_manager := vql_subsystem.NewServerACLManager(self.config, in.Creator) - - permissions := acls.COLLECT_CLIENT - perm, err := acls.CheckAccess(self.config, in.Creator, permissions) - if !perm || err != nil { - return nil, status.Error(codes.PermissionDenied, - "User is not allowed to launch hunts.") - } - - logging.GetLogger(self.config, &logging.Audit). - WithFields(logrus.Fields{ - "user": in.Creator, - "hunt_id": in.HuntId, - "details": fmt.Sprintf("%v", in), - }).Info("CreateHunt") - - result := &api_proto.StartFlowResponse{} - hunt_id, err := flows.CreateHunt( - ctx, self.config, acl_manager, in) - if err != nil { - return nil, err - } - - result.FlowId = hunt_id - - return result, nil -} - -func (self *ApiServer) ModifyHunt( - ctx context.Context, - in *api_proto.Hunt) (*empty.Empty, error) { - - defer Instrument("ModifyHunt")() - - // Log this event as an Audit event. - in.Creator = GetGRPCUserInfo(self.config, ctx).Name - - permissions := acls.COLLECT_CLIENT - perm, err := acls.CheckAccess(self.config, in.Creator, permissions) - if !perm || err != nil { - return nil, status.Error(codes.PermissionDenied, - "User is not allowed to modify hunts.") - } - - logging.GetLogger(self.config, &logging.Audit). - WithFields(logrus.Fields{ - "user": in.Creator, - "hunt_id": in.HuntId, - "details": fmt.Sprintf("%v", in), - }).Info("ModifyHunt") - - err = flows.ModifyHunt(ctx, self.config, in, in.Creator) - if err != nil { - return nil, err - } - - result := &empty.Empty{} - return result, nil -} - -func (self *ApiServer) ListHunts( - ctx context.Context, - in *api_proto.ListHuntsRequest) (*api_proto.ListHuntsResponse, error) { - - defer Instrument("ListHunts")() - - user_name := GetGRPCUserInfo(self.config, ctx).Name - permissions := acls.READ_RESULTS - perm, err := acls.CheckAccess(self.config, user_name, permissions) - if !perm || err != nil { - return nil, status.Error(codes.PermissionDenied, - "User is not allowed to view hunts.") - } - - result, err := flows.ListHunts(self.config, in) - if err != nil { - return nil, err - } - - return result, nil -} - -func (self *ApiServer) GetHunt( - ctx context.Context, - in *api_proto.GetHuntRequest) (*api_proto.Hunt, error) { - if in.HuntId == "" { - return &api_proto.Hunt{}, nil - } - - defer Instrument("GetHunt")() - - user_name := GetGRPCUserInfo(self.config, ctx).Name - permissions := acls.READ_RESULTS - perm, err := acls.CheckAccess(self.config, user_name, permissions) - if !perm || err != nil { - return nil, status.Error(codes.PermissionDenied, - "User is not allowed to view hunts.") - } - - result, err := flows.GetHunt(self.config, in) - if err != nil { - return nil, err - } - - return result, nil -} - -func (self *ApiServer) GetHuntResults( - ctx context.Context, - in *api_proto.GetHuntResultsRequest) (*api_proto.GetTableResponse, error) { - - defer Instrument("GetHuntResults")() - - user_name := GetGRPCUserInfo(self.config, ctx).Name - permissions := acls.READ_RESULTS - perm, err := acls.CheckAccess(self.config, user_name, permissions) - if !perm || err != nil { - return nil, status.Error(codes.PermissionDenied, - "User is not allowed to view results.") - } - - env := ordereddict.NewDict(). - Set("HuntID", in.HuntId). - Set("ArtifactName", in.Artifact) - - // More than 100 results are not very useful in the GUI - - // users should just download the json file for post - // processing or process in the notebook. - result, err := RunVQL(ctx, self.config, user_name, env, - "SELECT * FROM hunt_results(hunt_id=HuntID, "+ - "artifact=ArtifactName) LIMIT 100") - if err != nil { - return nil, err - } - - return result, nil -} - func (self *ApiServer) ListClients( ctx context.Context, in *api_proto.SearchClientsRequest) (*api_proto.SearchClientsResponse, error) { diff --git a/api/hunts.go b/api/hunts.go index 9d8d4bad9be..cea25e4784a 100644 --- a/api/hunts.go +++ b/api/hunts.go @@ -1,6 +1,11 @@ package api import ( + "fmt" + + "github.com/Velocidex/ordereddict" + "github.com/golang/protobuf/ptypes/empty" + "github.com/sirupsen/logrus" context "golang.org/x/net/context" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -10,9 +15,11 @@ import ( "www.velocidex.com/golang/velociraptor/file_store/csv" "www.velocidex.com/golang/velociraptor/file_store/result_sets" "www.velocidex.com/golang/velociraptor/flows" + "www.velocidex.com/golang/velociraptor/logging" "www.velocidex.com/golang/velociraptor/paths" "www.velocidex.com/golang/velociraptor/services" "www.velocidex.com/golang/velociraptor/utils" + vql_subsystem "www.velocidex.com/golang/velociraptor/vql" ) func (self *ApiServer) GetHuntFlows( @@ -75,3 +82,151 @@ func (self *ApiServer) GetHuntFlows( } return result, nil } + +func (self *ApiServer) CreateHunt( + ctx context.Context, + in *api_proto.Hunt) (*api_proto.StartFlowResponse, error) { + + defer Instrument("CreateHunt")() + + // Log this event as an Audit event. + in.Creator = GetGRPCUserInfo(self.config, ctx).Name + in.HuntId = flows.GetNewHuntId() + + acl_manager := vql_subsystem.NewServerACLManager(self.config, in.Creator) + + permissions := acls.COLLECT_CLIENT + perm, err := acls.CheckAccess(self.config, in.Creator, permissions) + if !perm || err != nil { + return nil, status.Error(codes.PermissionDenied, + "User is not allowed to launch hunts.") + } + + logging.GetLogger(self.config, &logging.Audit). + WithFields(logrus.Fields{ + "user": in.Creator, + "hunt_id": in.HuntId, + "details": fmt.Sprintf("%v", in), + }).Info("CreateHunt") + + result := &api_proto.StartFlowResponse{} + hunt_id, err := flows.CreateHunt( + ctx, self.config, acl_manager, in) + if err != nil { + return nil, err + } + + result.FlowId = hunt_id + + return result, nil +} + +func (self *ApiServer) ModifyHunt( + ctx context.Context, + in *api_proto.Hunt) (*empty.Empty, error) { + + defer Instrument("ModifyHunt")() + + // Log this event as an Audit event. + in.Creator = GetGRPCUserInfo(self.config, ctx).Name + + permissions := acls.COLLECT_CLIENT + perm, err := acls.CheckAccess(self.config, in.Creator, permissions) + if !perm || err != nil { + return nil, status.Error(codes.PermissionDenied, + "User is not allowed to modify hunts.") + } + + logging.GetLogger(self.config, &logging.Audit). + WithFields(logrus.Fields{ + "user": in.Creator, + "hunt_id": in.HuntId, + "details": fmt.Sprintf("%v", in), + }).Info("ModifyHunt") + + err = flows.ModifyHunt(ctx, self.config, in, in.Creator) + if err != nil { + return nil, err + } + + result := &empty.Empty{} + return result, nil +} + +func (self *ApiServer) ListHunts( + ctx context.Context, + in *api_proto.ListHuntsRequest) (*api_proto.ListHuntsResponse, error) { + + defer Instrument("ListHunts")() + + user_name := GetGRPCUserInfo(self.config, ctx).Name + permissions := acls.READ_RESULTS + perm, err := acls.CheckAccess(self.config, user_name, permissions) + if !perm || err != nil { + return nil, status.Error(codes.PermissionDenied, + "User is not allowed to view hunts.") + } + + result, err := flows.ListHunts(self.config, in) + if err != nil { + return nil, err + } + + return result, nil +} + +func (self *ApiServer) GetHunt( + ctx context.Context, + in *api_proto.GetHuntRequest) (*api_proto.Hunt, error) { + if in.HuntId == "" { + return &api_proto.Hunt{}, nil + } + + defer Instrument("GetHunt")() + + user_name := GetGRPCUserInfo(self.config, ctx).Name + permissions := acls.READ_RESULTS + perm, err := acls.CheckAccess(self.config, user_name, permissions) + if !perm || err != nil { + return nil, status.Error(codes.PermissionDenied, + "User is not allowed to view hunts.") + } + + result, err := flows.GetHunt(self.config, in) + if err != nil { + return nil, err + } + + return result, nil +} + +func (self *ApiServer) GetHuntResults( + ctx context.Context, + in *api_proto.GetHuntResultsRequest) (*api_proto.GetTableResponse, error) { + + defer Instrument("GetHuntResults")() + + user_name := GetGRPCUserInfo(self.config, ctx).Name + permissions := acls.READ_RESULTS + perm, err := acls.CheckAccess(self.config, user_name, permissions) + if !perm || err != nil { + return nil, status.Error(codes.PermissionDenied, + "User is not allowed to view results.") + } + + env := ordereddict.NewDict(). + Set("HuntID", in.HuntId). + Set("ArtifactName", in.Artifact) + + // More than 100 results are not very useful in the GUI - + // users should just download the json file for post + // processing or process in the notebook. + result, err := RunVQL(ctx, self.config, user_name, env, + "SELECT * FROM hunt_results(hunt_id=HuntID, "+ + "artifact=ArtifactName) LIMIT 100") + if err != nil { + return nil, err + } + + return result, nil +} diff --git a/api/notebooks.go b/api/notebooks.go index 5390004a8b6..89796cb4c08 100644 --- a/api/notebooks.go +++ b/api/notebooks.go @@ -24,6 +24,7 @@ import ( config_proto "www.velocidex.com/golang/velociraptor/config/proto" "www.velocidex.com/golang/velociraptor/datastore" file_store "www.velocidex.com/golang/velociraptor/file_store" + "www.velocidex.com/golang/velociraptor/flows" "www.velocidex.com/golang/velociraptor/json" "www.velocidex.com/golang/velociraptor/logging" "www.velocidex.com/golang/velociraptor/reporting" @@ -172,37 +173,28 @@ func (self *ApiServer) NewNotebook( in.CreatedTime = time.Now().Unix() in.ModifiedTime = in.CreatedTime - // Allow hunt notebooks to be created with specified hunt ID. + // Allow hunt notebooks to be created with a specified hunt ID. if !strings.HasPrefix(in.NotebookId, "N.H.") && !strings.HasPrefix(in.NotebookId, "N.F.") { in.NotebookId = NewNotebookId() } - new_cell_id := NewNotebookCellId() - - in.CellMetadata = append(in.CellMetadata, &api_proto.NotebookCell{ - CellId: new_cell_id, - Timestamp: time.Now().Unix(), - }) - db, err := datastore.GetDB(self.config) if err != nil { return nil, err } + // Store the notebook metadata first before creating the + // cells. Calculating the cells will try to open the notebook. notebook_path_manager := reporting.NewNotebookPathManager(in.NotebookId) err = db.SetSubject(self.config, notebook_path_manager.Path(), in) if err != nil { return nil, err } - // Add a new single cell to the notebook. - new_cell_request := &api_proto.NotebookCellRequest{ - Input: fmt.Sprintf("# %s\n\n%s\n", in.Name, in.Description), - NotebookId: in.NotebookId, - CellId: new_cell_id, - Type: "Markdown", - CurrentlyEditing: true, + err = self.createInitialNotebook(ctx, user_name, in) + if err != nil { + return nil, err } // Add the new notebook to the index so it can be seen. Only @@ -213,14 +205,143 @@ func (self *ApiServer) NewNotebook( return nil, err } - _, err = self.UpdateNotebookCell(ctx, new_cell_request) + err = db.SetSubject(self.config, notebook_path_manager.Path(), in) + return in, err +} + +// Create the initial cells of the notebook. +func (self *ApiServer) createInitialNotebook( + ctx context.Context, + user_name string, + notebook_metadata *api_proto.NotebookMetadata) error { + + // All cells receive a header from the name and description of + // the notebook. + new_cells := []*api_proto.NotebookCellRequest{{ + Input: fmt.Sprintf("# %s\n\n%s\n", notebook_metadata.Name, + notebook_metadata.Description), + Type: "Markdown", + CurrentlyEditing: true, + }} + + if notebook_metadata.Context != nil { + if notebook_metadata.Context.HuntId != "" { + new_cells = getCellsForHunt(ctx, self.config, + notebook_metadata.Context.HuntId, notebook_metadata) + } else if notebook_metadata.Context.FlowId != "" && + notebook_metadata.Context.ClientId != "" { + new_cells = getCellsForFlow(ctx, self.config, + notebook_metadata.Context.ClientId, + notebook_metadata.Context.FlowId, notebook_metadata) + } + } + + for _, cell := range new_cells { + new_cell_id := NewNotebookCellId() + + notebook_metadata.CellMetadata = append(notebook_metadata.CellMetadata, &api_proto.NotebookCell{ + CellId: new_cell_id, + Env: cell.Env, + Timestamp: time.Now().Unix(), + }) + cell.NotebookId = notebook_metadata.NotebookId + cell.CellId = new_cell_id + + _, err := self.updateNotebookCell(ctx, notebook_metadata, user_name, cell) + if err != nil { + return err + } + } + return nil +} + +func getCellsForHunt(ctx context.Context, + config_obj *config_proto.Config, + hunt_id string, + notebook_metadata *api_proto.NotebookMetadata) []*api_proto.NotebookCellRequest { + + dispatcher := services.GetHuntDispatcher() + if dispatcher == nil { + return nil + } + + hunt_obj, pres := dispatcher.GetHunt(hunt_id) + if !pres { + return nil + } + sources := hunt_obj.ArtifactSources + if len(sources) == 0 { + if hunt_obj.StartRequest != nil { + sources = hunt_obj.StartRequest.Artifacts + } else { + return nil + } + } + + return getDefaultCellsForSources(config_obj, sources) +} + +func getCellsForFlow(ctx context.Context, + config_obj *config_proto.Config, + client_id, flow_id string, + notebook_metadata *api_proto.NotebookMetadata) []*api_proto.NotebookCellRequest { + + flow_context, err := flows.LoadCollectionContext(config_obj, client_id, flow_id) if err != nil { - return nil, err + return nil } - notebook := &api_proto.NotebookMetadata{} - err = db.GetSubject(self.config, notebook_path_manager.Path(), notebook) - return notebook, err + return getDefaultCellsForSources(config_obj, flow_context.ArtifactsWithResults) +} + +func getDefaultCellsForSources(config_obj *config_proto.Config, + sources []string) []*api_proto.NotebookCellRequest { + manager, err := services.GetRepositoryManager() + if err != nil { + return nil + } + + repository, err := manager.GetGlobalRepository(config_obj) + if err != nil { + return nil + } + + // Create one table per artifact by default. + var result []*api_proto.NotebookCellRequest + + for _, source := range sources { + // Check if the artifact has custom notebook cells defined. + artifact_source, pres := repository.GetSource(config_obj, source) + if !pres { + continue + } + env := []*api_proto.Env{{Key: "ArtifactName", Value: source}} + + // If the artifact_source defines a notebook, let it do its own thing. + if len(artifact_source.Notebook) > 0 { + for _, cell := range artifact_source.Notebook { + result = append(result, &api_proto.NotebookCellRequest{ + Type: cell.Type, + Env: env, + Input: cell.Template}) + } + + } else { + // Otherwise build a default notebook. + result = append(result, &api_proto.NotebookCellRequest{ + Type: "Markdown", + Env: env, + Input: "# " + source}) + + result = append(result, &api_proto.NotebookCellRequest{ + Type: "VQL", + Env: env, + Input: "\nSELECT * FROM source()\nLIMIT 50\n", + }) + } + } + + return result } func (self *ApiServer) NewNotebookCell( @@ -310,6 +431,7 @@ func (self *ApiServer) NewNotebookCell( NotebookId: in.NotebookId, CellId: notebook.LatestCellId, Type: in.Type, + Env: in.Env, // New cells are opened for editing. CurrentlyEditing: true, @@ -486,6 +608,33 @@ func (self *ApiServer) UpdateNotebookCell( "User is not allowed to edit notebooks.") } + // Check that the user has access to this notebook. + notebook_path_manager := reporting.NewNotebookPathManager(in.NotebookId) + notebook_metadata := &api_proto.NotebookMetadata{} + db, err := datastore.GetDB(self.config) + if err != nil { + return nil, err + } + + err = db.GetSubject(self.config, + notebook_path_manager.Path(), notebook_metadata) + if err != nil { + return nil, err + } + + if !reporting.CheckNotebookAccess(notebook_metadata, user_record.Name) { + return nil, errors.New("Notebook is not shared with user.") + } + + return self.updateNotebookCell(ctx, notebook_metadata, user_name, in) +} + +func (self *ApiServer) updateNotebookCell( + ctx context.Context, + notebook_metadata *api_proto.NotebookMetadata, + user_name string, + in *api_proto.NotebookCellRequest) (*api_proto.NotebookCell, error) { + notebook_cell := &api_proto.NotebookCell{ Input: in.Input, Output: `
Calculating...
`, @@ -494,24 +643,16 @@ func (self *ApiServer) UpdateNotebookCell( Timestamp: time.Now().Unix(), CurrentlyEditing: in.CurrentlyEditing, Calculating: true, + Env: in.Env, } - db, _ := datastore.GetDB(self.config) - - // Check that the user has access to this notebook. - notebook_path_manager := reporting.NewNotebookPathManager(in.NotebookId) - notebook_metadata := &api_proto.NotebookMetadata{} - err = db.GetSubject(self.config, - notebook_path_manager.Path(), notebook_metadata) + db, err := datastore.GetDB(self.config) if err != nil { return nil, err } - if !reporting.CheckNotebookAccess(notebook_metadata, user_record.Name) { - return nil, errors.New("Notebook is not shared with user.") - } - // And store it for next time. + notebook_path_manager := reporting.NewNotebookPathManager(notebook_metadata.NotebookId) err = db.SetSubject(self.config, notebook_path_manager.Cell(in.CellId).Path(), notebook_cell) @@ -550,32 +691,19 @@ func (self *ApiServer) UpdateNotebookCell( start: time.Now(), } - input := in.Input - cell_type := in.Type - - // For artifacts we parse and check the artifact in the main - // thread so we can return errors to the user - // immediately. Ultimately the artifact will be converted to a - // VQL query to run which we pass to the template engine - // asynchronously. - if in.Type == "Artifact" { - // New artifacts are added to a temporary repository - // so they do not affect the global one. - repository := global_repo.Copy() - artifact_obj, err := repository.LoadYaml(input, true /* validate */) - if err != nil { - return nil, err - } + // Add the notebook environment into the cell template. + for _, env := range notebook_metadata.Env { + tmpl.SetEnv(env.Key, env.Value) + } - // Update the artifact plugin in the template. - /* FIXME - artifact_plugin := artifacts.NewArtifactRepositoryPlugin(repository) - tmpl.Env.Set("Artifact", artifact_plugin) - */ - input = fmt.Sprintf(`{{ Query "SELECT * FROM Artifact.%v()" | Table}}`, - artifact_obj.Name) + // Also apply the cell env + for _, env := range in.Env { + tmpl.SetEnv(env.Key, env.Value) } + input := in.Input + cell_type := in.Type + // Update the content asynchronously start_time := time.Now() @@ -626,7 +754,7 @@ func (self *ApiServer) UpdateNotebookCell( resp, err := updateCellContents(query_ctx, self.config, tmpl, in.CurrentlyEditing, in.NotebookId, - in.CellId, cell_type, input, in.Input) + in.CellId, cell_type, in.Env, input, in.Input) if err != nil { main_err = err logger := logging.GetLogger(self.config, &logging.GUIComponent) @@ -925,6 +1053,7 @@ func updateCellContents( tmpl *reporting.GuiTemplateEngine, currently_editing bool, notebook_id, cell_id, cell_type string, + env []*api_proto.Env, input, original_input string) (*api_proto.NotebookCell, error) { // Do not let exceptions take down the server. @@ -935,20 +1064,22 @@ func updateCellContents( switch cell_type { - case "Markdown", "Artifact": - output, err = tmpl.Execute( - &artifacts_proto.Report{Template: input}) + case "Markdown": + // A Markdown cell just feeds directly into the + // template. + output, err = tmpl.Execute(&artifacts_proto.Report{Template: input}) if err != nil { return nil, err } case "VQL": - if input != "" { - rows := tmpl.Query(input) - output_any, ok := tmpl.Table(rows).(string) - if ok { - output = output_any - } + // A VQL cell gets converted to a normal template + // first. + content, env := reporting.ConvertVQLCellToMarkdownCell(input) + tmpl.Env.MergeFrom(env) + output, err = tmpl.Execute(&artifacts_proto.Report{Template: content}) + if err != nil { + return nil, err } default: @@ -969,6 +1100,7 @@ func updateCellContents( Messages: tmpl.Messages(), CellId: cell_id, Type: cell_type, + Env: env, Timestamp: time.Now().Unix(), CurrentlyEditing: currently_editing, Duration: int64(time.Since(tmpl.Start).Seconds()), diff --git a/api/proto/api.pb.gw.go b/api/proto/api.pb.gw.go index 4a9dbeecbdc..2c3fad84faa 100644 --- a/api/proto/api.pb.gw.go +++ b/api/proto/api.pb.gw.go @@ -22,7 +22,7 @@ import ( "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" "google.golang.org/protobuf/proto" - proto_6 "www.velocidex.com/golang/velociraptor/artifacts/proto" + proto_5 "www.velocidex.com/golang/velociraptor/artifacts/proto" proto_3 "www.velocidex.com/golang/velociraptor/flows/proto" ) @@ -1283,7 +1283,7 @@ var ( ) func request_API_GetToolInfo_0(ctx context.Context, marshaler runtime.Marshaler, client APIClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq proto_6.Tool + var protoReq proto_5.Tool var metadata runtime.ServerMetadata if err := req.ParseForm(); err != nil { @@ -1299,7 +1299,7 @@ func request_API_GetToolInfo_0(ctx context.Context, marshaler runtime.Marshaler, } func local_request_API_GetToolInfo_0(ctx context.Context, marshaler runtime.Marshaler, server APIServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq proto_6.Tool + var protoReq proto_5.Tool var metadata runtime.ServerMetadata if err := req.ParseForm(); err != nil { @@ -1315,7 +1315,7 @@ func local_request_API_GetToolInfo_0(ctx context.Context, marshaler runtime.Mars } func request_API_SetToolInfo_0(ctx context.Context, marshaler runtime.Marshaler, client APIClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq proto_6.Tool + var protoReq proto_5.Tool var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) @@ -1332,7 +1332,7 @@ func request_API_SetToolInfo_0(ctx context.Context, marshaler runtime.Marshaler, } func local_request_API_SetToolInfo_0(ctx context.Context, marshaler runtime.Marshaler, server APIServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq proto_6.Tool + var protoReq proto_5.Tool var metadata runtime.ServerMetadata newReader, berr := utilities.IOReaderFactory(req.Body) diff --git a/api/proto/notebooks.pb.go b/api/proto/notebooks.pb.go index d63249c9071..7699e02072c 100644 --- a/api/proto/notebooks.pb.go +++ b/api/proto/notebooks.pb.go @@ -20,6 +20,61 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type Env struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` + Value string `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *Env) Reset() { + *x = Env{} + if protoimpl.UnsafeEnabled { + mi := &file_notebooks_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Env) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Env) ProtoMessage() {} + +func (x *Env) ProtoReflect() protoreflect.Message { + mi := &file_notebooks_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 Env.ProtoReflect.Descriptor instead. +func (*Env) Descriptor() ([]byte, []int) { + return file_notebooks_proto_rawDescGZIP(), []int{0} +} + +func (x *Env) GetKey() string { + if x != nil { + return x.Key + } + return "" +} + +func (x *Env) GetValue() string { + if x != nil { + return x.Value + } + return "" +} + type NotebookExportRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -32,7 +87,7 @@ type NotebookExportRequest struct { func (x *NotebookExportRequest) Reset() { *x = NotebookExportRequest{} if protoimpl.UnsafeEnabled { - mi := &file_notebooks_proto_msgTypes[0] + mi := &file_notebooks_proto_msgTypes[1] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -45,7 +100,7 @@ func (x *NotebookExportRequest) String() string { func (*NotebookExportRequest) ProtoMessage() {} func (x *NotebookExportRequest) ProtoReflect() protoreflect.Message { - mi := &file_notebooks_proto_msgTypes[0] + mi := &file_notebooks_proto_msgTypes[1] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -58,7 +113,7 @@ func (x *NotebookExportRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use NotebookExportRequest.ProtoReflect.Descriptor instead. func (*NotebookExportRequest) Descriptor() ([]byte, []int) { - return file_notebooks_proto_rawDescGZIP(), []int{0} + return file_notebooks_proto_rawDescGZIP(), []int{1} } func (x *NotebookExportRequest) GetNotebookId() string { @@ -87,12 +142,13 @@ type NotebookCellRequest struct { Count uint64 `protobuf:"varint,5,opt,name=count,proto3" json:"count,omitempty"` Type string `protobuf:"bytes,6,opt,name=type,proto3" json:"type,omitempty"` CurrentlyEditing bool `protobuf:"varint,8,opt,name=currently_editing,json=currentlyEditing,proto3" json:"currently_editing,omitempty"` + Env []*Env `protobuf:"bytes,9,rep,name=env,proto3" json:"env,omitempty"` } func (x *NotebookCellRequest) Reset() { *x = NotebookCellRequest{} if protoimpl.UnsafeEnabled { - mi := &file_notebooks_proto_msgTypes[1] + mi := &file_notebooks_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -105,7 +161,7 @@ func (x *NotebookCellRequest) String() string { func (*NotebookCellRequest) ProtoMessage() {} func (x *NotebookCellRequest) ProtoReflect() protoreflect.Message { - mi := &file_notebooks_proto_msgTypes[1] + mi := &file_notebooks_proto_msgTypes[2] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -118,7 +174,7 @@ func (x *NotebookCellRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use NotebookCellRequest.ProtoReflect.Descriptor instead. func (*NotebookCellRequest) Descriptor() ([]byte, []int) { - return file_notebooks_proto_rawDescGZIP(), []int{1} + return file_notebooks_proto_rawDescGZIP(), []int{2} } func (x *NotebookCellRequest) GetNotebookId() string { @@ -170,6 +226,84 @@ func (x *NotebookCellRequest) GetCurrentlyEditing() bool { return false } +func (x *NotebookCellRequest) GetEnv() []*Env { + if x != nil { + return x.Env + } + return nil +} + +type NotebookContext struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"` + HuntId string `protobuf:"bytes,2,opt,name=hunt_id,json=huntId,proto3" json:"hunt_id,omitempty"` + FlowId string `protobuf:"bytes,3,opt,name=flow_id,json=flowId,proto3" json:"flow_id,omitempty"` + ClientId string `protobuf:"bytes,4,opt,name=client_id,json=clientId,proto3" json:"client_id,omitempty"` +} + +func (x *NotebookContext) Reset() { + *x = NotebookContext{} + if protoimpl.UnsafeEnabled { + mi := &file_notebooks_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NotebookContext) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NotebookContext) ProtoMessage() {} + +func (x *NotebookContext) ProtoReflect() protoreflect.Message { + mi := &file_notebooks_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 NotebookContext.ProtoReflect.Descriptor instead. +func (*NotebookContext) Descriptor() ([]byte, []int) { + return file_notebooks_proto_rawDescGZIP(), []int{3} +} + +func (x *NotebookContext) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *NotebookContext) GetHuntId() string { + if x != nil { + return x.HuntId + } + return "" +} + +func (x *NotebookContext) GetFlowId() string { + if x != nil { + return x.FlowId + } + return "" +} + +func (x *NotebookContext) GetClientId() string { + if x != nil { + return x.ClientId + } + return "" +} + type NotebookMetadata struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -178,6 +312,8 @@ type NotebookMetadata struct { Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` Creator string `protobuf:"bytes,3,opt,name=creator,proto3" json:"creator,omitempty"` + // Type of notebook - Hunt, Flow or empty for default. + Context *NotebookContext `protobuf:"bytes,16,opt,name=context,proto3" json:"context,omitempty"` // A list of usernames that have access to this notebook. Collaborators []string `protobuf:"bytes,12,rep,name=collaborators,proto3" json:"collaborators,omitempty"` // If this is set, the notebook is public. @@ -191,12 +327,15 @@ type NotebookMetadata struct { LatestCellId string `protobuf:"bytes,8,opt,name=latest_cell_id,json=latestCellId,proto3" json:"latest_cell_id,omitempty"` Hidden bool `protobuf:"varint,9,opt,name=hidden,proto3" json:"hidden,omitempty"` AvailableDownloads *AvailableDownloads `protobuf:"bytes,10,opt,name=available_downloads,json=availableDownloads,proto3" json:"available_downloads,omitempty"` + // These environment variables will be populated into each + // notebook cell in this notebook. + Env []*Env `protobuf:"bytes,14,rep,name=env,proto3" json:"env,omitempty"` } func (x *NotebookMetadata) Reset() { *x = NotebookMetadata{} if protoimpl.UnsafeEnabled { - mi := &file_notebooks_proto_msgTypes[2] + mi := &file_notebooks_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -209,7 +348,7 @@ func (x *NotebookMetadata) String() string { func (*NotebookMetadata) ProtoMessage() {} func (x *NotebookMetadata) ProtoReflect() protoreflect.Message { - mi := &file_notebooks_proto_msgTypes[2] + mi := &file_notebooks_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -222,7 +361,7 @@ func (x *NotebookMetadata) ProtoReflect() protoreflect.Message { // Deprecated: Use NotebookMetadata.ProtoReflect.Descriptor instead. func (*NotebookMetadata) Descriptor() ([]byte, []int) { - return file_notebooks_proto_rawDescGZIP(), []int{2} + return file_notebooks_proto_rawDescGZIP(), []int{4} } func (x *NotebookMetadata) GetName() string { @@ -246,6 +385,13 @@ func (x *NotebookMetadata) GetCreator() string { return "" } +func (x *NotebookMetadata) GetContext() *NotebookContext { + if x != nil { + return x.Context + } + return nil +} + func (x *NotebookMetadata) GetCollaborators() []string { if x != nil { return x.Collaborators @@ -316,6 +462,13 @@ func (x *NotebookMetadata) GetAvailableDownloads() *AvailableDownloads { return nil } +func (x *NotebookMetadata) GetEnv() []*Env { + if x != nil { + return x.Env + } + return nil +} + type Notebooks struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -327,7 +480,7 @@ type Notebooks struct { func (x *Notebooks) Reset() { *x = Notebooks{} if protoimpl.UnsafeEnabled { - mi := &file_notebooks_proto_msgTypes[3] + mi := &file_notebooks_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -340,7 +493,7 @@ func (x *Notebooks) String() string { func (*Notebooks) ProtoMessage() {} func (x *Notebooks) ProtoReflect() protoreflect.Message { - mi := &file_notebooks_proto_msgTypes[3] + mi := &file_notebooks_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -353,7 +506,7 @@ func (x *Notebooks) ProtoReflect() protoreflect.Message { // Deprecated: Use Notebooks.ProtoReflect.Descriptor instead. func (*Notebooks) Descriptor() ([]byte, []int) { - return file_notebooks_proto_rawDescGZIP(), []int{3} + return file_notebooks_proto_rawDescGZIP(), []int{5} } func (x *Notebooks) GetItems() []*NotebookMetadata { @@ -379,12 +532,13 @@ type NotebookCell struct { Type string `protobuf:"bytes,7,opt,name=type,proto3" json:"type,omitempty"` CurrentlyEditing bool `protobuf:"varint,8,opt,name=currently_editing,json=currentlyEditing,proto3" json:"currently_editing,omitempty"` Calculating bool `protobuf:"varint,9,opt,name=calculating,proto3" json:"calculating,omitempty"` + Env []*Env `protobuf:"bytes,11,rep,name=env,proto3" json:"env,omitempty"` } func (x *NotebookCell) Reset() { *x = NotebookCell{} if protoimpl.UnsafeEnabled { - mi := &file_notebooks_proto_msgTypes[4] + mi := &file_notebooks_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -397,7 +551,7 @@ func (x *NotebookCell) String() string { func (*NotebookCell) ProtoMessage() {} func (x *NotebookCell) ProtoReflect() protoreflect.Message { - mi := &file_notebooks_proto_msgTypes[4] + mi := &file_notebooks_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -410,7 +564,7 @@ func (x *NotebookCell) ProtoReflect() protoreflect.Message { // Deprecated: Use NotebookCell.ProtoReflect.Descriptor instead. func (*NotebookCell) Descriptor() ([]byte, []int) { - return file_notebooks_proto_rawDescGZIP(), []int{4} + return file_notebooks_proto_rawDescGZIP(), []int{6} } func (x *NotebookCell) GetInput() string { @@ -483,6 +637,13 @@ func (x *NotebookCell) GetCalculating() bool { return false } +func (x *NotebookCell) GetEnv() []*Env { + if x != nil { + return x.Env + } + return nil +} + type NotebookFileUploadRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -496,7 +657,7 @@ type NotebookFileUploadRequest struct { func (x *NotebookFileUploadRequest) Reset() { *x = NotebookFileUploadRequest{} if protoimpl.UnsafeEnabled { - mi := &file_notebooks_proto_msgTypes[5] + mi := &file_notebooks_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -509,7 +670,7 @@ func (x *NotebookFileUploadRequest) String() string { func (*NotebookFileUploadRequest) ProtoMessage() {} func (x *NotebookFileUploadRequest) ProtoReflect() protoreflect.Message { - mi := &file_notebooks_proto_msgTypes[5] + mi := &file_notebooks_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -522,7 +683,7 @@ func (x *NotebookFileUploadRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use NotebookFileUploadRequest.ProtoReflect.Descriptor instead. func (*NotebookFileUploadRequest) Descriptor() ([]byte, []int) { - return file_notebooks_proto_rawDescGZIP(), []int{5} + return file_notebooks_proto_rawDescGZIP(), []int{7} } func (x *NotebookFileUploadRequest) GetData() string { @@ -557,7 +718,7 @@ type NotebookFileUploadResponse struct { func (x *NotebookFileUploadResponse) Reset() { *x = NotebookFileUploadResponse{} if protoimpl.UnsafeEnabled { - mi := &file_notebooks_proto_msgTypes[6] + mi := &file_notebooks_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -570,7 +731,7 @@ func (x *NotebookFileUploadResponse) String() string { func (*NotebookFileUploadResponse) ProtoMessage() {} func (x *NotebookFileUploadResponse) ProtoReflect() protoreflect.Message { - mi := &file_notebooks_proto_msgTypes[6] + mi := &file_notebooks_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -583,7 +744,7 @@ func (x *NotebookFileUploadResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use NotebookFileUploadResponse.ProtoReflect.Descriptor instead. func (*NotebookFileUploadResponse) Descriptor() ([]byte, []int) { - return file_notebooks_proto_rawDescGZIP(), []int{6} + return file_notebooks_proto_rawDescGZIP(), []int{8} } func (x *NotebookFileUploadResponse) GetUrl() string { @@ -598,91 +759,110 @@ var File_notebooks_proto protoreflect.FileDescriptor var file_notebooks_proto_rawDesc = []byte{ 0x0a, 0x0f, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x05, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x0b, 0x66, 0x6c, 0x6f, 0x77, 0x73, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x4c, 0x0a, 0x15, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, - 0x6b, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, - 0x0a, 0x0b, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x49, 0x64, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x22, 0xd4, 0x01, 0x0a, 0x13, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, - 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, - 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, - 0x63, 0x65, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, - 0x65, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6f, 0x66, 0x66, - 0x73, 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2b, 0x0a, - 0x11, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x5f, 0x65, 0x64, 0x69, 0x74, 0x69, - 0x6e, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x74, 0x6c, 0x79, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x22, 0xe3, 0x03, 0x0a, 0x10, 0x4e, - 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x12, - 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, - 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72, - 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x18, - 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x12, 0x21, 0x0a, - 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, - 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, - 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, - 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, - 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x6f, 0x74, 0x65, - 0x62, 0x6f, 0x6f, 0x6b, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, 0x73, 0x12, 0x38, 0x0a, 0x0d, - 0x63, 0x65, 0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x0b, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4e, 0x6f, 0x74, 0x65, - 0x62, 0x6f, 0x6f, 0x6b, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x0c, 0x63, 0x65, 0x6c, 0x6c, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, - 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, - 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x68, 0x69, - 0x64, 0x64, 0x65, 0x6e, 0x12, 0x4a, 0x0a, 0x13, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, - 0x65, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, - 0x62, 0x6c, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x52, 0x12, 0x61, 0x76, - 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x73, - 0x22, 0x3a, 0x0a, 0x09, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x73, 0x12, 0x2d, 0x0a, - 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0xa2, 0x02, 0x0a, - 0x0c, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x43, 0x65, 0x6c, 0x6c, 0x12, 0x14, 0x0a, - 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6e, - 0x70, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x64, - 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, - 0x17, 0x0a, 0x07, 0x63, 0x65, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x63, 0x65, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, - 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x5f, - 0x65, 0x64, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, - 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x12, - 0x20, 0x0a, 0x0b, 0x63, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x63, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6e, - 0x67, 0x22, 0x6c, 0x0a, 0x19, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x46, 0x69, 0x6c, - 0x65, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, - 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1f, - 0x0a, 0x0b, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x49, 0x64, 0x22, - 0x2e, 0x0a, 0x1a, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x46, 0x69, 0x6c, 0x65, 0x55, - 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, - 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x42, - 0x31, 0x5a, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x6c, 0x6f, 0x63, 0x69, 0x64, 0x65, 0x78, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x76, 0x65, 0x6c, 0x6f, - 0x63, 0x69, 0x72, 0x61, 0x70, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x2d, 0x0a, 0x03, 0x45, 0x6e, 0x76, 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, 0x22, 0x4c, 0x0a, 0x15, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, + 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, + 0x0b, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x49, 0x64, 0x12, 0x12, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x22, 0xf2, 0x01, 0x0a, 0x13, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x43, + 0x65, 0x6c, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x6f, + 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x63, + 0x65, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x65, + 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, + 0x66, 0x73, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, + 0x65, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2b, 0x0a, 0x11, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x5f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6e, + 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x6c, 0x79, 0x45, 0x64, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x0a, 0x03, 0x65, 0x6e, 0x76, + 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, + 0x6e, 0x76, 0x52, 0x03, 0x65, 0x6e, 0x76, 0x22, 0x74, 0x0a, 0x0f, 0x4e, 0x6f, 0x74, 0x65, 0x62, + 0x6f, 0x6f, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x17, + 0x0a, 0x07, 0x68, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x68, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x66, 0x6c, 0x6f, 0x77, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x66, 0x6c, 0x6f, 0x77, 0x49, 0x64, + 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0xb3, 0x04, + 0x0a, 0x10, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x6f, 0x72, 0x12, 0x30, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x18, 0x10, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4e, 0x6f, 0x74, 0x65, + 0x62, 0x6f, 0x6f, 0x6b, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6e, + 0x74, 0x65, 0x78, 0x74, 0x12, 0x24, 0x0a, 0x0d, 0x63, 0x6f, 0x6c, 0x6c, 0x61, 0x62, 0x6f, 0x72, + 0x61, 0x74, 0x6f, 0x72, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x6f, 0x6c, + 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x61, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x75, + 0x62, 0x6c, 0x69, 0x63, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52, 0x06, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x69, + 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, + 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x6d, 0x6f, + 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x6e, 0x6f, + 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x63, + 0x65, 0x6c, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x63, 0x65, 0x6c, 0x6c, + 0x73, 0x12, 0x38, 0x0a, 0x0d, 0x63, 0x65, 0x6c, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x43, 0x65, 0x6c, 0x6c, 0x52, 0x0c, 0x63, + 0x65, 0x6c, 0x6c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x24, 0x0a, 0x0e, 0x6c, + 0x61, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x65, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x43, 0x65, 0x6c, 0x6c, 0x49, + 0x64, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x06, 0x68, 0x69, 0x64, 0x64, 0x65, 0x6e, 0x12, 0x4a, 0x0a, 0x13, 0x61, 0x76, 0x61, + 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x73, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, + 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, + 0x73, 0x52, 0x12, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x6f, 0x77, 0x6e, + 0x6c, 0x6f, 0x61, 0x64, 0x73, 0x12, 0x1c, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x0e, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6e, 0x76, 0x52, 0x03, + 0x65, 0x6e, 0x76, 0x22, 0x3a, 0x0a, 0x09, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x73, + 0x12, 0x2d, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, + 0xc0, 0x02, 0x0a, 0x0c, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x43, 0x65, 0x6c, 0x6c, + 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x12, + 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x61, + 0x74, 0x61, 0x12, 0x17, 0x0a, 0x07, 0x63, 0x65, 0x6c, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x63, 0x65, 0x6c, 0x6c, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x08, 0x6d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x6c, 0x79, 0x5f, 0x65, 0x64, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, + 0x52, 0x10, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x6c, 0x79, 0x45, 0x64, 0x69, 0x74, 0x69, + 0x6e, 0x67, 0x12, 0x20, 0x0a, 0x0b, 0x63, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6e, + 0x67, 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x63, 0x61, 0x6c, 0x63, 0x75, 0x6c, 0x61, + 0x74, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x0a, 0x03, 0x65, 0x6e, 0x76, 0x18, 0x0b, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x0a, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x45, 0x6e, 0x76, 0x52, 0x03, 0x65, + 0x6e, 0x76, 0x22, 0x6c, 0x0a, 0x19, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x46, 0x69, + 0x6c, 0x65, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x1f, 0x0a, 0x0b, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x5f, 0x69, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x49, 0x64, + 0x22, 0x2e, 0x0a, 0x1a, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x46, 0x69, 0x6c, 0x65, + 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, + 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, + 0x42, 0x31, 0x5a, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x6c, 0x6f, 0x63, 0x69, 0x64, 0x65, + 0x78, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x76, 0x65, 0x6c, + 0x6f, 0x63, 0x69, 0x72, 0x61, 0x70, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -697,26 +877,32 @@ func file_notebooks_proto_rawDescGZIP() []byte { return file_notebooks_proto_rawDescData } -var file_notebooks_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_notebooks_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_notebooks_proto_goTypes = []interface{}{ - (*NotebookExportRequest)(nil), // 0: proto.NotebookExportRequest - (*NotebookCellRequest)(nil), // 1: proto.NotebookCellRequest - (*NotebookMetadata)(nil), // 2: proto.NotebookMetadata - (*Notebooks)(nil), // 3: proto.Notebooks - (*NotebookCell)(nil), // 4: proto.NotebookCell - (*NotebookFileUploadRequest)(nil), // 5: proto.NotebookFileUploadRequest - (*NotebookFileUploadResponse)(nil), // 6: proto.NotebookFileUploadResponse - (*AvailableDownloads)(nil), // 7: proto.AvailableDownloads + (*Env)(nil), // 0: proto.Env + (*NotebookExportRequest)(nil), // 1: proto.NotebookExportRequest + (*NotebookCellRequest)(nil), // 2: proto.NotebookCellRequest + (*NotebookContext)(nil), // 3: proto.NotebookContext + (*NotebookMetadata)(nil), // 4: proto.NotebookMetadata + (*Notebooks)(nil), // 5: proto.Notebooks + (*NotebookCell)(nil), // 6: proto.NotebookCell + (*NotebookFileUploadRequest)(nil), // 7: proto.NotebookFileUploadRequest + (*NotebookFileUploadResponse)(nil), // 8: proto.NotebookFileUploadResponse + (*AvailableDownloads)(nil), // 9: proto.AvailableDownloads } var file_notebooks_proto_depIdxs = []int32{ - 4, // 0: proto.NotebookMetadata.cell_metadata:type_name -> proto.NotebookCell - 7, // 1: proto.NotebookMetadata.available_downloads:type_name -> proto.AvailableDownloads - 2, // 2: proto.Notebooks.items:type_name -> proto.NotebookMetadata - 3, // [3:3] is the sub-list for method output_type - 3, // [3:3] is the sub-list for method input_type - 3, // [3:3] is the sub-list for extension type_name - 3, // [3:3] is the sub-list for extension extendee - 0, // [0:3] is the sub-list for field type_name + 0, // 0: proto.NotebookCellRequest.env:type_name -> proto.Env + 3, // 1: proto.NotebookMetadata.context:type_name -> proto.NotebookContext + 6, // 2: proto.NotebookMetadata.cell_metadata:type_name -> proto.NotebookCell + 9, // 3: proto.NotebookMetadata.available_downloads:type_name -> proto.AvailableDownloads + 0, // 4: proto.NotebookMetadata.env:type_name -> proto.Env + 4, // 5: proto.Notebooks.items:type_name -> proto.NotebookMetadata + 0, // 6: proto.NotebookCell.env:type_name -> proto.Env + 7, // [7:7] is the sub-list for method output_type + 7, // [7:7] is the sub-list for method input_type + 7, // [7:7] is the sub-list for extension type_name + 7, // [7:7] is the sub-list for extension extendee + 0, // [0:7] is the sub-list for field type_name } func init() { file_notebooks_proto_init() } @@ -727,7 +913,7 @@ func file_notebooks_proto_init() { file_flows_proto_init() if !protoimpl.UnsafeEnabled { file_notebooks_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotebookExportRequest); i { + switch v := v.(*Env); i { case 0: return &v.state case 1: @@ -739,7 +925,7 @@ func file_notebooks_proto_init() { } } file_notebooks_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotebookCellRequest); i { + switch v := v.(*NotebookExportRequest); i { case 0: return &v.state case 1: @@ -751,7 +937,7 @@ func file_notebooks_proto_init() { } } file_notebooks_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotebookMetadata); i { + switch v := v.(*NotebookCellRequest); i { case 0: return &v.state case 1: @@ -763,7 +949,7 @@ func file_notebooks_proto_init() { } } file_notebooks_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Notebooks); i { + switch v := v.(*NotebookContext); i { case 0: return &v.state case 1: @@ -775,7 +961,7 @@ func file_notebooks_proto_init() { } } file_notebooks_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotebookCell); i { + switch v := v.(*NotebookMetadata); i { case 0: return &v.state case 1: @@ -787,7 +973,7 @@ func file_notebooks_proto_init() { } } file_notebooks_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*NotebookFileUploadRequest); i { + switch v := v.(*Notebooks); i { case 0: return &v.state case 1: @@ -799,6 +985,30 @@ func file_notebooks_proto_init() { } } file_notebooks_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NotebookCell); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_notebooks_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NotebookFileUploadRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_notebooks_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*NotebookFileUploadResponse); i { case 0: return &v.state @@ -817,7 +1027,7 @@ func file_notebooks_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_notebooks_proto_rawDesc, NumEnums: 0, - NumMessages: 7, + NumMessages: 9, NumExtensions: 0, NumServices: 0, }, diff --git a/api/proto/notebooks.proto b/api/proto/notebooks.proto index 9c89d9ad210..66ba3f58eaa 100644 --- a/api/proto/notebooks.proto +++ b/api/proto/notebooks.proto @@ -6,6 +6,11 @@ package proto; option go_package = "www.velocidex.com/golang/velociraptor/api/proto"; +message Env { + string key = 1; + string value = 2; +} + message NotebookExportRequest { string notebook_id = 1; string type = 2; @@ -21,6 +26,15 @@ message NotebookCellRequest { string type = 6; bool currently_editing = 8; + + repeated Env env = 9; +} + +message NotebookContext { + string type = 1; + string hunt_id = 2; + string flow_id = 3; + string client_id = 4; } message NotebookMetadata { @@ -28,6 +42,9 @@ message NotebookMetadata { string description = 2; string creator = 3; + // Type of notebook - Hunt, Flow or empty for default. + NotebookContext context = 16; + // A list of usernames that have access to this notebook. repeated string collaborators = 12; @@ -49,6 +66,10 @@ message NotebookMetadata { bool hidden = 9; AvailableDownloads available_downloads = 10; + + // These environment variables will be populated into each + // notebook cell in this notebook. + repeated Env env = 14; } message Notebooks { @@ -71,6 +92,8 @@ message NotebookCell { bool currently_editing = 8; bool calculating = 9; + + repeated Env env = 11; } message NotebookFileUploadRequest { diff --git a/artifacts/definitions/Windows/Detection/EnvironmentVariables.yaml b/artifacts/definitions/Windows/Detection/EnvironmentVariables.yaml index 3873a9c69ec..552f0b7465d 100644 --- a/artifacts/definitions/Windows/Detection/EnvironmentVariables.yaml +++ b/artifacts/definitions/Windows/Detection/EnvironmentVariables.yaml @@ -6,7 +6,7 @@ parameters: - name: ProcessNameRegex default: . - name: EnvironmentVariableRegex - default: COMSPEC + default: COMSPEC|COR_PROFILER - name: FilterValueRegex default: . - name: WhitelistValueRegex @@ -31,3 +31,51 @@ sources: WHERE Var =~ EnvironmentVariableRegex AND Value =~ FilterValueRegex AND NOT Value =~ WhitelistValueRegex + + notebook: + - type: Markdown + template: |- + # Process Environment Variables + + Environment variables control the way subprocesses work. In + this artifact we look for processes with unusual sets of + environment variables. + + {{ $unusual := Query "SELECT * FROM source() WHERE \ + Var =~ 'COR_PROFILER|COMPlus_ETWEnabled'" | Expand }} + + {{ if $unusual }} + ## Some unusual environment variables. + + There have been some unusual environment variables + detected. These normally indicate malicious activity. + + {{ Table $unusual }} + + {{ end }} + + {{ $unusual = Query "SELECT * FROM source() WHERE \ + Var =~ 'COMSPEC' AND NOT CommandLine =~ 'cmd.exe$'" | Expand }} + {{ if $unusual }} + + ## Unusual COMSPEC setting. + + The `COMSPEC` environment variable is usually used to launch + the command prompt (cmd.exe) but Velociraptor found some + hits where this is not the case. It could indicate malicious + activity. + + {{ Table $unusual }} + + {{ end }} + + - type: VQL + template: | + + /* Markdown + ## All collected results. + + */ + + SELECT * FROM source() + LIMIT 50 diff --git a/artifacts/proto/artifact.pb.go b/artifacts/proto/artifact.pb.go index 582ae8a6ce5..1a75b7fff47 100644 --- a/artifacts/proto/artifact.pb.go +++ b/artifacts/proto/artifact.pb.go @@ -172,23 +172,80 @@ func (x *ArtifactParameter) GetFriendlyName() string { return "" } +type NotebookSourceCell struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Template string `protobuf:"bytes,1,opt,name=template,proto3" json:"template,omitempty"` + Type string `protobuf:"bytes,2,opt,name=type,proto3" json:"type,omitempty"` +} + +func (x *NotebookSourceCell) Reset() { + *x = NotebookSourceCell{} + if protoimpl.UnsafeEnabled { + mi := &file_artifact_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NotebookSourceCell) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NotebookSourceCell) ProtoMessage() {} + +func (x *NotebookSourceCell) ProtoReflect() protoreflect.Message { + mi := &file_artifact_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 NotebookSourceCell.ProtoReflect.Descriptor instead. +func (*NotebookSourceCell) Descriptor() ([]byte, []int) { + return file_artifact_proto_rawDescGZIP(), []int{2} +} + +func (x *NotebookSourceCell) GetTemplate() string { + if x != nil { + return x.Template + } + return "" +} + +func (x *NotebookSourceCell) GetType() string { + if x != nil { + return x.Type + } + return "" +} + type ArtifactSource struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` - Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"` - Precondition string `protobuf:"bytes,1,opt,name=precondition,proto3" json:"precondition,omitempty"` - Query string `protobuf:"bytes,6,opt,name=query,proto3" json:"query,omitempty"` - Queries []string `protobuf:"bytes,2,rep,name=queries,proto3" json:"queries,omitempty"` - PostProcess []string `protobuf:"bytes,5,rep,name=post_process,json=postProcess,proto3" json:"post_process,omitempty"` + Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"` + Precondition string `protobuf:"bytes,1,opt,name=precondition,proto3" json:"precondition,omitempty"` + Query string `protobuf:"bytes,6,opt,name=query,proto3" json:"query,omitempty"` + // Deprecated - use query above for new artifacts. + Queries []string `protobuf:"bytes,2,rep,name=queries,proto3" json:"queries,omitempty"` + // Notebook cells that will be added as part of the source. + Notebook []*NotebookSourceCell `protobuf:"bytes,5,rep,name=notebook,proto3" json:"notebook,omitempty"` } func (x *ArtifactSource) Reset() { *x = ArtifactSource{} if protoimpl.UnsafeEnabled { - mi := &file_artifact_proto_msgTypes[2] + mi := &file_artifact_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -201,7 +258,7 @@ func (x *ArtifactSource) String() string { func (*ArtifactSource) ProtoMessage() {} func (x *ArtifactSource) ProtoReflect() protoreflect.Message { - mi := &file_artifact_proto_msgTypes[2] + mi := &file_artifact_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -214,7 +271,7 @@ func (x *ArtifactSource) ProtoReflect() protoreflect.Message { // Deprecated: Use ArtifactSource.ProtoReflect.Descriptor instead. func (*ArtifactSource) Descriptor() ([]byte, []int) { - return file_artifact_proto_rawDescGZIP(), []int{2} + return file_artifact_proto_rawDescGZIP(), []int{3} } func (x *ArtifactSource) GetName() string { @@ -252,9 +309,9 @@ func (x *ArtifactSource) GetQueries() []string { return nil } -func (x *ArtifactSource) GetPostProcess() []string { +func (x *ArtifactSource) GetNotebook() []*NotebookSourceCell { if x != nil { - return x.PostProcess + return x.Notebook } return nil } @@ -277,7 +334,7 @@ type Report struct { func (x *Report) Reset() { *x = Report{} if protoimpl.UnsafeEnabled { - mi := &file_artifact_proto_msgTypes[3] + mi := &file_artifact_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -290,7 +347,7 @@ func (x *Report) String() string { func (*Report) ProtoMessage() {} func (x *Report) ProtoReflect() protoreflect.Message { - mi := &file_artifact_proto_msgTypes[3] + mi := &file_artifact_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -303,7 +360,7 @@ func (x *Report) ProtoReflect() protoreflect.Message { // Deprecated: Use Report.ProtoReflect.Descriptor instead. func (*Report) Descriptor() ([]byte, []int) { - return file_artifact_proto_rawDescGZIP(), []int{3} + return file_artifact_proto_rawDescGZIP(), []int{4} } func (x *Report) GetType() string { @@ -381,7 +438,7 @@ type Artifact struct { func (x *Artifact) Reset() { *x = Artifact{} if protoimpl.UnsafeEnabled { - mi := &file_artifact_proto_msgTypes[4] + mi := &file_artifact_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -394,7 +451,7 @@ func (x *Artifact) String() string { func (*Artifact) ProtoMessage() {} func (x *Artifact) ProtoReflect() protoreflect.Message { - mi := &file_artifact_proto_msgTypes[4] + mi := &file_artifact_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -407,7 +464,7 @@ func (x *Artifact) ProtoReflect() protoreflect.Message { // Deprecated: Use Artifact.ProtoReflect.Descriptor instead. func (*Artifact) Descriptor() ([]byte, []int) { - return file_artifact_proto_rawDescGZIP(), []int{4} + return file_artifact_proto_rawDescGZIP(), []int{5} } func (x *Artifact) GetName() string { @@ -540,7 +597,7 @@ type ArtifactDescriptors struct { func (x *ArtifactDescriptors) Reset() { *x = ArtifactDescriptors{} if protoimpl.UnsafeEnabled { - mi := &file_artifact_proto_msgTypes[5] + mi := &file_artifact_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -553,7 +610,7 @@ func (x *ArtifactDescriptors) String() string { func (*ArtifactDescriptors) ProtoMessage() {} func (x *ArtifactDescriptors) ProtoReflect() protoreflect.Message { - mi := &file_artifact_proto_msgTypes[5] + mi := &file_artifact_proto_msgTypes[6] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -566,7 +623,7 @@ func (x *ArtifactDescriptors) ProtoReflect() protoreflect.Message { // Deprecated: Use ArtifactDescriptors.ProtoReflect.Descriptor instead. func (*ArtifactDescriptors) Descriptor() ([]byte, []int) { - return file_artifact_proto_rawDescGZIP(), []int{5} + return file_artifact_proto_rawDescGZIP(), []int{6} } func (x *ArtifactDescriptors) GetItems() []*Artifact { @@ -623,7 +680,7 @@ type Tool struct { func (x *Tool) Reset() { *x = Tool{} if protoimpl.UnsafeEnabled { - mi := &file_artifact_proto_msgTypes[6] + mi := &file_artifact_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -636,7 +693,7 @@ func (x *Tool) String() string { func (*Tool) ProtoMessage() {} func (x *Tool) ProtoReflect() protoreflect.Message { - mi := &file_artifact_proto_msgTypes[6] + mi := &file_artifact_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -649,7 +706,7 @@ func (x *Tool) ProtoReflect() protoreflect.Message { // Deprecated: Use Tool.ProtoReflect.Descriptor instead. func (*Tool) Descriptor() ([]byte, []int) { - return file_artifact_proto_rawDescGZIP(), []int{6} + return file_artifact_proto_rawDescGZIP(), []int{7} } func (x *Tool) GetName() string { @@ -749,7 +806,7 @@ type ThirdParty struct { func (x *ThirdParty) Reset() { *x = ThirdParty{} if protoimpl.UnsafeEnabled { - mi := &file_artifact_proto_msgTypes[7] + mi := &file_artifact_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -762,7 +819,7 @@ func (x *ThirdParty) String() string { func (*ThirdParty) ProtoMessage() {} func (x *ThirdParty) ProtoReflect() protoreflect.Message { - mi := &file_artifact_proto_msgTypes[7] + mi := &file_artifact_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -775,7 +832,7 @@ func (x *ThirdParty) ProtoReflect() protoreflect.Message { // Deprecated: Use ThirdParty.ProtoReflect.Descriptor instead. func (*ThirdParty) Descriptor() ([]byte, []int) { - return file_artifact_proto_rawDescGZIP(), []int{7} + return file_artifact_proto_rawDescGZIP(), []int{8} } func (x *ThirdParty) GetTools() []*Tool { @@ -808,7 +865,7 @@ type Resources struct { func (x *Resources) Reset() { *x = Resources{} if protoimpl.UnsafeEnabled { - mi := &file_artifact_proto_msgTypes[8] + mi := &file_artifact_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -821,7 +878,7 @@ func (x *Resources) String() string { func (*Resources) ProtoMessage() {} func (x *Resources) ProtoReflect() protoreflect.Message { - mi := &file_artifact_proto_msgTypes[8] + mi := &file_artifact_proto_msgTypes[9] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -834,7 +891,7 @@ func (x *Resources) ProtoReflect() protoreflect.Message { // Deprecated: Use Resources.ProtoReflect.Descriptor instead. func (*Resources) Descriptor() ([]byte, []int) { - return file_artifact_proto_rawDescGZIP(), []int{8} + return file_artifact_proto_rawDescGZIP(), []int{9} } func (x *Resources) GetTimeout() uint64 { @@ -902,223 +959,224 @@ var file_artifact_proto_rawDesc = []byte{ 0x2e, 0x67, 0x2e, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x4a, 0x53, 0x4f, 0x4e, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x20, 0x4a, 0x53, 0x4f, 0x4e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x28, 0x29, 0x20, 0x56, 0x51, 0x4c, 0x20, 0x66, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x22, 0x88, 0x06, 0x0a, 0x0e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x53, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x12, 0xaf, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x9a, 0x01, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x93, 0x01, 0x12, 0x90, 0x01, - 0x54, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, - 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x65, 0x74, 0x20, 0x77, 0x65, 0x20, - 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, - 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x69, 0x74, 0x73, - 0x65, 0x6c, 0x66, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, - 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2e, - 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x8d, 0x01, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x6b, 0xe2, 0xfc, - 0xe3, 0xc4, 0x01, 0x65, 0x12, 0x63, 0x41, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, - 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x20, 0x4e, 0x6f, 0x74, 0x65, - 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x70, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x6f, 0x74, 0x68, - 0x65, 0x72, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x68, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6e, - 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x44, 0xe2, 0xfc, - 0xe3, 0xc4, 0x01, 0x3e, 0x12, 0x3c, 0x41, 0x20, 0x56, 0x51, 0x4c, 0x20, 0x65, 0x78, 0x70, 0x72, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x65, 0x76, 0x61, - 0x6c, 0x75, 0x61, 0x74, 0x65, 0x64, 0x20, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x20, 0x74, 0x6f, 0x20, - 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x2e, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x34, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, - 0x1e, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x18, 0x12, 0x16, 0x41, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, - 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x51, 0x4c, 0x20, 0x71, 0x75, 0x65, 0x72, 0x79, 0x52, - 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x74, 0x0a, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x42, 0x5a, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x54, 0x12, - 0x52, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, - 0x6c, 0x6c, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, - 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x66, 0x72, 0x6f, - 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, 0x20, 0x71, 0x75, 0x65, 0x72, 0x79, - 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, - 0x65, 0x64, 0x2e, 0x52, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x73, 0x0a, 0x0c, - 0x70, 0x6f, 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x09, 0x42, 0x50, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x4a, 0x12, 0x48, 0x41, 0x20, 0x6c, 0x69, - 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x20, 0x74, 0x68, - 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x6f, - 0x76, 0x65, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x73, 0x20, - 0x66, 0x6f, 0x72, 0x20, 0x70, 0x6f, 0x73, 0x74, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, - 0x69, 0x6e, 0x67, 0x2e, 0x52, 0x0b, 0x70, 0x6f, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, - 0x73, 0x3a, 0x29, 0xda, 0xfc, 0xe3, 0xc4, 0x01, 0x23, 0x0a, 0x21, 0x57, 0x68, 0x65, 0x72, 0x65, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x67, 0x65, - 0x74, 0x73, 0x20, 0x69, 0x74, 0x73, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x22, 0xd8, 0x02, 0x0a, - 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x3a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x26, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x20, 0x12, 0x1e, 0x54, - 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x3a, 0x20, 0x43, - 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x2c, 0x20, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x12, 0x0a, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x38, 0x0a, - 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, - 0x63, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, - 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x3a, 0x8d, 0x01, 0xda, 0xfc, 0xe3, 0xc4, 0x01, 0x86, - 0x01, 0x0a, 0x83, 0x01, 0x41, 0x20, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x69, 0x73, 0x20, - 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, - 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, - 0x74, 0x65, 0x64, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, - 0x65, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, 0x6c, 0x65, 0x20, 0x72, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x73, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, - 0x64, 0x20, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x22, 0xc2, 0x0c, 0x0a, 0x08, 0x41, 0x72, 0x74, 0x69, - 0x66, 0x61, 0x63, 0x74, 0x12, 0xb1, 0x01, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x9c, 0x01, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x95, 0x01, 0x12, 0x92, 0x01, - 0x54, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x20, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, - 0x20, 0x62, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, - 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x20, 0x64, 0x6f, 0x74, 0x73, 0x2e, - 0x20, 0x41, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, 0x6c, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, - 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x72, 0x65, 0x61, 0x6b, 0x20, 0x63, 0x61, 0x74, - 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x64, 0x6f, 0x74, - 0x20, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x4c, 0x69, 0x6e, 0x75, 0x78, 0x2e, 0x42, 0x72, 0x6f, 0x77, - 0x73, 0x65, 0x72, 0x73, 0x2e, 0x43, 0x68, 0x72, 0x6f, 0x6d, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, - 0x72, 0x79, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x51, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2f, 0xe2, - 0xfc, 0xe3, 0xc4, 0x01, 0x29, 0x12, 0x27, 0x57, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, - 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x72, 0x79, 0x69, - 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x2e, 0x52, 0x0b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x06, 0x61, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1f, 0xe2, 0xfc, 0xe3, - 0xc4, 0x01, 0x19, 0x12, 0x17, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, - 0x68, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x52, 0x06, 0x61, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x12, 0x44, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x42, 0x26, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x20, 0x12, - 0x1e, 0x41, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, - 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x52, - 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x73, 0x0a, 0x14, 0x72, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x42, 0x40, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x3a, - 0x12, 0x38, 0x41, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x20, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, - 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x52, 0x13, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x2e, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x13, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, - 0x21, 0x0a, 0x05, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x6f, 0x6f, 0x6c, 0x52, 0x05, 0x74, 0x6f, 0x6f, - 0x6c, 0x73, 0x12, 0x68, 0x0a, 0x0c, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x42, 0x44, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x3e, - 0x12, 0x3c, 0x41, 0x20, 0x56, 0x51, 0x4c, 0x20, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, - 0x65, 0x64, 0x20, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x69, 0x6e, - 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x0c, - 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6c, 0x0a, 0x0a, - 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, - 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x42, 0x32, 0xe2, 0xfc, 0xe3, 0xc4, - 0x01, 0x2c, 0x12, 0x2a, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x74, - 0x6f, 0x20, 0x62, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6f, - 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x52, 0x0a, - 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x4f, 0x0a, 0x04, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x42, 0x3b, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x35, - 0x12, 0x33, 0x54, 0x68, 0x65, 0x20, 0x74, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, - 0x65, 0x20, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x20, 0x43, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, - 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x2c, 0x20, 0x45, 0x56, 0x45, 0x4e, 0x54, 0x2c, 0x20, 0x53, - 0x45, 0x52, 0x56, 0x45, 0x52, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x5a, 0x0a, 0x07, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x53, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x42, 0x29, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x23, 0x12, 0x21, 0x57, 0x68, 0x65, - 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, - 0x67, 0x65, 0x74, 0x73, 0x20, 0x69, 0x74, 0x73, 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x07, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x6a, 0x0a, 0x07, 0x69, 0x6d, 0x70, 0x6f, 0x72, - 0x74, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x09, 0x42, 0x50, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x4a, - 0x12, 0x48, 0x41, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x74, 0x68, 0x65, - 0x72, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x27, 0x20, 0x65, 0x78, 0x70, - 0x6f, 0x72, 0x74, 0x20, 0x56, 0x51, 0x4c, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x72, 0x65, 0x6c, 0x6f, - 0x61, 0x64, 0x20, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, - 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x52, 0x07, 0x69, 0x6d, 0x70, 0x6f, - 0x72, 0x74, 0x73, 0x12, 0x7b, 0x0a, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x12, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x63, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x5d, 0x12, 0x5b, 0x56, 0x51, 0x4c, - 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, - 0x61, 0x63, 0x74, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2e, 0x20, 0x49, 0x74, 0x20, - 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, - 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x69, - 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, - 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x52, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, - 0x12, 0x6d, 0x0a, 0x07, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x42, 0x44, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x3e, 0x12, 0x3c, 0x41, 0x20, 0x6c, 0x69, 0x73, 0x74, - 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x70, - 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x70, 0x6f, 0x73, 0x74, 0x20, - 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x72, 0x74, - 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x52, 0x07, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x12, - 0x34, 0x0a, 0x0c, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, - 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, - 0x6c, 0x75, 0x6d, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, - 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x38, 0x0a, 0x03, 0x72, 0x61, 0x77, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x26, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x20, 0x12, 0x1e, 0x54, 0x68, 0x65, 0x20, - 0x72, 0x61, 0x77, 0x20, 0x59, 0x41, 0x4d, 0x4c, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, - 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x52, 0x03, 0x72, 0x61, 0x77, 0x12, - 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x64, 0x3a, 0x7f, 0xda, 0xfc, 0xe3, - 0xc4, 0x01, 0x79, 0x0a, 0x77, 0x41, 0x6e, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, - 0x20, 0x77, 0x72, 0x61, 0x70, 0x73, 0x20, 0x61, 0x20, 0x56, 0x51, 0x4c, 0x20, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x72, 0x65, 0x75, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x2c, 0x20, - 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x65, 0x64, 0x20, 0x77, 0x61, 0x79, 0x2e, 0x41, - 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, - 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6e, - 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6e, 0x61, - 0x6c, 0x79, 0x7a, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x65, 0x6d, 0x2e, 0x22, 0x3c, 0x0a, 0x13, - 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x6f, 0x72, 0x73, 0x12, 0x25, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, - 0x61, 0x63, 0x74, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x22, 0x82, 0x03, 0x0a, 0x04, 0x54, - 0x6f, 0x6f, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x5f, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, - 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, - 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x23, - 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, 0x65, 0x72, 0x76, 0x65, 0x4c, 0x6f, 0x63, 0x61, - 0x6c, 0x6c, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65, - 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x64, 0x6d, - 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, - 0x65, 0x72, 0x76, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, - 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, - 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, - 0x6f, 0x72, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, - 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, - 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, - 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x20, 0x0a, - 0x0b, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0b, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x22, - 0x4a, 0x0a, 0x0b, 0x74, 0x68, 0x69, 0x72, 0x64, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x12, 0x21, - 0x0a, 0x05, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x6f, 0x6f, 0x6c, 0x52, 0x05, 0x74, 0x6f, 0x6f, 0x6c, - 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x04, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x90, 0x01, 0x0a, 0x09, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, - 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, - 0x6f, 0x75, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x6f, 0x70, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x73, - 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x02, 0x52, 0x0c, 0x6f, 0x70, 0x73, - 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, - 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x61, 0x78, - 0x52, 0x6f, 0x77, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x70, 0x6c, 0x6f, - 0x61, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, - 0x6d, 0x61, 0x78, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x37, - 0x5a, 0x35, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, 0x6c, 0x6f, 0x63, 0x69, 0x64, 0x65, 0x78, 0x2e, - 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x67, 0x2f, 0x76, 0x65, 0x6c, 0x6f, 0x63, - 0x69, 0x72, 0x61, 0x70, 0x74, 0x6f, 0x72, 0x2f, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, - 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x22, 0x44, 0x0a, 0x12, 0x4e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6d, 0x70, 0x6c, + 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0xca, 0x05, 0x0a, 0x0e, 0x41, 0x72, 0x74, 0x69, + 0x66, 0x61, 0x63, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0xaf, 0x01, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x9a, 0x01, 0xe2, 0xfc, 0xe3, 0xc4, + 0x01, 0x93, 0x01, 0x12, 0x90, 0x01, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x6f, + 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x20, 0x49, 0x66, 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x73, + 0x65, 0x74, 0x20, 0x77, 0x65, 0x20, 0x75, 0x73, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x61, + 0x6d, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x20, 0x69, 0x74, 0x73, 0x65, 0x6c, 0x66, 0x2e, 0x20, 0x54, 0x68, 0x65, 0x20, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x69, 0x6c, 0x65, 0x72, + 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x20, 0x61, + 0x20, 0x71, 0x75, 0x65, 0x72, 0x79, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x74, 0x68, 0x69, 0x73, + 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x8d, 0x01, 0x0a, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x6b, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x65, 0x12, 0x63, 0x41, 0x20, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x2e, 0x20, 0x4e, 0x6f, 0x74, 0x65, 0x20, 0x69, 0x74, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, + 0x20, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x6f, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x20, 0x77, 0x69, + 0x74, 0x68, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x20, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x52, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x68, 0x0a, 0x0c, + 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x42, 0x44, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x3e, 0x12, 0x3c, 0x41, 0x20, 0x56, 0x51, + 0x4c, 0x20, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, + 0x62, 0x65, 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x64, 0x20, 0x70, 0x72, 0x69, + 0x6f, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, + 0x20, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6e, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1e, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x18, 0x12, 0x16, 0x41, + 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x2d, 0x6c, 0x69, 0x6e, 0x65, 0x20, 0x56, 0x51, 0x4c, 0x20, + 0x71, 0x75, 0x65, 0x72, 0x79, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x74, 0x0a, 0x07, + 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x42, 0x5a, 0xe2, + 0xfc, 0xe3, 0xc4, 0x01, 0x54, 0x12, 0x52, 0x51, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x20, 0x74, + 0x68, 0x61, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, + 0x6f, 0x72, 0x64, 0x65, 0x72, 0x2e, 0x20, 0x4f, 0x6e, 0x6c, 0x79, 0x20, 0x6f, 0x75, 0x74, 0x70, + 0x75, 0x74, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6c, 0x61, 0x73, 0x74, + 0x20, 0x71, 0x75, 0x65, 0x72, 0x79, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x63, + 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x2e, 0x52, 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, + 0x65, 0x73, 0x12, 0x35, 0x0a, 0x08, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x18, 0x05, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4e, 0x6f, 0x74, + 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x65, 0x6c, 0x6c, 0x52, + 0x08, 0x6e, 0x6f, 0x74, 0x65, 0x62, 0x6f, 0x6f, 0x6b, 0x3a, 0x29, 0xda, 0xfc, 0xe3, 0xc4, 0x01, + 0x23, 0x0a, 0x21, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x67, 0x65, 0x74, 0x73, 0x20, 0x69, 0x74, 0x73, 0x20, 0x64, + 0x61, 0x74, 0x61, 0x2e, 0x22, 0xd8, 0x02, 0x0a, 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, + 0x3a, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x26, 0xe2, + 0xfc, 0xe3, 0xc4, 0x01, 0x20, 0x12, 0x1e, 0x54, 0x79, 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x72, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x3a, 0x20, 0x43, 0x4c, 0x49, 0x45, 0x4e, 0x54, 0x2c, 0x20, 0x53, + 0x45, 0x52, 0x56, 0x45, 0x52, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x74, + 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x74, 0x69, + 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x65, 0x6d, + 0x70, 0x6c, 0x61, 0x74, 0x65, 0x12, 0x38, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, + 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, + 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x3a, + 0x8d, 0x01, 0xda, 0xfc, 0xe3, 0xc4, 0x01, 0x86, 0x01, 0x0a, 0x83, 0x01, 0x41, 0x20, 0x72, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x20, 0x69, 0x73, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6f, 0x75, 0x74, 0x70, 0x75, + 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x20, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x2e, 0x20, 0x54, 0x68, 0x65, + 0x72, 0x65, 0x20, 0x63, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x70, + 0x6c, 0x65, 0x20, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x74, 0x79, 0x70, 0x65, 0x73, 0x20, + 0x67, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x64, 0x20, 0x64, 0x65, 0x70, 0x65, 0x6e, 0x64, + 0x69, 0x6e, 0x67, 0x20, 0x6f, 0x6e, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x2e, 0x22, + 0xc2, 0x0c, 0x0a, 0x08, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0xb1, 0x01, 0x0a, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x9c, 0x01, 0xe2, 0xfc, + 0xe3, 0xc4, 0x01, 0x95, 0x01, 0x12, 0x92, 0x01, 0x54, 0x68, 0x65, 0x20, 0x6e, 0x61, 0x6d, 0x65, + 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, + 0x2e, 0x20, 0x53, 0x68, 0x6f, 0x75, 0x6c, 0x64, 0x20, 0x62, 0x65, 0x20, 0x75, 0x6e, 0x69, 0x71, + 0x75, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x6d, 0x61, 0x79, 0x20, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x20, 0x64, 0x6f, 0x74, 0x73, 0x2e, 0x20, 0x41, 0x20, 0x75, 0x73, 0x65, 0x66, 0x75, + 0x6c, 0x20, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x20, 0x69, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, + 0x72, 0x65, 0x61, 0x6b, 0x20, 0x63, 0x61, 0x74, 0x65, 0x67, 0x6f, 0x72, 0x69, 0x65, 0x73, 0x20, + 0x77, 0x69, 0x74, 0x68, 0x20, 0x64, 0x6f, 0x74, 0x20, 0x65, 0x2e, 0x67, 0x2e, 0x20, 0x4c, 0x69, + 0x6e, 0x75, 0x78, 0x2e, 0x42, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x73, 0x2e, 0x43, 0x68, 0x72, + 0x6f, 0x6d, 0x65, 0x48, 0x69, 0x73, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x12, 0x51, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x2f, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x29, 0x12, 0x27, 0x57, + 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, + 0x20, 0x69, 0x73, 0x20, 0x74, 0x72, 0x79, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, + 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x2e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x37, 0x0a, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x09, 0x42, 0x1f, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x19, 0x12, 0x17, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, + 0x61, 0x63, 0x74, 0x2e, 0x52, 0x06, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x12, 0x44, 0x0a, 0x09, + 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x42, + 0x26, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x20, 0x12, 0x1e, 0x41, 0x20, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x72, + 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x52, 0x09, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, + 0x63, 0x65, 0x12, 0x73, 0x0a, 0x14, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x5f, 0x70, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, + 0x42, 0x40, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x3a, 0x12, 0x38, 0x41, 0x20, 0x6c, 0x69, 0x73, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x20, 0x70, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x63, 0x6f, 0x6c, 0x6c, + 0x65, 0x63, 0x74, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x2e, 0x52, 0x13, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x50, 0x65, 0x72, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x09, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x05, 0x74, 0x6f, 0x6f, 0x6c, 0x73, + 0x18, 0x0f, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, + 0x6f, 0x6f, 0x6c, 0x52, 0x05, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x12, 0x68, 0x0a, 0x0c, 0x70, 0x72, + 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x44, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x3e, 0x12, 0x3c, 0x41, 0x20, 0x56, 0x51, 0x4c, 0x20, + 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, + 0x20, 0x65, 0x76, 0x61, 0x6c, 0x75, 0x61, 0x74, 0x65, 0x64, 0x20, 0x70, 0x72, 0x69, 0x6f, 0x72, + 0x20, 0x74, 0x6f, 0x20, 0x75, 0x73, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x52, 0x0c, 0x70, 0x72, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6c, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, + 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, + 0x65, 0x72, 0x42, 0x32, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x2c, 0x12, 0x2a, 0x50, 0x61, 0x72, 0x61, + 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x62, 0x65, 0x20, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, + 0x72, 0x73, 0x12, 0x4f, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x3b, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x35, 0x12, 0x33, 0x54, 0x68, 0x65, 0x20, 0x74, 0x79, + 0x70, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, + 0x20, 0x43, 0x61, 0x6e, 0x20, 0x62, 0x65, 0x20, 0x4e, 0x4f, 0x52, 0x4d, 0x41, 0x4c, 0x2c, 0x20, + 0x45, 0x56, 0x45, 0x4e, 0x54, 0x2c, 0x20, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x5a, 0x0a, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x41, 0x72, 0x74, + 0x69, 0x66, 0x61, 0x63, 0x74, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x42, 0x29, 0xe2, 0xfc, 0xe3, + 0xc4, 0x01, 0x23, 0x12, 0x21, 0x57, 0x68, 0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20, 0x61, + 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x67, 0x65, 0x74, 0x73, 0x20, 0x69, 0x74, 0x73, + 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x52, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, + 0x6a, 0x0a, 0x07, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x18, 0x11, 0x20, 0x03, 0x28, 0x09, + 0x42, 0x50, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x4a, 0x12, 0x48, 0x41, 0x20, 0x6c, 0x69, 0x73, 0x74, + 0x20, 0x6f, 0x66, 0x20, 0x6f, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, + 0x63, 0x74, 0x73, 0x27, 0x20, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x20, 0x56, 0x51, 0x4c, 0x20, + 0x74, 0x6f, 0x20, 0x70, 0x72, 0x65, 0x6c, 0x6f, 0x61, 0x64, 0x20, 0x70, 0x72, 0x69, 0x6f, 0x72, + 0x20, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x2e, 0x52, 0x07, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x7b, 0x0a, 0x06, 0x65, + 0x78, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, 0x42, 0x63, 0xe2, 0xfc, 0xe3, + 0xc4, 0x01, 0x5d, 0x12, 0x5b, 0x56, 0x51, 0x4c, 0x20, 0x74, 0x68, 0x61, 0x74, 0x20, 0x74, 0x68, + 0x69, 0x73, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x65, 0x78, 0x70, 0x6f, + 0x72, 0x74, 0x73, 0x2e, 0x20, 0x49, 0x74, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, + 0x61, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x20, 0x69, 0x6d, + 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x20, 0x69, 0x6e, 0x74, 0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x20, 0x73, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x52, 0x06, 0x65, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x6d, 0x0a, 0x07, 0x72, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x44, 0xe2, 0xfc, 0xe3, 0xc4, 0x01, 0x3e, + 0x12, 0x3c, 0x41, 0x20, 0x6c, 0x69, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x72, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x73, 0x20, 0x74, 0x6f, 0x20, 0x70, 0x6f, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x6c, 0x79, 0x20, 0x70, 0x6f, 0x73, 0x74, 0x20, 0x70, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x20, + 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x2e, 0x52, 0x07, + 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x0c, 0x63, 0x6f, 0x6c, 0x75, 0x6d, + 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x10, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x43, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x54, 0x79, 0x70, 0x65, + 0x52, 0x0b, 0x63, 0x6f, 0x6c, 0x75, 0x6d, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x38, 0x0a, + 0x03, 0x72, 0x61, 0x77, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x42, 0x26, 0xe2, 0xfc, 0xe3, 0xc4, + 0x01, 0x20, 0x12, 0x1e, 0x54, 0x68, 0x65, 0x20, 0x72, 0x61, 0x77, 0x20, 0x59, 0x41, 0x4d, 0x4c, + 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x69, 0x73, 0x20, 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, + 0x74, 0x2e, 0x52, 0x03, 0x72, 0x61, 0x77, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x69, + 0x6c, 0x65, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x70, 0x69, + 0x6c, 0x65, 0x64, 0x3a, 0x7f, 0xda, 0xfc, 0xe3, 0xc4, 0x01, 0x79, 0x0a, 0x77, 0x41, 0x6e, 0x20, + 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x20, 0x77, 0x72, 0x61, 0x70, 0x73, 0x20, 0x61, + 0x20, 0x56, 0x51, 0x4c, 0x20, 0x71, 0x75, 0x65, 0x72, 0x79, 0x20, 0x69, 0x6e, 0x20, 0x72, 0x65, + 0x75, 0x73, 0x61, 0x62, 0x6c, 0x65, 0x2c, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, + 0x65, 0x64, 0x20, 0x77, 0x61, 0x79, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, + 0x20, 0x61, 0x72, 0x65, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x62, 0x6f, 0x75, 0x74, 0x20, 0x63, + 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6e, 0x67, 0x20, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x73, + 0x20, 0x6e, 0x6f, 0x74, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x7a, 0x69, 0x6e, 0x67, 0x20, 0x74, + 0x68, 0x65, 0x6d, 0x2e, 0x22, 0x3c, 0x0a, 0x13, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, + 0x44, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x6f, 0x72, 0x73, 0x12, 0x25, 0x0a, 0x05, 0x69, + 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x2e, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x05, 0x69, 0x74, 0x65, + 0x6d, 0x73, 0x22, 0x82, 0x03, 0x0a, 0x04, 0x54, 0x6f, 0x6f, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, + 0x6c, 0x12, 0x25, 0x0a, 0x0e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x5f, 0x70, 0x72, 0x6f, 0x6a, + 0x65, 0x63, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x50, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x74, 0x68, + 0x75, 0x62, 0x5f, 0x61, 0x73, 0x73, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x67, 0x65, 0x78, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x41, 0x73, 0x73, 0x65, + 0x74, 0x52, 0x65, 0x67, 0x65, 0x78, 0x12, 0x23, 0x0a, 0x0d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x5f, + 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x73, + 0x65, 0x72, 0x76, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x6c, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x61, + 0x64, 0x6d, 0x69, 0x6e, 0x5f, 0x6f, 0x76, 0x65, 0x72, 0x72, 0x69, 0x64, 0x65, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x64, 0x6d, 0x69, 0x6e, 0x4f, 0x76, 0x65, 0x72, 0x72, 0x69, + 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x72, 0x76, 0x65, 0x55, 0x72, 0x6c, 0x12, + 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x72, 0x76, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x72, 0x76, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x25, + 0x0a, 0x0e, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x74, 0x6f, 0x72, + 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x61, 0x74, 0x65, 0x72, 0x69, 0x61, + 0x6c, 0x69, 0x7a, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6d, 0x61, 0x74, 0x65, + 0x72, 0x69, 0x61, 0x6c, 0x69, 0x7a, 0x65, 0x22, 0x4a, 0x0a, 0x0b, 0x74, 0x68, 0x69, 0x72, 0x64, + 0x5f, 0x70, 0x61, 0x72, 0x74, 0x79, 0x12, 0x21, 0x0a, 0x05, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x54, 0x6f, + 0x6f, 0x6c, 0x52, 0x05, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x22, 0x90, 0x01, 0x0a, 0x09, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x12, 0x18, 0x0a, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x07, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x24, 0x0a, 0x0e, 0x6f, + 0x70, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x02, 0x52, 0x0c, 0x6f, 0x70, 0x73, 0x50, 0x65, 0x72, 0x53, 0x65, 0x63, 0x6f, 0x6e, + 0x64, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x72, 0x6f, 0x77, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x04, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x52, 0x6f, 0x77, 0x73, 0x12, 0x28, 0x0a, 0x10, + 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x62, 0x79, 0x74, 0x65, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x42, 0x37, 0x5a, 0x35, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x65, + 0x6c, 0x6f, 0x63, 0x69, 0x64, 0x65, 0x78, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6c, 0x61, + 0x6e, 0x67, 0x2f, 0x76, 0x65, 0x6c, 0x6f, 0x63, 0x69, 0x72, 0x61, 0x70, 0x74, 0x6f, 0x72, 0x2f, + 0x61, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x73, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1133,33 +1191,35 @@ func file_artifact_proto_rawDescGZIP() []byte { return file_artifact_proto_rawDescData } -var file_artifact_proto_msgTypes = make([]protoimpl.MessageInfo, 9) +var file_artifact_proto_msgTypes = make([]protoimpl.MessageInfo, 10) var file_artifact_proto_goTypes = []interface{}{ (*ColumnType)(nil), // 0: proto.ColumnType (*ArtifactParameter)(nil), // 1: proto.ArtifactParameter - (*ArtifactSource)(nil), // 2: proto.ArtifactSource - (*Report)(nil), // 3: proto.Report - (*Artifact)(nil), // 4: proto.Artifact - (*ArtifactDescriptors)(nil), // 5: proto.ArtifactDescriptors - (*Tool)(nil), // 6: proto.Tool - (*ThirdParty)(nil), // 7: proto.third_party - (*Resources)(nil), // 8: proto.Resources + (*NotebookSourceCell)(nil), // 2: proto.NotebookSourceCell + (*ArtifactSource)(nil), // 3: proto.ArtifactSource + (*Report)(nil), // 4: proto.Report + (*Artifact)(nil), // 5: proto.Artifact + (*ArtifactDescriptors)(nil), // 6: proto.ArtifactDescriptors + (*Tool)(nil), // 7: proto.Tool + (*ThirdParty)(nil), // 8: proto.third_party + (*Resources)(nil), // 9: proto.Resources } var file_artifact_proto_depIdxs = []int32{ - 1, // 0: proto.Report.parameters:type_name -> proto.ArtifactParameter - 8, // 1: proto.Artifact.resources:type_name -> proto.Resources - 6, // 2: proto.Artifact.tools:type_name -> proto.Tool - 1, // 3: proto.Artifact.parameters:type_name -> proto.ArtifactParameter - 2, // 4: proto.Artifact.sources:type_name -> proto.ArtifactSource - 3, // 5: proto.Artifact.reports:type_name -> proto.Report - 0, // 6: proto.Artifact.column_types:type_name -> proto.ColumnType - 4, // 7: proto.ArtifactDescriptors.items:type_name -> proto.Artifact - 6, // 8: proto.third_party.tools:type_name -> proto.Tool - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 2, // 0: proto.ArtifactSource.notebook:type_name -> proto.NotebookSourceCell + 1, // 1: proto.Report.parameters:type_name -> proto.ArtifactParameter + 9, // 2: proto.Artifact.resources:type_name -> proto.Resources + 7, // 3: proto.Artifact.tools:type_name -> proto.Tool + 1, // 4: proto.Artifact.parameters:type_name -> proto.ArtifactParameter + 3, // 5: proto.Artifact.sources:type_name -> proto.ArtifactSource + 4, // 6: proto.Artifact.reports:type_name -> proto.Report + 0, // 7: proto.Artifact.column_types:type_name -> proto.ColumnType + 5, // 8: proto.ArtifactDescriptors.items:type_name -> proto.Artifact + 7, // 9: proto.third_party.tools:type_name -> proto.Tool + 10, // [10:10] is the sub-list for method output_type + 10, // [10:10] is the sub-list for method input_type + 10, // [10:10] is the sub-list for extension type_name + 10, // [10:10] is the sub-list for extension extendee + 0, // [0:10] is the sub-list for field type_name } func init() { file_artifact_proto_init() } @@ -1193,7 +1253,7 @@ func file_artifact_proto_init() { } } file_artifact_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ArtifactSource); i { + switch v := v.(*NotebookSourceCell); i { case 0: return &v.state case 1: @@ -1205,7 +1265,7 @@ func file_artifact_proto_init() { } } file_artifact_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Report); i { + switch v := v.(*ArtifactSource); i { case 0: return &v.state case 1: @@ -1217,7 +1277,7 @@ func file_artifact_proto_init() { } } file_artifact_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Artifact); i { + switch v := v.(*Report); i { case 0: return &v.state case 1: @@ -1229,7 +1289,7 @@ func file_artifact_proto_init() { } } file_artifact_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ArtifactDescriptors); i { + switch v := v.(*Artifact); i { case 0: return &v.state case 1: @@ -1241,7 +1301,7 @@ func file_artifact_proto_init() { } } file_artifact_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Tool); i { + switch v := v.(*ArtifactDescriptors); i { case 0: return &v.state case 1: @@ -1253,7 +1313,7 @@ func file_artifact_proto_init() { } } file_artifact_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ThirdParty); i { + switch v := v.(*Tool); i { case 0: return &v.state case 1: @@ -1265,6 +1325,18 @@ func file_artifact_proto_init() { } } file_artifact_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ThirdParty); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_artifact_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Resources); i { case 0: return &v.state @@ -1283,7 +1355,7 @@ func file_artifact_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_artifact_proto_rawDesc, NumEnums: 0, - NumMessages: 9, + NumMessages: 10, NumExtensions: 0, NumServices: 0, }, diff --git a/artifacts/proto/artifact.proto b/artifacts/proto/artifact.proto index 31e70376fe6..882a7a511c3 100644 --- a/artifacts/proto/artifact.proto +++ b/artifacts/proto/artifact.proto @@ -33,6 +33,12 @@ message ArtifactParameter { string friendly_name = 5; } +message NotebookSourceCell { + string template = 1; + string type = 2; +} + + message ArtifactSource { option (semantic) = { description: "Where the artifact gets its data." @@ -63,6 +69,9 @@ message ArtifactSource { description: "Queries that will run in order. Only output from " "the last query will be collected." }]; + + // Notebook cells that will be added as part of the source. + repeated NotebookSourceCell notebook = 5; } diff --git a/gui/velociraptor/src/components/core/paged-table.js b/gui/velociraptor/src/components/core/paged-table.js index e505c0e1fa7..152db31797f 100644 --- a/gui/velociraptor/src/components/core/paged-table.js +++ b/gui/velociraptor/src/components/core/paged-table.js @@ -91,6 +91,10 @@ class VeloPagedTable extends Component { // The URL Handler to fetch the table content. Defaults to // "v1/GetTable". url: PropTypes.string, + + + // When called will cause the table to be recalculated. + refresh: PropTypes.func, } state = { @@ -226,7 +230,10 @@ class VeloPagedTable extends Component { if (_.isEmpty(this.state.columns)) { return
- No Data Available. +
No Data Available.
+
; } diff --git a/gui/velociraptor/src/components/flows/flow-notebook.js b/gui/velociraptor/src/components/flows/flow-notebook.js index 0f085aede1b..46cba69d7ce 100644 --- a/gui/velociraptor/src/components/flows/flow-notebook.js +++ b/gui/velociraptor/src/components/flows/flow-notebook.js @@ -39,16 +39,12 @@ export default class FlowNotebook extends React.Component { } getCellVQL = (flow) => { - let client_id = flow.client_id; - var flow_id = flow.session_id; var query = "SELECT * \nFROM source(\n"; var sources = flow["artifacts_with_results"] || flow["request"]["artifacts"]; - query += " artifact='" + sources[0] + "',\n"; for (var i=1; i { @@ -92,14 +98,7 @@ export default class FlowNotebook extends React.Component { return; } - api.post('v1/NewNotebookCell', { - notebook_id: notebook_id, - type: "VQL", - cell_id: cell_metadata[0].cell_id, - input: this.getCellVQL(this.props.flow), - }).then((response) => { - this.fetchNotebooks(); - }); + this.fetchNotebooks(); }); }); } diff --git a/gui/velociraptor/src/components/hunts/hunt-list.js b/gui/velociraptor/src/components/hunts/hunt-list.js index 7d95f02456c..3da05f230db 100644 --- a/gui/velociraptor/src/components/hunts/hunt-list.js +++ b/gui/velociraptor/src/components/hunts/hunt-list.js @@ -238,7 +238,10 @@ class HuntList extends React.Component { { this.state.showDeleteNotebook && this.setState({showDeleteNotebook: false})}/> + onClose={e=>{ + this.setState({showDeleteNotebook: false}); + this.props.updateHunts(); + }}/> } { this.state.showExportNotebook && diff --git a/gui/velociraptor/src/components/hunts/hunt-notebook.js b/gui/velociraptor/src/components/hunts/hunt-notebook.js index 1c1621fc17a..3df291084b8 100644 --- a/gui/velociraptor/src/components/hunts/hunt-notebook.js +++ b/gui/velociraptor/src/components/hunts/hunt-notebook.js @@ -39,20 +39,6 @@ export default class HuntNotebook extends React.Component { clearInterval(this.interval); } - getCellVQL = (hunt) => { - var hunt_id = hunt["hunt_id"]; - var query = "SELECT * \nFROM hunt_results(\n"; - var sources = hunt["artifact_sources"] || hunt["start_request"]["artifacts"]; - query += " artifact='" + sources[0] + "',\n"; - for (var i=1; i { let hunt_id = this.props.hunt && this.props.hunt.hunt_id; if (!hunt_id) { @@ -77,11 +63,17 @@ export default class HuntNotebook extends React.Component { description: this.props.hunt.description || "This is a notebook for processing a hunt.", notebook_id: notebook_id, + context: { + type: "Hunt", + hunt_id: hunt_id, + }, // Hunt notebooks are all public. public: true, + env: [ + {key: "HuntId", value: hunt_id}, + ], }; - request.description += "\n\n* Click the cells bellow to edit VQL and refresh the data. *NOTE*: You need to refresh the data periodically to see the latest results.\n* Edit the content of this cell to provide a description of your hunt. You can export the hunt to HTML when done using the toolbar at the top right.\n* By default the result table below only shows 50 rows, edit the VQL to see more data."; api.post('v1/NewNotebook', request, this.source.token).then((response) => { if (response.cancel) return; let cell_metadata = response.data && response.data.cell_metadata; @@ -89,15 +81,7 @@ export default class HuntNotebook extends React.Component { return; } - api.post('v1/NewNotebookCell', { - notebook_id: notebook_id, - type: "VQL", - cell_id: cell_metadata[0].cell_id, - input: this.getCellVQL(this.props.hunt), - }, this.source.token).then((response) => { - if (response.cancel) return; - this.fetchNotebooks(); - }); + this.fetchNotebooks(); }); }); } diff --git a/gui/velociraptor/src/components/notebooks/notebook-cell-renderer.js b/gui/velociraptor/src/components/notebooks/notebook-cell-renderer.js index f03b9ac2cb8..40954d329b7 100644 --- a/gui/velociraptor/src/components/notebooks/notebook-cell-renderer.js +++ b/gui/velociraptor/src/components/notebooks/notebook-cell-renderer.js @@ -256,6 +256,7 @@ export default class NotebookCellRenderer extends React.Component { notebook_id: this.props.notebook_id, cell_id: this.state.cell.cell_id, type: this.state.cell.type || "Markdown", + env: this.state.cell.env, currently_editing: false, input: this.state.cell.input, }, this.source.token).then( (response) => { @@ -280,6 +281,7 @@ export default class NotebookCellRenderer extends React.Component { notebook_id: this.props.notebook_id, cell_id: cell.cell_id, type: cell.type || "Markdown", + env: this.state.cell.env, currently_editing: false, input: cell.input, }, this.source.token).then( (response) => { @@ -360,7 +362,8 @@ export default class NotebookCellRenderer extends React.Component { content += " notebook_cell_id=\""+ this.state.cell.cell_id + "\")\nLIMIT 50\n"; - this.props.addCell(this.state.cell.cell_id, "VQL", content); + + this.props.addCell(this.state.cell.cell_id, "VQL", content, this.state.cell.env); } @@ -438,14 +441,15 @@ export default class NotebookCellRenderer extends React.Component { { - this.props.addCell(this.state.cell.cell_id, "Markdown"); + // Preserve the current cell's environemnt for the new cell + this.props.addCell(this.state.cell.cell_id, "Markdown", "", this.state.cell.env); }}> Markdown { - this.props.addCell(this.state.cell.cell_id, "VQL"); + this.props.addCell(this.state.cell.cell_id, "VQL", "", this.state.cell.env); }}> VQL @@ -590,6 +594,7 @@ export default class NotebookCellRenderer extends React.Component { onClick={() => {this.props.setSelectedCellId(this.state.cell.cell_id);}} > { selected && _.map(this.state.cell.messages, (msg, idx) => { diff --git a/gui/velociraptor/src/components/notebooks/notebook-renderer.js b/gui/velociraptor/src/components/notebooks/notebook-renderer.js index f9b26afe6d0..1dbc015e2f6 100644 --- a/gui/velociraptor/src/components/notebooks/notebook-renderer.js +++ b/gui/velociraptor/src/components/notebooks/notebook-renderer.js @@ -130,7 +130,7 @@ export default class NotebookRenderer extends React.Component { } }; - addCell = (cell_id, cell_type, content) => { + addCell = (cell_id, cell_type, content, env) => { let request = {}; switch(cell_type) { case "VQL": @@ -140,6 +140,7 @@ export default class NotebookRenderer extends React.Component { notebook_id: this.props.notebook.notebook_id, type: cell_type, cell_id: cell_id, + env: env, input: content, }; break; default: diff --git a/gui/velociraptor/src/components/notebooks/notebook-report-renderer.js b/gui/velociraptor/src/components/notebooks/notebook-report-renderer.js index 602bfdaffb1..a2f59be3f05 100644 --- a/gui/velociraptor/src/components/notebooks/notebook-report-renderer.js +++ b/gui/velociraptor/src/components/notebooks/notebook-report-renderer.js @@ -2,11 +2,13 @@ import React from 'react'; import PropTypes from 'prop-types'; import parse from 'html-react-parser'; +import VeloTable from '../core/table.js'; import NotebookTableRenderer from './notebook-table-renderer.js'; export default class NotebookReportRenderer extends React.Component { static propTypes = { + refresh: PropTypes.func, cell: PropTypes.object, }; @@ -18,14 +20,36 @@ export default class NotebookReportRenderer extends React.Component { let template = parse(this.props.cell.output, { replace: (domNode) => { - if (domNode.name === "grr-csv-viewer") { - let params = JSON.parse(domNode.attribs.params); + // A table which contains the data inline. + if (domNode.name === "inline-table-viewer") { + try { + let data = JSON.parse(this.props.cell.data || '{}'); + let response = data[domNode.attribs.value || "unknown"] || {}; + let rows = JSON.parse(response.Response); + return ( + + ); + } catch(e) { + + }; + } - return ( - - ); + if (domNode.name === "grr-csv-viewer") { + let params = {}; + try { + let params = JSON.parse(domNode.attribs.params); + return ( + + ); + } catch(e) { + return; + } }; return domNode; } diff --git a/gui/velociraptor/src/components/notebooks/notebook-table-renderer.js b/gui/velociraptor/src/components/notebooks/notebook-table-renderer.js index 9c6af0ad6ad..4cb872d68d7 100644 --- a/gui/velociraptor/src/components/notebooks/notebook-table-renderer.js +++ b/gui/velociraptor/src/components/notebooks/notebook-table-renderer.js @@ -5,12 +5,14 @@ import VeloPagedTable from '../core/paged-table.js'; export default class NotebookTableRenderer extends React.Component { static propTypes = { + refresh: PropTypes.func, params: PropTypes.object, }; render() { return ; } diff --git a/reporting/cell_test.go b/reporting/cell_test.go new file mode 100644 index 00000000000..33cfdba96e8 --- /dev/null +++ b/reporting/cell_test.go @@ -0,0 +1,49 @@ +package reporting + +import ( + "testing" + + "github.com/Velocidex/ordereddict" + "github.com/alecthomas/assert" + "github.com/sebdah/goldie/v2" +) + +type testCases struct { + Name, Input string +} + +var TestCases = []testCases{ + {"Markdown in comments", ` +SELECT 1 / 2 FROM info() + +/* c + +# This is markdown + +*/ + +SELECT * FROM glob() +`}, +} + +func TestVQL2MarkdownConversion(t *testing.T) { + result := ordereddict.NewDict() + for _, testcase := range TestCases { + parsed, err := parseVQLCell(testcase.Input) + assert.NoError(t, err) + + result.Set(testcase.Name, parsed) + + content, env := ConvertVQLCellToMarkdownCell(testcase.Input) + result.Set(testcase.Name+" Markdown", content) + result.Set(testcase.Name+" Markdown Env", env) + } + + g := goldie.New( + t, + goldie.WithFixtureDir("fixtures"), + goldie.WithNameSuffix(".golden"), + goldie.WithDiffEngine(goldie.ColoredDiff), + ) + g.AssertJson(t, "VQL2MarkdownConversion", result) +} diff --git a/reporting/cells.go b/reporting/cells.go new file mode 100644 index 00000000000..996fde6ac53 --- /dev/null +++ b/reporting/cells.go @@ -0,0 +1,72 @@ +package reporting + +import ( + "fmt" + "strings" + + "github.com/Velocidex/ordereddict" + "github.com/alecthomas/participle" + "github.com/alecthomas/participle/lexer" + "github.com/alecthomas/participle/lexer/stateful" +) + +var ( + def = lexer.Must(stateful.New(stateful.Rules{ + "Root": { + {`VQLText`, `(?ms)([^/]|/[^*])+`, nil}, + {"CommentStart", `(?ms)/[*]`, stateful.Push("Comment")}, + }, + "Comment": { + {`CommentText`, `(?ms)([^*]|[*][^/])+`, nil}, + {"CommentEnd", `(?ms)[*]/`, stateful.Pop()}, + }, + })) + parser = participle.MustBuild(&Content{}, participle.Lexer(def)) +) + +type Fragment struct { + VQL string `( @VQLText |` + Comment string ` CommentStart @CommentText CommentEnd )` +} + +type Content struct { + Fragments []Fragment ` @@* ` +} + +func parseVQLCell(content string) (*Content, error) { + result := &Content{} + err := parser.ParseString(content, result) + return result, err +} + +// Convert the VQL cell into a template that produces markdown +// cells. VQL cells may interleave Markdown within them. +func ConvertVQLCellToMarkdownCell(content string) (string, *ordereddict.Dict) { + env := ordereddict.NewDict() + + cell_content, err := parseVQLCell(content) + if err != nil { + return fmt.Sprintf("# Error: %v", err), env + } + + result := "" + for idx, fragment := range cell_content.Fragments { + vql := strings.TrimSpace(fragment.VQL) + if vql != "" { + key := fmt.Sprintf("Query%v", idx) + env.Set(key, vql) + result += fmt.Sprintf( + "\n{{ Query \"SELECT * FROM query(query=%s)\" | Table }}\n", key) + continue + } + + lines := strings.SplitN(fragment.Comment, "\n", 2) + if len(lines) == 1 { + result += lines[0] + } else { + result += lines[1] + } + } + + return result, env +} diff --git a/reporting/fixtures/VQL2MarkdownConversion.golden b/reporting/fixtures/VQL2MarkdownConversion.golden new file mode 100644 index 00000000000..3d226b79a69 --- /dev/null +++ b/reporting/fixtures/VQL2MarkdownConversion.golden @@ -0,0 +1,23 @@ +{ + "Markdown in comments": { + "Fragments": [ + { + "VQL": "\nSELECT 1 / 2 FROM info()\n\n", + "Comment": "" + }, + { + "VQL": "", + "Comment": " c\n\n# This is markdown\n\n" + }, + { + "VQL": "\n\nSELECT * FROM glob()\n", + "Comment": "" + } + ] + }, + "Markdown in comments Markdown": "\n{{ Query \"SELECT * FROM query(query=Query0)\" | Table }}\n\n# This is markdown\n\n\n{{ Query \"SELECT * FROM query(query=Query2)\" | Table }}\n", + "Markdown in comments Markdown Env": { + "Query0": "SELECT 1 / 2 FROM info()", + "Query2": "SELECT * FROM glob()" + } +} \ No newline at end of file diff --git a/reporting/gui.go b/reporting/gui.go index c4ef18bda99..b893a594d01 100644 --- a/reporting/gui.go +++ b/reporting/gui.go @@ -175,7 +175,7 @@ func (self *GuiTemplateEngine) Table(values ...interface{}) interface{} { } return result - case []*ordereddict.Dict: + case []interface{}: if len(t) == 0 { // No rows returned. self.Scope.Log("Query produced no rows.") return "" @@ -193,7 +193,7 @@ func (self *GuiTemplateEngine) Table(values ...interface{}) interface{} { Columns: self.Scope.GetMembers(t[0]), } return fmt.Sprintf( - `
`, key) + `
`, key) } } @@ -581,6 +581,7 @@ func NewBlueMondayPolicy() *bluemonday.Policy { // Angular directives. p.AllowAttrs("value", "params").OnElements("grr-csv-viewer") + p.AllowAttrs("value", "params").OnElements("inline-table-viewer") p.AllowAttrs("value", "params").OnElements("grr-line-chart") p.AllowAttrs("value", "params").OnElements("grr-timeline") p.AllowAttrs("name").OnElements("grr-tool-viewer") diff --git a/services/repository.go b/services/repository.go index db9c9258c57..1a714aaaec7 100644 --- a/services/repository.go +++ b/services/repository.go @@ -92,6 +92,9 @@ type Repository interface { Get(config_obj *config_proto.Config, name string) (*artifacts_proto.Artifact, bool) + GetSource(config_obj *config_proto.Config, + name string) (*artifacts_proto.ArtifactSource, bool) + // An optimization that avoids copying the entire artifact definition GetArtifactType(config_obj *config_proto.Config, artifact_name string) (string, error) diff --git a/services/repository/repository.go b/services/repository/repository.go index f8ec671bae5..6fe24ec8aca 100644 --- a/services/repository/repository.go +++ b/services/repository/repository.go @@ -296,6 +296,23 @@ func (self *Repository) GetArtifactType( return artifact.Type, nil } +func (self *Repository) GetSource( + config_obj *config_proto.Config, name string) (*artifacts_proto.ArtifactSource, bool) { + artifact_name, source_name := paths.SplitFullSourceName(name) + + artifact, pres := self.Get(config_obj, artifact_name) + if !pres { + return nil, false + } + for _, source := range artifact.Sources { + if source.Name == source_name { + return source, true + } + } + + return nil, false +} + func (self *Repository) Get( config_obj *config_proto.Config, name string) (*artifacts_proto.Artifact, bool) { self.mu.Lock()