From 8eacaffe6afe8f2b6afb455f1ebef4a3fd0f8812 Mon Sep 17 00:00:00 2001 From: Ayushi Sharma Date: Fri, 22 Mar 2024 09:44:25 +0530 Subject: [PATCH 01/39] feat: support appeal metadata to story metadata in policy details --- core/appeal/mocks/metadataManager.go | 89 ++++++++++++++++++++ core/appeal/service.go | 117 +++++++++++++++++++++++++++ core/appeal/service_test.go | 3 + domain/metadata.go | 20 +++++ domain/policy.go | 21 ++--- plugins/identities/http.go | 20 +++++ plugins/identities/service.go | 10 +++ 7 files changed, 270 insertions(+), 10 deletions(-) create mode 100644 core/appeal/mocks/metadataManager.go create mode 100644 domain/metadata.go diff --git a/core/appeal/mocks/metadataManager.go b/core/appeal/mocks/metadataManager.go new file mode 100644 index 000000000..d51376851 --- /dev/null +++ b/core/appeal/mocks/metadataManager.go @@ -0,0 +1,89 @@ +// Code generated by mockery v2.33.0. DO NOT EDIT. + +package mocks + +import ( + domain "github.com/goto/guardian/domain" + mock "github.com/stretchr/testify/mock" +) + +// MetadataManager is an autogenerated mock type for the metadataManager type +type MetadataManager struct { + mock.Mock +} + +type MetadataManager_Expecter struct { + mock *mock.Mock +} + +func (_m *MetadataManager) EXPECT() *MetadataManager_Expecter { + return &MetadataManager_Expecter{mock: &_m.Mock} +} + +// ParseMetadataConfig provides a mock function with given fields: _a0 +func (_m *MetadataManager) ParseMetadataConfig(_a0 *domain.AppealMetadataConfig) (domain.SensitiveConfig, error) { + ret := _m.Called(_a0) + + var r0 domain.SensitiveConfig + var r1 error + if rf, ok := ret.Get(0).(func(*domain.AppealMetadataConfig) (domain.SensitiveConfig, error)); ok { + return rf(_a0) + } + if rf, ok := ret.Get(0).(func(*domain.AppealMetadataConfig) domain.SensitiveConfig); ok { + r0 = rf(_a0) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(domain.SensitiveConfig) + } + } + + if rf, ok := ret.Get(1).(func(*domain.AppealMetadataConfig) error); ok { + r1 = rf(_a0) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// MetadataManager_ParseMetadataConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseMetadataConfig' +type MetadataManager_ParseMetadataConfig_Call struct { + *mock.Call +} + +// ParseMetadataConfig is a helper method to define mock.On call +// - _a0 *domain.AppealMetadataConfig +func (_e *MetadataManager_Expecter) ParseMetadataConfig(_a0 interface{}) *MetadataManager_ParseMetadataConfig_Call { + return &MetadataManager_ParseMetadataConfig_Call{Call: _e.mock.On("ParseMetadataConfig", _a0)} +} + +func (_c *MetadataManager_ParseMetadataConfig_Call) Run(run func(_a0 *domain.AppealMetadataConfig)) *MetadataManager_ParseMetadataConfig_Call { + _c.Call.Run(func(args mock.Arguments) { + run(args[0].(*domain.AppealMetadataConfig)) + }) + return _c +} + +func (_c *MetadataManager_ParseMetadataConfig_Call) Return(_a0 domain.SensitiveConfig, _a1 error) *MetadataManager_ParseMetadataConfig_Call { + _c.Call.Return(_a0, _a1) + return _c +} + +func (_c *MetadataManager_ParseMetadataConfig_Call) RunAndReturn(run func(*domain.AppealMetadataConfig) (domain.SensitiveConfig, error)) *MetadataManager_ParseMetadataConfig_Call { + _c.Call.Return(run) + return _c +} + +// NewMetadataManager creates a new instance of MetadataManager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewMetadataManager(t interface { + mock.TestingT + Cleanup(func()) +}) *MetadataManager { + mock := &MetadataManager{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/core/appeal/service.go b/core/appeal/service.go index d83ee5a24..3b3f8ba3b 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -12,6 +12,7 @@ import ( "github.com/goto/guardian/domain" "github.com/goto/guardian/pkg/evaluator" "github.com/goto/guardian/pkg/log" + "github.com/goto/guardian/plugins/identities" "github.com/goto/guardian/plugins/notifiers" "github.com/goto/guardian/utils" "golang.org/x/sync/errgroup" @@ -47,6 +48,11 @@ type iamManager interface { domain.IAMManager } +//go:generate mockery --name=metadataManager --exported --with-expecter +type metadataManager interface { + domain.MetadataManager +} + //go:generate mockery --name=notifier --exported --with-expecter type notifier interface { notifiers.Client @@ -112,6 +118,7 @@ type ServiceDeps struct { PolicyService policyService GrantService grantService IAMManager iamManager + MetadataManager metadataManager Notifier notifier Validator *validator.Validate @@ -128,6 +135,7 @@ type Service struct { policyService policyService grantService grantService iam domain.IAMManager + metadata domain.MetadataManager notifier notifier validator *validator.Validate @@ -147,6 +155,7 @@ func NewService(deps ServiceDeps) *Service { deps.PolicyService, deps.GrantService, deps.IAMManager, + deps.MetadataManager, deps.Notifier, deps.Validator, @@ -295,6 +304,10 @@ func (s *Service) Create(ctx context.Context, appeals []*domain.Appeal, opts ... return err } + if err := s.populateAppealMetadata(ctx, appeal, policy); err != nil { + return fmt.Errorf("getting appeal metadata: %w", err) + } + if err := s.addCreatorDetails(ctx, appeal, policy); err != nil { return fmt.Errorf("getting creator details: %w", err) } @@ -1126,6 +1139,110 @@ func getPolicy(a *domain.Appeal, p *domain.Provider, policiesMap map[string]map[ return policy, nil } +func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, p *domain.Policy) error { + if p.AppealMetadataSources == nil { + return nil + } + + appealMetadata := map[string]interface{}{} + for key, metadata := range p.AppealMetadataSources { + if metadata.Type == "http" { + if metadata.Config.URL == "" { + return fmt.Errorf("URL cannot be empty for http type") + } + + metadataCl, err := s.getMetadataClient(metadata.Config) + if err != nil { + return fmt.Errorf("key: %s, %w", key, err) + } + + res, err := metadataCl.GetResourceMetadata() + if err != nil && !metadata.Config.AllowFailed { + return fmt.Errorf("error fetching resource: %w", err) + } + + responseMap := res.(map[string]interface{}) + params := map[string]interface{}{ + "response": responseMap, + "appeal": a, + } + value, err := s.getMetadataValue(metadata.Type, key, metadata.Value, params) + if err != nil { + return fmt.Errorf("error parsing value: %w", err) + } + appealMetadata[key] = value + + } else if metadata.Type == "static" { + params := map[string]interface{}{ + "appeal": a, + } + value, err := s.getMetadataValue(metadata.Type, key, metadata.Value, params) + if err != nil { + return fmt.Errorf("error parsing value: %w", err) + } + appealMetadata[key] = value + } + } + + a.Details["__policy_metadata"] = appealMetadata + + return nil +} + +func (s *Service) getMetadataClient(metadataCfg *domain.AppealMetadataConfig) (*identities.HTTPClient, error) { + metadataConfig, err := s.metadata.ParseMetadataConfig(metadataCfg) + if err != nil { + return nil, fmt.Errorf("error parsing metadata config: %w", err) + } + + clientConfig, ok := metadataConfig.(*identities.HTTPClientConfig) + if ok { + return nil, fmt.Errorf("invalid metadata config: %w", err) + } + + metadataCl, err := identities.NewHTTPClient(clientConfig) + if err != nil { + return nil, fmt.Errorf("error initializing metadata client: %w", err) + } + + return metadataCl, nil +} + +func (s *Service) getMetadataValue(metadataType string, key string, value interface{}, params map[string]interface{}) (interface{}, error) { + result := make(map[string]interface{}) + + switch v := value.(type) { + case string: + if strings.HasPrefix(v, "$appeal") || (metadataType == "http" && strings.HasPrefix(v, "$response")) { + finalVal, err := evaluator.Expression(v).EvaluateWithVars(params) + if err != nil { + return nil, err + } + result[key] = finalVal + } else { + result[key] = v + } + case map[string]interface{}: + for key, val := range v { + processedVal, err := s.getMetadataValue(metadataType, key, val, params) + if err != nil { + return nil, err + } + result[key] = processedVal + } + case interface{}: + processedVal, err := s.getMetadataValue(metadataType, key, v, params) + if err != nil { + return nil, err + } + result[key] = processedVal + default: + return nil, fmt.Errorf("unsupported value type") + } + + return result, nil +} + func (s *Service) addCreatorDetails(ctx context.Context, a *domain.Appeal, p *domain.Policy) error { if p.IAM == nil { return nil diff --git a/core/appeal/service_test.go b/core/appeal/service_test.go index c9a00c3d0..3a3e74645 100644 --- a/core/appeal/service_test.go +++ b/core/appeal/service_test.go @@ -28,6 +28,7 @@ type ServiceTestSuite struct { mockPolicyService *appealmocks.PolicyService mockGrantService *appealmocks.GrantService mockIAMManager *appealmocks.IamManager + mockMetadataManager *appealmocks.MetadataManager mockIAMClient *mocks.IAMClient mockNotifier *appealmocks.Notifier mockAuditLogger *appealmocks.AuditLogger @@ -48,6 +49,7 @@ func (s *ServiceTestSuite) setup() { s.mockPolicyService = new(appealmocks.PolicyService) s.mockGrantService = new(appealmocks.GrantService) s.mockIAMManager = new(appealmocks.IamManager) + s.mockMetadataManager = new(appealmocks.MetadataManager) s.mockIAMClient = new(mocks.IAMClient) s.mockNotifier = new(appealmocks.Notifier) s.mockAuditLogger = new(appealmocks.AuditLogger) @@ -61,6 +63,7 @@ func (s *ServiceTestSuite) setup() { s.mockPolicyService, s.mockGrantService, s.mockIAMManager, + s.mockMetadataManager, s.mockNotifier, validator.New(), log.NewNoop(), diff --git a/domain/metadata.go b/domain/metadata.go new file mode 100644 index 000000000..9af2ac156 --- /dev/null +++ b/domain/metadata.go @@ -0,0 +1,20 @@ +package domain + +type AppealMetadataSource struct { + Name string `json:"name" yaml:"name"` + Description string `json:"description,omitempty" yaml:"description,omitempty"` + Type string `json:"type" yaml:"type"` + Config *AppealMetadataConfig `json:"config,omitempty" yaml:"config,omitempty"` + Value interface{} `json:"value" yaml:"value"` +} + +type AppealMetadataConfig struct { + URL string `json:"url" yaml:"url"` + AllowFailed bool `json:"allow_failed,omitempty" yaml:"allow_failed,omitempty"` + Headers map[string]string `json:"headers,omitempty" yaml:"headers,omitempty"` + Auth interface{} `json:"auth,omitempty" yaml:"auth,omitempty"` +} + +type MetadataManager interface { + ParseMetadataConfig(*AppealMetadataConfig) (SensitiveConfig, error) +} diff --git a/domain/policy.go b/domain/policy.go index 6f8ac030e..e85096bbc 100644 --- a/domain/policy.go +++ b/domain/policy.go @@ -285,16 +285,17 @@ type Requirement struct { // Policy is the approval policy configuration type Policy struct { - ID string `json:"id" yaml:"id" validate:"required"` - Version uint `json:"version" yaml:"version" validate:"required"` - Description string `json:"description" yaml:"description"` - Steps []*Step `json:"steps" yaml:"steps" validate:"required,min=1,dive"` - AppealConfig *PolicyAppealConfig `json:"appeal_config" yaml:"appeal_config" validate:"omitempty,dive"` - Requirements []*Requirement `json:"requirements,omitempty" yaml:"requirements,omitempty" validate:"omitempty,min=1,dive"` - Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` - IAM *IAMConfig `json:"iam,omitempty" yaml:"iam,omitempty" validate:"omitempty,dive"` - CreatedAt time.Time `json:"created_at,omitempty" yaml:"created_at,omitempty"` - UpdatedAt time.Time `json:"updated_at,omitempty" yaml:"updated_at,omitempty"` + ID string `json:"id" yaml:"id" validate:"required"` + Version uint `json:"version" yaml:"version" validate:"required"` + Description string `json:"description" yaml:"description"` + Steps []*Step `json:"steps" yaml:"steps" validate:"required,min=1,dive"` + AppealConfig *PolicyAppealConfig `json:"appeal_config" yaml:"appeal_config" validate:"omitempty,dive"` + Requirements []*Requirement `json:"requirements,omitempty" yaml:"requirements,omitempty" validate:"omitempty,min=1,dive"` + Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` + IAM *IAMConfig `json:"iam,omitempty" yaml:"iam,omitempty" validate:"omitempty,dive"` + CreatedAt time.Time `json:"created_at,omitempty" yaml:"created_at,omitempty"` + UpdatedAt time.Time `json:"updated_at,omitempty" yaml:"updated_at,omitempty"` + AppealMetadataSources map[string]*AppealMetadataSource `json:"appeal_metadata_sources,omitempty" yaml:"appeal_metadata_sources,omitempty"` } type PolicyAppealConfig struct { diff --git a/plugins/identities/http.go b/plugins/identities/http.go index 5391cff31..80c7cd50a 100644 --- a/plugins/identities/http.go +++ b/plugins/identities/http.go @@ -257,6 +257,26 @@ func (c *HTTPClient) createRequest(userID string) (*http.Request, error) { return req, nil } +func (c *HTTPClient) GetResourceMetadata() (interface{}, error) { + req, err := http.NewRequest(http.MethodGet, c.config.URL, nil) + if err != nil { + return nil, err + } + + for k, v := range c.config.Headers { + req.Header.Set(k, v) + } + c.setAuth(req) + + req.Header.Set("Accept", "application/json") + var res interface{} + if err := c.sendRequest(req, &res); err != nil { + return nil, err + } + + return res, nil +} + func (c *HTTPClient) sendRequest(req *http.Request, v interface{}) error { res, err := c.httpClient.Do(req) if err != nil { diff --git a/plugins/identities/service.go b/plugins/identities/service.go index 375c7987e..017cc6957 100644 --- a/plugins/identities/service.go +++ b/plugins/identities/service.go @@ -23,6 +23,16 @@ func NewManager(crypto domain.Crypto, validator *validator.Validate) *manager { return &manager{crypto, validator} } +func (m *manager) ParseMetadataConfig(metadataConfig *domain.AppealMetadataConfig) (domain.SensitiveConfig, error) { + var clientConfig HTTPClientConfig + if err := mapstructure.Decode(metadataConfig, &clientConfig); err != nil { + return nil, fmt.Errorf("%w: %s", ErrInvalidConfig, err) + } + clientConfig.crypto = m.crypto + clientConfig.validator = m.validator + return &clientConfig, nil +} + func (m *manager) ParseConfig(iamConfig *domain.IAMConfig) (domain.SensitiveConfig, error) { switch iamConfig.Provider { case domain.IAMProviderTypeHTTP: From a666fb54f209a54bbc927604e9ce4040c81f8092 Mon Sep 17 00:00:00 2001 From: Ayushi Sharma Date: Fri, 22 Mar 2024 15:36:39 +0530 Subject: [PATCH 02/39] fix: review fixes --- core/appeal/mocks/metadataManager.go | 89 --------------- core/appeal/service.go | 124 +++++++++++--------- core/appeal/service_test.go | 3 - core/policy/service.go | 113 ++++++++++++++++++ core/policy/service_test.go | 1 + domain/metadata.go | 20 ---- domain/policy.go | 19 +++ internal/server/services.go | 1 + internal/store/postgres/model/policy.go | 36 ++++-- pkg/http/http.go | 146 ++++++++++++++++++++++++ 10 files changed, 375 insertions(+), 177 deletions(-) delete mode 100644 core/appeal/mocks/metadataManager.go delete mode 100644 domain/metadata.go create mode 100644 pkg/http/http.go diff --git a/core/appeal/mocks/metadataManager.go b/core/appeal/mocks/metadataManager.go deleted file mode 100644 index d51376851..000000000 --- a/core/appeal/mocks/metadataManager.go +++ /dev/null @@ -1,89 +0,0 @@ -// Code generated by mockery v2.33.0. DO NOT EDIT. - -package mocks - -import ( - domain "github.com/goto/guardian/domain" - mock "github.com/stretchr/testify/mock" -) - -// MetadataManager is an autogenerated mock type for the metadataManager type -type MetadataManager struct { - mock.Mock -} - -type MetadataManager_Expecter struct { - mock *mock.Mock -} - -func (_m *MetadataManager) EXPECT() *MetadataManager_Expecter { - return &MetadataManager_Expecter{mock: &_m.Mock} -} - -// ParseMetadataConfig provides a mock function with given fields: _a0 -func (_m *MetadataManager) ParseMetadataConfig(_a0 *domain.AppealMetadataConfig) (domain.SensitiveConfig, error) { - ret := _m.Called(_a0) - - var r0 domain.SensitiveConfig - var r1 error - if rf, ok := ret.Get(0).(func(*domain.AppealMetadataConfig) (domain.SensitiveConfig, error)); ok { - return rf(_a0) - } - if rf, ok := ret.Get(0).(func(*domain.AppealMetadataConfig) domain.SensitiveConfig); ok { - r0 = rf(_a0) - } else { - if ret.Get(0) != nil { - r0 = ret.Get(0).(domain.SensitiveConfig) - } - } - - if rf, ok := ret.Get(1).(func(*domain.AppealMetadataConfig) error); ok { - r1 = rf(_a0) - } else { - r1 = ret.Error(1) - } - - return r0, r1 -} - -// MetadataManager_ParseMetadataConfig_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ParseMetadataConfig' -type MetadataManager_ParseMetadataConfig_Call struct { - *mock.Call -} - -// ParseMetadataConfig is a helper method to define mock.On call -// - _a0 *domain.AppealMetadataConfig -func (_e *MetadataManager_Expecter) ParseMetadataConfig(_a0 interface{}) *MetadataManager_ParseMetadataConfig_Call { - return &MetadataManager_ParseMetadataConfig_Call{Call: _e.mock.On("ParseMetadataConfig", _a0)} -} - -func (_c *MetadataManager_ParseMetadataConfig_Call) Run(run func(_a0 *domain.AppealMetadataConfig)) *MetadataManager_ParseMetadataConfig_Call { - _c.Call.Run(func(args mock.Arguments) { - run(args[0].(*domain.AppealMetadataConfig)) - }) - return _c -} - -func (_c *MetadataManager_ParseMetadataConfig_Call) Return(_a0 domain.SensitiveConfig, _a1 error) *MetadataManager_ParseMetadataConfig_Call { - _c.Call.Return(_a0, _a1) - return _c -} - -func (_c *MetadataManager_ParseMetadataConfig_Call) RunAndReturn(run func(*domain.AppealMetadataConfig) (domain.SensitiveConfig, error)) *MetadataManager_ParseMetadataConfig_Call { - _c.Call.Return(run) - return _c -} - -// NewMetadataManager creates a new instance of MetadataManager. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewMetadataManager(t interface { - mock.TestingT - Cleanup(func()) -}) *MetadataManager { - mock := &MetadataManager{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/core/appeal/service.go b/core/appeal/service.go index 3b3f8ba3b..480cd3076 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -2,6 +2,7 @@ package appeal import ( "context" + "encoding/json" "errors" "fmt" "strings" @@ -11,8 +12,8 @@ import ( "github.com/goto/guardian/core/grant" "github.com/goto/guardian/domain" "github.com/goto/guardian/pkg/evaluator" + "github.com/goto/guardian/pkg/http" "github.com/goto/guardian/pkg/log" - "github.com/goto/guardian/plugins/identities" "github.com/goto/guardian/plugins/notifiers" "github.com/goto/guardian/utils" "golang.org/x/sync/errgroup" @@ -30,6 +31,8 @@ const ( RevokeReasonForExtension = "Automatically revoked for grant extension" RevokeReasonForOverride = "Automatically revoked for grant override" + + PolicyMetadataKey = "__policy_metadata" ) var TimeNow = time.Now @@ -48,11 +51,6 @@ type iamManager interface { domain.IAMManager } -//go:generate mockery --name=metadataManager --exported --with-expecter -type metadataManager interface { - domain.MetadataManager -} - //go:generate mockery --name=notifier --exported --with-expecter type notifier interface { notifiers.Client @@ -118,7 +116,6 @@ type ServiceDeps struct { PolicyService policyService GrantService grantService IAMManager iamManager - MetadataManager metadataManager Notifier notifier Validator *validator.Validate @@ -135,7 +132,6 @@ type Service struct { policyService policyService grantService grantService iam domain.IAMManager - metadata domain.MetadataManager notifier notifier validator *validator.Validate @@ -155,7 +151,6 @@ func NewService(deps ServiceDeps) *Service { deps.PolicyService, deps.GrantService, deps.IAMManager, - deps.MetadataManager, deps.Notifier, deps.Validator, @@ -200,10 +195,10 @@ func (s *Service) Create(ctx context.Context, appeals []*domain.Appeal, opts ... eg, egctx := errgroup.WithContext(ctx) var ( - resources map[string]*domain.Resource - providers map[string]map[string]*domain.Provider - policies map[string]map[uint]*domain.Policy - pendingAppeals map[string]map[string]map[string]*domain.Appeal + resources map[string]*domain.Resource + providers map[string]map[string]*domain.Provider + policies map[string]map[uint]*domain.Policy + pendingAppeals map[string]map[string]map[string]*domain.Appeal ) eg.Go(func() error { @@ -1144,63 +1139,84 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, return nil } + eg, _ := errgroup.WithContext(ctx) + appealMetadata := map[string]interface{}{} for key, metadata := range p.AppealMetadataSources { - if metadata.Type == "http" { - if metadata.Config.URL == "" { - return fmt.Errorf("URL cannot be empty for http type") - } + key, metadata := key, metadata + eg.Go(func() error { + switch metadata.Type { + case "http": + if metadata.Config.URL == "" { + return fmt.Errorf("URL cannot be empty for http type") + } - metadataCl, err := s.getMetadataClient(metadata.Config) - if err != nil { - return fmt.Errorf("key: %s, %w", key, err) - } + metadataCl, err := s.getMetadataClient(metadata.Config) + if err != nil { + return fmt.Errorf("key: %s, %w", key, err) + } - res, err := metadataCl.GetResourceMetadata() - if err != nil && !metadata.Config.AllowFailed { - return fmt.Errorf("error fetching resource: %w", err) - } + res, err := metadataCl.MakeRequest() + if err != nil || (res.StatusCode < 200 && res.StatusCode > 300) { + if !metadata.Config.AllowFailed { + return fmt.Errorf("error fetching resource: %w", err) + } + } - responseMap := res.(map[string]interface{}) - params := map[string]interface{}{ - "response": responseMap, - "appeal": a, - } - value, err := s.getMetadataValue(metadata.Type, key, metadata.Value, params) - if err != nil { - return fmt.Errorf("error parsing value: %w", err) - } - appealMetadata[key] = value + var responseBody interface{} + err = json.NewDecoder(res.Body).Decode(responseBody) + if err != nil { + return fmt.Errorf("error decoding response: %w", err) + } - } else if metadata.Type == "static" { - params := map[string]interface{}{ - "appeal": a, - } - value, err := s.getMetadataValue(metadata.Type, key, metadata.Value, params) - if err != nil { - return fmt.Errorf("error parsing value: %w", err) + responseMap := responseBody.(map[string]interface{}) + params := map[string]interface{}{ + "response": responseMap, + "appeal": a, + } + value, err := s.getMetadataValue(metadata.Type, key, metadata.Value, params) + if err != nil { + return fmt.Errorf("error parsing value: %w", err) + } + appealMetadata[key] = value + case "static": + params := map[string]interface{}{ + "appeal": a, + } + value, err := s.getMetadataValue(metadata.Type, key, metadata.Value, params) + if err != nil { + return fmt.Errorf("error parsing value: %w", err) + } + appealMetadata[key] = value + default: + return fmt.Errorf("invalid metadata source type") } - appealMetadata[key] = value - } + + return nil + }) } - a.Details["__policy_metadata"] = appealMetadata + if err := eg.Wait(); err == nil { + return err + } + + a.Details[PolicyMetadataKey] = appealMetadata return nil } -func (s *Service) getMetadataClient(metadataCfg *domain.AppealMetadataConfig) (*identities.HTTPClient, error) { - metadataConfig, err := s.metadata.ParseMetadataConfig(metadataCfg) - if err != nil { - return nil, fmt.Errorf("error parsing metadata config: %w", err) +func (s *Service) getMetadataClient(metadataCfg *domain.AppealMetadataConfig) (*http.HTTPClient, error) { + authCfg, ok := metadataCfg.Auth.(http.HTTPAuthConfig) + if !ok { + return nil, fmt.Errorf("invalid auth config") } - - clientConfig, ok := metadataConfig.(*identities.HTTPClientConfig) - if ok { - return nil, fmt.Errorf("invalid metadata config: %w", err) + metadataConfig := http.HTTPClientConfig{ + URL: metadataCfg.URL, + Headers: metadataCfg.Headers, + Auth: &authCfg, } - metadataCl, err := identities.NewHTTPClient(clientConfig) + metadataCl, err := http.NewHTTPClient(&metadataConfig) if err != nil { return nil, fmt.Errorf("error initializing metadata client: %w", err) } diff --git a/core/appeal/service_test.go b/core/appeal/service_test.go index 3a3e74645..c9a00c3d0 100644 --- a/core/appeal/service_test.go +++ b/core/appeal/service_test.go @@ -28,7 +28,6 @@ type ServiceTestSuite struct { mockPolicyService *appealmocks.PolicyService mockGrantService *appealmocks.GrantService mockIAMManager *appealmocks.IamManager - mockMetadataManager *appealmocks.MetadataManager mockIAMClient *mocks.IAMClient mockNotifier *appealmocks.Notifier mockAuditLogger *appealmocks.AuditLogger @@ -49,7 +48,6 @@ func (s *ServiceTestSuite) setup() { s.mockPolicyService = new(appealmocks.PolicyService) s.mockGrantService = new(appealmocks.GrantService) s.mockIAMManager = new(appealmocks.IamManager) - s.mockMetadataManager = new(appealmocks.MetadataManager) s.mockIAMClient = new(mocks.IAMClient) s.mockNotifier = new(appealmocks.Notifier) s.mockAuditLogger = new(appealmocks.AuditLogger) @@ -63,7 +61,6 @@ func (s *ServiceTestSuite) setup() { s.mockPolicyService, s.mockGrantService, s.mockIAMManager, - s.mockMetadataManager, s.mockNotifier, validator.New(), log.NewNoop(), diff --git a/core/policy/service.go b/core/policy/service.go index 360e132c2..fbc3da9f3 100644 --- a/core/policy/service.go +++ b/core/policy/service.go @@ -2,6 +2,7 @@ package policy import ( "context" + "encoding/json" "fmt" "reflect" "regexp" @@ -50,6 +51,7 @@ type Service struct { providerService providerService iam domain.IAMManager + crypto domain.Crypto validator *validator.Validate logger log.Logger auditLogger auditLogger @@ -61,6 +63,7 @@ type ServiceDeps struct { ProviderService providerService IAMManager domain.IAMManager + Crypto domain.Crypto Validator *validator.Validate Logger log.Logger AuditLogger auditLogger @@ -74,6 +77,7 @@ func NewService(deps ServiceDeps) *Service { deps.ProviderService, deps.IAMManager, + deps.Crypto, deps.Validator, deps.Logger, deps.AuditLogger, @@ -105,6 +109,13 @@ func (s *Service) Create(ctx context.Context, p *domain.Policy) error { p.IAM.Config = sensitiveConfig } + if p.HasAppealMetadataSources() { + err := s.encryptAppealMetadata(p) + if err != nil { + return err + } + } + if !isDryRun(ctx) { if err := s.repository.Create(ctx, p); err != nil { return err @@ -121,6 +132,13 @@ func (s *Service) Create(ctx context.Context, p *domain.Policy) error { } } + if p.HasAppealMetadataSources() { + err := s.decryptAppealMetadata(p) + if err != nil { + return err + } + } + return nil } @@ -137,6 +155,13 @@ func (s *Service) Find(ctx context.Context) ([]*domain.Policy, error) { return nil, err } } + + if p.AppealMetadataSources != nil { + err := s.decryptAppealMetadata(p) + if err != nil { + return nil, err + } + } } return policies, nil } @@ -154,6 +179,11 @@ func (s *Service) GetOne(ctx context.Context, id string, version uint) (*domain. } } + err = s.decryptAppealMetadata(p) + if err != nil { + return nil, err + } + return p, nil } @@ -189,6 +219,13 @@ func (s *Service) Update(ctx context.Context, p *domain.Policy) error { p.IAM.Config = sensitiveConfig } + if p.HasAppealMetadataSources() { + err := s.encryptAppealMetadata(p) + if err != nil { + return err + } + } + p.Version = latestPolicy.Version + 1 if !isDryRun(ctx) { @@ -206,6 +243,49 @@ func (s *Service) Update(ctx context.Context, p *domain.Policy) error { return err } } + + if p.HasAppealMetadataSources() { + err := s.decryptAppealMetadata(p) + if err != nil { + return err + } + } + + return nil +} + +func (s *Service) encryptAppealMetadata(p *domain.Policy) error { + for key, metadataSourceCfg := range p.AppealMetadataSources { + metadataJson, err := json.Marshal(metadataSourceCfg.Config.Auth) + if err != nil { + return fmt.Errorf("error marshalling metadata into json") + } + encryptedAuth, err := s.crypto.Encrypt(string(metadataJson)) + if err != nil { + return fmt.Errorf("error encrypting metadata config: %w", err) + } + + p.AppealMetadataSources[key].Config.Auth = encryptedAuth + } + return nil +} + +func (s *Service) decryptAppealMetadata(p *domain.Policy) error { + for key, metadataSourceCfg := range p.AppealMetadataSources { + decryptedAuth, err := s.crypto.Decrypt(metadataSourceCfg.Config.Auth.(string)) + if err != nil { + return fmt.Errorf("error decrypting metadata config: %w", err) + } + + var auth interface{} + err = json.Unmarshal([]byte(decryptedAuth), &auth) + if err != nil { + return fmt.Errorf("error marshalling metadata into json") + } + + p.AppealMetadataSources[key].Config.Auth = auth + } + return nil } @@ -264,6 +344,39 @@ func (s *Service) validatePolicy(ctx context.Context, p *domain.Policy, excluded } } + if p.HasAppealMetadataSources() { + for key, metadataSource := range p.AppealMetadataSources { + if err := s.validateAppealMetadataSource(ctx, metadataSource); err != nil { + return fmt.Errorf("invalid appeal metadata source: %s : %w", key, err) + } + } + } + + return nil +} + +func (s *Service) validateAppealMetadataSource(ctx context.Context, metadataSource *domain.AppealMetadataSource) error { + if metadataSource.Name == "" { + return fmt.Errorf("name should not be empty") + } + + if metadataSource.Value == nil { + return fmt.Errorf("value should not be empty") + } + + switch metadataSource.Type { + case "http": + if metadataSource.Config == nil { + return fmt.Errorf("config is required for type 'http'") + } + case "static": + if metadataSource.Config != nil { + return fmt.Errorf("config is not allowed for type 'static'") + } + default: + return fmt.Errorf("type of metadata source is invalid") + } + return nil } diff --git a/core/policy/service_test.go b/core/policy/service_test.go index 3c72dcc26..53d1c04bf 100644 --- a/core/policy/service_test.go +++ b/core/policy/service_test.go @@ -43,6 +43,7 @@ func (s *ServiceTestSuite) SetupTest() { ResourceService: s.mockResourceService, ProviderService: s.mockProviderService, IAMManager: iamManager, + Crypto: &mocks.Crypto{}, AuditLogger: s.mockAuditLogger, Validator: validator.New(), }) diff --git a/domain/metadata.go b/domain/metadata.go deleted file mode 100644 index 9af2ac156..000000000 --- a/domain/metadata.go +++ /dev/null @@ -1,20 +0,0 @@ -package domain - -type AppealMetadataSource struct { - Name string `json:"name" yaml:"name"` - Description string `json:"description,omitempty" yaml:"description,omitempty"` - Type string `json:"type" yaml:"type"` - Config *AppealMetadataConfig `json:"config,omitempty" yaml:"config,omitempty"` - Value interface{} `json:"value" yaml:"value"` -} - -type AppealMetadataConfig struct { - URL string `json:"url" yaml:"url"` - AllowFailed bool `json:"allow_failed,omitempty" yaml:"allow_failed,omitempty"` - Headers map[string]string `json:"headers,omitempty" yaml:"headers,omitempty"` - Auth interface{} `json:"auth,omitempty" yaml:"auth,omitempty"` -} - -type MetadataManager interface { - ParseMetadataConfig(*AppealMetadataConfig) (SensitiveConfig, error) -} diff --git a/domain/policy.go b/domain/policy.go index e85096bbc..dd86c9c5f 100644 --- a/domain/policy.go +++ b/domain/policy.go @@ -312,6 +312,21 @@ type PolicyAppealConfig struct { AllowCreatorDetailsFailure bool `json:"allow_creator_details_failure" yaml:"allow_creator_details_failure"` } +type AppealMetadataSource struct { + Name string `json:"name" yaml:"name"` + Description string `json:"description,omitempty" yaml:"description,omitempty"` + Type string `json:"type" yaml:"type"` + Config *AppealMetadataConfig `json:"config,omitempty" yaml:"config,omitempty"` + Value interface{} `json:"value" yaml:"value"` +} + +type AppealMetadataConfig struct { + URL string `json:"url" yaml:"url"` + AllowFailed bool `json:"allow_failed,omitempty" yaml:"allow_failed,omitempty"` + Headers map[string]string `json:"headers,omitempty" yaml:"headers,omitempty"` + Auth interface{} `json:"auth,omitempty" yaml:"auth,omitempty"` +} + type Question struct { Key string `json:"key" yaml:"key"` Question string `json:"question" yaml:"question"` @@ -332,3 +347,7 @@ type AppealDurationOption struct { func (p *Policy) HasIAMConfig() bool { return p.IAM != nil } + +func (p *Policy) HasAppealMetadataSources() bool { + return p.AppealMetadataSources != nil +} diff --git a/internal/server/services.go b/internal/server/services.go index 98ed6f7df..8b4c349ec 100644 --- a/internal/server/services.go +++ b/internal/server/services.go @@ -143,6 +143,7 @@ func InitServices(deps ServiceDeps) (*Services, error) { ResourceService: resourceService, ProviderService: providerService, IAMManager: iamManager, + Crypto: deps.Crypto, Validator: deps.Validator, Logger: deps.Logger, AuditLogger: auditLogger, diff --git a/internal/store/postgres/model/policy.go b/internal/store/postgres/model/policy.go index 81ccbfdd2..7753cb2d6 100644 --- a/internal/store/postgres/model/policy.go +++ b/internal/store/postgres/model/policy.go @@ -11,17 +11,18 @@ import ( // Policy is the database model for policy type Policy struct { - ID string `gorm:"primaryKey"` - Version uint `gorm:"primaryKey"` - Description string - Steps datatypes.JSON - AppealConfig datatypes.JSON - Labels datatypes.JSON - Requirements datatypes.JSON - IAM datatypes.JSON - CreatedAt time.Time `gorm:"autoCreateTime"` - UpdatedAt time.Time `gorm:"autoUpdateTime"` - DeletedAt gorm.DeletedAt `gorm:"index"` + ID string `gorm:"primaryKey"` + Version uint `gorm:"primaryKey"` + Description string + Steps datatypes.JSON + AppealConfig datatypes.JSON + Labels datatypes.JSON + Requirements datatypes.JSON + IAM datatypes.JSON + AppealMetadataSources datatypes.JSON + CreatedAt time.Time `gorm:"autoCreateTime"` + UpdatedAt time.Time `gorm:"autoUpdateTime"` + DeletedAt gorm.DeletedAt `gorm:"index"` } // TableName overrides the table name @@ -56,6 +57,11 @@ func (m *Policy) FromDomain(p *domain.Policy) error { return err } + metadataSources, err := json.Marshal(p.AppealMetadataSources) + if err != nil { + return err + } + m.ID = p.ID m.Version = p.Version m.Description = p.Description @@ -64,6 +70,7 @@ func (m *Policy) FromDomain(p *domain.Policy) error { m.Labels = datatypes.JSON(labels) m.Requirements = datatypes.JSON(requirements) m.IAM = datatypes.JSON(iam) + m.AppealMetadataSources = datatypes.JSON(metadataSources) m.CreatedAt = p.CreatedAt m.UpdatedAt = p.UpdatedAt @@ -103,6 +110,13 @@ func (m *Policy) ToDomain() (*domain.Policy, error) { } } + var metadataSources map[string]*domain.AppealMetadataSource + if m.AppealMetadataSources != nil { + if err := json.Unmarshal(m.AppealMetadataSources, &metadataSources); err != nil { + return nil, err + } + } + return &domain.Policy{ ID: m.ID, Version: m.Version, diff --git a/pkg/http/http.go b/pkg/http/http.go new file mode 100644 index 000000000..db12b2898 --- /dev/null +++ b/pkg/http/http.go @@ -0,0 +1,146 @@ +package http + +import ( + "context" + "encoding/base64" + "errors" + "fmt" + "net/http" + + "github.com/go-playground/validator/v10" + "github.com/goto/guardian/domain" + "github.com/mcuadros/go-defaults" + "golang.org/x/oauth2" + "google.golang.org/api/idtoken" +) + +var ErrFailedRequest = errors.New("request failed") + +const UserIDWildcard = "{user_id}" + +type HTTPAuthConfig struct { + Type string `mapstructure:"type" json:"type" yaml:"type" validate:"required,oneof=basic api_key bearer google_idtoken"` + + // basic auth + Username string `mapstructure:"username,omitempty" json:"username,omitempty" yaml:"username,omitempty" validate:"required_if=Type basic"` + Password string `mapstructure:"password,omitempty" json:"password,omitempty" yaml:"password,omitempty" validate:"required_if=Type basic"` + + // api key + In string `mapstructure:"in,omitempty" json:"in,omitempty" yaml:"in,omitempty" validate:"required_if=Type api_key,omitempty,oneof=query header"` + Key string `mapstructure:"key,omitempty" json:"key,omitempty" yaml:"key,omitempty" validate:"required_if=Type api_key"` + Value string `mapstructure:"value,omitempty" json:"value,omitempty" yaml:"value,omitempty" validate:"required_if=Type api_key"` + + // bearer + Token string `mapstructure:"token,omitempty" json:"token,omitempty" yaml:"token,omitempty" validate:"required_if=Type bearer"` + + // google_idtoken + Audience string `mapstructure:"audience,omitempty" json:"audience,omitempty" yaml:"audience,omitempty" validate:"required_if=Type google_idtoken"` + // CredentialsJSON accept a JSON stringified credentials + // Deprecated: CredentialsJSON is deprecated, use CredentialsJSONBase64 instead + CredentialsJSON string `mapstructure:"credentials_json,omitempty" json:"credentials_json,omitempty" yaml:"credentials_json,omitempty"` + // CredentialsJSONBase64 accept a base64 encoded JSON stringified credentials + CredentialsJSONBase64 string `mapstructure:"credentials_json_base64,omitempty" json:"credentials_json_base64,omitempty" yaml:"credentials_json_base64,omitempty"` +} + +// HTTPClientConfig is the configuration required by iam.Client +type HTTPClientConfig struct { + URL string `mapstructure:"url" json:"url" yaml:"url" validate:"required,url"` + Headers map[string]string `mapstructure:"headers,omitempty" json:"headers,omitempty" yaml:"headers,omitempty"` + Auth *HTTPAuthConfig `mapstructure:"auth,omitempty" json:"auth,omitempty" yaml:"auth,omitempty" validate:"omitempty,dive"` + + HTTPClient *http.Client `mapstructure:"-" json:"-" yaml:"-"` + Validator *validator.Validate + Crypto domain.Crypto +} + +// HTTPClient wraps the http client for external approver resolver service +type HTTPClient struct { + httpClient *http.Client + config *HTTPClientConfig + + url string +} + +// NewHTTPClient returns *iam.Client +func NewHTTPClient(config *HTTPClientConfig) (*HTTPClient, error) { + defaults.SetDefaults(config) + if err := validator.New().Struct(config); err != nil { + return nil, err + } + httpClient := config.HTTPClient + if httpClient == nil { + httpClient = http.DefaultClient + } + + if config.Auth.Type == "google_idtoken" { + var creds []byte + switch { + case config.Auth.CredentialsJSONBase64 != "": + v, err := base64.StdEncoding.DecodeString(config.Auth.CredentialsJSONBase64) + if err != nil { + return nil, fmt.Errorf("decoding credentials_json_base64: %w", err) + } + creds = v + case config.Auth.CredentialsJSON != "": + creds = []byte(config.Auth.CredentialsJSON) + default: + return nil, fmt.Errorf("missing credentials for google_idtoken auth") + } + + ctx := context.Background() + ts, err := idtoken.NewTokenSource(ctx, config.Auth.Audience, idtoken.WithCredentialsJSON(creds)) + if err != nil { + return nil, err + } + httpClient = oauth2.NewClient(ctx, ts) + } + + return &HTTPClient{ + httpClient: httpClient, + config: config, + url: config.URL, + }, nil +} + +func (c *HTTPClient) setAuth(req *http.Request) { + if c.config.Auth != nil { + switch c.config.Auth.Type { + case "basic": + req.SetBasicAuth(c.config.Auth.Username, c.config.Auth.Password) + case "api_key": + switch c.config.Auth.In { + case "query": + q := req.URL.Query() + q.Add(c.config.Auth.Key, c.config.Auth.Value) + req.URL.RawQuery = q.Encode() + case "header": + req.Header.Add(c.config.Auth.Key, c.config.Auth.Value) + default: + } + case "bearer": + req.Header.Add("Authorization", "Bearer "+c.config.Auth.Token) + default: + } + } +} + +func (c *HTTPClient) MakeRequest() (*http.Response, error) { + req, err := http.NewRequest(http.MethodGet, c.config.URL, nil) + if err != nil { + return nil, err + } + + req.Header.Set("Accept", "application/json") + + for k, v := range c.config.Headers { + req.Header.Set(k, v) + } + c.setAuth(req) + + res, err := c.httpClient.Do(req) + if err != nil { + return nil, err + } + + return res, nil +} From 49ce61e65495f98a33e5f54f93af09482920e0c0 Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Mon, 25 Mar 2024 15:02:45 +0700 Subject: [PATCH 03/39] chore: db migration for appeal_metadata_sources column --- .../000019_add_metadata_sources_in_policy.down.sql | 6 ++++++ .../000019_add_metadata_sources_in_policy.up.sql | 8 ++++++++ 2 files changed, 14 insertions(+) create mode 100644 internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.down.sql create mode 100644 internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.up.sql diff --git a/internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.down.sql b/internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.down.sql new file mode 100644 index 000000000..4bc530249 --- /dev/null +++ b/internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.down.sql @@ -0,0 +1,6 @@ +BEGIN; + +ALTER TABLE + "policies" DROP COLUMN IF EXISTS "appeal_metadata_sources"; + +COMMIT; \ No newline at end of file diff --git a/internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.up.sql b/internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.up.sql new file mode 100644 index 000000000..a5ce359c8 --- /dev/null +++ b/internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.up.sql @@ -0,0 +1,8 @@ +BEGIN; + +ALTER TABLE + "policies" +ADD + COLUMN IF NOT EXISTS "appeal_metadata_sources" JSONB; + +COMMIT; \ No newline at end of file From f49140a3ea4ce710690d791b28c2c3352e80856e Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Mon, 25 Mar 2024 23:44:30 +0700 Subject: [PATCH 04/39] chore: generate proto --- api/handler/v1beta1/adapter.go | 37 ++ api/handler/v1beta1/policy.go | 3 +- .../guardian/v1beta1/guardian.pb.go | 629 +++++++++++------- .../guardian/v1beta1/guardian.swagger.json | 22 + 4 files changed, 442 insertions(+), 249 deletions(-) diff --git a/api/handler/v1beta1/adapter.go b/api/handler/v1beta1/adapter.go index 13b115821..f2084dfb9 100644 --- a/api/handler/v1beta1/adapter.go +++ b/api/handler/v1beta1/adapter.go @@ -338,6 +338,20 @@ func (a *adapter) FromPolicyProto(p *guardianv1beta1.Policy) *domain.Policy { } } + if mdSources := p.GetAppealMetadataSources(); mdSources != nil { + policy.AppealMetadataSources = map[string]*domain.AppealMetadataSource{} + + for key, mdSource := range p.GetAppealMetadataSources() { + policy.AppealMetadataSources[key] = &domain.AppealMetadataSource{ + Name: mdSource.GetName(), + Description: mdSource.GetDescription(), + Type: mdSource.GetType(), + Config: mdSource.GetConfig().AsInterface(), + Value: mdSource.GetValue().AsInterface(), + } + } + } + if p.GetCreatedAt() != nil { policy.CreatedAt = p.GetCreatedAt().AsTime() } @@ -446,6 +460,29 @@ func (a *adapter) ToPolicyProto(p *domain.Policy) (*guardianv1beta1.Policy, erro policyProto.Appeal = a.ToPolicyAppealConfigProto(p) + if p.AppealMetadataSources != nil { + policyProto.AppealMetadataSources = map[string]*guardianv1beta1.Policy_AppealMetadataSource{} + + for key, mdSource := range p.AppealMetadataSources { + cfg, err := structpb.NewValue(mdSource.Config) + if err != nil { + return nil, err + } + value, err := structpb.NewValue(mdSource.Value) + if err != nil { + return nil, err + } + + policyProto.AppealMetadataSources[key] = &guardianv1beta1.Policy_AppealMetadataSource{ + Name: mdSource.Name, + Description: mdSource.Description, + Type: mdSource.Type, + Config: cfg, + Value: value, + } + } + } + if !p.CreatedAt.IsZero() { policyProto.CreatedAt = timestamppb.New(p.CreatedAt) } diff --git a/api/handler/v1beta1/policy.go b/api/handler/v1beta1/policy.go index 5443245cd..3ce7d872e 100644 --- a/api/handler/v1beta1/policy.go +++ b/api/handler/v1beta1/policy.go @@ -82,7 +82,8 @@ func (s *GRPCServer) UpdatePolicy(ctx context.Context, req *guardianv1beta1.Upda if req.GetDryRun() { ctx = policy.WithDryRun(ctx) } - p := s.adapter.FromPolicyProto(req.GetPolicy()) + pp := req.GetPolicy() + p := s.adapter.FromPolicyProto(pp) p.ID = req.GetId() if err := s.policyService.Update(ctx, p); err != nil { diff --git a/api/proto/gotocompany/guardian/v1beta1/guardian.pb.go b/api/proto/gotocompany/guardian/v1beta1/guardian.pb.go index b56bb9ca4..fd7461816 100644 --- a/api/proto/gotocompany/guardian/v1beta1/guardian.pb.go +++ b/api/proto/gotocompany/guardian/v1beta1/guardian.pb.go @@ -5165,16 +5165,17 @@ type Policy struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` - Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` - Steps []*Policy_ApprovalStep `protobuf:"bytes,4,rep,name=steps,proto3" json:"steps,omitempty"` - Labels map[string]string `protobuf:"bytes,5,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - CreatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` - UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` - Requirements []*Policy_Requirement `protobuf:"bytes,8,rep,name=requirements,proto3" json:"requirements,omitempty"` - Iam *Policy_IAM `protobuf:"bytes,9,opt,name=iam,proto3" json:"iam,omitempty"` - Appeal *PolicyAppealConfig `protobuf:"bytes,10,opt,name=appeal,proto3" json:"appeal,omitempty"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + Steps []*Policy_ApprovalStep `protobuf:"bytes,4,rep,name=steps,proto3" json:"steps,omitempty"` + Labels map[string]string `protobuf:"bytes,5,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + Requirements []*Policy_Requirement `protobuf:"bytes,8,rep,name=requirements,proto3" json:"requirements,omitempty"` + Iam *Policy_IAM `protobuf:"bytes,9,opt,name=iam,proto3" json:"iam,omitempty"` + Appeal *PolicyAppealConfig `protobuf:"bytes,10,opt,name=appeal,proto3" json:"appeal,omitempty"` + AppealMetadataSources map[string]*Policy_AppealMetadataSource `protobuf:"bytes,11,rep,name=appeal_metadata_sources,json=appealMetadataSources,proto3" json:"appeal_metadata_sources,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *Policy) Reset() { @@ -5279,6 +5280,13 @@ func (x *Policy) GetAppeal() *PolicyAppealConfig { return nil } +func (x *Policy) GetAppealMetadataSources() map[string]*Policy_AppealMetadataSource { + if x != nil { + return x.AppealMetadataSources + } + return nil +} + type AppealOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -6944,6 +6952,85 @@ func (x *Policy_IAM) GetSchema() map[string]string { return nil } +type Policy_AppealMetadataSource struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` + Config *structpb.Value `protobuf:"bytes,4,opt,name=config,proto3" json:"config,omitempty"` + Value *structpb.Value `protobuf:"bytes,5,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *Policy_AppealMetadataSource) Reset() { + *x = Policy_AppealMetadataSource{} + if protoimpl.UnsafeEnabled { + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[106] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Policy_AppealMetadataSource) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Policy_AppealMetadataSource) ProtoMessage() {} + +func (x *Policy_AppealMetadataSource) ProtoReflect() protoreflect.Message { + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[106] + 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 Policy_AppealMetadataSource.ProtoReflect.Descriptor instead. +func (*Policy_AppealMetadataSource) Descriptor() ([]byte, []int) { + return file_gotocompany_guardian_v1beta1_guardian_proto_rawDescGZIP(), []int{85, 4} +} + +func (x *Policy_AppealMetadataSource) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Policy_AppealMetadataSource) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *Policy_AppealMetadataSource) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *Policy_AppealMetadataSource) GetConfig() *structpb.Value { + if x != nil { + return x.Config + } + return nil +} + +func (x *Policy_AppealMetadataSource) GetValue() *structpb.Value { + if x != nil { + return x.Value + } + return nil +} + type Policy_Requirement_RequirementTrigger struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -6961,7 +7048,7 @@ type Policy_Requirement_RequirementTrigger struct { func (x *Policy_Requirement_RequirementTrigger) Reset() { *x = Policy_Requirement_RequirementTrigger{} if protoimpl.UnsafeEnabled { - mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[106] + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[108] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6974,7 +7061,7 @@ func (x *Policy_Requirement_RequirementTrigger) String() string { func (*Policy_Requirement_RequirementTrigger) ProtoMessage() {} func (x *Policy_Requirement_RequirementTrigger) ProtoReflect() protoreflect.Message { - mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[106] + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[108] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7053,7 +7140,7 @@ type Policy_Requirement_AdditionalAppeal struct { func (x *Policy_Requirement_AdditionalAppeal) Reset() { *x = Policy_Requirement_AdditionalAppeal{} if protoimpl.UnsafeEnabled { - mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[107] + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[109] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7066,7 +7153,7 @@ func (x *Policy_Requirement_AdditionalAppeal) String() string { func (*Policy_Requirement_AdditionalAppeal) ProtoMessage() {} func (x *Policy_Requirement_AdditionalAppeal) ProtoReflect() protoreflect.Message { - mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[107] + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[109] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7125,7 +7212,7 @@ type Policy_Requirement_AdditionalAppeal_ResourceIdentifier struct { func (x *Policy_Requirement_AdditionalAppeal_ResourceIdentifier) Reset() { *x = Policy_Requirement_AdditionalAppeal_ResourceIdentifier{} if protoimpl.UnsafeEnabled { - mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[108] + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[110] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7138,7 +7225,7 @@ func (x *Policy_Requirement_AdditionalAppeal_ResourceIdentifier) String() string func (*Policy_Requirement_AdditionalAppeal_ResourceIdentifier) ProtoMessage() {} func (x *Policy_Requirement_AdditionalAppeal_ResourceIdentifier) ProtoReflect() protoreflect.Message { - mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[108] + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[110] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7961,7 +8048,7 @@ var file_gotocompany_guardian_v1beta1_guardian_proto_rawDesc = []byte{ 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0xf4, 0x0f, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0e, 0x0a, + 0x6f, 0x6e, 0x22, 0xb4, 0x13, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, @@ -7996,98 +8083,126 @@ var file_gotocompany_guardian_v1beta1_guardian_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x1a, 0xff, - 0x01, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x53, 0x74, 0x65, 0x70, 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, 0x21, 0x0a, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x66, - 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x77, 0x68, 0x65, 0x6e, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x77, 0x68, 0x65, 0x6e, 0x12, 0x1a, 0x0a, 0x08, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x70, 0x70, 0x72, - 0x6f, 0x76, 0x65, 0x5f, 0x69, 0x66, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, - 0x70, 0x72, 0x6f, 0x76, 0x65, 0x49, 0x66, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x70, 0x70, 0x72, 0x6f, - 0x76, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, 0x70, 0x72, - 0x6f, 0x76, 0x65, 0x72, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0f, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, - 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, - 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x9e, 0x07, 0x0a, 0x0b, - 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x53, 0x0a, 0x02, 0x6f, - 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, - 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x02, 0x6f, 0x6e, - 0x12, 0x5b, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x41, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x12, 0x77, + 0x0a, 0x17, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x3f, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, + 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x15, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0xff, 0x01, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x72, + 0x6f, 0x76, 0x61, 0x6c, 0x53, 0x74, 0x65, 0x70, 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, 0x21, + 0x0a, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x46, 0x61, 0x69, 0x6c, 0x65, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x77, 0x68, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x77, 0x68, 0x65, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, + 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, + 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x5f, 0x69, 0x66, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x49, 0x66, + 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x12, 0x29, + 0x0a, 0x10, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x61, 0x73, + 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, + 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, + 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x9e, 0x07, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x53, 0x0a, 0x02, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x43, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, + 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x72, + 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x02, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x07, 0x61, 0x70, 0x70, + 0x65, 0x61, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x67, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, + 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x64, 0x64, + 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x52, 0x07, 0x61, + 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x1a, 0xa1, 0x02, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x69, + 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x23, 0x0a, + 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x75, + 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x55, 0x72, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x72, 0x6e, 0x12, 0x12, 0x0a, + 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, + 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, + 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, + 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, + 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0xb8, 0x03, 0x0a, 0x10, 0x41, + 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x12, + 0x70, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x54, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x41, 0x70, - 0x70, 0x65, 0x61, 0x6c, 0x52, 0x07, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x1a, 0xa1, 0x02, - 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x69, - 0x67, 0x67, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6e, 0x12, 0x23, 0x0a, 0x0d, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x72, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x55, 0x72, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, + 0x70, 0x65, 0x61, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, + 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x06, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, - 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x1a, 0xb8, 0x03, 0x0a, 0x10, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, - 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x12, 0x70, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x54, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, - 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x64, 0x64, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x08, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x07, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, - 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, - 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x70, 0x70, - 0x65, 0x61, 0x6c, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, + 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, + 0x63, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x1a, 0x92, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6e, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x75, 0x72, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x1a, 0xda, 0x01, 0x0a, 0x03, 0x49, 0x41, 0x4d, 0x12, 0x1a, 0x0a, + 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x06, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4c, 0x0a, 0x06, 0x73, 0x63, 0x68, + 0x65, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, + 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, + 0x49, 0x41, 0x4d, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x1a, 0x39, 0x0a, 0x0b, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, + 0x38, 0x01, 0x1a, 0xbe, 0x01, 0x0a, 0x14, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 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, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x1a, 0x83, 0x01, 0x0a, 0x1a, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x1a, 0x92, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x23, - 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, - 0x75, 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x55, 0x72, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, - 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6e, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x1a, 0xda, 0x01, 0x0a, - 0x03, 0x49, 0x41, 0x4d, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x12, 0x2e, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x12, 0x4c, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, - 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x49, 0x41, 0x4d, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x1a, 0x39, - 0x0a, 0x0b, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, - 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x70, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, @@ -8711,7 +8826,7 @@ func file_gotocompany_guardian_v1beta1_guardian_proto_rawDescGZIP() []byte { return file_gotocompany_guardian_v1beta1_guardian_proto_rawDescData } -var file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes = make([]protoimpl.MessageInfo, 112) +var file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes = make([]protoimpl.MessageInfo, 114) var file_gotocompany_guardian_v1beta1_guardian_proto_goTypes = []interface{}{ (*ListProvidersRequest)(nil), // 0: gotocompany.guardian.v1beta1.ListProvidersRequest (*ListProvidersResponse)(nil), // 1: gotocompany.guardian.v1beta1.ListProvidersResponse @@ -8819,15 +8934,17 @@ var file_gotocompany_guardian_v1beta1_guardian_proto_goTypes = []interface{}{ nil, // 103: gotocompany.guardian.v1beta1.Policy.LabelsEntry (*Policy_Requirement)(nil), // 104: gotocompany.guardian.v1beta1.Policy.Requirement (*Policy_IAM)(nil), // 105: gotocompany.guardian.v1beta1.Policy.IAM - (*Policy_Requirement_RequirementTrigger)(nil), // 106: gotocompany.guardian.v1beta1.Policy.Requirement.RequirementTrigger - (*Policy_Requirement_AdditionalAppeal)(nil), // 107: gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal - (*Policy_Requirement_AdditionalAppeal_ResourceIdentifier)(nil), // 108: gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal.ResourceIdentifier - nil, // 109: gotocompany.guardian.v1beta1.Policy.IAM.SchemaEntry - nil, // 110: gotocompany.guardian.v1beta1.Appeal.LabelsEntry - nil, // 111: gotocompany.guardian.v1beta1.Resource.LabelsEntry - (*timestamppb.Timestamp)(nil), // 112: google.protobuf.Timestamp - (*structpb.Value)(nil), // 113: google.protobuf.Value - (*structpb.Struct)(nil), // 114: google.protobuf.Struct + (*Policy_AppealMetadataSource)(nil), // 106: gotocompany.guardian.v1beta1.Policy.AppealMetadataSource + nil, // 107: gotocompany.guardian.v1beta1.Policy.AppealMetadataSourcesEntry + (*Policy_Requirement_RequirementTrigger)(nil), // 108: gotocompany.guardian.v1beta1.Policy.Requirement.RequirementTrigger + (*Policy_Requirement_AdditionalAppeal)(nil), // 109: gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal + (*Policy_Requirement_AdditionalAppeal_ResourceIdentifier)(nil), // 110: gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal.ResourceIdentifier + nil, // 111: gotocompany.guardian.v1beta1.Policy.IAM.SchemaEntry + nil, // 112: gotocompany.guardian.v1beta1.Appeal.LabelsEntry + nil, // 113: gotocompany.guardian.v1beta1.Resource.LabelsEntry + (*timestamppb.Timestamp)(nil), // 114: google.protobuf.Timestamp + (*structpb.Value)(nil), // 115: google.protobuf.Value + (*structpb.Struct)(nil), // 116: google.protobuf.Struct } var file_gotocompany_guardian_v1beta1_guardian_proto_depIdxs = []int32{ 81, // 0: gotocompany.guardian.v1beta1.ListProvidersResponse.providers:type_name -> gotocompany.guardian.v1beta1.Provider @@ -8839,12 +8956,12 @@ var file_gotocompany_guardian_v1beta1_guardian_proto_depIdxs = []int32{ 81, // 6: gotocompany.guardian.v1beta1.UpdateProviderResponse.provider:type_name -> gotocompany.guardian.v1beta1.Provider 90, // 7: gotocompany.guardian.v1beta1.ImportGrantsFromProviderResponse.grants:type_name -> gotocompany.guardian.v1beta1.Grant 78, // 8: gotocompany.guardian.v1beta1.ListRolesResponse.roles:type_name -> gotocompany.guardian.v1beta1.Role - 112, // 9: gotocompany.guardian.v1beta1.ImportActivitiesRequest.timestamp_gte:type_name -> google.protobuf.Timestamp - 112, // 10: gotocompany.guardian.v1beta1.ImportActivitiesRequest.timestamp_lte:type_name -> google.protobuf.Timestamp + 114, // 9: gotocompany.guardian.v1beta1.ImportActivitiesRequest.timestamp_gte:type_name -> google.protobuf.Timestamp + 114, // 10: gotocompany.guardian.v1beta1.ImportActivitiesRequest.timestamp_lte:type_name -> google.protobuf.Timestamp 91, // 11: gotocompany.guardian.v1beta1.ImportActivitiesResponse.activities:type_name -> gotocompany.guardian.v1beta1.ProviderActivity 91, // 12: gotocompany.guardian.v1beta1.GetActivityResponse.activity:type_name -> gotocompany.guardian.v1beta1.ProviderActivity - 112, // 13: gotocompany.guardian.v1beta1.ListActivitiesRequest.timestamp_gte:type_name -> google.protobuf.Timestamp - 112, // 14: gotocompany.guardian.v1beta1.ListActivitiesRequest.timestamp_lte:type_name -> google.protobuf.Timestamp + 114, // 13: gotocompany.guardian.v1beta1.ListActivitiesRequest.timestamp_gte:type_name -> google.protobuf.Timestamp + 114, // 14: gotocompany.guardian.v1beta1.ListActivitiesRequest.timestamp_lte:type_name -> google.protobuf.Timestamp 91, // 15: gotocompany.guardian.v1beta1.ListActivitiesResponse.activities:type_name -> gotocompany.guardian.v1beta1.ProviderActivity 85, // 16: gotocompany.guardian.v1beta1.ListPoliciesResponse.policies:type_name -> gotocompany.guardian.v1beta1.Policy 84, // 17: gotocompany.guardian.v1beta1.GetPolicyPreferencesResponse.appeal:type_name -> gotocompany.guardian.v1beta1.PolicyAppealConfig @@ -8878,146 +8995,150 @@ var file_gotocompany_guardian_v1beta1_guardian_proto_depIdxs = []int32{ 90, // 45: gotocompany.guardian.v1beta1.UpdateGrantResponse.grant:type_name -> gotocompany.guardian.v1beta1.Grant 90, // 46: gotocompany.guardian.v1beta1.RevokeGrantResponse.grant:type_name -> gotocompany.guardian.v1beta1.Grant 90, // 47: gotocompany.guardian.v1beta1.RevokeGrantsResponse.grants:type_name -> gotocompany.guardian.v1beta1.Grant - 113, // 48: gotocompany.guardian.v1beta1.Role.permissions:type_name -> google.protobuf.Value + 115, // 48: gotocompany.guardian.v1beta1.Role.permissions:type_name -> google.protobuf.Value 95, // 49: gotocompany.guardian.v1beta1.ProviderConfig.labels:type_name -> gotocompany.guardian.v1beta1.ProviderConfig.LabelsEntry - 113, // 50: gotocompany.guardian.v1beta1.ProviderConfig.credentials:type_name -> google.protobuf.Value + 115, // 50: gotocompany.guardian.v1beta1.ProviderConfig.credentials:type_name -> google.protobuf.Value 96, // 51: gotocompany.guardian.v1beta1.ProviderConfig.appeal:type_name -> gotocompany.guardian.v1beta1.ProviderConfig.AppealConfig 97, // 52: gotocompany.guardian.v1beta1.ProviderConfig.resources:type_name -> gotocompany.guardian.v1beta1.ProviderConfig.ResourceConfig 98, // 53: gotocompany.guardian.v1beta1.ProviderConfig.parameters:type_name -> gotocompany.guardian.v1beta1.ProviderConfig.ProviderParameter 80, // 54: gotocompany.guardian.v1beta1.Provider.config:type_name -> gotocompany.guardian.v1beta1.ProviderConfig - 112, // 55: gotocompany.guardian.v1beta1.Provider.created_at:type_name -> google.protobuf.Timestamp - 112, // 56: gotocompany.guardian.v1beta1.Provider.updated_at:type_name -> google.protobuf.Timestamp + 114, // 55: gotocompany.guardian.v1beta1.Provider.created_at:type_name -> google.protobuf.Timestamp + 114, // 56: gotocompany.guardian.v1beta1.Provider.updated_at:type_name -> google.protobuf.Timestamp 99, // 57: gotocompany.guardian.v1beta1.Condition.match:type_name -> gotocompany.guardian.v1beta1.Condition.MatchCondition 100, // 58: gotocompany.guardian.v1beta1.PolicyAppealConfig.duration_options:type_name -> gotocompany.guardian.v1beta1.PolicyAppealConfig.DurationOptions 101, // 59: gotocompany.guardian.v1beta1.PolicyAppealConfig.questions:type_name -> gotocompany.guardian.v1beta1.PolicyAppealConfig.Question 102, // 60: gotocompany.guardian.v1beta1.Policy.steps:type_name -> gotocompany.guardian.v1beta1.Policy.ApprovalStep 103, // 61: gotocompany.guardian.v1beta1.Policy.labels:type_name -> gotocompany.guardian.v1beta1.Policy.LabelsEntry - 112, // 62: gotocompany.guardian.v1beta1.Policy.created_at:type_name -> google.protobuf.Timestamp - 112, // 63: gotocompany.guardian.v1beta1.Policy.updated_at:type_name -> google.protobuf.Timestamp + 114, // 62: gotocompany.guardian.v1beta1.Policy.created_at:type_name -> google.protobuf.Timestamp + 114, // 63: gotocompany.guardian.v1beta1.Policy.updated_at:type_name -> google.protobuf.Timestamp 104, // 64: gotocompany.guardian.v1beta1.Policy.requirements:type_name -> gotocompany.guardian.v1beta1.Policy.Requirement 105, // 65: gotocompany.guardian.v1beta1.Policy.iam:type_name -> gotocompany.guardian.v1beta1.Policy.IAM 84, // 66: gotocompany.guardian.v1beta1.Policy.appeal:type_name -> gotocompany.guardian.v1beta1.PolicyAppealConfig - 112, // 67: gotocompany.guardian.v1beta1.AppealOptions.expiration_date:type_name -> google.protobuf.Timestamp - 86, // 68: gotocompany.guardian.v1beta1.Appeal.options:type_name -> gotocompany.guardian.v1beta1.AppealOptions - 110, // 69: gotocompany.guardian.v1beta1.Appeal.labels:type_name -> gotocompany.guardian.v1beta1.Appeal.LabelsEntry - 89, // 70: gotocompany.guardian.v1beta1.Appeal.resource:type_name -> gotocompany.guardian.v1beta1.Resource - 88, // 71: gotocompany.guardian.v1beta1.Appeal.approvals:type_name -> gotocompany.guardian.v1beta1.Approval - 112, // 72: gotocompany.guardian.v1beta1.Appeal.created_at:type_name -> google.protobuf.Timestamp - 112, // 73: gotocompany.guardian.v1beta1.Appeal.updated_at:type_name -> google.protobuf.Timestamp - 114, // 74: gotocompany.guardian.v1beta1.Appeal.details:type_name -> google.protobuf.Struct - 113, // 75: gotocompany.guardian.v1beta1.Appeal.creator:type_name -> google.protobuf.Value - 90, // 76: gotocompany.guardian.v1beta1.Appeal.grant:type_name -> gotocompany.guardian.v1beta1.Grant - 87, // 77: gotocompany.guardian.v1beta1.Approval.appeal:type_name -> gotocompany.guardian.v1beta1.Appeal - 112, // 78: gotocompany.guardian.v1beta1.Approval.created_at:type_name -> google.protobuf.Timestamp - 112, // 79: gotocompany.guardian.v1beta1.Approval.updated_at:type_name -> google.protobuf.Timestamp - 114, // 80: gotocompany.guardian.v1beta1.Resource.details:type_name -> google.protobuf.Struct - 111, // 81: gotocompany.guardian.v1beta1.Resource.labels:type_name -> gotocompany.guardian.v1beta1.Resource.LabelsEntry - 112, // 82: gotocompany.guardian.v1beta1.Resource.created_at:type_name -> google.protobuf.Timestamp - 112, // 83: gotocompany.guardian.v1beta1.Resource.updated_at:type_name -> google.protobuf.Timestamp - 89, // 84: gotocompany.guardian.v1beta1.Resource.children:type_name -> gotocompany.guardian.v1beta1.Resource - 112, // 85: gotocompany.guardian.v1beta1.Grant.expiration_date:type_name -> google.protobuf.Timestamp - 112, // 86: gotocompany.guardian.v1beta1.Grant.revoked_at:type_name -> google.protobuf.Timestamp - 112, // 87: gotocompany.guardian.v1beta1.Grant.created_at:type_name -> google.protobuf.Timestamp - 112, // 88: gotocompany.guardian.v1beta1.Grant.updated_at:type_name -> google.protobuf.Timestamp - 89, // 89: gotocompany.guardian.v1beta1.Grant.resource:type_name -> gotocompany.guardian.v1beta1.Resource - 87, // 90: gotocompany.guardian.v1beta1.Grant.appeal:type_name -> gotocompany.guardian.v1beta1.Appeal - 112, // 91: gotocompany.guardian.v1beta1.ProviderActivity.timestamp:type_name -> google.protobuf.Timestamp - 114, // 92: gotocompany.guardian.v1beta1.ProviderActivity.metadata:type_name -> google.protobuf.Struct - 112, // 93: gotocompany.guardian.v1beta1.ProviderActivity.created_at:type_name -> google.protobuf.Timestamp - 81, // 94: gotocompany.guardian.v1beta1.ProviderActivity.provider:type_name -> gotocompany.guardian.v1beta1.Provider - 89, // 95: gotocompany.guardian.v1beta1.ProviderActivity.resource:type_name -> gotocompany.guardian.v1beta1.Resource - 114, // 96: gotocompany.guardian.v1beta1.CreateAppealRequest.Resource.options:type_name -> google.protobuf.Struct - 114, // 97: gotocompany.guardian.v1beta1.CreateAppealRequest.Resource.details:type_name -> google.protobuf.Struct - 79, // 98: gotocompany.guardian.v1beta1.ProviderConfig.ResourceConfig.policy:type_name -> gotocompany.guardian.v1beta1.PolicyConfig - 78, // 99: gotocompany.guardian.v1beta1.ProviderConfig.ResourceConfig.roles:type_name -> gotocompany.guardian.v1beta1.Role - 113, // 100: gotocompany.guardian.v1beta1.Condition.MatchCondition.eq:type_name -> google.protobuf.Value - 106, // 101: gotocompany.guardian.v1beta1.Policy.Requirement.on:type_name -> gotocompany.guardian.v1beta1.Policy.Requirement.RequirementTrigger - 107, // 102: gotocompany.guardian.v1beta1.Policy.Requirement.appeals:type_name -> gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal - 113, // 103: gotocompany.guardian.v1beta1.Policy.IAM.config:type_name -> google.protobuf.Value - 109, // 104: gotocompany.guardian.v1beta1.Policy.IAM.schema:type_name -> gotocompany.guardian.v1beta1.Policy.IAM.SchemaEntry - 83, // 105: gotocompany.guardian.v1beta1.Policy.Requirement.RequirementTrigger.conditions:type_name -> gotocompany.guardian.v1beta1.Condition - 108, // 106: gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal.resource:type_name -> gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal.ResourceIdentifier - 86, // 107: gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal.options:type_name -> gotocompany.guardian.v1beta1.AppealOptions - 79, // 108: gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal.policy:type_name -> gotocompany.guardian.v1beta1.PolicyConfig - 0, // 109: gotocompany.guardian.v1beta1.GuardianService.ListProviders:input_type -> gotocompany.guardian.v1beta1.ListProvidersRequest - 2, // 110: gotocompany.guardian.v1beta1.GuardianService.GetProvider:input_type -> gotocompany.guardian.v1beta1.GetProviderRequest - 4, // 111: gotocompany.guardian.v1beta1.GuardianService.GetProviderTypes:input_type -> gotocompany.guardian.v1beta1.GetProviderTypesRequest - 6, // 112: gotocompany.guardian.v1beta1.GuardianService.CreateProvider:input_type -> gotocompany.guardian.v1beta1.CreateProviderRequest - 8, // 113: gotocompany.guardian.v1beta1.GuardianService.UpdateProvider:input_type -> gotocompany.guardian.v1beta1.UpdateProviderRequest - 10, // 114: gotocompany.guardian.v1beta1.GuardianService.DeleteProvider:input_type -> gotocompany.guardian.v1beta1.DeleteProviderRequest - 14, // 115: gotocompany.guardian.v1beta1.GuardianService.ListRoles:input_type -> gotocompany.guardian.v1beta1.ListRolesRequest - 16, // 116: gotocompany.guardian.v1beta1.GuardianService.ImportActivities:input_type -> gotocompany.guardian.v1beta1.ImportActivitiesRequest - 18, // 117: gotocompany.guardian.v1beta1.GuardianService.GetActivity:input_type -> gotocompany.guardian.v1beta1.GetActivityRequest - 20, // 118: gotocompany.guardian.v1beta1.GuardianService.ListActivities:input_type -> gotocompany.guardian.v1beta1.ListActivitiesRequest - 22, // 119: gotocompany.guardian.v1beta1.GuardianService.ListPolicies:input_type -> gotocompany.guardian.v1beta1.ListPoliciesRequest - 24, // 120: gotocompany.guardian.v1beta1.GuardianService.GetPolicy:input_type -> gotocompany.guardian.v1beta1.GetPolicyRequest - 28, // 121: gotocompany.guardian.v1beta1.GuardianService.CreatePolicy:input_type -> gotocompany.guardian.v1beta1.CreatePolicyRequest - 30, // 122: gotocompany.guardian.v1beta1.GuardianService.UpdatePolicy:input_type -> gotocompany.guardian.v1beta1.UpdatePolicyRequest - 25, // 123: gotocompany.guardian.v1beta1.GuardianService.GetPolicyPreferences:input_type -> gotocompany.guardian.v1beta1.GetPolicyPreferencesRequest - 32, // 124: gotocompany.guardian.v1beta1.GuardianService.ListResources:input_type -> gotocompany.guardian.v1beta1.ListResourcesRequest - 34, // 125: gotocompany.guardian.v1beta1.GuardianService.GetResource:input_type -> gotocompany.guardian.v1beta1.GetResourceRequest - 36, // 126: gotocompany.guardian.v1beta1.GuardianService.UpdateResource:input_type -> gotocompany.guardian.v1beta1.UpdateResourceRequest - 38, // 127: gotocompany.guardian.v1beta1.GuardianService.DeleteResource:input_type -> gotocompany.guardian.v1beta1.DeleteResourceRequest - 40, // 128: gotocompany.guardian.v1beta1.GuardianService.ListUserAppeals:input_type -> gotocompany.guardian.v1beta1.ListUserAppealsRequest - 42, // 129: gotocompany.guardian.v1beta1.GuardianService.ListAppeals:input_type -> gotocompany.guardian.v1beta1.ListAppealsRequest - 44, // 130: gotocompany.guardian.v1beta1.GuardianService.GetAppeal:input_type -> gotocompany.guardian.v1beta1.GetAppealRequest - 46, // 131: gotocompany.guardian.v1beta1.GuardianService.CancelAppeal:input_type -> gotocompany.guardian.v1beta1.CancelAppealRequest - 52, // 132: gotocompany.guardian.v1beta1.GuardianService.CreateAppeal:input_type -> gotocompany.guardian.v1beta1.CreateAppealRequest - 54, // 133: gotocompany.guardian.v1beta1.GuardianService.ListUserApprovals:input_type -> gotocompany.guardian.v1beta1.ListUserApprovalsRequest - 56, // 134: gotocompany.guardian.v1beta1.GuardianService.ListApprovals:input_type -> gotocompany.guardian.v1beta1.ListApprovalsRequest - 58, // 135: gotocompany.guardian.v1beta1.GuardianService.UpdateApproval:input_type -> gotocompany.guardian.v1beta1.UpdateApprovalRequest - 60, // 136: gotocompany.guardian.v1beta1.GuardianService.AddApprover:input_type -> gotocompany.guardian.v1beta1.AddApproverRequest - 62, // 137: gotocompany.guardian.v1beta1.GuardianService.DeleteApprover:input_type -> gotocompany.guardian.v1beta1.DeleteApproverRequest - 64, // 138: gotocompany.guardian.v1beta1.GuardianService.ListGrants:input_type -> gotocompany.guardian.v1beta1.ListGrantsRequest - 66, // 139: gotocompany.guardian.v1beta1.GuardianService.ListUserGrants:input_type -> gotocompany.guardian.v1beta1.ListUserGrantsRequest - 68, // 140: gotocompany.guardian.v1beta1.GuardianService.ListUserRoles:input_type -> gotocompany.guardian.v1beta1.ListUserRolesRequest - 70, // 141: gotocompany.guardian.v1beta1.GuardianService.GetGrant:input_type -> gotocompany.guardian.v1beta1.GetGrantRequest - 72, // 142: gotocompany.guardian.v1beta1.GuardianService.UpdateGrant:input_type -> gotocompany.guardian.v1beta1.UpdateGrantRequest - 74, // 143: gotocompany.guardian.v1beta1.GuardianService.RevokeGrant:input_type -> gotocompany.guardian.v1beta1.RevokeGrantRequest - 76, // 144: gotocompany.guardian.v1beta1.GuardianService.RevokeGrants:input_type -> gotocompany.guardian.v1beta1.RevokeGrantsRequest - 12, // 145: gotocompany.guardian.v1beta1.GuardianService.ImportGrantsFromProvider:input_type -> gotocompany.guardian.v1beta1.ImportGrantsFromProviderRequest - 1, // 146: gotocompany.guardian.v1beta1.GuardianService.ListProviders:output_type -> gotocompany.guardian.v1beta1.ListProvidersResponse - 3, // 147: gotocompany.guardian.v1beta1.GuardianService.GetProvider:output_type -> gotocompany.guardian.v1beta1.GetProviderResponse - 5, // 148: gotocompany.guardian.v1beta1.GuardianService.GetProviderTypes:output_type -> gotocompany.guardian.v1beta1.GetProviderTypesResponse - 7, // 149: gotocompany.guardian.v1beta1.GuardianService.CreateProvider:output_type -> gotocompany.guardian.v1beta1.CreateProviderResponse - 9, // 150: gotocompany.guardian.v1beta1.GuardianService.UpdateProvider:output_type -> gotocompany.guardian.v1beta1.UpdateProviderResponse - 11, // 151: gotocompany.guardian.v1beta1.GuardianService.DeleteProvider:output_type -> gotocompany.guardian.v1beta1.DeleteProviderResponse - 15, // 152: gotocompany.guardian.v1beta1.GuardianService.ListRoles:output_type -> gotocompany.guardian.v1beta1.ListRolesResponse - 17, // 153: gotocompany.guardian.v1beta1.GuardianService.ImportActivities:output_type -> gotocompany.guardian.v1beta1.ImportActivitiesResponse - 19, // 154: gotocompany.guardian.v1beta1.GuardianService.GetActivity:output_type -> gotocompany.guardian.v1beta1.GetActivityResponse - 21, // 155: gotocompany.guardian.v1beta1.GuardianService.ListActivities:output_type -> gotocompany.guardian.v1beta1.ListActivitiesResponse - 23, // 156: gotocompany.guardian.v1beta1.GuardianService.ListPolicies:output_type -> gotocompany.guardian.v1beta1.ListPoliciesResponse - 27, // 157: gotocompany.guardian.v1beta1.GuardianService.GetPolicy:output_type -> gotocompany.guardian.v1beta1.GetPolicyResponse - 29, // 158: gotocompany.guardian.v1beta1.GuardianService.CreatePolicy:output_type -> gotocompany.guardian.v1beta1.CreatePolicyResponse - 31, // 159: gotocompany.guardian.v1beta1.GuardianService.UpdatePolicy:output_type -> gotocompany.guardian.v1beta1.UpdatePolicyResponse - 26, // 160: gotocompany.guardian.v1beta1.GuardianService.GetPolicyPreferences:output_type -> gotocompany.guardian.v1beta1.GetPolicyPreferencesResponse - 33, // 161: gotocompany.guardian.v1beta1.GuardianService.ListResources:output_type -> gotocompany.guardian.v1beta1.ListResourcesResponse - 35, // 162: gotocompany.guardian.v1beta1.GuardianService.GetResource:output_type -> gotocompany.guardian.v1beta1.GetResourceResponse - 37, // 163: gotocompany.guardian.v1beta1.GuardianService.UpdateResource:output_type -> gotocompany.guardian.v1beta1.UpdateResourceResponse - 39, // 164: gotocompany.guardian.v1beta1.GuardianService.DeleteResource:output_type -> gotocompany.guardian.v1beta1.DeleteResourceResponse - 41, // 165: gotocompany.guardian.v1beta1.GuardianService.ListUserAppeals:output_type -> gotocompany.guardian.v1beta1.ListUserAppealsResponse - 43, // 166: gotocompany.guardian.v1beta1.GuardianService.ListAppeals:output_type -> gotocompany.guardian.v1beta1.ListAppealsResponse - 45, // 167: gotocompany.guardian.v1beta1.GuardianService.GetAppeal:output_type -> gotocompany.guardian.v1beta1.GetAppealResponse - 47, // 168: gotocompany.guardian.v1beta1.GuardianService.CancelAppeal:output_type -> gotocompany.guardian.v1beta1.CancelAppealResponse - 53, // 169: gotocompany.guardian.v1beta1.GuardianService.CreateAppeal:output_type -> gotocompany.guardian.v1beta1.CreateAppealResponse - 55, // 170: gotocompany.guardian.v1beta1.GuardianService.ListUserApprovals:output_type -> gotocompany.guardian.v1beta1.ListUserApprovalsResponse - 57, // 171: gotocompany.guardian.v1beta1.GuardianService.ListApprovals:output_type -> gotocompany.guardian.v1beta1.ListApprovalsResponse - 59, // 172: gotocompany.guardian.v1beta1.GuardianService.UpdateApproval:output_type -> gotocompany.guardian.v1beta1.UpdateApprovalResponse - 61, // 173: gotocompany.guardian.v1beta1.GuardianService.AddApprover:output_type -> gotocompany.guardian.v1beta1.AddApproverResponse - 63, // 174: gotocompany.guardian.v1beta1.GuardianService.DeleteApprover:output_type -> gotocompany.guardian.v1beta1.DeleteApproverResponse - 65, // 175: gotocompany.guardian.v1beta1.GuardianService.ListGrants:output_type -> gotocompany.guardian.v1beta1.ListGrantsResponse - 67, // 176: gotocompany.guardian.v1beta1.GuardianService.ListUserGrants:output_type -> gotocompany.guardian.v1beta1.ListUserGrantsResponse - 69, // 177: gotocompany.guardian.v1beta1.GuardianService.ListUserRoles:output_type -> gotocompany.guardian.v1beta1.ListUserRolesResponse - 71, // 178: gotocompany.guardian.v1beta1.GuardianService.GetGrant:output_type -> gotocompany.guardian.v1beta1.GetGrantResponse - 73, // 179: gotocompany.guardian.v1beta1.GuardianService.UpdateGrant:output_type -> gotocompany.guardian.v1beta1.UpdateGrantResponse - 75, // 180: gotocompany.guardian.v1beta1.GuardianService.RevokeGrant:output_type -> gotocompany.guardian.v1beta1.RevokeGrantResponse - 77, // 181: gotocompany.guardian.v1beta1.GuardianService.RevokeGrants:output_type -> gotocompany.guardian.v1beta1.RevokeGrantsResponse - 13, // 182: gotocompany.guardian.v1beta1.GuardianService.ImportGrantsFromProvider:output_type -> gotocompany.guardian.v1beta1.ImportGrantsFromProviderResponse - 146, // [146:183] is the sub-list for method output_type - 109, // [109:146] is the sub-list for method input_type - 109, // [109:109] is the sub-list for extension type_name - 109, // [109:109] is the sub-list for extension extendee - 0, // [0:109] is the sub-list for field type_name + 107, // 67: gotocompany.guardian.v1beta1.Policy.appeal_metadata_sources:type_name -> gotocompany.guardian.v1beta1.Policy.AppealMetadataSourcesEntry + 114, // 68: gotocompany.guardian.v1beta1.AppealOptions.expiration_date:type_name -> google.protobuf.Timestamp + 86, // 69: gotocompany.guardian.v1beta1.Appeal.options:type_name -> gotocompany.guardian.v1beta1.AppealOptions + 112, // 70: gotocompany.guardian.v1beta1.Appeal.labels:type_name -> gotocompany.guardian.v1beta1.Appeal.LabelsEntry + 89, // 71: gotocompany.guardian.v1beta1.Appeal.resource:type_name -> gotocompany.guardian.v1beta1.Resource + 88, // 72: gotocompany.guardian.v1beta1.Appeal.approvals:type_name -> gotocompany.guardian.v1beta1.Approval + 114, // 73: gotocompany.guardian.v1beta1.Appeal.created_at:type_name -> google.protobuf.Timestamp + 114, // 74: gotocompany.guardian.v1beta1.Appeal.updated_at:type_name -> google.protobuf.Timestamp + 116, // 75: gotocompany.guardian.v1beta1.Appeal.details:type_name -> google.protobuf.Struct + 115, // 76: gotocompany.guardian.v1beta1.Appeal.creator:type_name -> google.protobuf.Value + 90, // 77: gotocompany.guardian.v1beta1.Appeal.grant:type_name -> gotocompany.guardian.v1beta1.Grant + 87, // 78: gotocompany.guardian.v1beta1.Approval.appeal:type_name -> gotocompany.guardian.v1beta1.Appeal + 114, // 79: gotocompany.guardian.v1beta1.Approval.created_at:type_name -> google.protobuf.Timestamp + 114, // 80: gotocompany.guardian.v1beta1.Approval.updated_at:type_name -> google.protobuf.Timestamp + 116, // 81: gotocompany.guardian.v1beta1.Resource.details:type_name -> google.protobuf.Struct + 113, // 82: gotocompany.guardian.v1beta1.Resource.labels:type_name -> gotocompany.guardian.v1beta1.Resource.LabelsEntry + 114, // 83: gotocompany.guardian.v1beta1.Resource.created_at:type_name -> google.protobuf.Timestamp + 114, // 84: gotocompany.guardian.v1beta1.Resource.updated_at:type_name -> google.protobuf.Timestamp + 89, // 85: gotocompany.guardian.v1beta1.Resource.children:type_name -> gotocompany.guardian.v1beta1.Resource + 114, // 86: gotocompany.guardian.v1beta1.Grant.expiration_date:type_name -> google.protobuf.Timestamp + 114, // 87: gotocompany.guardian.v1beta1.Grant.revoked_at:type_name -> google.protobuf.Timestamp + 114, // 88: gotocompany.guardian.v1beta1.Grant.created_at:type_name -> google.protobuf.Timestamp + 114, // 89: gotocompany.guardian.v1beta1.Grant.updated_at:type_name -> google.protobuf.Timestamp + 89, // 90: gotocompany.guardian.v1beta1.Grant.resource:type_name -> gotocompany.guardian.v1beta1.Resource + 87, // 91: gotocompany.guardian.v1beta1.Grant.appeal:type_name -> gotocompany.guardian.v1beta1.Appeal + 114, // 92: gotocompany.guardian.v1beta1.ProviderActivity.timestamp:type_name -> google.protobuf.Timestamp + 116, // 93: gotocompany.guardian.v1beta1.ProviderActivity.metadata:type_name -> google.protobuf.Struct + 114, // 94: gotocompany.guardian.v1beta1.ProviderActivity.created_at:type_name -> google.protobuf.Timestamp + 81, // 95: gotocompany.guardian.v1beta1.ProviderActivity.provider:type_name -> gotocompany.guardian.v1beta1.Provider + 89, // 96: gotocompany.guardian.v1beta1.ProviderActivity.resource:type_name -> gotocompany.guardian.v1beta1.Resource + 116, // 97: gotocompany.guardian.v1beta1.CreateAppealRequest.Resource.options:type_name -> google.protobuf.Struct + 116, // 98: gotocompany.guardian.v1beta1.CreateAppealRequest.Resource.details:type_name -> google.protobuf.Struct + 79, // 99: gotocompany.guardian.v1beta1.ProviderConfig.ResourceConfig.policy:type_name -> gotocompany.guardian.v1beta1.PolicyConfig + 78, // 100: gotocompany.guardian.v1beta1.ProviderConfig.ResourceConfig.roles:type_name -> gotocompany.guardian.v1beta1.Role + 115, // 101: gotocompany.guardian.v1beta1.Condition.MatchCondition.eq:type_name -> google.protobuf.Value + 108, // 102: gotocompany.guardian.v1beta1.Policy.Requirement.on:type_name -> gotocompany.guardian.v1beta1.Policy.Requirement.RequirementTrigger + 109, // 103: gotocompany.guardian.v1beta1.Policy.Requirement.appeals:type_name -> gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal + 115, // 104: gotocompany.guardian.v1beta1.Policy.IAM.config:type_name -> google.protobuf.Value + 111, // 105: gotocompany.guardian.v1beta1.Policy.IAM.schema:type_name -> gotocompany.guardian.v1beta1.Policy.IAM.SchemaEntry + 115, // 106: gotocompany.guardian.v1beta1.Policy.AppealMetadataSource.config:type_name -> google.protobuf.Value + 115, // 107: gotocompany.guardian.v1beta1.Policy.AppealMetadataSource.value:type_name -> google.protobuf.Value + 106, // 108: gotocompany.guardian.v1beta1.Policy.AppealMetadataSourcesEntry.value:type_name -> gotocompany.guardian.v1beta1.Policy.AppealMetadataSource + 83, // 109: gotocompany.guardian.v1beta1.Policy.Requirement.RequirementTrigger.conditions:type_name -> gotocompany.guardian.v1beta1.Condition + 110, // 110: gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal.resource:type_name -> gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal.ResourceIdentifier + 86, // 111: gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal.options:type_name -> gotocompany.guardian.v1beta1.AppealOptions + 79, // 112: gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal.policy:type_name -> gotocompany.guardian.v1beta1.PolicyConfig + 0, // 113: gotocompany.guardian.v1beta1.GuardianService.ListProviders:input_type -> gotocompany.guardian.v1beta1.ListProvidersRequest + 2, // 114: gotocompany.guardian.v1beta1.GuardianService.GetProvider:input_type -> gotocompany.guardian.v1beta1.GetProviderRequest + 4, // 115: gotocompany.guardian.v1beta1.GuardianService.GetProviderTypes:input_type -> gotocompany.guardian.v1beta1.GetProviderTypesRequest + 6, // 116: gotocompany.guardian.v1beta1.GuardianService.CreateProvider:input_type -> gotocompany.guardian.v1beta1.CreateProviderRequest + 8, // 117: gotocompany.guardian.v1beta1.GuardianService.UpdateProvider:input_type -> gotocompany.guardian.v1beta1.UpdateProviderRequest + 10, // 118: gotocompany.guardian.v1beta1.GuardianService.DeleteProvider:input_type -> gotocompany.guardian.v1beta1.DeleteProviderRequest + 14, // 119: gotocompany.guardian.v1beta1.GuardianService.ListRoles:input_type -> gotocompany.guardian.v1beta1.ListRolesRequest + 16, // 120: gotocompany.guardian.v1beta1.GuardianService.ImportActivities:input_type -> gotocompany.guardian.v1beta1.ImportActivitiesRequest + 18, // 121: gotocompany.guardian.v1beta1.GuardianService.GetActivity:input_type -> gotocompany.guardian.v1beta1.GetActivityRequest + 20, // 122: gotocompany.guardian.v1beta1.GuardianService.ListActivities:input_type -> gotocompany.guardian.v1beta1.ListActivitiesRequest + 22, // 123: gotocompany.guardian.v1beta1.GuardianService.ListPolicies:input_type -> gotocompany.guardian.v1beta1.ListPoliciesRequest + 24, // 124: gotocompany.guardian.v1beta1.GuardianService.GetPolicy:input_type -> gotocompany.guardian.v1beta1.GetPolicyRequest + 28, // 125: gotocompany.guardian.v1beta1.GuardianService.CreatePolicy:input_type -> gotocompany.guardian.v1beta1.CreatePolicyRequest + 30, // 126: gotocompany.guardian.v1beta1.GuardianService.UpdatePolicy:input_type -> gotocompany.guardian.v1beta1.UpdatePolicyRequest + 25, // 127: gotocompany.guardian.v1beta1.GuardianService.GetPolicyPreferences:input_type -> gotocompany.guardian.v1beta1.GetPolicyPreferencesRequest + 32, // 128: gotocompany.guardian.v1beta1.GuardianService.ListResources:input_type -> gotocompany.guardian.v1beta1.ListResourcesRequest + 34, // 129: gotocompany.guardian.v1beta1.GuardianService.GetResource:input_type -> gotocompany.guardian.v1beta1.GetResourceRequest + 36, // 130: gotocompany.guardian.v1beta1.GuardianService.UpdateResource:input_type -> gotocompany.guardian.v1beta1.UpdateResourceRequest + 38, // 131: gotocompany.guardian.v1beta1.GuardianService.DeleteResource:input_type -> gotocompany.guardian.v1beta1.DeleteResourceRequest + 40, // 132: gotocompany.guardian.v1beta1.GuardianService.ListUserAppeals:input_type -> gotocompany.guardian.v1beta1.ListUserAppealsRequest + 42, // 133: gotocompany.guardian.v1beta1.GuardianService.ListAppeals:input_type -> gotocompany.guardian.v1beta1.ListAppealsRequest + 44, // 134: gotocompany.guardian.v1beta1.GuardianService.GetAppeal:input_type -> gotocompany.guardian.v1beta1.GetAppealRequest + 46, // 135: gotocompany.guardian.v1beta1.GuardianService.CancelAppeal:input_type -> gotocompany.guardian.v1beta1.CancelAppealRequest + 52, // 136: gotocompany.guardian.v1beta1.GuardianService.CreateAppeal:input_type -> gotocompany.guardian.v1beta1.CreateAppealRequest + 54, // 137: gotocompany.guardian.v1beta1.GuardianService.ListUserApprovals:input_type -> gotocompany.guardian.v1beta1.ListUserApprovalsRequest + 56, // 138: gotocompany.guardian.v1beta1.GuardianService.ListApprovals:input_type -> gotocompany.guardian.v1beta1.ListApprovalsRequest + 58, // 139: gotocompany.guardian.v1beta1.GuardianService.UpdateApproval:input_type -> gotocompany.guardian.v1beta1.UpdateApprovalRequest + 60, // 140: gotocompany.guardian.v1beta1.GuardianService.AddApprover:input_type -> gotocompany.guardian.v1beta1.AddApproverRequest + 62, // 141: gotocompany.guardian.v1beta1.GuardianService.DeleteApprover:input_type -> gotocompany.guardian.v1beta1.DeleteApproverRequest + 64, // 142: gotocompany.guardian.v1beta1.GuardianService.ListGrants:input_type -> gotocompany.guardian.v1beta1.ListGrantsRequest + 66, // 143: gotocompany.guardian.v1beta1.GuardianService.ListUserGrants:input_type -> gotocompany.guardian.v1beta1.ListUserGrantsRequest + 68, // 144: gotocompany.guardian.v1beta1.GuardianService.ListUserRoles:input_type -> gotocompany.guardian.v1beta1.ListUserRolesRequest + 70, // 145: gotocompany.guardian.v1beta1.GuardianService.GetGrant:input_type -> gotocompany.guardian.v1beta1.GetGrantRequest + 72, // 146: gotocompany.guardian.v1beta1.GuardianService.UpdateGrant:input_type -> gotocompany.guardian.v1beta1.UpdateGrantRequest + 74, // 147: gotocompany.guardian.v1beta1.GuardianService.RevokeGrant:input_type -> gotocompany.guardian.v1beta1.RevokeGrantRequest + 76, // 148: gotocompany.guardian.v1beta1.GuardianService.RevokeGrants:input_type -> gotocompany.guardian.v1beta1.RevokeGrantsRequest + 12, // 149: gotocompany.guardian.v1beta1.GuardianService.ImportGrantsFromProvider:input_type -> gotocompany.guardian.v1beta1.ImportGrantsFromProviderRequest + 1, // 150: gotocompany.guardian.v1beta1.GuardianService.ListProviders:output_type -> gotocompany.guardian.v1beta1.ListProvidersResponse + 3, // 151: gotocompany.guardian.v1beta1.GuardianService.GetProvider:output_type -> gotocompany.guardian.v1beta1.GetProviderResponse + 5, // 152: gotocompany.guardian.v1beta1.GuardianService.GetProviderTypes:output_type -> gotocompany.guardian.v1beta1.GetProviderTypesResponse + 7, // 153: gotocompany.guardian.v1beta1.GuardianService.CreateProvider:output_type -> gotocompany.guardian.v1beta1.CreateProviderResponse + 9, // 154: gotocompany.guardian.v1beta1.GuardianService.UpdateProvider:output_type -> gotocompany.guardian.v1beta1.UpdateProviderResponse + 11, // 155: gotocompany.guardian.v1beta1.GuardianService.DeleteProvider:output_type -> gotocompany.guardian.v1beta1.DeleteProviderResponse + 15, // 156: gotocompany.guardian.v1beta1.GuardianService.ListRoles:output_type -> gotocompany.guardian.v1beta1.ListRolesResponse + 17, // 157: gotocompany.guardian.v1beta1.GuardianService.ImportActivities:output_type -> gotocompany.guardian.v1beta1.ImportActivitiesResponse + 19, // 158: gotocompany.guardian.v1beta1.GuardianService.GetActivity:output_type -> gotocompany.guardian.v1beta1.GetActivityResponse + 21, // 159: gotocompany.guardian.v1beta1.GuardianService.ListActivities:output_type -> gotocompany.guardian.v1beta1.ListActivitiesResponse + 23, // 160: gotocompany.guardian.v1beta1.GuardianService.ListPolicies:output_type -> gotocompany.guardian.v1beta1.ListPoliciesResponse + 27, // 161: gotocompany.guardian.v1beta1.GuardianService.GetPolicy:output_type -> gotocompany.guardian.v1beta1.GetPolicyResponse + 29, // 162: gotocompany.guardian.v1beta1.GuardianService.CreatePolicy:output_type -> gotocompany.guardian.v1beta1.CreatePolicyResponse + 31, // 163: gotocompany.guardian.v1beta1.GuardianService.UpdatePolicy:output_type -> gotocompany.guardian.v1beta1.UpdatePolicyResponse + 26, // 164: gotocompany.guardian.v1beta1.GuardianService.GetPolicyPreferences:output_type -> gotocompany.guardian.v1beta1.GetPolicyPreferencesResponse + 33, // 165: gotocompany.guardian.v1beta1.GuardianService.ListResources:output_type -> gotocompany.guardian.v1beta1.ListResourcesResponse + 35, // 166: gotocompany.guardian.v1beta1.GuardianService.GetResource:output_type -> gotocompany.guardian.v1beta1.GetResourceResponse + 37, // 167: gotocompany.guardian.v1beta1.GuardianService.UpdateResource:output_type -> gotocompany.guardian.v1beta1.UpdateResourceResponse + 39, // 168: gotocompany.guardian.v1beta1.GuardianService.DeleteResource:output_type -> gotocompany.guardian.v1beta1.DeleteResourceResponse + 41, // 169: gotocompany.guardian.v1beta1.GuardianService.ListUserAppeals:output_type -> gotocompany.guardian.v1beta1.ListUserAppealsResponse + 43, // 170: gotocompany.guardian.v1beta1.GuardianService.ListAppeals:output_type -> gotocompany.guardian.v1beta1.ListAppealsResponse + 45, // 171: gotocompany.guardian.v1beta1.GuardianService.GetAppeal:output_type -> gotocompany.guardian.v1beta1.GetAppealResponse + 47, // 172: gotocompany.guardian.v1beta1.GuardianService.CancelAppeal:output_type -> gotocompany.guardian.v1beta1.CancelAppealResponse + 53, // 173: gotocompany.guardian.v1beta1.GuardianService.CreateAppeal:output_type -> gotocompany.guardian.v1beta1.CreateAppealResponse + 55, // 174: gotocompany.guardian.v1beta1.GuardianService.ListUserApprovals:output_type -> gotocompany.guardian.v1beta1.ListUserApprovalsResponse + 57, // 175: gotocompany.guardian.v1beta1.GuardianService.ListApprovals:output_type -> gotocompany.guardian.v1beta1.ListApprovalsResponse + 59, // 176: gotocompany.guardian.v1beta1.GuardianService.UpdateApproval:output_type -> gotocompany.guardian.v1beta1.UpdateApprovalResponse + 61, // 177: gotocompany.guardian.v1beta1.GuardianService.AddApprover:output_type -> gotocompany.guardian.v1beta1.AddApproverResponse + 63, // 178: gotocompany.guardian.v1beta1.GuardianService.DeleteApprover:output_type -> gotocompany.guardian.v1beta1.DeleteApproverResponse + 65, // 179: gotocompany.guardian.v1beta1.GuardianService.ListGrants:output_type -> gotocompany.guardian.v1beta1.ListGrantsResponse + 67, // 180: gotocompany.guardian.v1beta1.GuardianService.ListUserGrants:output_type -> gotocompany.guardian.v1beta1.ListUserGrantsResponse + 69, // 181: gotocompany.guardian.v1beta1.GuardianService.ListUserRoles:output_type -> gotocompany.guardian.v1beta1.ListUserRolesResponse + 71, // 182: gotocompany.guardian.v1beta1.GuardianService.GetGrant:output_type -> gotocompany.guardian.v1beta1.GetGrantResponse + 73, // 183: gotocompany.guardian.v1beta1.GuardianService.UpdateGrant:output_type -> gotocompany.guardian.v1beta1.UpdateGrantResponse + 75, // 184: gotocompany.guardian.v1beta1.GuardianService.RevokeGrant:output_type -> gotocompany.guardian.v1beta1.RevokeGrantResponse + 77, // 185: gotocompany.guardian.v1beta1.GuardianService.RevokeGrants:output_type -> gotocompany.guardian.v1beta1.RevokeGrantsResponse + 13, // 186: gotocompany.guardian.v1beta1.GuardianService.ImportGrantsFromProvider:output_type -> gotocompany.guardian.v1beta1.ImportGrantsFromProviderResponse + 150, // [150:187] is the sub-list for method output_type + 113, // [113:150] is the sub-list for method input_type + 113, // [113:113] is the sub-list for extension type_name + 113, // [113:113] is the sub-list for extension extendee + 0, // [0:113] is the sub-list for field type_name } func init() { file_gotocompany_guardian_v1beta1_guardian_proto_init() } @@ -10275,6 +10396,18 @@ func file_gotocompany_guardian_v1beta1_guardian_proto_init() { } } file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[106].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Policy_AppealMetadataSource); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[108].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Policy_Requirement_RequirementTrigger); i { case 0: return &v.state @@ -10286,7 +10419,7 @@ func file_gotocompany_guardian_v1beta1_guardian_proto_init() { return nil } } - file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[107].Exporter = func(v interface{}, i int) interface{} { + file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[109].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Policy_Requirement_AdditionalAppeal); i { case 0: return &v.state @@ -10298,7 +10431,7 @@ func file_gotocompany_guardian_v1beta1_guardian_proto_init() { return nil } } - file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[108].Exporter = func(v interface{}, i int) interface{} { + file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[110].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Policy_Requirement_AdditionalAppeal_ResourceIdentifier); i { case 0: return &v.state @@ -10317,7 +10450,7 @@ func file_gotocompany_guardian_v1beta1_guardian_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_gotocompany_guardian_v1beta1_guardian_proto_rawDesc, NumEnums: 0, - NumMessages: 112, + NumMessages: 114, NumExtensions: 0, NumServices: 1, }, diff --git a/third_party/OpenAPI/gotocompany/guardian/v1beta1/guardian.swagger.json b/third_party/OpenAPI/gotocompany/guardian/v1beta1/guardian.swagger.json index 2bff5a263..5ddd01395 100644 --- a/third_party/OpenAPI/gotocompany/guardian/v1beta1/guardian.swagger.json +++ b/third_party/OpenAPI/gotocompany/guardian/v1beta1/guardian.swagger.json @@ -2072,6 +2072,22 @@ } } }, + "PolicyAppealMetadataSource": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "description": { + "type": "string" + }, + "type": { + "type": "string" + }, + "config": {}, + "value": {} + } + }, "PolicyApprovalStep": { "type": "object", "properties": { @@ -3019,6 +3035,12 @@ }, "appeal": { "$ref": "#/definitions/v1beta1PolicyAppealConfig" + }, + "appealMetadataSources": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/PolicyAppealMetadataSource" + } } }, "title": "Policy is a configurable steps for appeal's approval" From 9ef182c6aa0a4ef99b6b918a86dc15ebaf78a105 Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Tue, 26 Mar 2024 00:30:04 +0700 Subject: [PATCH 05/39] chore: change AppealMetadataSource.Config type to interface{}; encrypt and decrypt at Config level --- core/appeal/service.go | 36 ++++++------------- core/policy/metadata_source.go | 8 +++++ core/policy/service.go | 30 ++++------------ domain/policy.go | 15 -------- domain/policy_metadata_source.go | 48 +++++++++++++++++++++++++ domain/policy_metadata_source_test.go | 11 ++++++ internal/store/postgres/model/policy.go | 21 +++++------ pkg/http/http.go | 12 ------- plugins/identities/http.go | 20 ----------- plugins/identities/service.go | 10 ------ 10 files changed, 95 insertions(+), 116 deletions(-) create mode 100644 core/policy/metadata_source.go create mode 100644 domain/policy_metadata_source.go create mode 100644 domain/policy_metadata_source_test.go diff --git a/core/appeal/service.go b/core/appeal/service.go index 480cd3076..8b68da9fb 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -10,12 +10,14 @@ import ( "github.com/go-playground/validator/v10" "github.com/goto/guardian/core/grant" + "github.com/goto/guardian/core/policy" "github.com/goto/guardian/domain" "github.com/goto/guardian/pkg/evaluator" "github.com/goto/guardian/pkg/http" "github.com/goto/guardian/pkg/log" "github.com/goto/guardian/plugins/notifiers" "github.com/goto/guardian/utils" + "github.com/mitchellh/mapstructure" "golang.org/x/sync/errgroup" ) @@ -1147,18 +1149,23 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, eg.Go(func() error { switch metadata.Type { case "http": - if metadata.Config.URL == "" { + var cfg policy.AppealMetadataSourceConfigHTTP + if err := mapstructure.Decode(metadata.Config, &cfg); err != nil { + return fmt.Errorf("error decoding metadata config: %w", err) + } + + if cfg.URL == "" { return fmt.Errorf("URL cannot be empty for http type") } - metadataCl, err := s.getMetadataClient(metadata.Config) + metadataCl, err := http.NewHTTPClient(&cfg.HTTPClientConfig) if err != nil { return fmt.Errorf("key: %s, %w", key, err) } res, err := metadataCl.MakeRequest() if err != nil || (res.StatusCode < 200 && res.StatusCode > 300) { - if !metadata.Config.AllowFailed { + if !cfg.AllowFailed { return fmt.Errorf("error fetching resource: %w", err) } } @@ -1180,9 +1187,7 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, } appealMetadata[key] = value case "static": - params := map[string]interface{}{ - "appeal": a, - } + params := map[string]interface{}{"appeal": a} value, err := s.getMetadataValue(metadata.Type, key, metadata.Value, params) if err != nil { return fmt.Errorf("error parsing value: %w", err) @@ -1205,25 +1210,6 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, return nil } -func (s *Service) getMetadataClient(metadataCfg *domain.AppealMetadataConfig) (*http.HTTPClient, error) { - authCfg, ok := metadataCfg.Auth.(http.HTTPAuthConfig) - if !ok { - return nil, fmt.Errorf("invalid auth config") - } - metadataConfig := http.HTTPClientConfig{ - URL: metadataCfg.URL, - Headers: metadataCfg.Headers, - Auth: &authCfg, - } - - metadataCl, err := http.NewHTTPClient(&metadataConfig) - if err != nil { - return nil, fmt.Errorf("error initializing metadata client: %w", err) - } - - return metadataCl, nil -} - func (s *Service) getMetadataValue(metadataType string, key string, value interface{}, params map[string]interface{}) (interface{}, error) { result := make(map[string]interface{}) diff --git a/core/policy/metadata_source.go b/core/policy/metadata_source.go new file mode 100644 index 000000000..fae743394 --- /dev/null +++ b/core/policy/metadata_source.go @@ -0,0 +1,8 @@ +package policy + +import "github.com/goto/guardian/pkg/http" + +type AppealMetadataSourceConfigHTTP struct { + http.HTTPClientConfig + AllowFailed bool `mapstructure:"allow_failed,omitempty" json:"allow_failed,omitempty" yaml:"allow_failed,omitempty"` +} diff --git a/core/policy/service.go b/core/policy/service.go index fbc3da9f3..4b188975d 100644 --- a/core/policy/service.go +++ b/core/policy/service.go @@ -2,7 +2,6 @@ package policy import ( "context" - "encoding/json" "fmt" "reflect" "regexp" @@ -255,37 +254,20 @@ func (s *Service) Update(ctx context.Context, p *domain.Policy) error { } func (s *Service) encryptAppealMetadata(p *domain.Policy) error { - for key, metadataSourceCfg := range p.AppealMetadataSources { - metadataJson, err := json.Marshal(metadataSourceCfg.Config.Auth) - if err != nil { - return fmt.Errorf("error marshalling metadata into json") - } - encryptedAuth, err := s.crypto.Encrypt(string(metadataJson)) - if err != nil { - return fmt.Errorf("error encrypting metadata config: %w", err) + for _, sourceCfg := range p.AppealMetadataSources { + if err := sourceCfg.EncryptConfig(s.crypto); err != nil { + return err } - - p.AppealMetadataSources[key].Config.Auth = encryptedAuth } return nil } func (s *Service) decryptAppealMetadata(p *domain.Policy) error { - for key, metadataSourceCfg := range p.AppealMetadataSources { - decryptedAuth, err := s.crypto.Decrypt(metadataSourceCfg.Config.Auth.(string)) - if err != nil { - return fmt.Errorf("error decrypting metadata config: %w", err) - } - - var auth interface{} - err = json.Unmarshal([]byte(decryptedAuth), &auth) - if err != nil { - return fmt.Errorf("error marshalling metadata into json") + for _, sourceCfg := range p.AppealMetadataSources { + if err := sourceCfg.DecryptConfig(s.crypto); err != nil { + return err } - - p.AppealMetadataSources[key].Config.Auth = auth } - return nil } diff --git a/domain/policy.go b/domain/policy.go index dd86c9c5f..5351af886 100644 --- a/domain/policy.go +++ b/domain/policy.go @@ -312,21 +312,6 @@ type PolicyAppealConfig struct { AllowCreatorDetailsFailure bool `json:"allow_creator_details_failure" yaml:"allow_creator_details_failure"` } -type AppealMetadataSource struct { - Name string `json:"name" yaml:"name"` - Description string `json:"description,omitempty" yaml:"description,omitempty"` - Type string `json:"type" yaml:"type"` - Config *AppealMetadataConfig `json:"config,omitempty" yaml:"config,omitempty"` - Value interface{} `json:"value" yaml:"value"` -} - -type AppealMetadataConfig struct { - URL string `json:"url" yaml:"url"` - AllowFailed bool `json:"allow_failed,omitempty" yaml:"allow_failed,omitempty"` - Headers map[string]string `json:"headers,omitempty" yaml:"headers,omitempty"` - Auth interface{} `json:"auth,omitempty" yaml:"auth,omitempty"` -} - type Question struct { Key string `json:"key" yaml:"key"` Question string `json:"question" yaml:"question"` diff --git a/domain/policy_metadata_source.go b/domain/policy_metadata_source.go new file mode 100644 index 000000000..35630bcce --- /dev/null +++ b/domain/policy_metadata_source.go @@ -0,0 +1,48 @@ +package domain + +import ( + "encoding/json" + "fmt" +) + +type AppealMetadataSource struct { + Name string `json:"name" yaml:"name"` + Description string `json:"description,omitempty" yaml:"description,omitempty"` + Type string `json:"type" yaml:"type"` + Config interface{} `json:"config,omitempty" yaml:"config,omitempty"` + Value interface{} `json:"value" yaml:"value"` +} + +func (c *AppealMetadataSource) EncryptConfig(enc Encryptor) error { + configStr, err := json.Marshal(c.Config) + if err != nil { + return fmt.Errorf("failed to json.Marshal config: %w", err) + } + + encryptedConfig, err := enc.Encrypt(string(configStr)) + if err != nil { + return err + } + c.Config = encryptedConfig + + return nil +} + +func (c *AppealMetadataSource) DecryptConfig(dec Decryptor) error { + configStr, ok := c.Config.(string) + if !ok { + return fmt.Errorf("invalid config type: %T, expected string", c.Config) + } + decryptedConfig, err := dec.Decrypt(string(configStr)) + if err != nil { + return err + } + + var cfg interface{} + if err := json.Unmarshal([]byte(decryptedConfig), &cfg); err != nil { + return fmt.Errorf("failed to json.Unmarshal config: %w", err) + } + c.Config = cfg + + return nil +} diff --git a/domain/policy_metadata_source_test.go b/domain/policy_metadata_source_test.go new file mode 100644 index 000000000..b1d407018 --- /dev/null +++ b/domain/policy_metadata_source_test.go @@ -0,0 +1,11 @@ +package domain_test + +import "testing" + +func TestAppealMetadataSource_EncryptConfig(t *testing.T) { + t.Skip("TODO: implement") +} + +func TestAppealMetadataSource_DecryptConfig(t *testing.T) { + t.Skip("TODO: implement") +} diff --git a/internal/store/postgres/model/policy.go b/internal/store/postgres/model/policy.go index 7753cb2d6..de59c22da 100644 --- a/internal/store/postgres/model/policy.go +++ b/internal/store/postgres/model/policy.go @@ -118,15 +118,16 @@ func (m *Policy) ToDomain() (*domain.Policy, error) { } return &domain.Policy{ - ID: m.ID, - Version: m.Version, - Description: m.Description, - Steps: steps, - AppealConfig: appealConfig, - Labels: labels, - Requirements: requirements, - IAM: iam, - CreatedAt: m.CreatedAt, - UpdatedAt: m.UpdatedAt, + ID: m.ID, + Version: m.Version, + Description: m.Description, + Steps: steps, + AppealConfig: appealConfig, + Labels: labels, + Requirements: requirements, + IAM: iam, + AppealMetadataSources: metadataSources, + CreatedAt: m.CreatedAt, + UpdatedAt: m.UpdatedAt, }, nil } diff --git a/pkg/http/http.go b/pkg/http/http.go index db12b2898..fa42325ad 100644 --- a/pkg/http/http.go +++ b/pkg/http/http.go @@ -3,21 +3,15 @@ package http import ( "context" "encoding/base64" - "errors" "fmt" "net/http" "github.com/go-playground/validator/v10" - "github.com/goto/guardian/domain" "github.com/mcuadros/go-defaults" "golang.org/x/oauth2" "google.golang.org/api/idtoken" ) -var ErrFailedRequest = errors.New("request failed") - -const UserIDWildcard = "{user_id}" - type HTTPAuthConfig struct { Type string `mapstructure:"type" json:"type" yaml:"type" validate:"required,oneof=basic api_key bearer google_idtoken"` @@ -35,9 +29,6 @@ type HTTPAuthConfig struct { // google_idtoken Audience string `mapstructure:"audience,omitempty" json:"audience,omitempty" yaml:"audience,omitempty" validate:"required_if=Type google_idtoken"` - // CredentialsJSON accept a JSON stringified credentials - // Deprecated: CredentialsJSON is deprecated, use CredentialsJSONBase64 instead - CredentialsJSON string `mapstructure:"credentials_json,omitempty" json:"credentials_json,omitempty" yaml:"credentials_json,omitempty"` // CredentialsJSONBase64 accept a base64 encoded JSON stringified credentials CredentialsJSONBase64 string `mapstructure:"credentials_json_base64,omitempty" json:"credentials_json_base64,omitempty" yaml:"credentials_json_base64,omitempty"` } @@ -50,7 +41,6 @@ type HTTPClientConfig struct { HTTPClient *http.Client `mapstructure:"-" json:"-" yaml:"-"` Validator *validator.Validate - Crypto domain.Crypto } // HTTPClient wraps the http client for external approver resolver service @@ -81,8 +71,6 @@ func NewHTTPClient(config *HTTPClientConfig) (*HTTPClient, error) { return nil, fmt.Errorf("decoding credentials_json_base64: %w", err) } creds = v - case config.Auth.CredentialsJSON != "": - creds = []byte(config.Auth.CredentialsJSON) default: return nil, fmt.Errorf("missing credentials for google_idtoken auth") } diff --git a/plugins/identities/http.go b/plugins/identities/http.go index 80c7cd50a..5391cff31 100644 --- a/plugins/identities/http.go +++ b/plugins/identities/http.go @@ -257,26 +257,6 @@ func (c *HTTPClient) createRequest(userID string) (*http.Request, error) { return req, nil } -func (c *HTTPClient) GetResourceMetadata() (interface{}, error) { - req, err := http.NewRequest(http.MethodGet, c.config.URL, nil) - if err != nil { - return nil, err - } - - for k, v := range c.config.Headers { - req.Header.Set(k, v) - } - c.setAuth(req) - - req.Header.Set("Accept", "application/json") - var res interface{} - if err := c.sendRequest(req, &res); err != nil { - return nil, err - } - - return res, nil -} - func (c *HTTPClient) sendRequest(req *http.Request, v interface{}) error { res, err := c.httpClient.Do(req) if err != nil { diff --git a/plugins/identities/service.go b/plugins/identities/service.go index 017cc6957..375c7987e 100644 --- a/plugins/identities/service.go +++ b/plugins/identities/service.go @@ -23,16 +23,6 @@ func NewManager(crypto domain.Crypto, validator *validator.Validate) *manager { return &manager{crypto, validator} } -func (m *manager) ParseMetadataConfig(metadataConfig *domain.AppealMetadataConfig) (domain.SensitiveConfig, error) { - var clientConfig HTTPClientConfig - if err := mapstructure.Decode(metadataConfig, &clientConfig); err != nil { - return nil, fmt.Errorf("%w: %s", ErrInvalidConfig, err) - } - clientConfig.crypto = m.crypto - clientConfig.validator = m.validator - return &clientConfig, nil -} - func (m *manager) ParseConfig(iamConfig *domain.IAMConfig) (domain.SensitiveConfig, error) { switch iamConfig.Provider { case domain.IAMProviderTypeHTTP: From 57f98539c27eb0ff94433f1463c9a6a83093146c Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Tue, 26 Mar 2024 00:55:24 +0700 Subject: [PATCH 06/39] fix: fix err == nil --- core/appeal/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/appeal/service.go b/core/appeal/service.go index 8b68da9fb..98d8be6d7 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -1201,7 +1201,7 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, }) } - if err := eg.Wait(); err == nil { + if err := eg.Wait(); err != nil { return err } From 55363b4db2c53dd665d882e687b2148d92ee5668 Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Tue, 26 Mar 2024 00:55:42 +0700 Subject: [PATCH 07/39] fix: squash mapstructure embedded struct --- core/policy/metadata_source.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/policy/metadata_source.go b/core/policy/metadata_source.go index fae743394..33ab3efcf 100644 --- a/core/policy/metadata_source.go +++ b/core/policy/metadata_source.go @@ -3,6 +3,6 @@ package policy import "github.com/goto/guardian/pkg/http" type AppealMetadataSourceConfigHTTP struct { - http.HTTPClientConfig - AllowFailed bool `mapstructure:"allow_failed,omitempty" json:"allow_failed,omitempty" yaml:"allow_failed,omitempty"` + http.HTTPClientConfig `mapstructure:",squash"` + AllowFailed bool `mapstructure:"allow_failed,omitempty" json:"allow_failed,omitempty" yaml:"allow_failed,omitempty"` } From c59604dfdf1d554f493bf172ae9c9d668b4b6d33 Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Tue, 26 Mar 2024 01:08:07 +0700 Subject: [PATCH 08/39] feat: evaluate url if contains "$appeal" string --- core/appeal/service.go | 16 ++++++++++++++++ domain/appeal.go | 4 ++++ 2 files changed, 20 insertions(+) diff --git a/core/appeal/service.go b/core/appeal/service.go index 98d8be6d7..b93d67077 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -1157,6 +1157,22 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, if cfg.URL == "" { return fmt.Errorf("URL cannot be empty for http type") } + if strings.Contains(cfg.URL, "$appeal") { + appealMap, err := a.ToMap() + if err != nil { + return fmt.Errorf("error converting appeal to map: %w", err) + } + params := map[string]interface{}{"appeal": appealMap} + url, err := evaluator.Expression(cfg.URL).EvaluateWithVars(params) + if err != nil { + return fmt.Errorf("error evaluating URL expression: %w", err) + } + urlStr, ok := url.(string) + if !ok { + return fmt.Errorf("URL expression must evaluate to a string") + } + cfg.URL = urlStr + } metadataCl, err := http.NewHTTPClient(&cfg.HTTPClientConfig) if err != nil { diff --git a/domain/appeal.go b/domain/appeal.go index 86911bd49..ab82d5239 100644 --- a/domain/appeal.go +++ b/domain/appeal.go @@ -265,6 +265,10 @@ func (a *Appeal) AdvanceApproval(policy *Policy) error { return nil } +func (a *Appeal) ToMap() (map[string]interface{}, error) { + return utils.StructToMap(a) +} + type ApprovalActionType string const ( From a92cef3d35f549f5f59c9d3e3d44cead488b26b1 Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Tue, 26 Mar 2024 01:16:35 +0700 Subject: [PATCH 09/39] fix: cherry pick response struct into map --- core/appeal/service.go | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/core/appeal/service.go b/core/appeal/service.go index b93d67077..8423b2863 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "io" "strings" "time" @@ -1186,13 +1187,23 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, } } - var responseBody interface{} - err = json.NewDecoder(res.Body).Decode(responseBody) + body, err := io.ReadAll(res.Body) if err != nil { - return fmt.Errorf("error decoding response: %w", err) + return fmt.Errorf("error reading response body: %w", err) + } + res.Body.Close() + var jsonBody interface{} + err = json.Unmarshal(body, &jsonBody) + if err != nil { + return fmt.Errorf("error unmarshaling response body: %w", err) } - responseMap := responseBody.(map[string]interface{}) + responseMap := map[string]interface{}{ + "status": res.Status, + "status_code": res.StatusCode, + "headers": res.Header, + "body": jsonBody, + } params := map[string]interface{}{ "response": responseMap, "appeal": a, From 97233eff9989aef9da2eb8be4ef8100d24bff266 Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Tue, 26 Mar 2024 01:39:53 +0700 Subject: [PATCH 10/39] fix: resolve metadata value --- core/appeal/service.go | 46 ++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/core/appeal/service.go b/core/appeal/service.go index 8423b2863..a8858c4c4 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -1208,14 +1208,14 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, "response": responseMap, "appeal": a, } - value, err := s.getMetadataValue(metadata.Type, key, metadata.Value, params) + value, err := s.getMetadataValue(metadata.Value, params) if err != nil { return fmt.Errorf("error parsing value: %w", err) } appealMetadata[key] = value case "static": params := map[string]interface{}{"appeal": a} - value, err := s.getMetadataValue(metadata.Type, key, metadata.Value, params) + value, err := s.getMetadataValue(metadata.Value, params) if err != nil { return fmt.Errorf("error parsing value: %w", err) } @@ -1237,39 +1237,41 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, return nil } -func (s *Service) getMetadataValue(metadataType string, key string, value interface{}, params map[string]interface{}) (interface{}, error) { - result := make(map[string]interface{}) - - switch v := value.(type) { +func (s *Service) getMetadataValue(value interface{}, params map[string]interface{}) (interface{}, error) { + switch value := value.(type) { case string: - if strings.HasPrefix(v, "$appeal") || (metadataType == "http" && strings.HasPrefix(v, "$response")) { - finalVal, err := evaluator.Expression(v).EvaluateWithVars(params) + if strings.HasPrefix(value, "$appeal") || strings.HasPrefix(value, "$response") { + result, err := evaluator.Expression(value).EvaluateWithVars(params) if err != nil { return nil, err } - result[key] = finalVal + return result, nil } else { - result[key] = v + return value, nil } - case map[string]interface{}: - for key, val := range v { - processedVal, err := s.getMetadataValue(metadataType, key, val, params) + case map[string]interface{}: // TODO: handle map[string]int and other types + mapResult := map[string]interface{}{} + for key, val := range value { + processedVal, err := s.getMetadataValue(val, params) if err != nil { return nil, err } - result[key] = processedVal + mapResult[key] = processedVal } - case interface{}: - processedVal, err := s.getMetadataValue(metadataType, key, v, params) - if err != nil { - return nil, err + return mapResult, nil + case []interface{}: // TODO: handle []int and other types + arrayResult := make([]interface{}, len(value)) + for i, val := range value { + processedVal, err := s.getMetadataValue(val, params) + if err != nil { + return nil, err + } + arrayResult[i] = processedVal } - result[key] = processedVal + return arrayResult, nil default: - return nil, fmt.Errorf("unsupported value type") + return value, nil } - - return result, nil } func (s *Service) addCreatorDetails(ctx context.Context, a *domain.Appeal, p *domain.Policy) error { From 93cd89d534bacee779d17744f027aaa8cd0fc04b Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Tue, 26 Mar 2024 01:59:58 +0700 Subject: [PATCH 11/39] refactor: move evaluate value logic to domain --- core/appeal/service.go | 41 ++----------------------- domain/policy_metadata_source.go | 44 +++++++++++++++++++++++++++ domain/policy_metadata_source_test.go | 4 +++ 3 files changed, 50 insertions(+), 39 deletions(-) diff --git a/core/appeal/service.go b/core/appeal/service.go index a8858c4c4..fb57aeaf4 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -1208,14 +1208,14 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, "response": responseMap, "appeal": a, } - value, err := s.getMetadataValue(metadata.Value, params) + value, err := metadata.EvaluateValue(params) if err != nil { return fmt.Errorf("error parsing value: %w", err) } appealMetadata[key] = value case "static": params := map[string]interface{}{"appeal": a} - value, err := s.getMetadataValue(metadata.Value, params) + value, err := metadata.EvaluateValue(params) if err != nil { return fmt.Errorf("error parsing value: %w", err) } @@ -1237,43 +1237,6 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, return nil } -func (s *Service) getMetadataValue(value interface{}, params map[string]interface{}) (interface{}, error) { - switch value := value.(type) { - case string: - if strings.HasPrefix(value, "$appeal") || strings.HasPrefix(value, "$response") { - result, err := evaluator.Expression(value).EvaluateWithVars(params) - if err != nil { - return nil, err - } - return result, nil - } else { - return value, nil - } - case map[string]interface{}: // TODO: handle map[string]int and other types - mapResult := map[string]interface{}{} - for key, val := range value { - processedVal, err := s.getMetadataValue(val, params) - if err != nil { - return nil, err - } - mapResult[key] = processedVal - } - return mapResult, nil - case []interface{}: // TODO: handle []int and other types - arrayResult := make([]interface{}, len(value)) - for i, val := range value { - processedVal, err := s.getMetadataValue(val, params) - if err != nil { - return nil, err - } - arrayResult[i] = processedVal - } - return arrayResult, nil - default: - return value, nil - } -} - func (s *Service) addCreatorDetails(ctx context.Context, a *domain.Appeal, p *domain.Policy) error { if p.IAM == nil { return nil diff --git a/domain/policy_metadata_source.go b/domain/policy_metadata_source.go index 35630bcce..ce89e9ccc 100644 --- a/domain/policy_metadata_source.go +++ b/domain/policy_metadata_source.go @@ -3,6 +3,9 @@ package domain import ( "encoding/json" "fmt" + "strings" + + "github.com/goto/guardian/pkg/evaluator" ) type AppealMetadataSource struct { @@ -46,3 +49,44 @@ func (c *AppealMetadataSource) DecryptConfig(dec Decryptor) error { return nil } + +func (c *AppealMetadataSource) EvaluateValue(params map[string]interface{}) (interface{}, error) { + return c.evaluateValue(c.Value, params) +} + +func (c *AppealMetadataSource) evaluateValue(value interface{}, params map[string]interface{}) (interface{}, error) { + switch value := value.(type) { + case string: + if strings.HasPrefix(value, "$appeal") || strings.HasPrefix(value, "$response") { + result, err := evaluator.Expression(value).EvaluateWithVars(params) + if err != nil { + return nil, err + } + return result, nil + } else { + return value, nil + } + case map[string]interface{}: // TODO: handle map[string]int and other types + mapResult := map[string]interface{}{} + for key, val := range value { + processedVal, err := c.evaluateValue(val, params) + if err != nil { + return nil, err + } + mapResult[key] = processedVal + } + return mapResult, nil + case []interface{}: // TODO: handle []int and other types + arrayResult := make([]interface{}, len(value)) + for i, val := range value { + processedVal, err := c.evaluateValue(val, params) + if err != nil { + return nil, err + } + arrayResult[i] = processedVal + } + return arrayResult, nil + default: + return value, nil + } +} diff --git a/domain/policy_metadata_source_test.go b/domain/policy_metadata_source_test.go index b1d407018..f51dfecef 100644 --- a/domain/policy_metadata_source_test.go +++ b/domain/policy_metadata_source_test.go @@ -9,3 +9,7 @@ func TestAppealMetadataSource_EncryptConfig(t *testing.T) { func TestAppealMetadataSource_DecryptConfig(t *testing.T) { t.Skip("TODO: implement") } + +func TestAppealMetadataSource_EvaluateValue(t *testing.T) { + t.Skip("TODO: implement") +} From 833eff6596ac722d47d7d74ab5b5406c550b17b9 Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Tue, 26 Mar 2024 02:04:34 +0700 Subject: [PATCH 12/39] fix: make appealMetadata concurent safe --- core/appeal/service.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/appeal/service.go b/core/appeal/service.go index fb57aeaf4..9a6cefe27 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -7,6 +7,7 @@ import ( "fmt" "io" "strings" + "sync" "time" "github.com/go-playground/validator/v10" @@ -1143,7 +1144,7 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, } eg, _ := errgroup.WithContext(ctx) - + var mu sync.Mutex appealMetadata := map[string]interface{}{} for key, metadata := range p.AppealMetadataSources { key, metadata := key, metadata @@ -1212,14 +1213,18 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, if err != nil { return fmt.Errorf("error parsing value: %w", err) } + mu.Lock() appealMetadata[key] = value + mu.Unlock() case "static": params := map[string]interface{}{"appeal": a} value, err := metadata.EvaluateValue(params) if err != nil { return fmt.Errorf("error parsing value: %w", err) } + mu.Lock() appealMetadata[key] = value + mu.Unlock() default: return fmt.Errorf("invalid metadata source type") } From 6bca409b59749d08810f4bcf07c63cadc00928e1 Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Tue, 26 Mar 2024 02:06:37 +0700 Subject: [PATCH 13/39] feat: use context in http fetch --- core/appeal/service.go | 4 ++-- pkg/http/http.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/appeal/service.go b/core/appeal/service.go index 9a6cefe27..e9c422995 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -1143,7 +1143,7 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, return nil } - eg, _ := errgroup.WithContext(ctx) + eg, egctx := errgroup.WithContext(ctx) var mu sync.Mutex appealMetadata := map[string]interface{}{} for key, metadata := range p.AppealMetadataSources { @@ -1181,7 +1181,7 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, return fmt.Errorf("key: %s, %w", key, err) } - res, err := metadataCl.MakeRequest() + res, err := metadataCl.MakeRequest(egctx) if err != nil || (res.StatusCode < 200 && res.StatusCode > 300) { if !cfg.AllowFailed { return fmt.Errorf("error fetching resource: %w", err) diff --git a/pkg/http/http.go b/pkg/http/http.go index fa42325ad..f47055d43 100644 --- a/pkg/http/http.go +++ b/pkg/http/http.go @@ -112,12 +112,12 @@ func (c *HTTPClient) setAuth(req *http.Request) { } } -func (c *HTTPClient) MakeRequest() (*http.Response, error) { +func (c *HTTPClient) MakeRequest(ctx context.Context) (*http.Response, error) { req, err := http.NewRequest(http.MethodGet, c.config.URL, nil) if err != nil { return nil, err } - + req = req.WithContext(ctx) req.Header.Set("Accept", "application/json") for k, v := range c.config.Headers { From 534f2d3eae0c7375bc742d1ee6dbe4701c184115 Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Tue, 26 Mar 2024 02:55:30 +0700 Subject: [PATCH 14/39] feat!: move metadata sources config into policy.appeal --- api/handler/v1beta1/adapter.go | 84 +- api/handler/v1beta1/grpc.go | 2 +- api/handler/v1beta1/policy.go | 5 +- .../guardian/v1beta1/guardian.pb.go | 1935 ++++++++--------- core/appeal/service.go | 4 +- core/policy/service.go | 14 +- docs/docs/reference/policy.md | 4 +- domain/policy.go | 26 +- ...19_add_metadata_sources_in_policy.down.sql | 6 - ...0019_add_metadata_sources_in_policy.up.sql | 8 - internal/store/postgres/model/policy.go | 57 +- .../guardian/v1beta1/guardian.swagger.json | 42 +- 12 files changed, 1085 insertions(+), 1102 deletions(-) delete mode 100644 internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.down.sql delete mode 100644 internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.up.sql diff --git a/api/handler/v1beta1/adapter.go b/api/handler/v1beta1/adapter.go index f2084dfb9..e6e55cdad 100644 --- a/api/handler/v1beta1/adapter.go +++ b/api/handler/v1beta1/adapter.go @@ -311,6 +311,7 @@ func (a *adapter) FromPolicyProto(p *guardianv1beta1.Policy) *domain.Policy { if p.GetAppeal() != nil { var durationOptions []domain.AppealDurationOption var questions []domain.Question + var metadataSources map[string]*domain.AppealMetadataSource for _, d := range p.GetAppeal().GetDurationOptions() { option := domain.AppealDurationOption{ Name: d.GetName(), @@ -328,6 +329,19 @@ func (a *adapter) FromPolicyProto(p *guardianv1beta1.Policy) *domain.Policy { questions = append(questions, question) } + if mds := p.GetAppeal().GetMetadataSources(); mds != nil { + metadataSources = make(map[string]*domain.AppealMetadataSource) + for key, metadataCfg := range mds { + metadataSources[key] = &domain.AppealMetadataSource{ + Name: metadataCfg.GetName(), + Description: metadataCfg.GetDescription(), + Type: metadataCfg.GetType(), + Config: metadataCfg.GetConfig().AsInterface(), + Value: metadataCfg.GetValue().AsInterface(), + } + } + } + policy.AppealConfig = &domain.PolicyAppealConfig{ DurationOptions: durationOptions, AllowOnBehalf: p.GetAppeal().GetAllowOnBehalf(), @@ -335,20 +349,7 @@ func (a *adapter) FromPolicyProto(p *guardianv1beta1.Policy) *domain.Policy { AllowPermanentAccess: p.GetAppeal().GetAllowPermanentAccess(), AllowActiveAccessExtensionIn: p.GetAppeal().GetAllowActiveAccessExtensionIn(), AllowCreatorDetailsFailure: p.GetAppeal().GetAllowCreatorDetailsFailure(), - } - } - - if mdSources := p.GetAppealMetadataSources(); mdSources != nil { - policy.AppealMetadataSources = map[string]*domain.AppealMetadataSource{} - - for key, mdSource := range p.GetAppealMetadataSources() { - policy.AppealMetadataSources[key] = &domain.AppealMetadataSource{ - Name: mdSource.GetName(), - Description: mdSource.GetDescription(), - Type: mdSource.GetType(), - Config: mdSource.GetConfig().AsInterface(), - Value: mdSource.GetValue().AsInterface(), - } + MetadataSources: metadataSources, } } @@ -458,30 +459,11 @@ func (a *adapter) ToPolicyProto(p *domain.Policy) (*guardianv1beta1.Policy, erro } } - policyProto.Appeal = a.ToPolicyAppealConfigProto(p) - - if p.AppealMetadataSources != nil { - policyProto.AppealMetadataSources = map[string]*guardianv1beta1.Policy_AppealMetadataSource{} - - for key, mdSource := range p.AppealMetadataSources { - cfg, err := structpb.NewValue(mdSource.Config) - if err != nil { - return nil, err - } - value, err := structpb.NewValue(mdSource.Value) - if err != nil { - return nil, err - } - - policyProto.AppealMetadataSources[key] = &guardianv1beta1.Policy_AppealMetadataSource{ - Name: mdSource.Name, - Description: mdSource.Description, - Type: mdSource.Type, - Config: cfg, - Value: value, - } - } + appealConfig, err := a.ToPolicyAppealConfigProto(p) + if err != nil { + return nil, fmt.Errorf("failed to convert appeal config to proto: %w", err) } + policyProto.Appeal = appealConfig if !p.CreatedAt.IsZero() { policyProto.CreatedAt = timestamppb.New(p.CreatedAt) @@ -493,9 +475,9 @@ func (a *adapter) ToPolicyProto(p *domain.Policy) (*guardianv1beta1.Policy, erro return policyProto, nil } -func (a *adapter) ToPolicyAppealConfigProto(p *domain.Policy) *guardianv1beta1.PolicyAppealConfig { +func (a *adapter) ToPolicyAppealConfigProto(p *domain.Policy) (*guardianv1beta1.PolicyAppealConfig, error) { if p.AppealConfig == nil { - return nil + return nil, nil } policyAppealConfigProto := &guardianv1beta1.PolicyAppealConfig{} @@ -522,7 +504,29 @@ func (a *adapter) ToPolicyAppealConfigProto(p *domain.Policy) *guardianv1beta1.P Description: q.Description, }) } - return policyAppealConfigProto + + for key, metadataSource := range p.AppealConfig.MetadataSources { + cfg, err := structpb.NewValue(metadataSource.Config) + if err != nil { + return nil, err + } + value, err := structpb.NewValue(metadataSource.Value) + if err != nil { + return nil, err + } + if policyAppealConfigProto.MetadataSources == nil { + policyAppealConfigProto.MetadataSources = make(map[string]*guardianv1beta1.PolicyAppealConfig_MetadataSource) + } + policyAppealConfigProto.MetadataSources[key] = &guardianv1beta1.PolicyAppealConfig_MetadataSource{ + Name: metadataSource.Name, + Description: metadataSource.Description, + Type: metadataSource.Type, + Config: cfg, + Value: value, + } + } + + return policyAppealConfigProto, nil } func (a *adapter) FromResourceProto(r *guardianv1beta1.Resource) *domain.Resource { diff --git a/api/handler/v1beta1/grpc.go b/api/handler/v1beta1/grpc.go index a8d29e392..1ae90844b 100644 --- a/api/handler/v1beta1/grpc.go +++ b/api/handler/v1beta1/grpc.go @@ -27,7 +27,7 @@ type ProtoAdapter interface { FromPolicyProto(*guardianv1beta1.Policy) *domain.Policy ToPolicyProto(*domain.Policy) (*guardianv1beta1.Policy, error) - ToPolicyAppealConfigProto(policy *domain.Policy) *guardianv1beta1.PolicyAppealConfig + ToPolicyAppealConfigProto(policy *domain.Policy) (*guardianv1beta1.PolicyAppealConfig, error) FromResourceProto(*guardianv1beta1.Resource) *domain.Resource ToResourceProto(*domain.Resource) (*guardianv1beta1.Resource, error) diff --git a/api/handler/v1beta1/policy.go b/api/handler/v1beta1/policy.go index 3ce7d872e..9da968477 100644 --- a/api/handler/v1beta1/policy.go +++ b/api/handler/v1beta1/policy.go @@ -117,7 +117,10 @@ func (s *GRPCServer) GetPolicyPreferences(ctx context.Context, req *guardianv1be } } - appealConfigProto := s.adapter.ToPolicyAppealConfigProto(p) + appealConfigProto, err := s.adapter.ToPolicyAppealConfigProto(p) + if err != nil { + return nil, s.internalError(ctx, "failed to parse policy preferences: %v", err) + } return &guardianv1beta1.GetPolicyPreferencesResponse{ Appeal: appealConfigProto, diff --git a/api/proto/gotocompany/guardian/v1beta1/guardian.pb.go b/api/proto/gotocompany/guardian/v1beta1/guardian.pb.go index fd7461816..dd9350d00 100644 --- a/api/proto/gotocompany/guardian/v1beta1/guardian.pb.go +++ b/api/proto/gotocompany/guardian/v1beta1/guardian.pb.go @@ -5077,12 +5077,13 @@ type PolicyAppealConfig struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - DurationOptions []*PolicyAppealConfig_DurationOptions `protobuf:"bytes,1,rep,name=duration_options,json=durationOptions,proto3" json:"duration_options,omitempty"` - AllowOnBehalf bool `protobuf:"varint,2,opt,name=allow_on_behalf,json=allowOnBehalf,proto3" json:"allow_on_behalf,omitempty"` - AllowPermanentAccess bool `protobuf:"varint,3,opt,name=allow_permanent_access,json=allowPermanentAccess,proto3" json:"allow_permanent_access,omitempty"` - AllowActiveAccessExtensionIn string `protobuf:"bytes,4,opt,name=allow_active_access_extension_in,json=allowActiveAccessExtensionIn,proto3" json:"allow_active_access_extension_in,omitempty"` - Questions []*PolicyAppealConfig_Question `protobuf:"bytes,5,rep,name=questions,proto3" json:"questions,omitempty"` - AllowCreatorDetailsFailure bool `protobuf:"varint,6,opt,name=allow_creator_details_failure,json=allowCreatorDetailsFailure,proto3" json:"allow_creator_details_failure,omitempty"` + DurationOptions []*PolicyAppealConfig_DurationOptions `protobuf:"bytes,1,rep,name=duration_options,json=durationOptions,proto3" json:"duration_options,omitempty"` + AllowOnBehalf bool `protobuf:"varint,2,opt,name=allow_on_behalf,json=allowOnBehalf,proto3" json:"allow_on_behalf,omitempty"` + AllowPermanentAccess bool `protobuf:"varint,3,opt,name=allow_permanent_access,json=allowPermanentAccess,proto3" json:"allow_permanent_access,omitempty"` + AllowActiveAccessExtensionIn string `protobuf:"bytes,4,opt,name=allow_active_access_extension_in,json=allowActiveAccessExtensionIn,proto3" json:"allow_active_access_extension_in,omitempty"` + Questions []*PolicyAppealConfig_Question `protobuf:"bytes,5,rep,name=questions,proto3" json:"questions,omitempty"` + AllowCreatorDetailsFailure bool `protobuf:"varint,6,opt,name=allow_creator_details_failure,json=allowCreatorDetailsFailure,proto3" json:"allow_creator_details_failure,omitempty"` + MetadataSources map[string]*PolicyAppealConfig_MetadataSource `protobuf:"bytes,7,rep,name=metadata_sources,json=metadataSources,proto3" json:"metadata_sources,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *PolicyAppealConfig) Reset() { @@ -5159,23 +5160,29 @@ func (x *PolicyAppealConfig) GetAllowCreatorDetailsFailure() bool { return false } +func (x *PolicyAppealConfig) GetMetadataSources() map[string]*PolicyAppealConfig_MetadataSource { + if x != nil { + return x.MetadataSources + } + return nil +} + // Policy is a configurable steps for appeal's approval type Policy struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` - Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` - Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` - Steps []*Policy_ApprovalStep `protobuf:"bytes,4,rep,name=steps,proto3" json:"steps,omitempty"` - Labels map[string]string `protobuf:"bytes,5,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` - CreatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` - UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` - Requirements []*Policy_Requirement `protobuf:"bytes,8,rep,name=requirements,proto3" json:"requirements,omitempty"` - Iam *Policy_IAM `protobuf:"bytes,9,opt,name=iam,proto3" json:"iam,omitempty"` - Appeal *PolicyAppealConfig `protobuf:"bytes,10,opt,name=appeal,proto3" json:"appeal,omitempty"` - AppealMetadataSources map[string]*Policy_AppealMetadataSource `protobuf:"bytes,11,rep,name=appeal_metadata_sources,json=appealMetadataSources,proto3" json:"appeal_metadata_sources,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"` + Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"` + Steps []*Policy_ApprovalStep `protobuf:"bytes,4,rep,name=steps,proto3" json:"steps,omitempty"` + Labels map[string]string `protobuf:"bytes,5,rep,name=labels,proto3" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + CreatedAt *timestamppb.Timestamp `protobuf:"bytes,6,opt,name=created_at,json=createdAt,proto3" json:"created_at,omitempty"` + UpdatedAt *timestamppb.Timestamp `protobuf:"bytes,7,opt,name=updated_at,json=updatedAt,proto3" json:"updated_at,omitempty"` + Requirements []*Policy_Requirement `protobuf:"bytes,8,rep,name=requirements,proto3" json:"requirements,omitempty"` + Iam *Policy_IAM `protobuf:"bytes,9,opt,name=iam,proto3" json:"iam,omitempty"` + Appeal *PolicyAppealConfig `protobuf:"bytes,10,opt,name=appeal,proto3" json:"appeal,omitempty"` } func (x *Policy) Reset() { @@ -5280,13 +5287,6 @@ func (x *Policy) GetAppeal() *PolicyAppealConfig { return nil } -func (x *Policy) GetAppealMetadataSources() map[string]*Policy_AppealMetadataSource { - if x != nil { - return x.AppealMetadataSources - } - return nil -} - type AppealOptions struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -6731,6 +6731,85 @@ func (x *PolicyAppealConfig_Question) GetDescription() string { return "" } +type PolicyAppealConfig_MetadataSource struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` + Config *structpb.Value `protobuf:"bytes,4,opt,name=config,proto3" json:"config,omitempty"` + Value *structpb.Value `protobuf:"bytes,5,opt,name=value,proto3" json:"value,omitempty"` +} + +func (x *PolicyAppealConfig_MetadataSource) Reset() { + *x = PolicyAppealConfig_MetadataSource{} + if protoimpl.UnsafeEnabled { + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[102] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PolicyAppealConfig_MetadataSource) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PolicyAppealConfig_MetadataSource) ProtoMessage() {} + +func (x *PolicyAppealConfig_MetadataSource) ProtoReflect() protoreflect.Message { + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[102] + 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 PolicyAppealConfig_MetadataSource.ProtoReflect.Descriptor instead. +func (*PolicyAppealConfig_MetadataSource) Descriptor() ([]byte, []int) { + return file_gotocompany_guardian_v1beta1_guardian_proto_rawDescGZIP(), []int{84, 2} +} + +func (x *PolicyAppealConfig_MetadataSource) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *PolicyAppealConfig_MetadataSource) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *PolicyAppealConfig_MetadataSource) GetType() string { + if x != nil { + return x.Type + } + return "" +} + +func (x *PolicyAppealConfig_MetadataSource) GetConfig() *structpb.Value { + if x != nil { + return x.Config + } + return nil +} + +func (x *PolicyAppealConfig_MetadataSource) GetValue() *structpb.Value { + if x != nil { + return x.Value + } + return nil +} + type Policy_ApprovalStep struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -6749,7 +6828,7 @@ type Policy_ApprovalStep struct { func (x *Policy_ApprovalStep) Reset() { *x = Policy_ApprovalStep{} if protoimpl.UnsafeEnabled { - mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[102] + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[104] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6762,7 +6841,7 @@ func (x *Policy_ApprovalStep) String() string { func (*Policy_ApprovalStep) ProtoMessage() {} func (x *Policy_ApprovalStep) ProtoReflect() protoreflect.Message { - mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[102] + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[104] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6846,7 +6925,7 @@ type Policy_Requirement struct { func (x *Policy_Requirement) Reset() { *x = Policy_Requirement{} if protoimpl.UnsafeEnabled { - mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[104] + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[106] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6859,7 +6938,7 @@ func (x *Policy_Requirement) String() string { func (*Policy_Requirement) ProtoMessage() {} func (x *Policy_Requirement) ProtoReflect() protoreflect.Message { - mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[104] + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[106] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6902,7 +6981,7 @@ type Policy_IAM struct { func (x *Policy_IAM) Reset() { *x = Policy_IAM{} if protoimpl.UnsafeEnabled { - mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[105] + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[107] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -6915,7 +6994,7 @@ func (x *Policy_IAM) String() string { func (*Policy_IAM) ProtoMessage() {} func (x *Policy_IAM) ProtoReflect() protoreflect.Message { - mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[105] + mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[107] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -6952,85 +7031,6 @@ func (x *Policy_IAM) GetSchema() map[string]string { return nil } -type Policy_AppealMetadataSource struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` - Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` - Type string `protobuf:"bytes,3,opt,name=type,proto3" json:"type,omitempty"` - Config *structpb.Value `protobuf:"bytes,4,opt,name=config,proto3" json:"config,omitempty"` - Value *structpb.Value `protobuf:"bytes,5,opt,name=value,proto3" json:"value,omitempty"` -} - -func (x *Policy_AppealMetadataSource) Reset() { - *x = Policy_AppealMetadataSource{} - if protoimpl.UnsafeEnabled { - mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[106] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Policy_AppealMetadataSource) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Policy_AppealMetadataSource) ProtoMessage() {} - -func (x *Policy_AppealMetadataSource) ProtoReflect() protoreflect.Message { - mi := &file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[106] - 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 Policy_AppealMetadataSource.ProtoReflect.Descriptor instead. -func (*Policy_AppealMetadataSource) Descriptor() ([]byte, []int) { - return file_gotocompany_guardian_v1beta1_guardian_proto_rawDescGZIP(), []int{85, 4} -} - -func (x *Policy_AppealMetadataSource) GetName() string { - if x != nil { - return x.Name - } - return "" -} - -func (x *Policy_AppealMetadataSource) GetDescription() string { - if x != nil { - return x.Description - } - return "" -} - -func (x *Policy_AppealMetadataSource) GetType() string { - if x != nil { - return x.Type - } - return "" -} - -func (x *Policy_AppealMetadataSource) GetConfig() *structpb.Value { - if x != nil { - return x.Config - } - return nil -} - -func (x *Policy_AppealMetadataSource) GetValue() *structpb.Value { - if x != nil { - return x.Value - } - return nil -} - type Policy_Requirement_RequirementTrigger struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -8008,7 +8008,7 @@ var file_gotocompany_guardian_v1beta1_guardian_proto_rawDesc = []byte{ 0x0e, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x02, 0x65, 0x71, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x52, 0x02, 0x65, 0x71, 0x22, 0xf8, 0x04, 0x0a, 0x12, 0x50, 0x6f, 0x6c, 0x69, + 0x6c, 0x75, 0x65, 0x52, 0x02, 0x65, 0x71, 0x22, 0xab, 0x08, 0x0a, 0x12, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x6b, 0x0a, 0x10, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, @@ -8036,782 +8036,781 @@ var file_gotocompany_guardian_v1beta1_guardian_proto_rawDesc = []byte{ 0x6c, 0x6f, 0x77, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x5f, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x43, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x44, - 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x1a, 0x3b, 0x0a, - 0x0f, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x76, 0x0a, 0x08, 0x51, 0x75, - 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, - 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x22, 0xb4, 0x13, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x0e, 0x0a, - 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, - 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x05, 0x73, 0x74, 0x65, - 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, - 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x52, 0x05, 0x73, 0x74, 0x65, - 0x70, 0x73, 0x12, 0x48, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x05, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, - 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, - 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x39, 0x0a, 0x0a, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, - 0x41, 0x74, 0x12, 0x54, 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, - 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0c, 0x72, 0x65, 0x71, 0x75, - 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x03, 0x69, 0x61, 0x6d, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, + 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x12, 0x70, 0x0a, + 0x10, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x45, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x70, 0x70, + 0x65, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0f, + 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, + 0x3b, 0x0a, 0x0f, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x76, 0x0a, 0x08, + 0x51, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, + 0x65, 0x64, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0xb8, 0x01, 0x0a, 0x0e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 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, 0x12, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x1a, + 0x83, 0x01, 0x0a, 0x14, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x55, 0x0a, 0x05, 0x76, 0x61, + 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x67, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, + 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, + 0x70, 0x70, 0x65, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xf4, 0x0f, 0x0a, 0x06, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x05, + 0x73, 0x74, 0x65, 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x67, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, + 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x53, 0x74, 0x65, 0x70, 0x52, 0x05, + 0x73, 0x74, 0x65, 0x70, 0x73, 0x12, 0x48, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, + 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x49, 0x41, 0x4d, 0x52, - 0x03, 0x69, 0x61, 0x6d, 0x12, 0x48, 0x0a, 0x06, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x18, 0x0a, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x12, 0x77, - 0x0a, 0x17, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, - 0x61, 0x5f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x3f, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, - 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x52, 0x15, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x1a, 0xff, 0x01, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x72, - 0x6f, 0x76, 0x61, 0x6c, 0x53, 0x74, 0x65, 0x70, 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, 0x21, - 0x0a, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x46, 0x61, 0x69, 0x6c, 0x65, - 0x64, 0x12, 0x12, 0x0a, 0x04, 0x77, 0x68, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x77, 0x68, 0x65, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, - 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, - 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x5f, 0x69, 0x66, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x49, 0x66, - 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x12, 0x29, - 0x0a, 0x10, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x61, 0x73, - 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, - 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, - 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x9e, 0x07, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x53, 0x0a, 0x02, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x43, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, - 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x72, - 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x02, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x07, 0x61, 0x70, 0x70, - 0x65, 0x61, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x67, 0x6f, 0x74, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x4c, 0x61, 0x62, 0x65, + 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, + 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x54, 0x0a, 0x0c, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x67, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, + 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x0c, 0x72, + 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x3a, 0x0a, 0x03, 0x69, + 0x61, 0x6d, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x49, + 0x41, 0x4d, 0x52, 0x03, 0x69, 0x61, 0x6d, 0x12, 0x48, 0x0a, 0x06, 0x61, 0x70, 0x70, 0x65, 0x61, + 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x41, 0x70, 0x70, + 0x65, 0x61, 0x6c, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x61, 0x70, 0x70, 0x65, 0x61, + 0x6c, 0x1a, 0xff, 0x01, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x53, 0x74, + 0x65, 0x70, 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, 0x21, 0x0a, 0x0c, 0x61, 0x6c, 0x6c, 0x6f, + 0x77, 0x5f, 0x66, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x77, + 0x68, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x77, 0x68, 0x65, 0x6e, 0x12, + 0x1a, 0x0a, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x73, 0x74, 0x72, 0x61, 0x74, 0x65, 0x67, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x61, + 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x5f, 0x69, 0x66, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x49, 0x66, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x70, + 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, + 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x6a, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0f, 0x72, 0x65, 0x6a, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x9e, + 0x07, 0x0a, 0x0b, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x53, + 0x0a, 0x02, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x43, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x64, 0x64, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x52, 0x07, 0x61, - 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x1a, 0xa1, 0x02, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x69, - 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x23, 0x0a, - 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x75, - 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x55, 0x72, 0x6e, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x75, 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x55, 0x72, 0x6e, 0x12, 0x12, 0x0a, - 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, - 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, - 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, - 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, - 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, - 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0xb8, 0x03, 0x0a, 0x10, 0x41, - 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x12, - 0x70, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x54, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, - 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x41, 0x70, - 0x70, 0x65, 0x61, 0x6c, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, - 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x06, - 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x67, - 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, - 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x1a, 0x92, 0x01, 0x0a, 0x12, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, - 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x71, + 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, + 0x02, 0x6f, 0x6e, 0x12, 0x5b, 0x0a, 0x07, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, + 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, + 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, + 0x6c, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x52, 0x07, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, + 0x1a, 0xa1, 0x02, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6e, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x75, 0x72, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x02, 0x69, 0x64, 0x1a, 0xda, 0x01, 0x0a, 0x03, 0x49, 0x41, 0x4d, 0x12, 0x1a, 0x0a, - 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x06, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x4c, 0x0a, 0x06, 0x73, 0x63, 0x68, - 0x65, 0x6d, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, - 0x49, 0x41, 0x4d, 0x2e, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x1a, 0x39, 0x0a, 0x0b, 0x53, 0x63, 0x68, 0x65, 0x6d, - 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x1a, 0xbe, 0x01, 0x0a, 0x14, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 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, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x2e, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2c, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x05, 0x76, 0x61, - 0x6c, 0x75, 0x65, 0x1a, 0x83, 0x01, 0x0a, 0x1a, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x4d, 0x65, - 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4f, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, - 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x05, - 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x70, 0x0a, 0x0d, 0x41, 0x70, 0x70, - 0x65, 0x61, 0x6c, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x65, 0x78, - 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x0e, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, 0x74, 0x65, 0x12, - 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xcc, 0x07, 0x0a, 0x06, - 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x48, 0x0a, - 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 0x2e, - 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, - 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x70, 0x70, - 0x65, 0x61, 0x6c, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x44, 0x0a, 0x09, 0x61, - 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, - 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, - 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x70, - 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x52, 0x09, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, - 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, - 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, - 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x31, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, - 0x6c, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, - 0x74, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, - 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x13, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x12, 0x30, 0x0a, 0x07, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x12, 0x20, - 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x15, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x39, 0x0a, 0x05, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x23, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, - 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, - 0x72, 0x61, 0x6e, 0x74, 0x52, 0x05, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x64, - 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x39, 0x0a, - 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, - 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, - 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, - 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x0e, 0x10, 0x0f, 0x4a, 0x04, - 0x08, 0x0f, 0x10, 0x10, 0x4a, 0x04, 0x08, 0x10, 0x10, 0x11, 0x22, 0xa7, 0x03, 0x0a, 0x08, 0x41, - 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x61, - 0x70, 0x70, 0x65, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x14, 0x0a, 0x05, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, 0x70, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x70, - 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, - 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x12, 0x3c, 0x0a, 0x06, 0x61, 0x70, 0x70, 0x65, - 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x52, 0x06, - 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, - 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x16, 0x0a, 0x06, - 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x65, - 0x61, 0x73, 0x6f, 0x6e, 0x22, 0xeb, 0x04, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x79, - 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x75, 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x55, 0x72, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x47, 0x0a, 0x0a, 0x63, + 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x27, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, + 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, + 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x64, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x72, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x1a, 0xb8, 0x03, 0x0a, 0x10, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x61, 0x6c, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x12, 0x70, 0x0a, 0x08, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x54, 0x2e, 0x67, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, + 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x64, + 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, + 0x6f, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, + 0x45, 0x0a, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, + 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x42, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, + 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x1a, 0x92, 0x01, 0x0a, 0x12, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x66, 0x69, 0x65, + 0x72, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, + 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, - 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, - 0x03, 0x75, 0x72, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6e, 0x12, - 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x07, 0x64, - 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4a, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, - 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, - 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x2e, 0x4c, - 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, - 0x6c, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, - 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x5f, 0x64, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, - 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, - 0x6e, 0x74, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, - 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, - 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, - 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x6c, 0x6f, 0x62, - 0x61, 0x6c, 0x5f, 0x75, 0x72, 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x6c, - 0x6f, 0x62, 0x61, 0x6c, 0x55, 0x72, 0x6e, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, - 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, - 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, - 0x38, 0x01, 0x22, 0xbf, 0x06, 0x0a, 0x05, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, - 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x43, 0x0a, + 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x10, 0x0a, + 0x03, 0x75, 0x72, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x6e, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x1a, + 0xda, 0x01, 0x0a, 0x03, 0x49, 0x41, 0x4d, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x12, 0x2e, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x06, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x4c, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, + 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x2e, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x2e, 0x49, 0x41, 0x4d, 0x2e, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, + 0x61, 0x1a, 0x39, 0x0a, 0x0b, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, + 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x70, 0x0a, 0x0d, + 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x43, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, 0x61, 0x74, 0x65, - 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x44, 0x61, - 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x49, 0x64, 0x12, - 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x0a, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x42, 0x79, 0x12, 0x39, - 0x0a, 0x0a, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, - 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x41, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x76, - 0x6f, 0x6b, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0c, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x1d, - 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x0d, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x12, 0x39, 0x0a, - 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x64, 0x41, 0x74, 0x12, 0x42, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, - 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, - 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x3c, 0x0a, 0x06, 0x61, 0x70, 0x70, 0x65, 0x61, - 0x6c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x52, 0x06, 0x61, - 0x70, 0x70, 0x65, 0x61, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x6d, - 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x50, - 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x69, 0x6e, 0x5f, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x49, 0x6e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x14, - 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6f, - 0x77, 0x6e, 0x65, 0x72, 0x22, 0xf7, 0x04, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x38, 0x0a, - 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x26, 0x0a, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, - 0x79, 0x70, 0x65, 0x12, 0x33, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x08, - 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x41, 0x74, 0x12, 0x42, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, - 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x08, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x74, 0x6f, + 0x74, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x64, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xcc, + 0x07, 0x0a, 0x06, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, + 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x79, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x0d, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x45, 0x0a, 0x07, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x67, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, + 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, + 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x48, 0x0a, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, + 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x06, 0x6c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x42, 0x0a, 0x08, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, + 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x44, + 0x0a, 0x09, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x18, 0x0b, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, + 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2e, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x52, 0x09, 0x61, 0x70, 0x70, 0x72, 0x6f, + 0x76, 0x61, 0x6c, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, + 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0d, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x31, 0x0a, 0x07, 0x64, 0x65, + 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x75, 0x63, 0x74, 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x21, 0x0a, + 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x12, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, 0x13, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, 0x12, + 0x30, 0x0a, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, 0x72, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x63, 0x72, 0x65, 0x61, 0x74, 0x6f, + 0x72, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x15, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x39, 0x0a, 0x05, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x18, 0x16, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, + 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, + 0x31, 0x2e, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x05, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x12, 0x20, + 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x17, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, + 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x4a, 0x04, 0x08, 0x0e, 0x10, + 0x0f, 0x4a, 0x04, 0x08, 0x0f, 0x10, 0x10, 0x4a, 0x04, 0x08, 0x10, 0x10, 0x11, 0x22, 0xa7, 0x03, + 0x0a, 0x08, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1b, + 0x0a, 0x09, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x49, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x61, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x49, 0x64, 0x12, 0x25, 0x0a, 0x0e, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0d, + 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, + 0x09, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x09, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x12, 0x3c, 0x0a, 0x06, 0x61, + 0x70, 0x70, 0x65, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, + 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x61, + 0x6c, 0x52, 0x06, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, + 0x61, 0x74, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, + 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x22, 0xeb, 0x04, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x55, 0x72, 0x6e, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, + 0x72, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x31, 0x0a, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, + 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, + 0x52, 0x07, 0x64, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x4a, 0x0a, 0x06, 0x6c, 0x61, 0x62, + 0x65, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x30, 0x0a, 0x14, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, - 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x70, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x49, 0x64, 0x12, 0x2f, 0x0a, - 0x13, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x72, 0x65, 0x6c, 0x61, - 0x74, 0x65, 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x32, 0x97, - 0x2f, 0x0a, 0x0f, 0x47, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x94, 0x01, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, - 0x64, 0x65, 0x72, 0x73, 0x12, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x93, 0x01, 0x0a, 0x0b, 0x47, 0x65, - 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, + 0x65, 0x2e, 0x4c, 0x61, 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x06, 0x6c, + 0x61, 0x62, 0x65, 0x6c, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, + 0x12, 0x39, 0x0a, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x09, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x69, + 0x73, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x09, 0x69, 0x73, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, + 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x42, 0x0a, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, + 0x72, 0x65, 0x6e, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, - 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, - 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, - 0xa3, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, - 0x79, 0x70, 0x65, 0x73, 0x12, 0x35, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, - 0x79, 0x70, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x67, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, - 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x2f, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x12, 0x9f, 0x01, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, + 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x08, 0x63, 0x68, 0x69, 0x6c, 0x64, 0x72, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x67, + 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x5f, 0x75, 0x72, 0x6e, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x67, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x55, 0x72, 0x6e, 0x1a, 0x39, 0x0a, 0x0b, 0x4c, 0x61, + 0x62, 0x65, 0x6c, 0x73, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x76, + 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, + 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0xbf, 0x06, 0x0a, 0x05, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, + 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x20, + 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x43, 0x0a, 0x0f, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x64, + 0x61, 0x74, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0e, 0x65, 0x78, 0x70, 0x69, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x44, 0x61, 0x74, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x5f, + 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, + 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x5f, 0x62, 0x79, + 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x42, + 0x79, 0x12, 0x39, 0x0a, 0x0a, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, + 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x09, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x64, 0x41, 0x74, 0x12, 0x23, 0x0a, 0x0d, + 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x5f, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x0c, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x52, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x62, 0x79, 0x18, + 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x42, 0x79, + 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0e, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x75, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x75, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x42, 0x0a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, - 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, - 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x3a, 0x06, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0xdd, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x33, 0x2e, 0x67, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, - 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, - 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x60, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x5a, 0x3a, 0x06, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5a, 0x37, 0x3a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x1a, - 0x2d, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, - 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x7d, 0x2f, 0x7b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x75, 0x72, 0x6e, 0x7d, 0x1a, 0x17, - 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9c, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x33, 0x2e, 0x67, 0x6f, 0x74, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x3c, 0x0a, 0x06, 0x61, 0x70, + 0x70, 0x65, 0x61, 0x6c, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, - 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, - 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, - 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x2a, 0x17, 0x2f, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xad, 0x01, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x2e, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x39, 0x12, 0x37, 0x2f, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, - 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, - 0x2f, 0x7b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x7d, - 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0xa8, 0x01, 0x0a, 0x10, 0x49, 0x6d, 0x70, 0x6f, 0x72, - 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x35, 0x2e, 0x67, 0x6f, + 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, + 0x52, 0x06, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x73, 0x5f, 0x70, + 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, + 0x69, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x13, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x12, 0x2c, 0x0a, 0x12, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x5f, 0x69, 0x6e, + 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x14, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x10, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x49, 0x6e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x12, 0x14, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x22, 0xf7, 0x04, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x12, 0x0e, 0x0a, 0x02, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x1f, 0x0a, 0x0b, + 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1f, 0x0a, + 0x0b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x64, 0x12, 0x1d, + 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, + 0x0c, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x26, 0x0a, 0x0e, 0x61, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0e, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x33, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, + 0x74, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x39, 0x0a, 0x0a, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x42, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x52, 0x08, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x42, 0x0a, 0x08, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x67, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, + 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x52, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x30, + 0x0a, 0x14, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x49, 0x64, + 0x12, 0x2f, 0x0a, 0x13, 0x72, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x70, 0x65, 0x72, 0x6d, + 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x72, + 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x32, 0x97, 0x2f, 0x0a, 0x0f, 0x47, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x94, 0x01, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, - 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, - 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, - 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x69, - 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, - 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2f, 0x69, 0x6d, 0x70, 0x6f, 0x72, - 0x74, 0x12, 0x94, 0x01, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x79, 0x12, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, - 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, 0x65, + 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0x93, 0x01, 0x0a, + 0x0b, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x67, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, + 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, + 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, + 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, + 0x64, 0x7d, 0x12, 0xa3, 0x01, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x35, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, + 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, + 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x54, 0x79, 0x70, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, - 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x69, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x98, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x73, - 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x33, 0x2e, 0x67, 0x6f, + 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x73, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x12, 0x9f, 0x01, 0x0a, 0x0e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, - 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, - 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x12, 0x13, - 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, - 0x69, 0x65, 0x73, 0x12, 0x90, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, - 0x63, 0x69, 0x65, 0x73, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x3a, 0x06, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x12, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x12, 0xdd, 0x01, 0x0a, 0x0e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x33, 0x2e, + 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, + 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, + 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, + 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x60, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x5a, + 0x3a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5a, 0x37, 0x3a, 0x06, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x1a, 0x2d, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x7d, 0x2f, 0x7b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x75, 0x72, 0x6e, + 0x7d, 0x1a, 0x17, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x64, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9c, 0x01, 0x0a, 0x0e, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x33, 0x2e, + 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, + 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, + 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, + 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, + 0x2a, 0x17, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xad, 0x01, 0x0a, 0x09, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x2e, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x6f, 0x6c, 0x65, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x39, + 0x12, 0x37, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x7d, 0x2f, 0x72, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0xa8, 0x01, 0x0a, 0x10, 0x49, 0x6d, + 0x70, 0x6f, 0x72, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x35, + 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, + 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x6d, + 0x70, 0x6f, 0x72, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, + 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, + 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x25, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x3a, 0x01, 0x2a, 0x22, 0x1a, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x2f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2f, 0x69, 0x6d, + 0x70, 0x6f, 0x72, 0x74, 0x12, 0x94, 0x01, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x79, 0x12, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x79, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, + 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, + 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1a, 0x12, 0x18, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x69, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x98, 0x01, 0x0a, 0x0e, + 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x33, + 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, + 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, + 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x74, 0x69, 0x65, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x63, 0x74, 0x69, + 0x76, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x90, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x6f, - 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x9f, 0x01, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x12, 0x2e, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, 0x12, 0x29, 0x2f, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, - 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, - 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x12, 0x98, 0x01, 0x0a, 0x0c, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, + 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, + 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x19, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x9f, 0x01, 0x0a, 0x09, 0x47, 0x65, + 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x2e, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x31, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2b, + 0x12, 0x29, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, + 0x69, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x2f, 0x7b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x12, 0x98, 0x01, 0x0a, 0x0c, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x3a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x22, 0x11, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, - 0x69, 0x65, 0x73, 0x12, 0x9d, 0x01, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, + 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x3a, 0x06, 0x70, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x22, 0x11, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x6f, + 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x12, 0x9d, 0x01, 0x0a, 0x0c, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6f, 0x6c, - 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x20, 0x3a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x1a, 0x16, 0x2f, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2f, 0x7b, - 0x69, 0x64, 0x7d, 0x12, 0xcc, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x39, 0x2e, 0x67, - 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, - 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, - 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, - 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x3d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x37, 0x12, 0x35, 0x2f, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, 0x73, 0x2f, 0x7b, - 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x2f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, - 0x65, 0x73, 0x12, 0x94, 0x01, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x73, 0x12, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, - 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, - 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, - 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x93, 0x01, 0x0a, 0x0b, 0x47, 0x65, - 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, - 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, - 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, - 0xa6, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x12, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, - 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x69, 0x63, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, + 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x1a, 0x16, + 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, + 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0xcc, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x50, 0x6f, + 0x6c, 0x69, 0x63, 0x79, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, + 0x39, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, + 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, + 0x65, 0x74, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, + 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, 0x67, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, + 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6f, 0x6c, + 0x69, 0x63, 0x79, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x3d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x37, 0x12, 0x35, + 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x69, 0x65, + 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, + 0x7b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x2f, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, + 0x65, 0x6e, 0x63, 0x65, 0x73, 0x12, 0x94, 0x01, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x29, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x3a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x1a, - 0x17, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9c, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x33, 0x2e, 0x67, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, - 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, - 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x2a, 0x17, - 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9b, 0x01, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, - 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x12, 0x34, 0x2e, 0x67, 0x6f, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, - 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x35, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, - 0x12, 0x13, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x6d, 0x65, 0x2f, 0x61, 0x70, - 0x70, 0x65, 0x61, 0x6c, 0x73, 0x12, 0x8c, 0x01, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, - 0x70, 0x65, 0x61, 0x6c, 0x73, 0x12, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, + 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x93, 0x01, 0x0a, + 0x0b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x30, 0x2e, 0x67, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, + 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, + 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, + 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, + 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x12, 0x17, 0x2f, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, + 0x64, 0x7d, 0x12, 0xa6, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, - 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x65, 0x61, - 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x70, 0x70, - 0x65, 0x61, 0x6c, 0x73, 0x12, 0x8b, 0x01, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x65, - 0x61, 0x6c, 0x12, 0x2e, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, - 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, - 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x2f, 0x7b, 0x69, - 0x64, 0x7d, 0x12, 0x9b, 0x01, 0x0a, 0x0c, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x70, 0x70, - 0x65, 0x61, 0x6c, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, + 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x3a, 0x08, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x1a, 0x17, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9c, 0x01, 0x0a, 0x0e, + 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x12, 0x33, + 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, + 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, + 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x19, 0x2a, 0x17, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x72, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9b, 0x01, 0x0a, 0x0f, 0x4c, + 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x12, 0x34, + 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, + 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, + 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x65, + 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x15, 0x12, 0x13, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x6d, 0x65, + 0x2f, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x12, 0x8c, 0x01, 0x0a, 0x0b, 0x4c, 0x69, 0x73, + 0x74, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x12, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x65, + 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, + 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, + 0x70, 0x65, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x18, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x12, 0x10, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, + 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x12, 0x8b, 0x01, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x41, + 0x70, 0x70, 0x65, 0x61, 0x6c, 0x12, 0x2e, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, + 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, + 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, + 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, + 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9b, 0x01, 0x0a, 0x0c, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x70, 0x70, 0x65, - 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1e, 0x1a, 0x1c, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x70, 0x70, - 0x65, 0x61, 0x6c, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, - 0x12, 0x92, 0x01, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x65, 0x61, - 0x6c, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, + 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, + 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, + 0x70, 0x70, 0x65, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x24, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x1a, 0x1c, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, + 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x63, 0x61, 0x6e, + 0x63, 0x65, 0x6c, 0x12, 0x92, 0x01, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, + 0x70, 0x65, 0x61, 0x6c, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x65, 0x61, 0x6c, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, - 0x3a, 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x70, - 0x70, 0x65, 0x61, 0x6c, 0x73, 0x12, 0xa3, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x36, 0x2e, 0x67, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, - 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, - 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x72, 0x6f, - 0x76, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1d, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x6d, - 0x65, 0x2f, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x94, 0x01, 0x0a, 0x0d, - 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x32, 0x2e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, + 0x65, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1b, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, + 0x2f, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x12, 0xa3, 0x01, 0x0a, 0x11, 0x4c, 0x69, 0x73, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x36, + 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, + 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, + 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, + 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, + 0x31, 0x2f, 0x6d, 0x65, 0x2f, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x94, + 0x01, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, + 0x12, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, + 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, + 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x70, 0x70, 0x72, + 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x12, 0xbc, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x12, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, + 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, - 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, + 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x3f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x39, 0x3a, 0x06, 0x61, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x22, 0x2f, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x70, + 0x70, 0x65, 0x61, 0x6c, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x70, 0x70, 0x72, 0x6f, + 0x76, 0x61, 0x6c, 0x73, 0x2f, 0x7b, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x7d, 0x12, 0xbd, 0x01, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x41, 0x70, 0x70, 0x72, + 0x6f, 0x76, 0x65, 0x72, 0x12, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, + 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, + 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x49, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x43, 0x3a, 0x01, 0x2a, 0x22, 0x3e, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, + 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x2f, 0x7b, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x5f, 0x69, + 0x64, 0x7d, 0x2f, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x2f, 0x7b, 0x61, 0x70, + 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x70, 0x70, 0x72, 0x6f, + 0x76, 0x65, 0x72, 0x73, 0x12, 0xcb, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, + 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x12, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x70, + 0x72, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, + 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, + 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x4e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x48, 0x2a, 0x46, 0x2f, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x2f, 0x7b, 0x61, 0x70, + 0x70, 0x65, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, + 0x6c, 0x73, 0x2f, 0x7b, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x7d, + 0x2f, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x65, 0x6d, 0x61, 0x69, + 0x6c, 0x7d, 0x12, 0x88, 0x01, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, + 0x73, 0x12, 0x2f, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, 0x12, 0x12, - 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, - 0x6c, 0x73, 0x12, 0xbc, 0x01, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, - 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x12, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, + 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x97, 0x01, + 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, + 0x12, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, + 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x72, 0x6f, - 0x76, 0x61, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, - 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x3f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x39, 0x3a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x22, 0x2f, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x70, 0x70, 0x65, 0x61, - 0x6c, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, - 0x73, 0x2f, 0x7b, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x5f, 0x6e, 0x61, 0x6d, 0x65, - 0x7d, 0x12, 0xbd, 0x01, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, - 0x72, 0x12, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, - 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x41, 0x64, 0x64, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, - 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x41, 0x64, 0x64, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x49, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x43, 0x3a, 0x01, - 0x2a, 0x22, 0x3e, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x61, 0x70, 0x70, 0x65, - 0x61, 0x6c, 0x73, 0x2f, 0x7b, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x7d, 0x2f, - 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x2f, 0x7b, 0x61, 0x70, 0x70, 0x72, 0x6f, - 0x76, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, - 0x73, 0x12, 0xcb, 0x01, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x70, 0x72, - 0x6f, 0x76, 0x65, 0x72, 0x12, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, - 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x70, 0x70, 0x72, 0x6f, 0x76, - 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x61, + 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, + 0x93, 0x02, 0x14, 0x12, 0x12, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x6d, 0x65, + 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x9a, 0x01, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, + 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, - 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, - 0x70, 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x4e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x48, 0x2a, 0x46, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2f, 0x61, 0x70, 0x70, 0x65, 0x61, 0x6c, 0x73, 0x2f, 0x7b, 0x61, 0x70, 0x70, 0x65, 0x61, - 0x6c, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x2f, - 0x7b, 0x61, 0x70, 0x70, 0x72, 0x6f, 0x76, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x70, - 0x70, 0x72, 0x6f, 0x76, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x7d, 0x12, - 0x88, 0x01, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x2f, - 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, - 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, - 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x17, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x11, 0x12, 0x0f, 0x2f, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x97, 0x01, 0x0a, 0x0e, 0x4c, - 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x33, 0x2e, + 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, + 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, - 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x14, - 0x12, 0x12, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x6d, 0x65, 0x2f, 0x67, 0x72, - 0x61, 0x6e, 0x74, 0x73, 0x12, 0x9a, 0x01, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, - 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, - 0x6c, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x67, 0x6f, 0x74, - 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, - 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, - 0x31, 0x2f, 0x6d, 0x65, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x2f, 0x72, 0x6f, 0x6c, 0x65, - 0x73, 0x12, 0x87, 0x01, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x12, 0x2d, - 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, - 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, - 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, - 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x1c, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, - 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x93, 0x01, 0x0a, 0x0b, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x12, 0x30, 0x2e, 0x67, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, - 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, - 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, - 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x3a, 0x01, 0x2a, 0x32, 0x14, 0x2f, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, - 0x7d, 0x12, 0x9a, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x47, 0x72, 0x61, 0x6e, - 0x74, 0x12, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x6f, 0x6c, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x76, 0x31, 0x62, + 0x65, 0x74, 0x61, 0x31, 0x2f, 0x6d, 0x65, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x2f, 0x72, + 0x6f, 0x6c, 0x65, 0x73, 0x12, 0x87, 0x01, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x47, 0x72, 0x61, 0x6e, + 0x74, 0x12, 0x2d, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, - 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, - 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, - 0x61, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x20, 0x3a, 0x01, - 0x2a, 0x1a, 0x1b, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x67, 0x72, 0x61, 0x6e, - 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x12, 0x98, - 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x12, - 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, - 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, - 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, + 0x2e, 0x47, 0x65, 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2e, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, + 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x47, 0x65, 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, 0x12, 0x14, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, + 0x61, 0x31, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x93, + 0x01, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x12, 0x30, + 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, + 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, + 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x1f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x19, 0x3a, 0x01, 0x2a, 0x32, 0x14, + 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x2f, + 0x7b, 0x69, 0x64, 0x7d, 0x12, 0x9a, 0x01, 0x0a, 0x0b, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x47, + 0x72, 0x61, 0x6e, 0x74, 0x12, 0x30, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, + 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, + 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, + 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, + 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x47, 0x72, 0x61, 0x6e, + 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x26, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x20, 0x3a, 0x01, 0x2a, 0x1a, 0x1b, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x67, + 0x72, 0x61, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x2f, 0x72, 0x65, 0x76, 0x6f, 0x6b, + 0x65, 0x12, 0x98, 0x01, 0x0a, 0x0c, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x47, 0x72, 0x61, 0x6e, + 0x74, 0x73, 0x12, 0x31, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x3a, 0x01, - 0x2a, 0x1a, 0x16, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x67, 0x72, 0x61, 0x6e, - 0x74, 0x73, 0x2f, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x12, 0xbc, 0x01, 0x0a, 0x18, 0x49, 0x6d, - 0x70, 0x6f, 0x72, 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x3d, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, - 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, - 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x47, 0x72, 0x61, 0x6e, - 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, 0x76, 0x31, 0x62, - 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, - 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x3a, 0x01, 0x2a, - 0x22, 0x16, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x67, 0x72, 0x61, 0x6e, 0x74, - 0x73, 0x2f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x48, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x6e, 0x2f, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x3b, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x76, 0x31, 0x62, 0x65, - 0x74, 0x61, 0x31, 0x92, 0x41, 0x0c, 0x12, 0x07, 0x32, 0x05, 0x30, 0x2e, 0x31, 0x2e, 0x30, 0x2a, - 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x74, 0x61, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x47, 0x72, 0x61, 0x6e, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x1b, 0x3a, 0x01, 0x2a, 0x1a, 0x16, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x67, + 0x72, 0x61, 0x6e, 0x74, 0x73, 0x2f, 0x72, 0x65, 0x76, 0x6f, 0x6b, 0x65, 0x12, 0xbc, 0x01, 0x0a, + 0x18, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x46, 0x72, 0x6f, + 0x6d, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x3d, 0x2e, 0x67, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, + 0x2e, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x47, + 0x72, 0x61, 0x6e, 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, + 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3e, 0x2e, 0x67, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6d, 0x70, 0x61, 0x6e, 0x79, 0x2e, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2e, + 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2e, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x47, 0x72, + 0x61, 0x6e, 0x74, 0x73, 0x46, 0x72, 0x6f, 0x6d, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, + 0x3a, 0x01, 0x2a, 0x22, 0x16, 0x2f, 0x76, 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x2f, 0x67, 0x72, + 0x61, 0x6e, 0x74, 0x73, 0x2f, 0x69, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x48, 0x5a, 0x37, 0x67, + 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x74, 0x6f, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x2f, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x2f, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x3b, 0x67, 0x75, 0x61, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x76, + 0x31, 0x62, 0x65, 0x74, 0x61, 0x31, 0x92, 0x41, 0x0c, 0x12, 0x07, 0x32, 0x05, 0x30, 0x2e, 0x31, + 0x2e, 0x30, 0x2a, 0x01, 0x01, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -8828,114 +8827,114 @@ func file_gotocompany_guardian_v1beta1_guardian_proto_rawDescGZIP() []byte { var file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes = make([]protoimpl.MessageInfo, 114) var file_gotocompany_guardian_v1beta1_guardian_proto_goTypes = []interface{}{ - (*ListProvidersRequest)(nil), // 0: gotocompany.guardian.v1beta1.ListProvidersRequest - (*ListProvidersResponse)(nil), // 1: gotocompany.guardian.v1beta1.ListProvidersResponse - (*GetProviderRequest)(nil), // 2: gotocompany.guardian.v1beta1.GetProviderRequest - (*GetProviderResponse)(nil), // 3: gotocompany.guardian.v1beta1.GetProviderResponse - (*GetProviderTypesRequest)(nil), // 4: gotocompany.guardian.v1beta1.GetProviderTypesRequest - (*GetProviderTypesResponse)(nil), // 5: gotocompany.guardian.v1beta1.GetProviderTypesResponse - (*CreateProviderRequest)(nil), // 6: gotocompany.guardian.v1beta1.CreateProviderRequest - (*CreateProviderResponse)(nil), // 7: gotocompany.guardian.v1beta1.CreateProviderResponse - (*UpdateProviderRequest)(nil), // 8: gotocompany.guardian.v1beta1.UpdateProviderRequest - (*UpdateProviderResponse)(nil), // 9: gotocompany.guardian.v1beta1.UpdateProviderResponse - (*DeleteProviderRequest)(nil), // 10: gotocompany.guardian.v1beta1.DeleteProviderRequest - (*DeleteProviderResponse)(nil), // 11: gotocompany.guardian.v1beta1.DeleteProviderResponse - (*ImportGrantsFromProviderRequest)(nil), // 12: gotocompany.guardian.v1beta1.ImportGrantsFromProviderRequest - (*ImportGrantsFromProviderResponse)(nil), // 13: gotocompany.guardian.v1beta1.ImportGrantsFromProviderResponse - (*ListRolesRequest)(nil), // 14: gotocompany.guardian.v1beta1.ListRolesRequest - (*ListRolesResponse)(nil), // 15: gotocompany.guardian.v1beta1.ListRolesResponse - (*ImportActivitiesRequest)(nil), // 16: gotocompany.guardian.v1beta1.ImportActivitiesRequest - (*ImportActivitiesResponse)(nil), // 17: gotocompany.guardian.v1beta1.ImportActivitiesResponse - (*GetActivityRequest)(nil), // 18: gotocompany.guardian.v1beta1.GetActivityRequest - (*GetActivityResponse)(nil), // 19: gotocompany.guardian.v1beta1.GetActivityResponse - (*ListActivitiesRequest)(nil), // 20: gotocompany.guardian.v1beta1.ListActivitiesRequest - (*ListActivitiesResponse)(nil), // 21: gotocompany.guardian.v1beta1.ListActivitiesResponse - (*ListPoliciesRequest)(nil), // 22: gotocompany.guardian.v1beta1.ListPoliciesRequest - (*ListPoliciesResponse)(nil), // 23: gotocompany.guardian.v1beta1.ListPoliciesResponse - (*GetPolicyRequest)(nil), // 24: gotocompany.guardian.v1beta1.GetPolicyRequest - (*GetPolicyPreferencesRequest)(nil), // 25: gotocompany.guardian.v1beta1.GetPolicyPreferencesRequest - (*GetPolicyPreferencesResponse)(nil), // 26: gotocompany.guardian.v1beta1.GetPolicyPreferencesResponse - (*GetPolicyResponse)(nil), // 27: gotocompany.guardian.v1beta1.GetPolicyResponse - (*CreatePolicyRequest)(nil), // 28: gotocompany.guardian.v1beta1.CreatePolicyRequest - (*CreatePolicyResponse)(nil), // 29: gotocompany.guardian.v1beta1.CreatePolicyResponse - (*UpdatePolicyRequest)(nil), // 30: gotocompany.guardian.v1beta1.UpdatePolicyRequest - (*UpdatePolicyResponse)(nil), // 31: gotocompany.guardian.v1beta1.UpdatePolicyResponse - (*ListResourcesRequest)(nil), // 32: gotocompany.guardian.v1beta1.ListResourcesRequest - (*ListResourcesResponse)(nil), // 33: gotocompany.guardian.v1beta1.ListResourcesResponse - (*GetResourceRequest)(nil), // 34: gotocompany.guardian.v1beta1.GetResourceRequest - (*GetResourceResponse)(nil), // 35: gotocompany.guardian.v1beta1.GetResourceResponse - (*UpdateResourceRequest)(nil), // 36: gotocompany.guardian.v1beta1.UpdateResourceRequest - (*UpdateResourceResponse)(nil), // 37: gotocompany.guardian.v1beta1.UpdateResourceResponse - (*DeleteResourceRequest)(nil), // 38: gotocompany.guardian.v1beta1.DeleteResourceRequest - (*DeleteResourceResponse)(nil), // 39: gotocompany.guardian.v1beta1.DeleteResourceResponse - (*ListUserAppealsRequest)(nil), // 40: gotocompany.guardian.v1beta1.ListUserAppealsRequest - (*ListUserAppealsResponse)(nil), // 41: gotocompany.guardian.v1beta1.ListUserAppealsResponse - (*ListAppealsRequest)(nil), // 42: gotocompany.guardian.v1beta1.ListAppealsRequest - (*ListAppealsResponse)(nil), // 43: gotocompany.guardian.v1beta1.ListAppealsResponse - (*GetAppealRequest)(nil), // 44: gotocompany.guardian.v1beta1.GetAppealRequest - (*GetAppealResponse)(nil), // 45: gotocompany.guardian.v1beta1.GetAppealResponse - (*CancelAppealRequest)(nil), // 46: gotocompany.guardian.v1beta1.CancelAppealRequest - (*CancelAppealResponse)(nil), // 47: gotocompany.guardian.v1beta1.CancelAppealResponse - (*RevokeAppealRequest)(nil), // 48: gotocompany.guardian.v1beta1.RevokeAppealRequest - (*RevokeAppealResponse)(nil), // 49: gotocompany.guardian.v1beta1.RevokeAppealResponse - (*RevokeAppealsRequest)(nil), // 50: gotocompany.guardian.v1beta1.RevokeAppealsRequest - (*RevokeAppealsResponse)(nil), // 51: gotocompany.guardian.v1beta1.RevokeAppealsResponse - (*CreateAppealRequest)(nil), // 52: gotocompany.guardian.v1beta1.CreateAppealRequest - (*CreateAppealResponse)(nil), // 53: gotocompany.guardian.v1beta1.CreateAppealResponse - (*ListUserApprovalsRequest)(nil), // 54: gotocompany.guardian.v1beta1.ListUserApprovalsRequest - (*ListUserApprovalsResponse)(nil), // 55: gotocompany.guardian.v1beta1.ListUserApprovalsResponse - (*ListApprovalsRequest)(nil), // 56: gotocompany.guardian.v1beta1.ListApprovalsRequest - (*ListApprovalsResponse)(nil), // 57: gotocompany.guardian.v1beta1.ListApprovalsResponse - (*UpdateApprovalRequest)(nil), // 58: gotocompany.guardian.v1beta1.UpdateApprovalRequest - (*UpdateApprovalResponse)(nil), // 59: gotocompany.guardian.v1beta1.UpdateApprovalResponse - (*AddApproverRequest)(nil), // 60: gotocompany.guardian.v1beta1.AddApproverRequest - (*AddApproverResponse)(nil), // 61: gotocompany.guardian.v1beta1.AddApproverResponse - (*DeleteApproverRequest)(nil), // 62: gotocompany.guardian.v1beta1.DeleteApproverRequest - (*DeleteApproverResponse)(nil), // 63: gotocompany.guardian.v1beta1.DeleteApproverResponse - (*ListGrantsRequest)(nil), // 64: gotocompany.guardian.v1beta1.ListGrantsRequest - (*ListGrantsResponse)(nil), // 65: gotocompany.guardian.v1beta1.ListGrantsResponse - (*ListUserGrantsRequest)(nil), // 66: gotocompany.guardian.v1beta1.ListUserGrantsRequest - (*ListUserGrantsResponse)(nil), // 67: gotocompany.guardian.v1beta1.ListUserGrantsResponse - (*ListUserRolesRequest)(nil), // 68: gotocompany.guardian.v1beta1.ListUserRolesRequest - (*ListUserRolesResponse)(nil), // 69: gotocompany.guardian.v1beta1.ListUserRolesResponse - (*GetGrantRequest)(nil), // 70: gotocompany.guardian.v1beta1.GetGrantRequest - (*GetGrantResponse)(nil), // 71: gotocompany.guardian.v1beta1.GetGrantResponse - (*UpdateGrantRequest)(nil), // 72: gotocompany.guardian.v1beta1.UpdateGrantRequest - (*UpdateGrantResponse)(nil), // 73: gotocompany.guardian.v1beta1.UpdateGrantResponse - (*RevokeGrantRequest)(nil), // 74: gotocompany.guardian.v1beta1.RevokeGrantRequest - (*RevokeGrantResponse)(nil), // 75: gotocompany.guardian.v1beta1.RevokeGrantResponse - (*RevokeGrantsRequest)(nil), // 76: gotocompany.guardian.v1beta1.RevokeGrantsRequest - (*RevokeGrantsResponse)(nil), // 77: gotocompany.guardian.v1beta1.RevokeGrantsResponse - (*Role)(nil), // 78: gotocompany.guardian.v1beta1.Role - (*PolicyConfig)(nil), // 79: gotocompany.guardian.v1beta1.PolicyConfig - (*ProviderConfig)(nil), // 80: gotocompany.guardian.v1beta1.ProviderConfig - (*Provider)(nil), // 81: gotocompany.guardian.v1beta1.Provider - (*ProviderType)(nil), // 82: gotocompany.guardian.v1beta1.ProviderType - (*Condition)(nil), // 83: gotocompany.guardian.v1beta1.Condition - (*PolicyAppealConfig)(nil), // 84: gotocompany.guardian.v1beta1.PolicyAppealConfig - (*Policy)(nil), // 85: gotocompany.guardian.v1beta1.Policy - (*AppealOptions)(nil), // 86: gotocompany.guardian.v1beta1.AppealOptions - (*Appeal)(nil), // 87: gotocompany.guardian.v1beta1.Appeal - (*Approval)(nil), // 88: gotocompany.guardian.v1beta1.Approval - (*Resource)(nil), // 89: gotocompany.guardian.v1beta1.Resource - (*Grant)(nil), // 90: gotocompany.guardian.v1beta1.Grant - (*ProviderActivity)(nil), // 91: gotocompany.guardian.v1beta1.ProviderActivity - (*RevokeAppealRequest_Reason)(nil), // 92: gotocompany.guardian.v1beta1.RevokeAppealRequest.Reason - (*CreateAppealRequest_Resource)(nil), // 93: gotocompany.guardian.v1beta1.CreateAppealRequest.Resource - (*UpdateApprovalRequest_Action)(nil), // 94: gotocompany.guardian.v1beta1.UpdateApprovalRequest.Action - nil, // 95: gotocompany.guardian.v1beta1.ProviderConfig.LabelsEntry - (*ProviderConfig_AppealConfig)(nil), // 96: gotocompany.guardian.v1beta1.ProviderConfig.AppealConfig - (*ProviderConfig_ResourceConfig)(nil), // 97: gotocompany.guardian.v1beta1.ProviderConfig.ResourceConfig - (*ProviderConfig_ProviderParameter)(nil), // 98: gotocompany.guardian.v1beta1.ProviderConfig.ProviderParameter - (*Condition_MatchCondition)(nil), // 99: gotocompany.guardian.v1beta1.Condition.MatchCondition - (*PolicyAppealConfig_DurationOptions)(nil), // 100: gotocompany.guardian.v1beta1.PolicyAppealConfig.DurationOptions - (*PolicyAppealConfig_Question)(nil), // 101: gotocompany.guardian.v1beta1.PolicyAppealConfig.Question - (*Policy_ApprovalStep)(nil), // 102: gotocompany.guardian.v1beta1.Policy.ApprovalStep - nil, // 103: gotocompany.guardian.v1beta1.Policy.LabelsEntry - (*Policy_Requirement)(nil), // 104: gotocompany.guardian.v1beta1.Policy.Requirement - (*Policy_IAM)(nil), // 105: gotocompany.guardian.v1beta1.Policy.IAM - (*Policy_AppealMetadataSource)(nil), // 106: gotocompany.guardian.v1beta1.Policy.AppealMetadataSource - nil, // 107: gotocompany.guardian.v1beta1.Policy.AppealMetadataSourcesEntry + (*ListProvidersRequest)(nil), // 0: gotocompany.guardian.v1beta1.ListProvidersRequest + (*ListProvidersResponse)(nil), // 1: gotocompany.guardian.v1beta1.ListProvidersResponse + (*GetProviderRequest)(nil), // 2: gotocompany.guardian.v1beta1.GetProviderRequest + (*GetProviderResponse)(nil), // 3: gotocompany.guardian.v1beta1.GetProviderResponse + (*GetProviderTypesRequest)(nil), // 4: gotocompany.guardian.v1beta1.GetProviderTypesRequest + (*GetProviderTypesResponse)(nil), // 5: gotocompany.guardian.v1beta1.GetProviderTypesResponse + (*CreateProviderRequest)(nil), // 6: gotocompany.guardian.v1beta1.CreateProviderRequest + (*CreateProviderResponse)(nil), // 7: gotocompany.guardian.v1beta1.CreateProviderResponse + (*UpdateProviderRequest)(nil), // 8: gotocompany.guardian.v1beta1.UpdateProviderRequest + (*UpdateProviderResponse)(nil), // 9: gotocompany.guardian.v1beta1.UpdateProviderResponse + (*DeleteProviderRequest)(nil), // 10: gotocompany.guardian.v1beta1.DeleteProviderRequest + (*DeleteProviderResponse)(nil), // 11: gotocompany.guardian.v1beta1.DeleteProviderResponse + (*ImportGrantsFromProviderRequest)(nil), // 12: gotocompany.guardian.v1beta1.ImportGrantsFromProviderRequest + (*ImportGrantsFromProviderResponse)(nil), // 13: gotocompany.guardian.v1beta1.ImportGrantsFromProviderResponse + (*ListRolesRequest)(nil), // 14: gotocompany.guardian.v1beta1.ListRolesRequest + (*ListRolesResponse)(nil), // 15: gotocompany.guardian.v1beta1.ListRolesResponse + (*ImportActivitiesRequest)(nil), // 16: gotocompany.guardian.v1beta1.ImportActivitiesRequest + (*ImportActivitiesResponse)(nil), // 17: gotocompany.guardian.v1beta1.ImportActivitiesResponse + (*GetActivityRequest)(nil), // 18: gotocompany.guardian.v1beta1.GetActivityRequest + (*GetActivityResponse)(nil), // 19: gotocompany.guardian.v1beta1.GetActivityResponse + (*ListActivitiesRequest)(nil), // 20: gotocompany.guardian.v1beta1.ListActivitiesRequest + (*ListActivitiesResponse)(nil), // 21: gotocompany.guardian.v1beta1.ListActivitiesResponse + (*ListPoliciesRequest)(nil), // 22: gotocompany.guardian.v1beta1.ListPoliciesRequest + (*ListPoliciesResponse)(nil), // 23: gotocompany.guardian.v1beta1.ListPoliciesResponse + (*GetPolicyRequest)(nil), // 24: gotocompany.guardian.v1beta1.GetPolicyRequest + (*GetPolicyPreferencesRequest)(nil), // 25: gotocompany.guardian.v1beta1.GetPolicyPreferencesRequest + (*GetPolicyPreferencesResponse)(nil), // 26: gotocompany.guardian.v1beta1.GetPolicyPreferencesResponse + (*GetPolicyResponse)(nil), // 27: gotocompany.guardian.v1beta1.GetPolicyResponse + (*CreatePolicyRequest)(nil), // 28: gotocompany.guardian.v1beta1.CreatePolicyRequest + (*CreatePolicyResponse)(nil), // 29: gotocompany.guardian.v1beta1.CreatePolicyResponse + (*UpdatePolicyRequest)(nil), // 30: gotocompany.guardian.v1beta1.UpdatePolicyRequest + (*UpdatePolicyResponse)(nil), // 31: gotocompany.guardian.v1beta1.UpdatePolicyResponse + (*ListResourcesRequest)(nil), // 32: gotocompany.guardian.v1beta1.ListResourcesRequest + (*ListResourcesResponse)(nil), // 33: gotocompany.guardian.v1beta1.ListResourcesResponse + (*GetResourceRequest)(nil), // 34: gotocompany.guardian.v1beta1.GetResourceRequest + (*GetResourceResponse)(nil), // 35: gotocompany.guardian.v1beta1.GetResourceResponse + (*UpdateResourceRequest)(nil), // 36: gotocompany.guardian.v1beta1.UpdateResourceRequest + (*UpdateResourceResponse)(nil), // 37: gotocompany.guardian.v1beta1.UpdateResourceResponse + (*DeleteResourceRequest)(nil), // 38: gotocompany.guardian.v1beta1.DeleteResourceRequest + (*DeleteResourceResponse)(nil), // 39: gotocompany.guardian.v1beta1.DeleteResourceResponse + (*ListUserAppealsRequest)(nil), // 40: gotocompany.guardian.v1beta1.ListUserAppealsRequest + (*ListUserAppealsResponse)(nil), // 41: gotocompany.guardian.v1beta1.ListUserAppealsResponse + (*ListAppealsRequest)(nil), // 42: gotocompany.guardian.v1beta1.ListAppealsRequest + (*ListAppealsResponse)(nil), // 43: gotocompany.guardian.v1beta1.ListAppealsResponse + (*GetAppealRequest)(nil), // 44: gotocompany.guardian.v1beta1.GetAppealRequest + (*GetAppealResponse)(nil), // 45: gotocompany.guardian.v1beta1.GetAppealResponse + (*CancelAppealRequest)(nil), // 46: gotocompany.guardian.v1beta1.CancelAppealRequest + (*CancelAppealResponse)(nil), // 47: gotocompany.guardian.v1beta1.CancelAppealResponse + (*RevokeAppealRequest)(nil), // 48: gotocompany.guardian.v1beta1.RevokeAppealRequest + (*RevokeAppealResponse)(nil), // 49: gotocompany.guardian.v1beta1.RevokeAppealResponse + (*RevokeAppealsRequest)(nil), // 50: gotocompany.guardian.v1beta1.RevokeAppealsRequest + (*RevokeAppealsResponse)(nil), // 51: gotocompany.guardian.v1beta1.RevokeAppealsResponse + (*CreateAppealRequest)(nil), // 52: gotocompany.guardian.v1beta1.CreateAppealRequest + (*CreateAppealResponse)(nil), // 53: gotocompany.guardian.v1beta1.CreateAppealResponse + (*ListUserApprovalsRequest)(nil), // 54: gotocompany.guardian.v1beta1.ListUserApprovalsRequest + (*ListUserApprovalsResponse)(nil), // 55: gotocompany.guardian.v1beta1.ListUserApprovalsResponse + (*ListApprovalsRequest)(nil), // 56: gotocompany.guardian.v1beta1.ListApprovalsRequest + (*ListApprovalsResponse)(nil), // 57: gotocompany.guardian.v1beta1.ListApprovalsResponse + (*UpdateApprovalRequest)(nil), // 58: gotocompany.guardian.v1beta1.UpdateApprovalRequest + (*UpdateApprovalResponse)(nil), // 59: gotocompany.guardian.v1beta1.UpdateApprovalResponse + (*AddApproverRequest)(nil), // 60: gotocompany.guardian.v1beta1.AddApproverRequest + (*AddApproverResponse)(nil), // 61: gotocompany.guardian.v1beta1.AddApproverResponse + (*DeleteApproverRequest)(nil), // 62: gotocompany.guardian.v1beta1.DeleteApproverRequest + (*DeleteApproverResponse)(nil), // 63: gotocompany.guardian.v1beta1.DeleteApproverResponse + (*ListGrantsRequest)(nil), // 64: gotocompany.guardian.v1beta1.ListGrantsRequest + (*ListGrantsResponse)(nil), // 65: gotocompany.guardian.v1beta1.ListGrantsResponse + (*ListUserGrantsRequest)(nil), // 66: gotocompany.guardian.v1beta1.ListUserGrantsRequest + (*ListUserGrantsResponse)(nil), // 67: gotocompany.guardian.v1beta1.ListUserGrantsResponse + (*ListUserRolesRequest)(nil), // 68: gotocompany.guardian.v1beta1.ListUserRolesRequest + (*ListUserRolesResponse)(nil), // 69: gotocompany.guardian.v1beta1.ListUserRolesResponse + (*GetGrantRequest)(nil), // 70: gotocompany.guardian.v1beta1.GetGrantRequest + (*GetGrantResponse)(nil), // 71: gotocompany.guardian.v1beta1.GetGrantResponse + (*UpdateGrantRequest)(nil), // 72: gotocompany.guardian.v1beta1.UpdateGrantRequest + (*UpdateGrantResponse)(nil), // 73: gotocompany.guardian.v1beta1.UpdateGrantResponse + (*RevokeGrantRequest)(nil), // 74: gotocompany.guardian.v1beta1.RevokeGrantRequest + (*RevokeGrantResponse)(nil), // 75: gotocompany.guardian.v1beta1.RevokeGrantResponse + (*RevokeGrantsRequest)(nil), // 76: gotocompany.guardian.v1beta1.RevokeGrantsRequest + (*RevokeGrantsResponse)(nil), // 77: gotocompany.guardian.v1beta1.RevokeGrantsResponse + (*Role)(nil), // 78: gotocompany.guardian.v1beta1.Role + (*PolicyConfig)(nil), // 79: gotocompany.guardian.v1beta1.PolicyConfig + (*ProviderConfig)(nil), // 80: gotocompany.guardian.v1beta1.ProviderConfig + (*Provider)(nil), // 81: gotocompany.guardian.v1beta1.Provider + (*ProviderType)(nil), // 82: gotocompany.guardian.v1beta1.ProviderType + (*Condition)(nil), // 83: gotocompany.guardian.v1beta1.Condition + (*PolicyAppealConfig)(nil), // 84: gotocompany.guardian.v1beta1.PolicyAppealConfig + (*Policy)(nil), // 85: gotocompany.guardian.v1beta1.Policy + (*AppealOptions)(nil), // 86: gotocompany.guardian.v1beta1.AppealOptions + (*Appeal)(nil), // 87: gotocompany.guardian.v1beta1.Appeal + (*Approval)(nil), // 88: gotocompany.guardian.v1beta1.Approval + (*Resource)(nil), // 89: gotocompany.guardian.v1beta1.Resource + (*Grant)(nil), // 90: gotocompany.guardian.v1beta1.Grant + (*ProviderActivity)(nil), // 91: gotocompany.guardian.v1beta1.ProviderActivity + (*RevokeAppealRequest_Reason)(nil), // 92: gotocompany.guardian.v1beta1.RevokeAppealRequest.Reason + (*CreateAppealRequest_Resource)(nil), // 93: gotocompany.guardian.v1beta1.CreateAppealRequest.Resource + (*UpdateApprovalRequest_Action)(nil), // 94: gotocompany.guardian.v1beta1.UpdateApprovalRequest.Action + nil, // 95: gotocompany.guardian.v1beta1.ProviderConfig.LabelsEntry + (*ProviderConfig_AppealConfig)(nil), // 96: gotocompany.guardian.v1beta1.ProviderConfig.AppealConfig + (*ProviderConfig_ResourceConfig)(nil), // 97: gotocompany.guardian.v1beta1.ProviderConfig.ResourceConfig + (*ProviderConfig_ProviderParameter)(nil), // 98: gotocompany.guardian.v1beta1.ProviderConfig.ProviderParameter + (*Condition_MatchCondition)(nil), // 99: gotocompany.guardian.v1beta1.Condition.MatchCondition + (*PolicyAppealConfig_DurationOptions)(nil), // 100: gotocompany.guardian.v1beta1.PolicyAppealConfig.DurationOptions + (*PolicyAppealConfig_Question)(nil), // 101: gotocompany.guardian.v1beta1.PolicyAppealConfig.Question + (*PolicyAppealConfig_MetadataSource)(nil), // 102: gotocompany.guardian.v1beta1.PolicyAppealConfig.MetadataSource + nil, // 103: gotocompany.guardian.v1beta1.PolicyAppealConfig.MetadataSourcesEntry + (*Policy_ApprovalStep)(nil), // 104: gotocompany.guardian.v1beta1.Policy.ApprovalStep + nil, // 105: gotocompany.guardian.v1beta1.Policy.LabelsEntry + (*Policy_Requirement)(nil), // 106: gotocompany.guardian.v1beta1.Policy.Requirement + (*Policy_IAM)(nil), // 107: gotocompany.guardian.v1beta1.Policy.IAM (*Policy_Requirement_RequirementTrigger)(nil), // 108: gotocompany.guardian.v1beta1.Policy.Requirement.RequirementTrigger (*Policy_Requirement_AdditionalAppeal)(nil), // 109: gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal (*Policy_Requirement_AdditionalAppeal_ResourceIdentifier)(nil), // 110: gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal.ResourceIdentifier @@ -9007,14 +9006,14 @@ var file_gotocompany_guardian_v1beta1_guardian_proto_depIdxs = []int32{ 99, // 57: gotocompany.guardian.v1beta1.Condition.match:type_name -> gotocompany.guardian.v1beta1.Condition.MatchCondition 100, // 58: gotocompany.guardian.v1beta1.PolicyAppealConfig.duration_options:type_name -> gotocompany.guardian.v1beta1.PolicyAppealConfig.DurationOptions 101, // 59: gotocompany.guardian.v1beta1.PolicyAppealConfig.questions:type_name -> gotocompany.guardian.v1beta1.PolicyAppealConfig.Question - 102, // 60: gotocompany.guardian.v1beta1.Policy.steps:type_name -> gotocompany.guardian.v1beta1.Policy.ApprovalStep - 103, // 61: gotocompany.guardian.v1beta1.Policy.labels:type_name -> gotocompany.guardian.v1beta1.Policy.LabelsEntry - 114, // 62: gotocompany.guardian.v1beta1.Policy.created_at:type_name -> google.protobuf.Timestamp - 114, // 63: gotocompany.guardian.v1beta1.Policy.updated_at:type_name -> google.protobuf.Timestamp - 104, // 64: gotocompany.guardian.v1beta1.Policy.requirements:type_name -> gotocompany.guardian.v1beta1.Policy.Requirement - 105, // 65: gotocompany.guardian.v1beta1.Policy.iam:type_name -> gotocompany.guardian.v1beta1.Policy.IAM - 84, // 66: gotocompany.guardian.v1beta1.Policy.appeal:type_name -> gotocompany.guardian.v1beta1.PolicyAppealConfig - 107, // 67: gotocompany.guardian.v1beta1.Policy.appeal_metadata_sources:type_name -> gotocompany.guardian.v1beta1.Policy.AppealMetadataSourcesEntry + 103, // 60: gotocompany.guardian.v1beta1.PolicyAppealConfig.metadata_sources:type_name -> gotocompany.guardian.v1beta1.PolicyAppealConfig.MetadataSourcesEntry + 104, // 61: gotocompany.guardian.v1beta1.Policy.steps:type_name -> gotocompany.guardian.v1beta1.Policy.ApprovalStep + 105, // 62: gotocompany.guardian.v1beta1.Policy.labels:type_name -> gotocompany.guardian.v1beta1.Policy.LabelsEntry + 114, // 63: gotocompany.guardian.v1beta1.Policy.created_at:type_name -> google.protobuf.Timestamp + 114, // 64: gotocompany.guardian.v1beta1.Policy.updated_at:type_name -> google.protobuf.Timestamp + 106, // 65: gotocompany.guardian.v1beta1.Policy.requirements:type_name -> gotocompany.guardian.v1beta1.Policy.Requirement + 107, // 66: gotocompany.guardian.v1beta1.Policy.iam:type_name -> gotocompany.guardian.v1beta1.Policy.IAM + 84, // 67: gotocompany.guardian.v1beta1.Policy.appeal:type_name -> gotocompany.guardian.v1beta1.PolicyAppealConfig 114, // 68: gotocompany.guardian.v1beta1.AppealOptions.expiration_date:type_name -> google.protobuf.Timestamp 86, // 69: gotocompany.guardian.v1beta1.Appeal.options:type_name -> gotocompany.guardian.v1beta1.AppealOptions 112, // 70: gotocompany.guardian.v1beta1.Appeal.labels:type_name -> gotocompany.guardian.v1beta1.Appeal.LabelsEntry @@ -9049,13 +9048,13 @@ var file_gotocompany_guardian_v1beta1_guardian_proto_depIdxs = []int32{ 79, // 99: gotocompany.guardian.v1beta1.ProviderConfig.ResourceConfig.policy:type_name -> gotocompany.guardian.v1beta1.PolicyConfig 78, // 100: gotocompany.guardian.v1beta1.ProviderConfig.ResourceConfig.roles:type_name -> gotocompany.guardian.v1beta1.Role 115, // 101: gotocompany.guardian.v1beta1.Condition.MatchCondition.eq:type_name -> google.protobuf.Value - 108, // 102: gotocompany.guardian.v1beta1.Policy.Requirement.on:type_name -> gotocompany.guardian.v1beta1.Policy.Requirement.RequirementTrigger - 109, // 103: gotocompany.guardian.v1beta1.Policy.Requirement.appeals:type_name -> gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal - 115, // 104: gotocompany.guardian.v1beta1.Policy.IAM.config:type_name -> google.protobuf.Value - 111, // 105: gotocompany.guardian.v1beta1.Policy.IAM.schema:type_name -> gotocompany.guardian.v1beta1.Policy.IAM.SchemaEntry - 115, // 106: gotocompany.guardian.v1beta1.Policy.AppealMetadataSource.config:type_name -> google.protobuf.Value - 115, // 107: gotocompany.guardian.v1beta1.Policy.AppealMetadataSource.value:type_name -> google.protobuf.Value - 106, // 108: gotocompany.guardian.v1beta1.Policy.AppealMetadataSourcesEntry.value:type_name -> gotocompany.guardian.v1beta1.Policy.AppealMetadataSource + 115, // 102: gotocompany.guardian.v1beta1.PolicyAppealConfig.MetadataSource.config:type_name -> google.protobuf.Value + 115, // 103: gotocompany.guardian.v1beta1.PolicyAppealConfig.MetadataSource.value:type_name -> google.protobuf.Value + 102, // 104: gotocompany.guardian.v1beta1.PolicyAppealConfig.MetadataSourcesEntry.value:type_name -> gotocompany.guardian.v1beta1.PolicyAppealConfig.MetadataSource + 108, // 105: gotocompany.guardian.v1beta1.Policy.Requirement.on:type_name -> gotocompany.guardian.v1beta1.Policy.Requirement.RequirementTrigger + 109, // 106: gotocompany.guardian.v1beta1.Policy.Requirement.appeals:type_name -> gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal + 115, // 107: gotocompany.guardian.v1beta1.Policy.IAM.config:type_name -> google.protobuf.Value + 111, // 108: gotocompany.guardian.v1beta1.Policy.IAM.schema:type_name -> gotocompany.guardian.v1beta1.Policy.IAM.SchemaEntry 83, // 109: gotocompany.guardian.v1beta1.Policy.Requirement.RequirementTrigger.conditions:type_name -> gotocompany.guardian.v1beta1.Condition 110, // 110: gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal.resource:type_name -> gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal.ResourceIdentifier 86, // 111: gotocompany.guardian.v1beta1.Policy.Requirement.AdditionalAppeal.options:type_name -> gotocompany.guardian.v1beta1.AppealOptions @@ -10360,7 +10359,7 @@ func file_gotocompany_guardian_v1beta1_guardian_proto_init() { } } file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[102].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Policy_ApprovalStep); i { + switch v := v.(*PolicyAppealConfig_MetadataSource); i { case 0: return &v.state case 1: @@ -10372,7 +10371,7 @@ func file_gotocompany_guardian_v1beta1_guardian_proto_init() { } } file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[104].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Policy_Requirement); i { + switch v := v.(*Policy_ApprovalStep); i { case 0: return &v.state case 1: @@ -10383,8 +10382,8 @@ func file_gotocompany_guardian_v1beta1_guardian_proto_init() { return nil } } - file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[105].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Policy_IAM); i { + file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[106].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Policy_Requirement); i { case 0: return &v.state case 1: @@ -10395,8 +10394,8 @@ func file_gotocompany_guardian_v1beta1_guardian_proto_init() { return nil } } - file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[106].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Policy_AppealMetadataSource); i { + file_gotocompany_guardian_v1beta1_guardian_proto_msgTypes[107].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Policy_IAM); i { case 0: return &v.state case 1: diff --git a/core/appeal/service.go b/core/appeal/service.go index e9c422995..6b0097902 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -1139,14 +1139,14 @@ func getPolicy(a *domain.Appeal, p *domain.Provider, policiesMap map[string]map[ } func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, p *domain.Policy) error { - if p.AppealMetadataSources == nil { + if !p.HasAppealMetadataSources() { return nil } eg, egctx := errgroup.WithContext(ctx) var mu sync.Mutex appealMetadata := map[string]interface{}{} - for key, metadata := range p.AppealMetadataSources { + for key, metadata := range p.AppealConfig.MetadataSources { key, metadata := key, metadata eg.Go(func() error { switch metadata.Type { diff --git a/core/policy/service.go b/core/policy/service.go index 4b188975d..d0bb149e7 100644 --- a/core/policy/service.go +++ b/core/policy/service.go @@ -155,7 +155,7 @@ func (s *Service) Find(ctx context.Context) ([]*domain.Policy, error) { } } - if p.AppealMetadataSources != nil { + if p.HasAppealMetadataSources() { err := s.decryptAppealMetadata(p) if err != nil { return nil, err @@ -254,7 +254,10 @@ func (s *Service) Update(ctx context.Context, p *domain.Policy) error { } func (s *Service) encryptAppealMetadata(p *domain.Policy) error { - for _, sourceCfg := range p.AppealMetadataSources { + if p.AppealConfig == nil { + return nil + } + for _, sourceCfg := range p.AppealConfig.MetadataSources { if err := sourceCfg.EncryptConfig(s.crypto); err != nil { return err } @@ -263,7 +266,10 @@ func (s *Service) encryptAppealMetadata(p *domain.Policy) error { } func (s *Service) decryptAppealMetadata(p *domain.Policy) error { - for _, sourceCfg := range p.AppealMetadataSources { + if p.AppealConfig == nil { + return nil + } + for _, sourceCfg := range p.AppealConfig.MetadataSources { if err := sourceCfg.DecryptConfig(s.crypto); err != nil { return err } @@ -327,7 +333,7 @@ func (s *Service) validatePolicy(ctx context.Context, p *domain.Policy, excluded } if p.HasAppealMetadataSources() { - for key, metadataSource := range p.AppealMetadataSources { + for key, metadataSource := range p.AppealConfig.MetadataSources { if err := s.validateAppealMetadataSource(ctx, metadataSource); err != nil { return fmt.Errorf("invalid appeal metadata source: %s : %w", key, err) } diff --git a/docs/docs/reference/policy.md b/docs/docs/reference/policy.md index 862052512..61c8c3204 100644 --- a/docs/docs/reference/policy.md +++ b/docs/docs/reference/policy.md @@ -17,7 +17,7 @@ steps: strategy: manual approvers: - $appeal.resource.details.owner -appeal_config: +appeal: duration_options: - name: 1 Day value: 24h @@ -68,7 +68,7 @@ requirements: | `id` | `string` | Policy unique identifier | YES | | `version` | `uint` | Auto increment value. Keeping the | NO | | `steps` | [`[]object(Step)`](#step) | Sequence of approval steps | YES | -| `appeal_config` | [`object(PolicyAppealConfig)`](#policyappealconfig) | appeal configuration options | NO | +| `appeal` | [`object(PolicyAppealConfig)`](#policyappealconfig) | appeal configuration options | NO | | `iam` | [`object(IAM)`](#iam) | Identity manager configuration for client and identity/creator schema | NO | | `requirements` | [`[]object(Requirement)`](#requirement) | Additional appeals | YES | diff --git a/domain/policy.go b/domain/policy.go index 5351af886..89049408b 100644 --- a/domain/policy.go +++ b/domain/policy.go @@ -285,17 +285,16 @@ type Requirement struct { // Policy is the approval policy configuration type Policy struct { - ID string `json:"id" yaml:"id" validate:"required"` - Version uint `json:"version" yaml:"version" validate:"required"` - Description string `json:"description" yaml:"description"` - Steps []*Step `json:"steps" yaml:"steps" validate:"required,min=1,dive"` - AppealConfig *PolicyAppealConfig `json:"appeal_config" yaml:"appeal_config" validate:"omitempty,dive"` - Requirements []*Requirement `json:"requirements,omitempty" yaml:"requirements,omitempty" validate:"omitempty,min=1,dive"` - Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` - IAM *IAMConfig `json:"iam,omitempty" yaml:"iam,omitempty" validate:"omitempty,dive"` - CreatedAt time.Time `json:"created_at,omitempty" yaml:"created_at,omitempty"` - UpdatedAt time.Time `json:"updated_at,omitempty" yaml:"updated_at,omitempty"` - AppealMetadataSources map[string]*AppealMetadataSource `json:"appeal_metadata_sources,omitempty" yaml:"appeal_metadata_sources,omitempty"` + ID string `json:"id" yaml:"id" validate:"required"` + Version uint `json:"version" yaml:"version" validate:"required"` + Description string `json:"description" yaml:"description"` + Steps []*Step `json:"steps" yaml:"steps" validate:"required,min=1,dive"` + AppealConfig *PolicyAppealConfig `json:"appeal" yaml:"appeal" validate:"omitempty,dive"` + Requirements []*Requirement `json:"requirements,omitempty" yaml:"requirements,omitempty" validate:"omitempty,min=1,dive"` + Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` + IAM *IAMConfig `json:"iam,omitempty" yaml:"iam,omitempty" validate:"omitempty,dive"` + CreatedAt time.Time `json:"created_at,omitempty" yaml:"created_at,omitempty"` + UpdatedAt time.Time `json:"updated_at,omitempty" yaml:"updated_at,omitempty"` } type PolicyAppealConfig struct { @@ -309,7 +308,8 @@ type PolicyAppealConfig struct { // value of `creator` field in the appeal will be nil. // Note: any expression that tries to access `$appeal.creator.*` is still evaluated as usual, it might need to have // proper nil checking to avoid accessing nil value. - AllowCreatorDetailsFailure bool `json:"allow_creator_details_failure" yaml:"allow_creator_details_failure"` + AllowCreatorDetailsFailure bool `json:"allow_creator_details_failure" yaml:"allow_creator_details_failure"` + MetadataSources map[string]*AppealMetadataSource `json:"metadata_sources,omitempty" yaml:"metadata_sources,omitempty"` } type Question struct { @@ -334,5 +334,5 @@ func (p *Policy) HasIAMConfig() bool { } func (p *Policy) HasAppealMetadataSources() bool { - return p.AppealMetadataSources != nil + return p.AppealConfig != nil && p.AppealConfig.MetadataSources != nil } diff --git a/internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.down.sql b/internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.down.sql deleted file mode 100644 index 4bc530249..000000000 --- a/internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.down.sql +++ /dev/null @@ -1,6 +0,0 @@ -BEGIN; - -ALTER TABLE - "policies" DROP COLUMN IF EXISTS "appeal_metadata_sources"; - -COMMIT; \ No newline at end of file diff --git a/internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.up.sql b/internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.up.sql deleted file mode 100644 index a5ce359c8..000000000 --- a/internal/store/postgres/migrations/000019_add_metadata_sources_in_policy.up.sql +++ /dev/null @@ -1,8 +0,0 @@ -BEGIN; - -ALTER TABLE - "policies" -ADD - COLUMN IF NOT EXISTS "appeal_metadata_sources" JSONB; - -COMMIT; \ No newline at end of file diff --git a/internal/store/postgres/model/policy.go b/internal/store/postgres/model/policy.go index de59c22da..81ccbfdd2 100644 --- a/internal/store/postgres/model/policy.go +++ b/internal/store/postgres/model/policy.go @@ -11,18 +11,17 @@ import ( // Policy is the database model for policy type Policy struct { - ID string `gorm:"primaryKey"` - Version uint `gorm:"primaryKey"` - Description string - Steps datatypes.JSON - AppealConfig datatypes.JSON - Labels datatypes.JSON - Requirements datatypes.JSON - IAM datatypes.JSON - AppealMetadataSources datatypes.JSON - CreatedAt time.Time `gorm:"autoCreateTime"` - UpdatedAt time.Time `gorm:"autoUpdateTime"` - DeletedAt gorm.DeletedAt `gorm:"index"` + ID string `gorm:"primaryKey"` + Version uint `gorm:"primaryKey"` + Description string + Steps datatypes.JSON + AppealConfig datatypes.JSON + Labels datatypes.JSON + Requirements datatypes.JSON + IAM datatypes.JSON + CreatedAt time.Time `gorm:"autoCreateTime"` + UpdatedAt time.Time `gorm:"autoUpdateTime"` + DeletedAt gorm.DeletedAt `gorm:"index"` } // TableName overrides the table name @@ -57,11 +56,6 @@ func (m *Policy) FromDomain(p *domain.Policy) error { return err } - metadataSources, err := json.Marshal(p.AppealMetadataSources) - if err != nil { - return err - } - m.ID = p.ID m.Version = p.Version m.Description = p.Description @@ -70,7 +64,6 @@ func (m *Policy) FromDomain(p *domain.Policy) error { m.Labels = datatypes.JSON(labels) m.Requirements = datatypes.JSON(requirements) m.IAM = datatypes.JSON(iam) - m.AppealMetadataSources = datatypes.JSON(metadataSources) m.CreatedAt = p.CreatedAt m.UpdatedAt = p.UpdatedAt @@ -110,24 +103,16 @@ func (m *Policy) ToDomain() (*domain.Policy, error) { } } - var metadataSources map[string]*domain.AppealMetadataSource - if m.AppealMetadataSources != nil { - if err := json.Unmarshal(m.AppealMetadataSources, &metadataSources); err != nil { - return nil, err - } - } - return &domain.Policy{ - ID: m.ID, - Version: m.Version, - Description: m.Description, - Steps: steps, - AppealConfig: appealConfig, - Labels: labels, - Requirements: requirements, - IAM: iam, - AppealMetadataSources: metadataSources, - CreatedAt: m.CreatedAt, - UpdatedAt: m.UpdatedAt, + ID: m.ID, + Version: m.Version, + Description: m.Description, + Steps: steps, + AppealConfig: appealConfig, + Labels: labels, + Requirements: requirements, + IAM: iam, + CreatedAt: m.CreatedAt, + UpdatedAt: m.UpdatedAt, }, nil } diff --git a/third_party/OpenAPI/gotocompany/guardian/v1beta1/guardian.swagger.json b/third_party/OpenAPI/gotocompany/guardian/v1beta1/guardian.swagger.json index 5ddd01395..3aa14dfc2 100644 --- a/third_party/OpenAPI/gotocompany/guardian/v1beta1/guardian.swagger.json +++ b/third_party/OpenAPI/gotocompany/guardian/v1beta1/guardian.swagger.json @@ -2055,37 +2055,37 @@ } } }, - "PolicyAppealConfigQuestion": { + "PolicyAppealConfigMetadataSource": { "type": "object", "properties": { - "key": { + "name": { "type": "string" }, - "question": { + "description": { "type": "string" }, - "required": { - "type": "boolean" - }, - "description": { + "type": { "type": "string" - } + }, + "config": {}, + "value": {} } }, - "PolicyAppealMetadataSource": { + "PolicyAppealConfigQuestion": { "type": "object", "properties": { - "name": { + "key": { "type": "string" }, - "description": { + "question": { "type": "string" }, - "type": { - "type": "string" + "required": { + "type": "boolean" }, - "config": {}, - "value": {} + "description": { + "type": "string" + } } }, "PolicyApprovalStep": { @@ -3035,12 +3035,6 @@ }, "appeal": { "$ref": "#/definitions/v1beta1PolicyAppealConfig" - }, - "appealMetadataSources": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/PolicyAppealMetadataSource" - } } }, "title": "Policy is a configurable steps for appeal's approval" @@ -3073,6 +3067,12 @@ }, "allowCreatorDetailsFailure": { "type": "boolean" + }, + "metadataSources": { + "type": "object", + "additionalProperties": { + "$ref": "#/definitions/PolicyAppealConfigMetadataSource" + } } } }, From ebbc2485129ec2906f1f1a6f6e82da9abffe65cc Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Tue, 26 Mar 2024 02:58:05 +0700 Subject: [PATCH 15/39] refactor: revert debugging leftover --- api/handler/v1beta1/policy.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/api/handler/v1beta1/policy.go b/api/handler/v1beta1/policy.go index 9da968477..6a2dd467a 100644 --- a/api/handler/v1beta1/policy.go +++ b/api/handler/v1beta1/policy.go @@ -82,8 +82,7 @@ func (s *GRPCServer) UpdatePolicy(ctx context.Context, req *guardianv1beta1.Upda if req.GetDryRun() { ctx = policy.WithDryRun(ctx) } - pp := req.GetPolicy() - p := s.adapter.FromPolicyProto(pp) + p := s.adapter.FromPolicyProto(req.GetPolicy()) p.ID = req.GetId() if err := s.policyService.Update(ctx, p); err != nil { From 6c51b4ae791a66eba9f2b29692198d7142b595c5 Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Tue, 26 Mar 2024 03:01:21 +0700 Subject: [PATCH 16/39] lint: fix lint errors --- domain/policy_metadata_source.go | 2 +- internal/store/postgres/appeal_repository_test.go | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/domain/policy_metadata_source.go b/domain/policy_metadata_source.go index ce89e9ccc..2d5c20e97 100644 --- a/domain/policy_metadata_source.go +++ b/domain/policy_metadata_source.go @@ -36,7 +36,7 @@ func (c *AppealMetadataSource) DecryptConfig(dec Decryptor) error { if !ok { return fmt.Errorf("invalid config type: %T, expected string", c.Config) } - decryptedConfig, err := dec.Decrypt(string(configStr)) + decryptedConfig, err := dec.Decrypt(configStr) if err != nil { return err } diff --git a/internal/store/postgres/appeal_repository_test.go b/internal/store/postgres/appeal_repository_test.go index 710e2fc49..f49b1761c 100644 --- a/internal/store/postgres/appeal_repository_test.go +++ b/internal/store/postgres/appeal_repository_test.go @@ -191,7 +191,6 @@ func (s *AppealRepositoryTestSuite) TestGetByID() { } func (s *AppealRepositoryTestSuite) TestGetAppealsTotalCount() { - dummyAppeals := []*domain.Appeal{ { ResourceID: s.dummyResource.ID, From 60d50256cd7044eda0357c17b79790e9d559732b Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Wed, 27 Mar 2024 00:48:00 +0700 Subject: [PATCH 17/39] feat: use reflection for evaluating metadata value --- domain/policy_metadata_source.go | 29 ++++---- domain/policy_metadata_source_test.go | 100 +++++++++++++++++++++++++- 2 files changed, 114 insertions(+), 15 deletions(-) diff --git a/domain/policy_metadata_source.go b/domain/policy_metadata_source.go index 2d5c20e97..28e94044d 100644 --- a/domain/policy_metadata_source.go +++ b/domain/policy_metadata_source.go @@ -3,6 +3,7 @@ package domain import ( "encoding/json" "fmt" + "reflect" "strings" "github.com/goto/guardian/pkg/evaluator" @@ -55,30 +56,32 @@ func (c *AppealMetadataSource) EvaluateValue(params map[string]interface{}) (int } func (c *AppealMetadataSource) evaluateValue(value interface{}, params map[string]interface{}) (interface{}, error) { - switch value := value.(type) { - case string: - if strings.HasPrefix(value, "$appeal") || strings.HasPrefix(value, "$response") { - result, err := evaluator.Expression(value).EvaluateWithVars(params) + v := reflect.ValueOf(value) + switch v.Kind() { + case reflect.String: + if strings.Contains(v.String(), "$appeal") || strings.Contains(v.String(), "$response") { + result, err := evaluator.Expression(v.String()).EvaluateWithVars(params) if err != nil { return nil, err } return result, nil - } else { - return value, nil } - case map[string]interface{}: // TODO: handle map[string]int and other types + return value, nil + case reflect.Map: mapResult := map[string]interface{}{} - for key, val := range value { + for _, key := range v.MapKeys() { + val := v.MapIndex(key).Interface() processedVal, err := c.evaluateValue(val, params) if err != nil { return nil, err } - mapResult[key] = processedVal + mapResult[key.String()] = processedVal } return mapResult, nil - case []interface{}: // TODO: handle []int and other types - arrayResult := make([]interface{}, len(value)) - for i, val := range value { + case reflect.Slice: + arrayResult := make([]interface{}, v.Len()) + for i := 0; i < v.Len(); i++ { + val := v.Index(i).Interface() processedVal, err := c.evaluateValue(val, params) if err != nil { return nil, err @@ -87,6 +90,6 @@ func (c *AppealMetadataSource) evaluateValue(value interface{}, params map[strin } return arrayResult, nil default: - return value, nil + return v.Interface(), nil } } diff --git a/domain/policy_metadata_source_test.go b/domain/policy_metadata_source_test.go index f51dfecef..16cbc9fc2 100644 --- a/domain/policy_metadata_source_test.go +++ b/domain/policy_metadata_source_test.go @@ -1,6 +1,11 @@ package domain_test -import "testing" +import ( + "testing" + + "github.com/goto/guardian/domain" + "github.com/stretchr/testify/assert" +) func TestAppealMetadataSource_EncryptConfig(t *testing.T) { t.Skip("TODO: implement") @@ -11,5 +16,96 @@ func TestAppealMetadataSource_DecryptConfig(t *testing.T) { } func TestAppealMetadataSource_EvaluateValue(t *testing.T) { - t.Skip("TODO: implement") + testCases := []struct { + name string + value interface{} + params map[string]interface{} + expectedValue interface{} + }{ + { + name: "string value", + value: "test", + expectedValue: "test", + }, + { + name: "int value", + value: 10, + expectedValue: 10, + }, + { + name: "string value with params", + value: "$appeal.foo", + params: map[string]interface{}{ + "appeal": map[string]interface{}{ + "foo": "bar", + }, + }, + expectedValue: "bar", + }, + { + name: "string value with nested params", + value: "$appeal.foo.bar", + params: map[string]interface{}{ + "appeal": map[string]interface{}{ + "foo": map[string]interface{}{ + "bar": "baz", + }, + }, + }, + expectedValue: "baz", + }, + { + name: "complex", + value: map[string]interface{}{ + "policy": `$appeal.policy_id + "@" + string($appeal.policy_version)`, + "user_details": `$response.status_code == 200 ? $response.body.user[0] : nil`, + "string_list": []string{ + "$appeal.details.list[0]", + "$appeal.details.list[1]", + "$appeal.details.list[2]", + }, + }, + params: map[string]interface{}{ + "appeal": map[string]interface{}{ + "id": "123", + "policy_id": "test-policy", + "policy_version": 1, + "details": map[string]interface{}{ + "list": []string{"a", "b", "c"}, + }, + }, + "response": map[string]interface{}{ + "status_code": 200, + "body": map[string]interface{}{ + "user": []map[string]interface{}{ + { + "id": "123", + "email": "user@example.com", + }, + }, + }, + }, + }, + expectedValue: map[string]interface{}{ + "policy": "test-policy@1", + "user_details": map[string]interface{}{ + "id": "123", + "email": "user@example.com", + }, + "string_list": []interface{}{"a", "b", "c"}, + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + ms := &domain.AppealMetadataSource{ + Value: tc.value, + } + + result, err := ms.EvaluateValue(tc.params) + assert.NoError(t, err) + assert.Equal(t, tc.expectedValue, result) + }) + } } From f42ee6fee647c7bf2a7431146da05eb9f6da2da9 Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Wed, 27 Mar 2024 16:04:37 +0700 Subject: [PATCH 18/39] feat: remove sensitive values before sending response --- api/handler/v1beta1/adapter.go | 25 +++++++++++++++---------- api/handler/v1beta1/policy.go | 9 +++------ api/handler/v1beta1/policy_test.go | 15 +++++++++++++++ domain/policy.go | 11 +++++++++++ 4 files changed, 44 insertions(+), 16 deletions(-) diff --git a/api/handler/v1beta1/adapter.go b/api/handler/v1beta1/adapter.go index e6e55cdad..14d9c2bed 100644 --- a/api/handler/v1beta1/adapter.go +++ b/api/handler/v1beta1/adapter.go @@ -506,14 +506,6 @@ func (a *adapter) ToPolicyAppealConfigProto(p *domain.Policy) (*guardianv1beta1. } for key, metadataSource := range p.AppealConfig.MetadataSources { - cfg, err := structpb.NewValue(metadataSource.Config) - if err != nil { - return nil, err - } - value, err := structpb.NewValue(metadataSource.Value) - if err != nil { - return nil, err - } if policyAppealConfigProto.MetadataSources == nil { policyAppealConfigProto.MetadataSources = make(map[string]*guardianv1beta1.PolicyAppealConfig_MetadataSource) } @@ -521,8 +513,21 @@ func (a *adapter) ToPolicyAppealConfigProto(p *domain.Policy) (*guardianv1beta1. Name: metadataSource.Name, Description: metadataSource.Description, Type: metadataSource.Type, - Config: cfg, - Value: value, + } + + if metadataSource.Config != nil { + cfg, err := structpb.NewValue(metadataSource.Config) + if err != nil { + return nil, err + } + policyAppealConfigProto.MetadataSources[key].Config = cfg + } + if metadataSource.Value != nil { + value, err := structpb.NewValue(metadataSource.Value) + if err != nil { + return nil, err + } + policyAppealConfigProto.MetadataSources[key].Value = value } } diff --git a/api/handler/v1beta1/policy.go b/api/handler/v1beta1/policy.go index 6a2dd467a..6f47b8252 100644 --- a/api/handler/v1beta1/policy.go +++ b/api/handler/v1beta1/policy.go @@ -18,9 +18,7 @@ func (s *GRPCServer) ListPolicies(ctx context.Context, req *guardianv1beta1.List policyProtos := []*guardianv1beta1.Policy{} for _, p := range policies { - if p.IAM != nil { - p.IAM.Config = nil - } + p.RemoveSensitiveValues() policyProto, err := s.adapter.ToPolicyProto(p) if err != nil { return nil, s.internalError(ctx, "failed to parse policy %v: %v", p.ID, err) @@ -44,9 +42,7 @@ func (s *GRPCServer) GetPolicy(ctx context.Context, req *guardianv1beta1.GetPoli } } - if p.IAM != nil { - p.IAM.Config = nil - } + p.RemoveSensitiveValues() policyProto, err := s.adapter.ToPolicyProto(p) if err != nil { return nil, s.internalError(ctx, "failed to parse policy: %v", err) @@ -116,6 +112,7 @@ func (s *GRPCServer) GetPolicyPreferences(ctx context.Context, req *guardianv1be } } + p.RemoveSensitiveValues() appealConfigProto, err := s.adapter.ToPolicyAppealConfigProto(p) if err != nil { return nil, s.internalError(ctx, "failed to parse policy preferences: %v", err) diff --git a/api/handler/v1beta1/policy_test.go b/api/handler/v1beta1/policy_test.go index bbecf19a6..80392c111 100644 --- a/api/handler/v1beta1/policy_test.go +++ b/api/handler/v1beta1/policy_test.go @@ -28,6 +28,13 @@ func (s *GrpcHandlersSuite) TestListPolicies() { Config: expectedIAMConfig, Provider: "provider", }, + Appeal: &guardianv1beta1.PolicyAppealConfig{ + MetadataSources: map[string]*guardianv1beta1.PolicyAppealConfig_MetadataSource{ + "test-source": { + Name: "test-source", + }, + }, + }, }, }, } @@ -38,6 +45,14 @@ func (s *GrpcHandlersSuite) TestListPolicies() { Config: map[string]interface{}{"foo": "bar"}, Provider: "provider", }, + AppealConfig: &domain.PolicyAppealConfig{ + MetadataSources: map[string]*domain.AppealMetadataSource{ + "test-source": { + Name: "test-source", + Config: map[string]interface{}{"foo": "bar"}, + }, + }, + }, }, } s.policyService.EXPECT().Find(mock.MatchedBy(func(ctx context.Context) bool { return true })).Return(dummyPolicies, nil).Once() diff --git a/domain/policy.go b/domain/policy.go index 89049408b..b857e906f 100644 --- a/domain/policy.go +++ b/domain/policy.go @@ -297,6 +297,17 @@ type Policy struct { UpdatedAt time.Time `json:"updated_at,omitempty" yaml:"updated_at,omitempty"` } +func (p *Policy) RemoveSensitiveValues() { + if p.IAM != nil { + p.IAM.Config = nil + } + if p.AppealConfig != nil { + for key := range p.AppealConfig.MetadataSources { + p.AppealConfig.MetadataSources[key].Config = nil + } + } +} + type PolicyAppealConfig struct { DurationOptions []AppealDurationOption `json:"duration_options" yaml:"duration_options" validate:"omitempty,min=1,dive"` AllowOnBehalf bool `json:"allow_on_behalf" yaml:"allow_on_behalf"` From 3a02025e4e809d2c32efffcaa41a98e7b9fd779c Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Thu, 28 Mar 2024 14:47:06 +0700 Subject: [PATCH 19/39] fix: nil check for config.Auth in http pkg --- pkg/http/http.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/http/http.go b/pkg/http/http.go index f47055d43..09a6488af 100644 --- a/pkg/http/http.go +++ b/pkg/http/http.go @@ -62,7 +62,7 @@ func NewHTTPClient(config *HTTPClientConfig) (*HTTPClient, error) { httpClient = http.DefaultClient } - if config.Auth.Type == "google_idtoken" { + if config.Auth != nil && config.Auth.Type == "google_idtoken" { var creds []byte switch { case config.Auth.CredentialsJSONBase64 != "": From bb2d63c7f641d2ba5902086403bc7c0b41fc0feb Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Sat, 30 Mar 2024 01:27:57 +0700 Subject: [PATCH 20/39] test: increase coverage --- api/handler/v1beta1/policy_test.go | 120 +++++++++++++++++++++++++++++ domain/appeal.go | 2 +- 2 files changed, 121 insertions(+), 1 deletion(-) diff --git a/api/handler/v1beta1/policy_test.go b/api/handler/v1beta1/policy_test.go index 80392c111..aae9cd95c 100644 --- a/api/handler/v1beta1/policy_test.go +++ b/api/handler/v1beta1/policy_test.go @@ -418,11 +418,24 @@ func (s *GrpcHandlersSuite) TestCreatePolicy() { Description: "Please provide the name of the team you are in", }, }, + MetadataSources: map[string]*domain.AppealMetadataSource{ + "test-source": { + Name: "test-source", + Description: "test-description", + Type: "test-type", + Config: map[string]interface{}{"foo": "bar"}, + Value: "test-value", + }, + }, }, } expectedVersion := uint(1) expectedIAMConfig, err := structpb.NewValue(expectedPolicy.IAM.Config) s.Require().NoError(err) + expectedMetadataSourceConfig, err := structpb.NewValue(expectedPolicy.AppealConfig.MetadataSources["test-source"].Config) + s.Require().NoError(err) + expectedMetadataSourceValue, err := structpb.NewValue(expectedPolicy.AppealConfig.MetadataSources["test-source"].Value) + s.Require().NoError(err) expectedResponse := &guardianv1beta1.CreatePolicyResponse{ Policy: &guardianv1beta1.Policy{ Id: expectedPolicy.ID, @@ -479,6 +492,15 @@ func (s *GrpcHandlersSuite) TestCreatePolicy() { Description: "Please provide the name of the team you are in", }, }, + MetadataSources: map[string]*guardianv1beta1.PolicyAppealConfig_MetadataSource{ + "test-source": { + Name: "test-source", + Description: "test-description", + Type: "test-type", + Config: expectedMetadataSourceConfig, + Value: expectedMetadataSourceValue, + }, + }, }, CreatedAt: timestamppb.New(timeNow), UpdatedAt: timestamppb.New(timeNow), @@ -546,6 +568,15 @@ func (s *GrpcHandlersSuite) TestCreatePolicy() { Description: "Please provide the name of the team you are in", }, }, + MetadataSources: map[string]*guardianv1beta1.PolicyAppealConfig_MetadataSource{ + "test-source": { + Name: "test-source", + Description: "test-description", + Type: "test-type", + Config: expectedMetadataSourceConfig, + Value: expectedMetadataSourceValue, + }, + }, }, }, } @@ -813,3 +844,92 @@ func (s *GrpcHandlersSuite) TestUpdatePolicy() { s.policyService.AssertExpectations(s.T()) }) } + +func (s *GrpcHandlersSuite) TestGetPolicyPreferences() { + s.Run("should return policy preferences on success", func() { + s.setup() + + dummyPolicy := &domain.Policy{ + ID: "test-policy", + Version: 1, + AppealConfig: &domain.PolicyAppealConfig{ + AllowActiveAccessExtensionIn: "24h", + AllowPermanentAccess: true, + MetadataSources: map[string]*domain.AppealMetadataSource{ + "test-source": { + Name: "test-source", + Config: map[string]interface{}{"foo": "bar"}, + }, + }, + }, + } + + s.policyService.EXPECT(). + GetOne(mock.MatchedBy(func(ctx context.Context) bool { return true }), dummyPolicy.ID, dummyPolicy.Version). + Return(dummyPolicy, nil).Once() + expectedResponse := &guardianv1beta1.GetPolicyPreferencesResponse{ + Appeal: &guardianv1beta1.PolicyAppealConfig{ + AllowActiveAccessExtensionIn: "24h", + AllowPermanentAccess: true, + MetadataSources: map[string]*guardianv1beta1.PolicyAppealConfig_MetadataSource{ + "test-source": { + Name: "test-source", + }, + }, + }, + } + + req := &guardianv1beta1.GetPolicyPreferencesRequest{ + Id: dummyPolicy.ID, + Version: uint32(dummyPolicy.Version), + } + res, err := s.grpcServer.GetPolicyPreferences(context.Background(), req) + + s.NoError(err) + s.Equal(expectedResponse, res) + s.Nil(res.Appeal.MetadataSources["test-source"].Config) // config that might contain sensitive value should be removed + s.policyService.AssertExpectations(s.T()) + }) + + s.Run("should return not found error if policy not found", func() { + s.setup() + + policyID := "test-policy" + policyVersion := uint(1) + expectedError := policy.ErrPolicyNotFound + s.policyService.EXPECT(). + GetOne(mock.MatchedBy(func(ctx context.Context) bool { return true }), policyID, policyVersion). + Return(nil, expectedError).Once() + + req := &guardianv1beta1.GetPolicyPreferencesRequest{ + Id: policyID, + Version: uint32(policyVersion), + } + res, err := s.grpcServer.GetPolicyPreferences(context.Background(), req) + + s.Equal(codes.NotFound, status.Code(err)) + s.Nil(res) + s.policyService.AssertExpectations(s.T()) + }) + + s.Run("should return internal error if policy service returns error", func() { + s.setup() + + policyID := "test-policy" + policyVersion := uint(1) + expectedError := errors.New("random error") + s.policyService.EXPECT(). + GetOne(mock.MatchedBy(func(ctx context.Context) bool { return true }), policyID, policyVersion). + Return(nil, expectedError).Once() + + req := &guardianv1beta1.GetPolicyPreferencesRequest{ + Id: policyID, + Version: uint32(policyVersion), + } + res, err := s.grpcServer.GetPolicyPreferences(context.Background(), req) + + s.Equal(codes.Internal, status.Code(err)) + s.Nil(res) + s.policyService.AssertExpectations(s.T()) + }) +} diff --git a/domain/appeal.go b/domain/appeal.go index ab82d5239..5108fbf8c 100644 --- a/domain/appeal.go +++ b/domain/appeal.go @@ -207,7 +207,7 @@ func (a *Appeal) AdvanceApproval(policy *Policy) error { if approval.Status == ApprovalStatusPending { stepConfig := policy.Steps[approval.Index] - appealMap, err := utils.StructToMap(a) + appealMap, err := a.ToMap() if err != nil { return fmt.Errorf("parsing appeal struct to map: %w", err) } From 37a15ab4ad4a042581ca0b5b6e1d4ade2de8e774 Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Sun, 31 Mar 2024 22:18:34 +0700 Subject: [PATCH 21/39] test: add unit test for appeal metadata --- core/appeal/service.go | 3 + core/appeal/service_test.go | 266 ++++++++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+) diff --git a/core/appeal/service.go b/core/appeal/service.go index 6b0097902..beb2668c0 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -1237,6 +1237,9 @@ func (s *Service) populateAppealMetadata(ctx context.Context, a *domain.Appeal, return err } + if a.Details == nil { + a.Details = map[string]interface{}{} + } a.Details[PolicyMetadataKey] = appealMetadata return nil diff --git a/core/appeal/service_test.go b/core/appeal/service_test.go index c9a00c3d0..9100f7418 100644 --- a/core/appeal/service_test.go +++ b/core/appeal/service_test.go @@ -2,8 +2,11 @@ package appeal_test import ( "context" + "encoding/json" "errors" "fmt" + "net/http" + "net/http/httptest" "testing" "time" @@ -2047,6 +2050,269 @@ func (s *ServiceTestSuite) TestCreateAppeal__WithAdditionalAppeals() { s.NoError(err) } +func (s *ServiceTestSuite) TestCreate__WithAppealMetadata() { + s.setup() + accountID := "test@email.com" + + expectedUserDetails := map[string]interface{}{ + "managers": []interface{}{"user.approver@email.com"}, + "name": "test-name", + "role": "test-role-1", + "roles": []interface{}{"test-role-1", "test-role-2"}, + } + testServer := http.NewServeMux() + testServer.HandleFunc(fmt.Sprintf("/users/%s", accountID), func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusOK) + resp, _ := json.Marshal(expectedUserDetails) + w.Write([]byte(resp)) + }) + ts := httptest.NewServer(testServer) + + resources := []*domain.Resource{ + { + ID: "1", + Type: "resource_type_1", + ProviderType: "provider_type", + ProviderURN: "provider1", + Details: map[string]interface{}{ + "owner": []string{"resource.owner@email.com"}, + }, + }, + } + providers := []*domain.Provider{ + { + ID: "1", + Type: "provider_type", + URN: "provider1", + Config: &domain.ProviderConfig{ + Appeal: &domain.AppealConfig{ + AllowPermanentAccess: true, + AllowActiveAccessExtensionIn: "24h", + }, + Resources: []*domain.ResourceConfig{ + { + Type: "resource_type_1", + Policy: &domain.PolicyConfig{ + ID: "policy_1", + Version: 1, + }, + Roles: []*domain.Role{ + { + ID: "role_id", + Permissions: []interface{}{"test-permission-1"}, + }, + }, + }, + }, + }, + }, + } + expDate := timeNow.Add(23 * time.Hour) + expectedExistingAppeals := []*domain.Appeal{} + expectedActiveGrants := []domain.Grant{ + { + ID: "99", + AccountID: accountID, + ResourceID: "2", + Resource: &domain.Resource{ + ID: "2", + URN: "urn", + }, + Role: "role_id", + Status: domain.GrantStatusActive, + ExpirationDate: &expDate, + }, + } + policies := []*domain.Policy{ + { + ID: "policy_1", + Version: 1, + Steps: []*domain.Step{ + { + Name: "step_1", + Strategy: "manual", + Approvers: []string{ + "$appeal.resource.details.owner", + }, + }, + { + Name: "step_2", + Strategy: "manual", + Approvers: []string{ + "$appeal.details.__policy_metadata.creator.managers", + }, + }, + }, + AppealConfig: &domain.PolicyAppealConfig{ + MetadataSources: map[string]*domain.AppealMetadataSource{ + "creator": { + Type: "http", + Config: map[string]interface{}{ + "url": fmt.Sprintf(`"%s/users/" + $appeal.created_by`, ts.URL), + }, + Value: map[string]interface{}{ + "managers": "$response.body.managers", + }, + }, + }, + }, + }, + } + expectedAppealsInsertionParam := []*domain.Appeal{ + { + ResourceID: resources[0].ID, + Resource: resources[0], + PolicyID: "policy_1", + PolicyVersion: 1, + Status: domain.AppealStatusPending, + AccountID: accountID, + AccountType: domain.DefaultAppealAccountType, + CreatedBy: accountID, + Role: "role_id", + Permissions: []string{"test-permission-1"}, + Approvals: []*domain.Approval{ + { + Name: "step_1", + Index: 0, + Status: domain.ApprovalStatusPending, + PolicyID: "policy_1", + PolicyVersion: 1, + Approvers: []string{"resource.owner@email.com"}, + }, + { + Name: "step_2", + Index: 1, + Status: domain.ApprovalStatusBlocked, + PolicyID: "policy_1", + PolicyVersion: 1, + Approvers: []string{"user.approver@email.com"}, + }, + }, + Description: "The answer is 42", + Details: map[string]interface{}{ + "__policy_metadata": map[string]interface{}{ + "creator": map[string]interface{}{ + "managers": []interface{}{"user.approver@email.com"}, + }, + }, + }, + }, + } + expectedResult := []*domain.Appeal{ + { + ID: "1", + ResourceID: "1", + Resource: resources[0], + PolicyID: "policy_1", + PolicyVersion: 1, + Status: domain.AppealStatusPending, + AccountID: accountID, + AccountType: domain.DefaultAppealAccountType, + CreatedBy: accountID, + Role: "role_id", + Permissions: []string{"test-permission-1"}, + Approvals: []*domain.Approval{ + { + ID: "1", + Name: "step_1", + Index: 0, + Status: domain.ApprovalStatusPending, + PolicyID: "policy_1", + PolicyVersion: 1, + Approvers: []string{"resource.owner@email.com"}, + }, + { + ID: "2", + Name: "step_2", + Index: 1, + Status: domain.ApprovalStatusBlocked, + PolicyID: "policy_1", + PolicyVersion: 1, + Approvers: []string{"user.approver@email.com"}, + }, + }, + Description: "The answer is 42", + Details: map[string]interface{}{ + "__policy_metadata": map[string]interface{}{ + "creator": map[string]interface{}{ + "managers": []interface{}{"user.approver@email.com"}, + }, + }, + }, + }, + } + + expectedResourceFilters := domain.ListResourcesFilter{IDs: []string{resources[0].ID}} + s.mockResourceService.EXPECT(). + Find(mock.Anything, expectedResourceFilters). + Return(resources, nil).Once() + s.mockProviderService.EXPECT(). + Find(mock.Anything).Return(providers, nil).Once() + s.mockPolicyService.EXPECT(). + Find(mock.Anything).Return(policies, nil).Once() + expectedExistingAppealsFilters := &domain.ListAppealsFilter{ + Statuses: []string{domain.AppealStatusPending}, + AccountIDs: []string{"test@email.com"}, + } + s.mockRepository.EXPECT(). + Find(mock.MatchedBy(func(ctx context.Context) bool { return true }), expectedExistingAppealsFilters). + Return(expectedExistingAppeals, nil).Once() + s.mockGrantService.EXPECT(). + List(mock.MatchedBy(func(ctx context.Context) bool { return true }), domain.ListGrantsFilter{ + Statuses: []string{string(domain.GrantStatusActive)}, + AccountIDs: []string{accountID}, + ResourceIDs: []string{"1"}, + Roles: []string{"role_id"}, + OrderBy: []string{"updated_at:desc"}, + }). + Return(expectedActiveGrants, nil).Once() + s.mockProviderService.EXPECT(). + ValidateAppeal(mock.Anything, mock.Anything, mock.Anything, mock.Anything). + Return(nil) + s.mockProviderService.EXPECT(). + GetPermissions(mock.Anything, mock.Anything, mock.AnythingOfType("string"), "role_id"). + Return([]interface{}{"test-permission-1"}, nil) + + s.mockRepository.EXPECT(). + BulkUpsert(mock.MatchedBy(func(ctx context.Context) bool { return true }), expectedAppealsInsertionParam). + Return(nil). + Run(func(_a0 context.Context, appeals []*domain.Appeal) { + for i, a := range appeals { + a.ID = expectedResult[i].ID + for j, approval := range a.Approvals { + approval.ID = expectedResult[i].Approvals[j].ID + } + } + }). + Once() + s.mockNotifier.EXPECT(). + Notify(mock.MatchedBy(func(ctx context.Context) bool { return true }), mock.Anything). + Return(nil).Once() + s.mockAuditLogger.EXPECT(). + Log(mock.Anything, appeal.AuditKeyBulkInsert, mock.Anything). + Return(nil).Once() + + appeals := []*domain.Appeal{ + { + CreatedBy: accountID, + AccountID: accountID, + ResourceID: "1", + Resource: &domain.Resource{ + ID: "1", + URN: "urn", + }, + Role: "role_id", + Description: "The answer is 42", + }, + } + actualError := s.service.Create(context.Background(), appeals) + + s.Nil(actualError) + s.Equal(expectedResult, appeals) + s.mockProviderService.AssertExpectations(s.T()) + s.mockRepository.AssertExpectations(s.T()) +} + func (s *ServiceTestSuite) TestUpdateApproval() { appealID := uuid.New().String() appeal.TimeNow = func() time.Time { From a2900cca7252a556082172d4388d019f656c370c Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Sun, 31 Mar 2024 22:22:04 +0700 Subject: [PATCH 22/39] lint: fix lint errors --- core/appeal/service_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/appeal/service_test.go b/core/appeal/service_test.go index 9100f7418..8eb6ed29a 100644 --- a/core/appeal/service_test.go +++ b/core/appeal/service_test.go @@ -2064,7 +2064,7 @@ func (s *ServiceTestSuite) TestCreate__WithAppealMetadata() { testServer.HandleFunc(fmt.Sprintf("/users/%s", accountID), func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) resp, _ := json.Marshal(expectedUserDetails) - w.Write([]byte(resp)) + w.Write(resp) }) ts := httptest.NewServer(testServer) From 0246be198d6907e79bf3ec9b9cbe3ddb49a93f7c Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Mon, 1 Apr 2024 00:06:43 +0700 Subject: [PATCH 23/39] test: add unit test for policy service --- core/policy/service.go | 41 +++--- core/policy/service_test.go | 249 ++++++++++++++++++++++++++---------- 2 files changed, 199 insertions(+), 91 deletions(-) diff --git a/core/policy/service.go b/core/policy/service.go index d0bb149e7..c8acc5268 100644 --- a/core/policy/service.go +++ b/core/policy/service.go @@ -109,8 +109,7 @@ func (s *Service) Create(ctx context.Context, p *domain.Policy) error { } if p.HasAppealMetadataSources() { - err := s.encryptAppealMetadata(p) - if err != nil { + if err := s.encryptAppealMetadata(p); err != nil { return err } } @@ -132,8 +131,7 @@ func (s *Service) Create(ctx context.Context, p *domain.Policy) error { } if p.HasAppealMetadataSources() { - err := s.decryptAppealMetadata(p) - if err != nil { + if err := s.decryptAppealMetadata(p); err != nil { return err } } @@ -156,8 +154,7 @@ func (s *Service) Find(ctx context.Context) ([]*domain.Policy, error) { } if p.HasAppealMetadataSources() { - err := s.decryptAppealMetadata(p) - if err != nil { + if err := s.decryptAppealMetadata(p); err != nil { return nil, err } } @@ -178,9 +175,10 @@ func (s *Service) GetOne(ctx context.Context, id string, version uint) (*domain. } } - err = s.decryptAppealMetadata(p) - if err != nil { - return nil, err + if p.HasAppealMetadataSources() { + if err := s.decryptAppealMetadata(p); err != nil { + return nil, err + } } return p, nil @@ -219,8 +217,7 @@ func (s *Service) Update(ctx context.Context, p *domain.Policy) error { } if p.HasAppealMetadataSources() { - err := s.encryptAppealMetadata(p) - if err != nil { + if err := s.encryptAppealMetadata(p); err != nil { return err } } @@ -244,8 +241,7 @@ func (s *Service) Update(ctx context.Context, p *domain.Policy) error { } if p.HasAppealMetadataSources() { - err := s.decryptAppealMetadata(p) - if err != nil { + if err := s.decryptAppealMetadata(p); err != nil { return err } } @@ -258,6 +254,9 @@ func (s *Service) encryptAppealMetadata(p *domain.Policy) error { return nil } for _, sourceCfg := range p.AppealConfig.MetadataSources { + if sourceCfg.Config == nil { + continue + } if err := sourceCfg.EncryptConfig(s.crypto); err != nil { return err } @@ -270,6 +269,9 @@ func (s *Service) decryptAppealMetadata(p *domain.Policy) error { return nil } for _, sourceCfg := range p.AppealConfig.MetadataSources { + if sourceCfg.Config == nil { + continue + } if err := sourceCfg.DecryptConfig(s.crypto); err != nil { return err } @@ -347,7 +349,6 @@ func (s *Service) validateAppealMetadataSource(ctx context.Context, metadataSour if metadataSource.Name == "" { return fmt.Errorf("name should not be empty") } - if metadataSource.Value == nil { return fmt.Errorf("value should not be empty") } @@ -355,17 +356,15 @@ func (s *Service) validateAppealMetadataSource(ctx context.Context, metadataSour switch metadataSource.Type { case "http": if metadataSource.Config == nil { - return fmt.Errorf("config is required for type 'http'") + return fmt.Errorf(`"config" is required for type http`) } + // TODO: validate http config + return nil case "static": - if metadataSource.Config != nil { - return fmt.Errorf("config is not allowed for type 'static'") - } + return nil default: - return fmt.Errorf("type of metadata source is invalid") + return fmt.Errorf("invalid metadata source type: %s", metadataSource.Type) } - - return nil } func (s *Service) validateRequirements(ctx context.Context, requirements []*domain.Requirement) error { diff --git a/core/policy/service_test.go b/core/policy/service_test.go index 53d1c04bf..0c27d5d82 100644 --- a/core/policy/service_test.go +++ b/core/policy/service_test.go @@ -2,6 +2,7 @@ package policy_test import ( "context" + "encoding/json" "errors" "testing" @@ -43,7 +44,7 @@ func (s *ServiceTestSuite) SetupTest() { ResourceService: s.mockResourceService, ProviderService: s.mockProviderService, IAMManager: iamManager, - Crypto: &mocks.Crypto{}, + Crypto: s.mockCrypto, AuditLogger: s.mockAuditLogger, Validator: validator.New(), }) @@ -301,93 +302,118 @@ func (s *ServiceTestSuite) TestCreate() { }) }) - validPolicy := &domain.Policy{ - ID: "id", - Version: 1, - Steps: []*domain.Step{ - { - Name: "test", - Strategy: "manual", - Approvers: []string{ - "user@email.com", + getValidPolicy := func() *domain.Policy { + return &domain.Policy{ + ID: "id", + Version: 1, + Steps: []*domain.Step{ + { + Name: "test", + Strategy: "manual", + Approvers: []string{ + "user@email.com", + }, }, }, - }, - AppealConfig: &domain.PolicyAppealConfig{ - DurationOptions: []domain.AppealDurationOption{ - { - Name: "1 day", - Value: "24h", + AppealConfig: &domain.PolicyAppealConfig{ + DurationOptions: []domain.AppealDurationOption{ + { + Name: "1 day", + Value: "24h", + }, + { + Name: "2 days", + Value: "48h", + }, }, - { - Name: "2 days", - Value: "48h", + AllowPermanentAccess: false, + AllowActiveAccessExtensionIn: "24h", + MetadataSources: map[string]*domain.AppealMetadataSource{ + "test-static-source": { + Type: "static", + Name: "test name", + Description: "test description", + Value: "test value", + }, + "test-http-source": { + Type: "http", + Name: "test name", + Description: "test description", + Config: map[string]interface{}{ + "url": "http://test-localhost:8080", + }, + Value: "$response.body", + }, }, }, - AllowPermanentAccess: false, - AllowActiveAccessExtensionIn: "24h", - }, - IAM: &domain.IAMConfig{ - Provider: "http", - Config: map[string]interface{}{ - "url": "http://test-localhost:8080", - "auth": map[string]interface{}{ - "type": "basic", - "username": "test-user", - "password": "test-password", + IAM: &domain.IAMConfig{ + Provider: "http", + Config: map[string]interface{}{ + "url": "http://test-localhost:8080", + "auth": map[string]interface{}{ + "type": "basic", + "username": "test-user", + "password": "test-password", + }, }, }, - }, + } } s.Run("should return error if got error from the policy repository", func() { + validPolicy := getValidPolicy() expectedError := errors.New("error from repository") s.mockPolicyRepository.EXPECT().Create(mock.MatchedBy(func(ctx context.Context) bool { return true }), mock.Anything).Return(expectedError).Once() - s.mockCrypto.EXPECT().Encrypt("test-password").Return("test-password", nil).Once() - s.mockCrypto.EXPECT().Decrypt("test-password").Return("test-password", nil).Once() + s.mockCrypto.EXPECT().Encrypt("test-password").Return("encrypted-test-password", nil).Once() + s.mockCrypto.EXPECT().Encrypt(`{"url":"http://test-localhost:8080"}`).Return("encrypted-config", nil).Once() actualError := s.service.Create(context.Background(), validPolicy) s.EqualError(actualError, expectedError.Error()) + s.mockPolicyRepository.AssertExpectations(s.T()) + s.mockCrypto.AssertExpectations(s.T()) }) s.Run("should set initial version to 1", func() { - p := &domain.Policy{ - ID: "test", - Steps: validPolicy.Steps, - } + validPolicy := getValidPolicy() expectedVersion := uint(1) - s.mockPolicyRepository.EXPECT().Create(mock.MatchedBy(func(ctx context.Context) bool { return true }), p).Return(nil).Once() - s.mockCrypto.EXPECT().Encrypt("test-password").Return("test-password", nil).Once() - s.mockCrypto.EXPECT().Decrypt("test-password").Return("test-password", nil).Once() - s.mockAuditLogger.EXPECT().Log(mock.Anything, policy.AuditKeyPolicyCreate, mock.Anything).Return(nil).Once() - - actualError := s.service.Create(context.Background(), p) - - s.Nil(actualError) - s.Equal(expectedVersion, p.Version) - s.mockPolicyRepository.AssertExpectations(s.T()) - s.mockAuditLogger.AssertExpectations(s.T()) - }) - - s.Run("should pass the model from the param", func() { - s.mockPolicyRepository.EXPECT().Create(mock.MatchedBy(func(ctx context.Context) bool { return true }), validPolicy).Return(nil).Once() + s.mockPolicyRepository.EXPECT(). + Create( + mock.MatchedBy(func(ctx context.Context) bool { return true }), + mock.MatchedBy(func(arg interface{}) bool { + insertedPolicy := arg.(*domain.Policy) + return (insertedPolicy.ID == validPolicy.ID && + insertedPolicy.Version == expectedVersion && + insertedPolicy.AppealConfig.MetadataSources["test-http-source"].Config == "encrypted-config" && + insertedPolicy.IAM.Config.(*identities.HTTPClientConfig).Auth.Password == "encrypted-test-password") + }), + ). + Return(nil).Once() + s.mockCrypto.EXPECT().Encrypt("test-password").Return("encrypted-test-password", nil).Once() + s.mockCrypto.EXPECT().Encrypt(`{"url":"http://test-localhost:8080"}`).Return("encrypted-config", nil).Once() + s.mockCrypto.EXPECT().Decrypt("encrypted-test-password").Return("test-password", nil).Once() + s.mockCrypto.EXPECT().Decrypt("encrypted-config").Return(`{"url":"http://test-localhost:8080"}`, nil).Once() s.mockAuditLogger.EXPECT().Log(mock.Anything, policy.AuditKeyPolicyCreate, mock.Anything).Return(nil).Once() - s.mockCrypto.EXPECT().Encrypt("test-password").Return("test-password", nil).Once() - s.mockCrypto.EXPECT().Decrypt("test-password").Return("test-password", nil).Once() actualError := s.service.Create(context.Background(), validPolicy) s.Nil(actualError) + s.Equal(expectedVersion, validPolicy.Version) s.mockPolicyRepository.AssertExpectations(s.T()) s.mockAuditLogger.AssertExpectations(s.T()) + s.mockCrypto.AssertExpectations(s.T()) }) s.Run("with dryRun true", func() { + validPolicy := getValidPolicy() s.Run("with valid policy should not call repository", func() { - ctx := policy.WithDryRun(context.Background()) + s.mockCrypto.EXPECT().Encrypt("test-password").Return("test-password", nil).Once() + s.mockCrypto.EXPECT().Encrypt(`{"url":"http://test-localhost:8080"}`).Return("encrypted-config", nil).Once() + s.mockCrypto.EXPECT().Decrypt("test-password").Return("test-password", nil).Once() + s.mockCrypto.EXPECT().Decrypt("encrypted-config").Return(`{"url":"http://test-localhost:8080"}`, nil).Once() + ctx := policy.WithDryRun(context.Background()) actualError := s.service.Create(ctx, validPolicy) s.Nil(actualError) @@ -647,7 +673,7 @@ func (s *ServiceTestSuite) TestFind() { }) s.Run("should return list of records on success", func() { - expectedResult := []*domain.Policy{ + dummyPolicies := []*domain.Policy{ { IAM: &domain.IAMConfig{ Provider: "http", @@ -656,20 +682,46 @@ func (s *ServiceTestSuite) TestFind() { "auth": map[string]interface{}{ "type": "basic", "username": "test-user", - "password": "test-password", + "password": "encrypted-test-password", + }, + }, + }, + AppealConfig: &domain.PolicyAppealConfig{ + MetadataSources: map[string]*domain.AppealMetadataSource{ + "test-static-source": { + Type: "static", + Name: "test name", + Description: "test description", + Value: "test value", + }, + "test-http-source": { + Type: "http", + Name: "test name", + Description: "test description", + Config: "encrypted-config", + Value: "$response.body", }, }, }, }, } - s.mockPolicyRepository.EXPECT().Find(mock.MatchedBy(func(ctx context.Context) bool { return true })).Return(expectedResult, nil).Once() - s.mockCrypto.EXPECT().Decrypt("test-password").Return("test-password", nil).Once() + s.mockPolicyRepository.EXPECT(). + Find(mock.MatchedBy(func(ctx context.Context) bool { return true })). + Return(dummyPolicies, nil).Once() + expectedPassword := "test-password" + s.mockCrypto.EXPECT().Decrypt("encrypted-test-password").Return(expectedPassword, nil).Once() + expectedConfig := map[string]interface{}{"url": "http://test-localhost:8080"} + expectedConfigJSON, _ := json.Marshal(expectedConfig) + s.mockCrypto.EXPECT().Decrypt("encrypted-config").Return(string(expectedConfigJSON), nil).Once() actualResult, actualError := s.service.Find(context.Background()) - s.Equal(expectedResult, actualResult) + s.Len(actualResult, len(dummyPolicies)) + s.Equal(actualResult[0].IAM.Config.(map[string]any)["auth"].(map[string]any)["password"], expectedPassword) + s.Equal(actualResult[0].AppealConfig.MetadataSources["test-http-source"].Config, expectedConfig) s.Nil(actualError) s.mockPolicyRepository.AssertExpectations(s.T()) + s.mockCrypto.AssertExpectations(s.T()) }) } @@ -685,7 +737,7 @@ func (s *ServiceTestSuite) TestGetOne() { }) s.Run("should return list of records on success", func() { - expectedResult := &domain.Policy{ + dummyPolicy := &domain.Policy{ IAM: &domain.IAMConfig{ Provider: "http", Config: map[string]interface{}{ @@ -693,19 +745,42 @@ func (s *ServiceTestSuite) TestGetOne() { "auth": map[string]interface{}{ "type": "basic", "username": "test-user", - "password": "test-password", + "password": "encrypted-test-password", + }, + }, + }, + AppealConfig: &domain.PolicyAppealConfig{ + MetadataSources: map[string]*domain.AppealMetadataSource{ + "test-static-source": { + Type: "static", + Name: "test name", + Description: "test description", + Value: "test value", + }, + "test-http-source": { + Type: "http", + Name: "test name", + Description: "test description", + Config: "encrypted-config", + Value: "$response.body", }, }, }, } - s.mockPolicyRepository.EXPECT().GetOne(mock.MatchedBy(func(ctx context.Context) bool { return true }), mock.Anything, mock.Anything).Return(expectedResult, nil).Once() - s.mockCrypto.EXPECT().Decrypt("test-password").Return("test-password", nil).Once() + s.mockPolicyRepository.EXPECT().GetOne(mock.MatchedBy(func(ctx context.Context) bool { return true }), mock.Anything, mock.Anything).Return(dummyPolicy, nil).Once() + expectedPassword := "test-password" + s.mockCrypto.EXPECT().Decrypt("encrypted-test-password").Return(expectedPassword, nil).Once() + expectedConfig := map[string]interface{}{"url": "http://test-localhost:8080"} + expectedConfigJSON, _ := json.Marshal(expectedConfig) + s.mockCrypto.EXPECT().Decrypt("encrypted-config").Return(string(expectedConfigJSON), nil).Once() actualResult, actualError := s.service.GetOne(context.Background(), "", 0) - s.Equal(expectedResult, actualResult) + s.Equal(actualResult.IAM.Config.(map[string]any)["auth"].(map[string]any)["password"], expectedPassword) + s.Equal(actualResult.AppealConfig.MetadataSources["test-http-source"].Config, expectedConfig) s.Nil(actualError) s.mockPolicyRepository.AssertExpectations(s.T()) + s.mockCrypto.AssertExpectations(s.T()) }) } @@ -743,6 +818,25 @@ func (s *ServiceTestSuite) TestUpdate() { }, }, }, + AppealConfig: &domain.PolicyAppealConfig{ + MetadataSources: map[string]*domain.AppealMetadataSource{ + "test-static-source": { + Type: "static", + Name: "test name", + Description: "test description", + Value: "test value", + }, + "test-http-source": { + Type: "http", + Name: "test name", + Description: "test description", + Config: map[string]interface{}{ + "url": "http://test-localhost:8080", + }, + Value: "$response.body", + }, + }, + }, } expectedLatestPolicy := &domain.Policy{ @@ -750,17 +844,32 @@ func (s *ServiceTestSuite) TestUpdate() { Version: 5, } expectedNewVersion := uint(6) - s.mockPolicyRepository.EXPECT().GetOne(mock.MatchedBy(func(ctx context.Context) bool { return true }), p.ID, uint(0)).Return(expectedLatestPolicy, nil).Once() - s.mockPolicyRepository.EXPECT().Create(mock.MatchedBy(func(ctx context.Context) bool { return true }), p).Return(nil) - s.mockCrypto.EXPECT().Encrypt("test-password").Return("test-password", nil).Once() - s.mockCrypto.EXPECT().Decrypt("test-password").Return("test-password", nil).Once() + s.mockPolicyRepository.EXPECT(). + GetOne(mock.MatchedBy(func(ctx context.Context) bool { return true }), p.ID, uint(0)). + Return(expectedLatestPolicy, nil).Once() + s.mockPolicyRepository.EXPECT(). + Create( + mock.MatchedBy(func(ctx context.Context) bool { return true }), + mock.MatchedBy(func(arg interface{}) bool { + insertedPolicy := arg.(*domain.Policy) + return (insertedPolicy.ID == p.ID && + insertedPolicy.Version == expectedNewVersion && + insertedPolicy.AppealConfig.MetadataSources["test-http-source"].Config == "encrypted-config" && + insertedPolicy.IAM.Config.(*identities.HTTPClientConfig).Auth.Password == "encrypted-test-password") + }), + ).Return(nil) + s.mockCrypto.EXPECT().Encrypt("test-password").Return("encrypted-test-password", nil).Once() + s.mockCrypto.EXPECT().Encrypt(`{"url":"http://test-localhost:8080"}`).Return("encrypted-config", nil).Once() + s.mockCrypto.EXPECT().Decrypt("encrypted-test-password").Return("test-password", nil).Once() + s.mockCrypto.EXPECT().Decrypt("encrypted-config").Return(`{"url":"http://test-localhost:8080"}`, nil).Once() s.mockAuditLogger.EXPECT().Log(mock.Anything, policy.AuditKeyPolicyUpdate, mock.Anything).Return(nil).Once() s.service.Update(context.Background(), p) + s.Equal(expectedNewVersion, p.Version) s.mockPolicyRepository.AssertExpectations(s.T()) s.mockAuditLogger.AssertExpectations(s.T()) - s.Equal(expectedNewVersion, p.Version) + s.mockCrypto.AssertExpectations(s.T()) }) s.Run("with dryRun true", func() { From 36019e281516142cb8517bfac401976225014aaf Mon Sep 17 00:00:00 2001 From: Rahmat Hidayat Date: Mon, 1 Apr 2024 00:29:42 +0700 Subject: [PATCH 24/39] test: add unit test for metadata source encrypt & decrypt --- domain/policy_metadata_source_test.go | 90 ++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/domain/policy_metadata_source_test.go b/domain/policy_metadata_source_test.go index 16cbc9fc2..d41e5bd7e 100644 --- a/domain/policy_metadata_source_test.go +++ b/domain/policy_metadata_source_test.go @@ -4,15 +4,101 @@ import ( "testing" "github.com/goto/guardian/domain" + "github.com/goto/guardian/mocks" "github.com/stretchr/testify/assert" ) func TestAppealMetadataSource_EncryptConfig(t *testing.T) { - t.Skip("TODO: implement") + t.Run("should encrypt config", func(t *testing.T) { + mockEncryptor := new(mocks.Crypto) + mockEncryptor.EXPECT().Encrypt(`{"key":"value"}`).Return("encrypted", nil) + defer mockEncryptor.AssertExpectations(t) + + ms := &domain.AppealMetadataSource{ + Config: map[string]interface{}{ + "key": "value", + }, + } + err := ms.EncryptConfig(mockEncryptor) + + assert.NoError(t, err) + assert.Equal(t, "encrypted", ms.Config) + }) + + t.Run("should return error if marshalling fails", func(t *testing.T) { + ms := &domain.AppealMetadataSource{ + Config: make(chan int), + } + err := ms.EncryptConfig(nil) + + assert.Error(t, err) + }) + + t.Run("should return error if encryption fails", func(t *testing.T) { + mockEncryptor := new(mocks.Crypto) + mockEncryptor.EXPECT().Encrypt(`{"key":"value"}`).Return("", assert.AnError) + defer mockEncryptor.AssertExpectations(t) + + ms := &domain.AppealMetadataSource{ + Config: map[string]interface{}{ + "key": "value", + }, + } + err := ms.EncryptConfig(mockEncryptor) + + assert.Error(t, err) + }) } func TestAppealMetadataSource_DecryptConfig(t *testing.T) { - t.Skip("TODO: implement") + t.Run("should decrypt config", func(t *testing.T) { + mockDecryptor := new(mocks.Crypto) + mockDecryptor.EXPECT().Decrypt("encrypted").Return(`{"key":"value"}`, nil) + defer mockDecryptor.AssertExpectations(t) + + ms := &domain.AppealMetadataSource{ + Config: "encrypted", + } + err := ms.DecryptConfig(mockDecryptor) + + assert.NoError(t, err) + assert.Equal(t, map[string]interface{}{"key": "value"}, ms.Config) + }) + + t.Run("should return error if config is not a string", func(t *testing.T) { + ms := &domain.AppealMetadataSource{ + Config: 123, + } + err := ms.DecryptConfig(nil) + + assert.Error(t, err) + }) + + t.Run("should return error if decryption fails", func(t *testing.T) { + mockDecryptor := new(mocks.Crypto) + mockDecryptor.EXPECT().Decrypt("encrypted").Return("", assert.AnError) + defer mockDecryptor.AssertExpectations(t) + + ms := &domain.AppealMetadataSource{ + Config: "encrypted", + } + err := ms.DecryptConfig(mockDecryptor) + + assert.Error(t, err) + }) + + t.Run("should return error if unmarshalling fails", func(t *testing.T) { + mockDecryptor := new(mocks.Crypto) + mockDecryptor.EXPECT().Decrypt("encrypted").Return("invalid-json", nil) + defer mockDecryptor.AssertExpectations(t) + + ms := &domain.AppealMetadataSource{ + Config: "encrypted", + } + err := ms.DecryptConfig(mockDecryptor) + + assert.Error(t, err) + }) } func TestAppealMetadataSource_EvaluateValue(t *testing.T) { From c6a9db37930248ee9dfc001e7b1d67c0293290c6 Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Mon, 18 Mar 2024 13:40:18 +0700 Subject: [PATCH 25/39] feat: sending notification concurrently --- core/appeal/service.go | 86 ++++++++++++---------- core/grant/service.go | 162 +++++++++++++++++++++-------------------- 2 files changed, 130 insertions(+), 118 deletions(-) diff --git a/core/appeal/service.go b/core/appeal/service.go index d83ee5a24..fce518eba 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -191,10 +191,10 @@ func (s *Service) Create(ctx context.Context, appeals []*domain.Appeal, opts ... eg, egctx := errgroup.WithContext(ctx) var ( - resources map[string]*domain.Resource - providers map[string]map[string]*domain.Provider - policies map[string]map[uint]*domain.Policy - pendingAppeals map[string]map[string]map[string]*domain.Appeal + resources map[string]*domain.Resource + providers map[string]map[string]*domain.Provider + policies map[string]map[uint]*domain.Policy + pendingAppeals map[string]map[string]map[string]*domain.Appeal ) eg.Go(func() error { @@ -392,11 +392,13 @@ func (s *Service) Create(ctx context.Context, appeals []*domain.Appeal, opts ... } if len(notifications) > 0 { - if errs := s.notifier.Notify(ctx, notifications); errs != nil { - for _, err1 := range errs { - s.logger.Error(ctx, "failed to send notifications", "error", err1.Error()) + go func() { + if errs := s.notifier.Notify(ctx, notifications); errs != nil { + for _, err1 := range errs { + s.logger.Error(ctx, "failed to send notifications", "error", err1.Error()) + } } - } + }() } return nil @@ -606,11 +608,13 @@ func (s *Service) UpdateApproval(ctx context.Context, approvalAction domain.Appr notifications = append(notifications, s.getApprovalNotifications(ctx, appeal)...) } if len(notifications) > 0 { - if errs := s.notifier.Notify(ctx, notifications); errs != nil { - for _, err1 := range errs { - s.logger.Error(ctx, "failed to send notifications", "error", err1.Error()) + go func() { + if errs := s.notifier.Notify(ctx, notifications); errs != nil { + for _, err1 := range errs { + s.logger.Error(ctx, "failed to send notifications", "error", err1.Error()) + } } - } + }() } var auditKey string @@ -718,37 +722,39 @@ func (s *Service) AddApprover(ctx context.Context, appealID, approvalID, email s } } - if errs := s.notifier.Notify(ctx, []domain.Notification{ - { - User: email, - Labels: map[string]string{ - "appeal_id": appeal.ID, - }, - Message: domain.NotificationMessage{ - Type: domain.NotificationTypeApproverNotification, - Variables: map[string]interface{}{ - "resource_name": fmt.Sprintf("%s (%s: %s)", appeal.Resource.Name, appeal.Resource.ProviderType, appeal.Resource.URN), - "role": appeal.Role, - "requestor": appeal.CreatedBy, - "appeal_id": appeal.ID, - "account_id": appeal.AccountID, - "account_type": appeal.AccountType, - "provider_type": appeal.Resource.ProviderType, - "resource_type": appeal.Resource.Type, - "created_at": appeal.CreatedAt, - "approval_step": approval.Name, - "actor": email, - "details": appeal.Details, - "duration": duration, - "creator": appeal.Creator, + go func() { + if errs := s.notifier.Notify(ctx, []domain.Notification{ + { + User: email, + Labels: map[string]string{ + "appeal_id": appeal.ID, + }, + Message: domain.NotificationMessage{ + Type: domain.NotificationTypeApproverNotification, + Variables: map[string]interface{}{ + "resource_name": fmt.Sprintf("%s (%s: %s)", appeal.Resource.Name, appeal.Resource.ProviderType, appeal.Resource.URN), + "role": appeal.Role, + "requestor": appeal.CreatedBy, + "appeal_id": appeal.ID, + "account_id": appeal.AccountID, + "account_type": appeal.AccountType, + "provider_type": appeal.Resource.ProviderType, + "resource_type": appeal.Resource.Type, + "created_at": appeal.CreatedAt, + "approval_step": approval.Name, + "actor": email, + "details": appeal.Details, + "duration": duration, + "creator": appeal.Creator, + }, }, }, - }, - }); errs != nil { - for _, err1 := range errs { - s.logger.Error(ctx, "failed to send notifications", "error", err1.Error()) + }); errs != nil { + for _, err1 := range errs { + s.logger.Error(ctx, "failed to send notifications", "error", err1.Error()) + } } - } + }() return appeal, nil } diff --git a/core/grant/service.go b/core/grant/service.go index 91e842fc4..f51ee0102 100644 --- a/core/grant/service.go +++ b/core/grant/service.go @@ -140,37 +140,39 @@ func (s *Service) Update(ctx context.Context, payload *domain.Grant) error { } if previousOwner != updatedGrant.Owner { - message := domain.NotificationMessage{ - Type: domain.NotificationTypeGrantOwnerChanged, - Variables: map[string]interface{}{ - "grant_id": grantDetails.ID, - "previous_owner": previousOwner, - "new_owner": updatedGrant.Owner, - }, - } - notifications := []domain.Notification{{ - User: updatedGrant.Owner, - Labels: map[string]string{ - "appeal_id": grantDetails.AppealID, - "grant_id": grantDetails.ID, - }, - Message: message, - }} - if previousOwner != "" { - notifications = append(notifications, domain.Notification{ - User: previousOwner, + go func() { + message := domain.NotificationMessage{ + Type: domain.NotificationTypeGrantOwnerChanged, + Variables: map[string]interface{}{ + "grant_id": grantDetails.ID, + "previous_owner": previousOwner, + "new_owner": updatedGrant.Owner, + }, + } + notifications := []domain.Notification{{ + User: updatedGrant.Owner, Labels: map[string]string{ "appeal_id": grantDetails.AppealID, "grant_id": grantDetails.ID, }, Message: message, - }) - } - if errs := s.notifier.Notify(ctx, notifications); errs != nil { - for _, err1 := range errs { - s.logger.Error(ctx, "failed to send notifications", "error", err1.Error()) + }} + if previousOwner != "" { + notifications = append(notifications, domain.Notification{ + User: previousOwner, + Labels: map[string]string{ + "appeal_id": grantDetails.AppealID, + "grant_id": grantDetails.ID, + }, + Message: message, + }) } - } + if errs := s.notifier.Notify(ctx, notifications); errs != nil { + for _, err1 := range errs { + s.logger.Error(ctx, "failed to send notifications", "error", err1.Error()) + } + } + }() } return nil @@ -218,28 +220,30 @@ func (s *Service) Revoke(ctx context.Context, id, actor, reason string, opts ... } if !options.skipNotification { - if errs := s.notifier.Notify(ctx, []domain.Notification{{ - User: grant.CreatedBy, - Labels: map[string]string{ - "appeal_id": grant.AppealID, - "grant_id": grant.ID, - }, - Message: domain.NotificationMessage{ - Type: domain.NotificationTypeAccessRevoked, - Variables: map[string]interface{}{ - "resource_name": fmt.Sprintf("%s (%s: %s)", grant.Resource.Name, grant.Resource.ProviderType, grant.Resource.URN), - "role": grant.Role, - "account_type": grant.AccountType, - "account_id": grant.AccountID, - "requestor": grant.Owner, - "revoke_reason": grant.RevokeReason, + go func() { + if errs := s.notifier.Notify(ctx, []domain.Notification{{ + User: grant.CreatedBy, + Labels: map[string]string{ + "appeal_id": grant.AppealID, + "grant_id": grant.ID, }, - }, - }}); errs != nil { - for _, err1 := range errs { - s.logger.Error(ctx, "failed to send notifications", "error", err1.Error()) + Message: domain.NotificationMessage{ + Type: domain.NotificationTypeAccessRevoked, + Variables: map[string]interface{}{ + "resource_name": fmt.Sprintf("%s (%s: %s)", grant.Resource.Name, grant.Resource.ProviderType, grant.Resource.URN), + "role": grant.Role, + "account_type": grant.AccountType, + "account_id": grant.AccountID, + "requestor": grant.Owner, + "revoke_reason": grant.RevokeReason, + }, + }, + }}); errs != nil { + for _, err1 := range errs { + s.logger.Error(ctx, "failed to send notifications", "error", err1.Error()) + } } - } + }() } s.logger.Info(ctx, "grant revoked", "grant_id", id) @@ -571,44 +575,46 @@ func (s *Service) DormancyCheck(ctx context.Context, criteria domain.DormancyChe return fmt.Errorf("updating grants expiration date: %w", err) } - var notifications []domain.Notification -prepare_notifications: - for owner, grants := range dormantGrantsByOwner { - var grantsMap []map[string]interface{} - var grantIDs []string - - for _, g := range grants { - grantMap, err := utils.StructToMap(g) - if err != nil { - s.logger.Error(ctx, "failed to convert grant to map", "error", err) - continue prepare_notifications + go func() { + var notifications []domain.Notification + prepare_notifications: + for owner, grants := range dormantGrantsByOwner { + var grantsMap []map[string]interface{} + var grantIDs []string + + for _, g := range grants { + grantMap, err := utils.StructToMap(g) + if err != nil { + s.logger.Error(ctx, "failed to convert grant to map", "error", err) + continue prepare_notifications + } + grantsMap = append(grantsMap, grantMap) } - grantsMap = append(grantsMap, grantMap) - } - notifications = append(notifications, domain.Notification{ - User: owner, - Labels: map[string]string{ - "owner": owner, - "grant_ids": strings.Join(grantIDs, ", "), - }, - Message: domain.NotificationMessage{ - Type: domain.NotificationTypeUnusedGrant, - Variables: map[string]interface{}{ - "dormant_grants": grantsMap, - "period": criteria.Period.String(), - "retain_duration": criteria.RetainDuration.String(), - "start_date_formatted": startDate.Format("Jan 02, 2006 15:04:05 UTC"), + notifications = append(notifications, domain.Notification{ + User: owner, + Labels: map[string]string{ + "owner": owner, + "grant_ids": strings.Join(grantIDs, ", "), }, - }, - }) - } + Message: domain.NotificationMessage{ + Type: domain.NotificationTypeUnusedGrant, + Variables: map[string]interface{}{ + "dormant_grants": grantsMap, + "period": criteria.Period.String(), + "retain_duration": criteria.RetainDuration.String(), + "start_date_formatted": startDate.Format("Jan 02, 2006 15:04:05 UTC"), + }, + }, + }) + } - if errs := s.notifier.Notify(ctx, notifications); errs != nil { - for _, err1 := range errs { - s.logger.Error(ctx, "failed to send notifications", "error", err1.Error(), "provider_urn", provider.URN) + if errs := s.notifier.Notify(ctx, notifications); errs != nil { + for _, err1 := range errs { + s.logger.Error(ctx, "failed to send notifications", "error", err1.Error(), "provider_urn", provider.URN) + } } - } + }() return nil } From 581b6a55e4cc41baf0d221858284a528968bbc83 Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Mon, 18 Mar 2024 14:49:04 +0700 Subject: [PATCH 26/39] test: update unit test --- core/appeal/service_test.go | 2 +- core/grant/service_test.go | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/core/appeal/service_test.go b/core/appeal/service_test.go index c9a00c3d0..22e1956d0 100644 --- a/core/appeal/service_test.go +++ b/core/appeal/service_test.go @@ -3001,7 +3001,7 @@ func (s *ServiceTestSuite) TestAddApprover() { s.Equal(tc.newApprover, n.User) s.Equal(domain.NotificationTypeApproverNotification, n.Message.Type) }). - Return(nil).Once() + Return(nil) actualAppeal, actualError := s.service.AddApprover(context.Background(), appealID, approvalID, newApprover) diff --git a/core/grant/service_test.go b/core/grant/service_test.go index bf139d332..9afe440d5 100644 --- a/core/grant/service_test.go +++ b/core/grant/service_test.go @@ -328,6 +328,27 @@ func (s *ServiceTestSuite) TestRevoke() { }). Return(nil).Once() + s.mockNotifier.EXPECT(). + Notify(mock.MatchedBy(func(ctx context.Context) bool { return true }), []domain.Notification{{ + User: expectedGrantDetails.CreatedBy, + Labels: map[string]string{ + "appeal_id": expectedGrantDetails.AppealID, + "grant_id": expectedGrantDetails.ID, + }, + Message: domain.NotificationMessage{ + Type: domain.NotificationTypeAccessRevoked, + Variables: map[string]interface{}{ + "resource_name": fmt.Sprintf("%s (%s: %s)", expectedGrantDetails.Resource.Name, expectedGrantDetails.Resource.ProviderType, expectedGrantDetails.Resource.URN), + "role": expectedGrantDetails.Role, + "account_type": expectedGrantDetails.AccountType, + "account_id": expectedGrantDetails.AccountID, + "requestor": expectedGrantDetails.Owner, + "revoke_reason": reason, + }, + }, + }}). + Return(nil).Once() + expectedGrant, err := s.service.Revoke(context.Background(), id, actor, reason, grant.SkipRevokeAccessInProvider(), grant.SkipNotifications()) s.NoError(err) From 46a46ab1b0332a6a16fd524f2e1ea3d852148461 Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Wed, 20 Mar 2024 11:47:20 +0700 Subject: [PATCH 27/39] test: fix unit test --- core/appeal/service_test.go | 4 ++-- core/grant/service.go | 37 +++++++++++++++++++------------------ core/grant/service_test.go | 37 +++++++++++++++++++------------------ 3 files changed, 40 insertions(+), 38 deletions(-) diff --git a/core/appeal/service_test.go b/core/appeal/service_test.go index 22e1956d0..93b90d531 100644 --- a/core/appeal/service_test.go +++ b/core/appeal/service_test.go @@ -2408,7 +2408,6 @@ func (s *ServiceTestSuite) TestUpdateApproval() { s.mockRepository.AssertExpectations(s.T()) s.mockPolicyService.AssertExpectations(s.T()) s.mockGrantService.AssertExpectations(s.T()) - s.mockNotifier.AssertExpectations(s.T()) s.mockAuditLogger.AssertExpectations(s.T()) s.Nil(actualError) }) @@ -3001,10 +3000,11 @@ func (s *ServiceTestSuite) TestAddApprover() { s.Equal(tc.newApprover, n.User) s.Equal(domain.NotificationTypeApproverNotification, n.Message.Type) }). - Return(nil) + Return(nil).Once() actualAppeal, actualError := s.service.AddApprover(context.Background(), appealID, approvalID, newApprover) + time.Sleep(time.Second) s.NoError(actualError) s.Equal(expectedApproval, actualAppeal.Approvals[0]) s.mockRepository.AssertExpectations(s.T()) diff --git a/core/grant/service.go b/core/grant/service.go index f51ee0102..d2962c7bf 100644 --- a/core/grant/service.go +++ b/core/grant/service.go @@ -220,25 +220,26 @@ func (s *Service) Revoke(ctx context.Context, id, actor, reason string, opts ... } if !options.skipNotification { - go func() { - if errs := s.notifier.Notify(ctx, []domain.Notification{{ - User: grant.CreatedBy, - Labels: map[string]string{ - "appeal_id": grant.AppealID, - "grant_id": grant.ID, - }, - Message: domain.NotificationMessage{ - Type: domain.NotificationTypeAccessRevoked, - Variables: map[string]interface{}{ - "resource_name": fmt.Sprintf("%s (%s: %s)", grant.Resource.Name, grant.Resource.ProviderType, grant.Resource.URN), - "role": grant.Role, - "account_type": grant.AccountType, - "account_id": grant.AccountID, - "requestor": grant.Owner, - "revoke_reason": grant.RevokeReason, - }, + notifications := []domain.Notification{{ + User: grant.CreatedBy, + Labels: map[string]string{ + "appeal_id": grant.AppealID, + "grant_id": grant.ID, + }, + Message: domain.NotificationMessage{ + Type: domain.NotificationTypeAccessRevoked, + Variables: map[string]interface{}{ + "resource_name": fmt.Sprintf("%s (%s: %s)", grant.Resource.Name, grant.Resource.ProviderType, grant.Resource.URN), + "role": grant.Role, + "account_type": grant.AccountType, + "account_id": grant.AccountID, + "requestor": grant.Owner, + "revoke_reason": grant.RevokeReason, }, - }}); errs != nil { + }, + }} + go func() { + if errs := s.notifier.Notify(ctx, notifications); errs != nil { for _, err1 := range errs { s.logger.Error(ctx, "failed to send notifications", "error", err1.Error()) } diff --git a/core/grant/service_test.go b/core/grant/service_test.go index 9afe440d5..9b0200b4d 100644 --- a/core/grant/service_test.go +++ b/core/grant/service_test.go @@ -328,25 +328,26 @@ func (s *ServiceTestSuite) TestRevoke() { }). Return(nil).Once() - s.mockNotifier.EXPECT(). - Notify(mock.MatchedBy(func(ctx context.Context) bool { return true }), []domain.Notification{{ - User: expectedGrantDetails.CreatedBy, - Labels: map[string]string{ - "appeal_id": expectedGrantDetails.AppealID, - "grant_id": expectedGrantDetails.ID, - }, - Message: domain.NotificationMessage{ - Type: domain.NotificationTypeAccessRevoked, - Variables: map[string]interface{}{ - "resource_name": fmt.Sprintf("%s (%s: %s)", expectedGrantDetails.Resource.Name, expectedGrantDetails.Resource.ProviderType, expectedGrantDetails.Resource.URN), - "role": expectedGrantDetails.Role, - "account_type": expectedGrantDetails.AccountType, - "account_id": expectedGrantDetails.AccountID, - "requestor": expectedGrantDetails.Owner, - "revoke_reason": reason, - }, + notifications := []domain.Notification{{ + User: expectedGrantDetails.CreatedBy, + Labels: map[string]string{ + "appeal_id": expectedGrantDetails.AppealID, + "grant_id": expectedGrantDetails.ID, + }, + Message: domain.NotificationMessage{ + Type: domain.NotificationTypeAccessRevoked, + Variables: map[string]interface{}{ + "resource_name": fmt.Sprintf("%s (%s: %s)", expectedGrantDetails.Resource.Name, expectedGrantDetails.Resource.ProviderType, expectedGrantDetails.Resource.URN), + "role": expectedGrantDetails.Role, + "account_type": expectedGrantDetails.AccountType, + "account_id": expectedGrantDetails.AccountID, + "requestor": expectedGrantDetails.Owner, + "revoke_reason": reason, }, - }}). + }, + }} + s.mockNotifier.EXPECT(). + Notify(mock.MatchedBy(func(ctx context.Context) bool { return true }), notifications). Return(nil).Once() expectedGrant, err := s.service.Revoke(context.Background(), id, actor, reason, grant.SkipRevokeAccessInProvider(), grant.SkipNotifications()) From 4ebe653afc83e2ed23f276e8739e321dc7ad000a Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Wed, 20 Mar 2024 16:42:44 +0700 Subject: [PATCH 28/39] test: fix race data --- core/appeal/service.go | 54 +++++------ core/appeal/service_test.go | 173 ++++++++++++++++++++++++------------ 2 files changed, 144 insertions(+), 83 deletions(-) diff --git a/core/appeal/service.go b/core/appeal/service.go index fce518eba..8bb320ed1 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -722,34 +722,36 @@ func (s *Service) AddApprover(ctx context.Context, appealID, approvalID, email s } } - go func() { - if errs := s.notifier.Notify(ctx, []domain.Notification{ - { - User: email, - Labels: map[string]string{ - "appeal_id": appeal.ID, - }, - Message: domain.NotificationMessage{ - Type: domain.NotificationTypeApproverNotification, - Variables: map[string]interface{}{ - "resource_name": fmt.Sprintf("%s (%s: %s)", appeal.Resource.Name, appeal.Resource.ProviderType, appeal.Resource.URN), - "role": appeal.Role, - "requestor": appeal.CreatedBy, - "appeal_id": appeal.ID, - "account_id": appeal.AccountID, - "account_type": appeal.AccountType, - "provider_type": appeal.Resource.ProviderType, - "resource_type": appeal.Resource.Type, - "created_at": appeal.CreatedAt, - "approval_step": approval.Name, - "actor": email, - "details": appeal.Details, - "duration": duration, - "creator": appeal.Creator, - }, + notifications := []domain.Notification{ + { + User: email, + Labels: map[string]string{ + "appeal_id": appeal.ID, + }, + Message: domain.NotificationMessage{ + Type: domain.NotificationTypeApproverNotification, + Variables: map[string]interface{}{ + "resource_name": fmt.Sprintf("%s (%s: %s)", appeal.Resource.Name, appeal.Resource.ProviderType, appeal.Resource.URN), + "role": appeal.Role, + "requestor": appeal.CreatedBy, + "appeal_id": appeal.ID, + "account_id": appeal.AccountID, + "account_type": appeal.AccountType, + "provider_type": appeal.Resource.ProviderType, + "resource_type": appeal.Resource.Type, + "created_at": appeal.CreatedAt, + "approval_step": approval.Name, + "actor": email, + "details": appeal.Details, + "duration": duration, + "creator": appeal.Creator, }, }, - }); errs != nil { + }, + } + + go func() { + if errs := s.notifier.Notify(ctx, notifications); errs != nil { for _, err1 := range errs { s.logger.Error(ctx, "failed to send notifications", "error", err1.Error()) } diff --git a/core/appeal/service_test.go b/core/appeal/service_test.go index 93b90d531..8071e6f28 100644 --- a/core/appeal/service_test.go +++ b/core/appeal/service_test.go @@ -15,6 +15,7 @@ import ( "github.com/goto/guardian/domain" "github.com/goto/guardian/mocks" "github.com/goto/guardian/pkg/log" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/suite" ) @@ -2939,78 +2940,136 @@ func (s *ServiceTestSuite) TestCancel() { } func (s *ServiceTestSuite) TestAddApprover() { - s.Run("should return appeal on success", func() { + s.Run("should return appeal on success with approval ID", func() { appealID := uuid.New().String() approvalID := uuid.New().String() approvalName := "test-approval-name" newApprover := "user@example.com" - testCases := []struct { + tc := struct { name, appealID, approvalID, newApprover string + expectedAppeal *domain.Appeal + expectedApproval *domain.Approval }{ - { - name: "with approval ID", - appealID: appealID, approvalID: approvalID, newApprover: newApprover, + name: "with approval ID", + appealID: appealID, approvalID: approvalID, newApprover: newApprover, + expectedAppeal: &domain.Appeal{ + ID: appealID, + Status: domain.AppealStatusPending, + Approvals: []*domain.Approval{ + { + ID: approvalID, + Name: approvalName, + Status: domain.ApprovalStatusPending, + Approvers: []string{ + "existing.approver@example.com", + }, + }, + }, + Resource: &domain.Resource{}, }, - { - name: "with approval name", - appealID: appealID, approvalID: approvalName, newApprover: newApprover, + expectedApproval: &domain.Approval{ + ID: approvalID, + Name: approvalName, + Status: domain.ApprovalStatusPending, + Approvers: []string{ + "existing.approver@example.com", + newApprover, + }, }, } - for _, tc := range testCases { - s.Run(tc.name, func() { - expectedAppeal := &domain.Appeal{ - ID: appealID, - Status: domain.AppealStatusPending, - Approvals: []*domain.Approval{ - { - ID: approvalID, - Name: approvalName, - Status: domain.ApprovalStatusPending, - Approvers: []string{ - "existing.approver@example.com", - }, + s.mockRepository.EXPECT(). + GetByID(mock.MatchedBy(func(ctx context.Context) bool { return true }), appealID). + Return(tc.expectedAppeal, nil).Once() + s.mockApprovalService.EXPECT(). + AddApprover(mock.MatchedBy(func(ctx context.Context) bool { return true }), approvalID, newApprover). + Return(nil).Once() + s.mockAuditLogger.EXPECT(). + Log(mock.MatchedBy(func(ctx context.Context) bool { return true }), appeal.AuditKeyAddApprover, tc.expectedApproval).Return(nil).Once() + s.mockNotifier.EXPECT(). + Notify(mock.MatchedBy(func(ctx context.Context) bool { return true }), mock.Anything). + Run(func(ctx context.Context, notifications []domain.Notification) { + assert.Equal(s.T(), len(notifications), 1) + n := notifications[0] + ng := n + assert.Equal(s.T(), tc.newApprover, ng.User) + assert.Equal(s.T(), domain.NotificationTypeApproverNotification, ng.Message.Type) + }). + Return(nil).Once() + + actualAppeal, actualError := s.service.AddApprover(context.Background(), appealID, approvalID, newApprover) + + s.NoError(actualError) + s.Equal(tc.expectedApproval, actualAppeal.Approvals[0]) + s.mockRepository.AssertExpectations(s.T()) + s.mockApprovalService.AssertExpectations(s.T()) + }) + + s.Run("should return appeal on success with approval name", func() { + appealID := uuid.New().String() + approvalID := uuid.New().String() + approvalName := "test-approval-name" + newApprover := "user@example.com" + + tc := struct { + name, appealID, approvalID, newApprover string + expectedAppeal *domain.Appeal + expectedApproval *domain.Approval + }{ + name: "with approval name", + appealID: appealID, approvalID: approvalName, newApprover: newApprover, + expectedAppeal: &domain.Appeal{ + ID: appealID, + Status: domain.AppealStatusPending, + Approvals: []*domain.Approval{ + { + ID: approvalID, + Name: approvalName, + Status: domain.ApprovalStatusPending, + Approvers: []string{ + "existing.approver@example.com", }, }, - Resource: &domain.Resource{}, - } - expectedApproval := &domain.Approval{ - ID: approvalID, - Name: approvalName, - Status: domain.ApprovalStatusPending, - Approvers: []string{ - "existing.approver@example.com", - tc.newApprover, - }, - } - s.mockRepository.EXPECT(). - GetByID(mock.MatchedBy(func(ctx context.Context) bool { return true }), appealID). - Return(expectedAppeal, nil).Once() - s.mockApprovalService.EXPECT(). - AddApprover(mock.MatchedBy(func(ctx context.Context) bool { return true }), approvalID, newApprover). - Return(nil).Once() - s.mockAuditLogger.EXPECT(). - Log(mock.MatchedBy(func(ctx context.Context) bool { return true }), appeal.AuditKeyAddApprover, expectedApproval).Return(nil).Once() - s.mockNotifier.EXPECT(). - Notify(mock.MatchedBy(func(ctx context.Context) bool { return true }), mock.Anything). - Run(func(ctx context.Context, notifications []domain.Notification) { - s.Len(notifications, 1) - n := notifications[0] - s.Equal(tc.newApprover, n.User) - s.Equal(domain.NotificationTypeApproverNotification, n.Message.Type) - }). - Return(nil).Once() + }, + Resource: &domain.Resource{}, + }, + expectedApproval: &domain.Approval{ + ID: approvalID, + Name: approvalName, + Status: domain.ApprovalStatusPending, + Approvers: []string{ + "existing.approver@example.com", + newApprover, + }, + }, + } + + s.mockRepository.EXPECT(). + GetByID(mock.MatchedBy(func(ctx context.Context) bool { return true }), appealID). + Return(tc.expectedAppeal, nil).Once() + s.mockApprovalService.EXPECT(). + AddApprover(mock.MatchedBy(func(ctx context.Context) bool { return true }), approvalID, newApprover). + Return(nil).Once() + s.mockAuditLogger.EXPECT(). + Log(mock.MatchedBy(func(ctx context.Context) bool { return true }), appeal.AuditKeyAddApprover, tc.expectedApproval).Return(nil).Once() + s.mockNotifier.EXPECT(). + Notify(mock.MatchedBy(func(ctx context.Context) bool { return true }), mock.Anything). + Run(func(ctx context.Context, notifications []domain.Notification) { + assert.Equal(s.T(), len(notifications), 1) + n := notifications[0] + ng := n + assert.Equal(s.T(), tc.newApprover, ng.User) + assert.Equal(s.T(), domain.NotificationTypeApproverNotification, ng.Message.Type) + }). + Return(nil).Once() - actualAppeal, actualError := s.service.AddApprover(context.Background(), appealID, approvalID, newApprover) + actualAppeal, actualError := s.service.AddApprover(context.Background(), appealID, approvalID, newApprover) - time.Sleep(time.Second) - s.NoError(actualError) - s.Equal(expectedApproval, actualAppeal.Approvals[0]) - s.mockRepository.AssertExpectations(s.T()) - s.mockApprovalService.AssertExpectations(s.T()) - }) - } + s.NoError(actualError) + s.Equal(tc.expectedApproval, actualAppeal.Approvals[0]) + s.mockRepository.AssertExpectations(s.T()) + s.mockApprovalService.AssertExpectations(s.T()) }) s.Run("params validation", func() { From 81371ae305b623a8b09a302de9de2fcfe01c9967 Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Wed, 20 Mar 2024 14:43:01 +0700 Subject: [PATCH 29/39] feat(notifier): retry mechanism on slack notif --- pkg/http/retry.go | 77 +++++++++++++++++++++++++++++++++++++ plugins/notifiers/client.go | 5 +-- 2 files changed, 79 insertions(+), 3 deletions(-) create mode 100644 pkg/http/retry.go diff --git a/pkg/http/retry.go b/pkg/http/retry.go new file mode 100644 index 000000000..04337091d --- /dev/null +++ b/pkg/http/retry.go @@ -0,0 +1,77 @@ +package http + +import ( + "bytes" + "io" + "math" + "net/http" + "time" +) + +const RetryCount = 3 + +type retryableTransport struct { + transport http.RoundTripper +} + +func NewRetryableClient() *http.Client { + transport := &retryableTransport{ + transport: &http.Transport{}, + } + + return &http.Client{ + Transport: transport, + } +} + +func (t *retryableTransport) RoundTrip(req *http.Request) (*http.Response, error) { + // Clone the request body + var bodyBytes []byte + if req.Body != nil { + bodyBytes, _ = io.ReadAll(req.Body) + req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) + } + // Send the request + resp, err := t.transport.RoundTrip(req) + // Retry logic + retries := 0 + for shouldRetry(err, resp) && retries < RetryCount { + // Wait for the specified backoff period + time.Sleep(backoff(retries)) + // We're going to retry, consume any response to reuse the connection. + drainBody(resp) + // Clone the request body again + if req.Body != nil { + req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) + } + // Retry the request + resp, err = t.transport.RoundTrip(req) + retries++ + } + // Return the response + return resp, err +} + +func backoff(retries int) time.Duration { + return time.Duration(math.Pow(2, float64(retries))) * time.Second +} + +func shouldRetry(err error, resp *http.Response) bool { + if err != nil { + return true + } + + if resp.StatusCode == http.StatusBadGateway || + resp.StatusCode == http.StatusServiceUnavailable || + resp.StatusCode == http.StatusGatewayTimeout { + return true + } + return false +} + +func drainBody(resp *http.Response) { + if resp.Body != nil { + io.Copy(io.Discard, resp.Body) + resp.Body.Close() + } +} diff --git a/plugins/notifiers/client.go b/plugins/notifiers/client.go index deb4b27ab..313be0f4b 100644 --- a/plugins/notifiers/client.go +++ b/plugins/notifiers/client.go @@ -4,9 +4,8 @@ import ( "context" "errors" "fmt" - "net/http" - "time" + "github.com/goto/guardian/pkg/http" "github.com/goto/guardian/pkg/log" "github.com/mitchellh/mapstructure" @@ -47,7 +46,7 @@ func NewClient(config *Config, logger log.Logger) (Client, error) { return nil, err } - httpClient := &http.Client{Timeout: 10 * time.Second} + httpClient := http.NewRetryableClient() return slack.NewNotifier(slackConfig, httpClient, logger), nil } From fb37aa287a628e807ba6936de944f6d9bea234fb Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Mon, 25 Mar 2024 16:19:33 +0700 Subject: [PATCH 30/39] chore: update client --- pkg/http/retry.go | 25 +++++++------------------ plugins/notifiers/client.go | 13 +++++++++++-- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/pkg/http/retry.go b/pkg/http/retry.go index 04337091d..72c3a7822 100644 --- a/pkg/http/retry.go +++ b/pkg/http/retry.go @@ -8,23 +8,12 @@ import ( "time" ) -const RetryCount = 3 - -type retryableTransport struct { - transport http.RoundTripper -} - -func NewRetryableClient() *http.Client { - transport := &retryableTransport{ - transport: &http.Transport{}, - } - - return &http.Client{ - Transport: transport, - } +type RetryableTransport struct { + Transport http.RoundTripper + RetryCount int } -func (t *retryableTransport) RoundTrip(req *http.Request) (*http.Response, error) { +func (t *RetryableTransport) RoundTrip(req *http.Request) (*http.Response, error) { // Clone the request body var bodyBytes []byte if req.Body != nil { @@ -32,10 +21,10 @@ func (t *retryableTransport) RoundTrip(req *http.Request) (*http.Response, error req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) } // Send the request - resp, err := t.transport.RoundTrip(req) + resp, err := t.Transport.RoundTrip(req) // Retry logic retries := 0 - for shouldRetry(err, resp) && retries < RetryCount { + for shouldRetry(err, resp) && retries < t.RetryCount { // Wait for the specified backoff period time.Sleep(backoff(retries)) // We're going to retry, consume any response to reuse the connection. @@ -45,7 +34,7 @@ func (t *retryableTransport) RoundTrip(req *http.Request) (*http.Response, error req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) } // Retry the request - resp, err = t.transport.RoundTrip(req) + resp, err = t.Transport.RoundTrip(req) retries++ } // Return the response diff --git a/plugins/notifiers/client.go b/plugins/notifiers/client.go index 313be0f4b..b310d824a 100644 --- a/plugins/notifiers/client.go +++ b/plugins/notifiers/client.go @@ -4,8 +4,10 @@ import ( "context" "errors" "fmt" + "net/http" + "time" - "github.com/goto/guardian/pkg/http" + retryablehttp "github.com/goto/guardian/pkg/http" "github.com/goto/guardian/pkg/log" "github.com/mitchellh/mapstructure" @@ -46,7 +48,14 @@ func NewClient(config *Config, logger log.Logger) (Client, error) { return nil, err } - httpClient := http.NewRetryableClient() + retryableTransport := &retryablehttp.RetryableTransport{ + Transport: &http.Transport{}, + RetryCount: 3, + } + httpClient := &http.Client{ + Timeout: 10 * time.Second, + Transport: retryableTransport, + } return slack.NewNotifier(slackConfig, httpClient, logger), nil } From f67976c544ae1b47dc7f8cb5247499fe39264346 Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Wed, 27 Mar 2024 15:22:08 +0700 Subject: [PATCH 31/39] chore: update round trip flow Co-authored-by: StewartJingga --- pkg/http/retry.go | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/pkg/http/retry.go b/pkg/http/retry.go index 72c3a7822..ef1e4a902 100644 --- a/pkg/http/retry.go +++ b/pkg/http/retry.go @@ -14,30 +14,27 @@ type RetryableTransport struct { } func (t *RetryableTransport) RoundTrip(req *http.Request) (*http.Response, error) { - // Clone the request body var bodyBytes []byte - if req.Body != nil { - bodyBytes, _ = io.ReadAll(req.Body) - req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) + bodyBytes, err := io.ReadAll(req.Body) + if err != nil { + return nil, fmt.Errorf("error reading body: %w", err) } - // Send the request - resp, err := t.Transport.RoundTrip(req) - // Retry logic - retries := 0 + + var resp *http.Response + retries := -1 for shouldRetry(err, resp) && retries < t.RetryCount { - // Wait for the specified backoff period - time.Sleep(backoff(retries)) - // We're going to retry, consume any response to reuse the connection. - drainBody(resp) - // Clone the request body again - if req.Body != nil { - req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) + if retries > -1 { + time.Sleep(backoff(retries)) + // consume any response to reuse the connection. + drainBody(resp) } - // Retry the request + + req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) resp, err = t.Transport.RoundTrip(req) + retries++ } - // Return the response + return resp, err } From 119c44f3c53e9c8db44e7fc8d908a4feafedd01d Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Wed, 27 Mar 2024 15:23:05 +0700 Subject: [PATCH 32/39] chore: update status checking return flow Co-authored-by: StewartJingga --- pkg/http/retry.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pkg/http/retry.go b/pkg/http/retry.go index ef1e4a902..0b555c0d9 100644 --- a/pkg/http/retry.go +++ b/pkg/http/retry.go @@ -47,12 +47,9 @@ func shouldRetry(err error, resp *http.Response) bool { return true } - if resp.StatusCode == http.StatusBadGateway || + return resp.StatusCode == http.StatusBadGateway || resp.StatusCode == http.StatusServiceUnavailable || - resp.StatusCode == http.StatusGatewayTimeout { - return true - } - return false + resp.StatusCode == http.StatusGatewayTimeout } func drainBody(resp *http.Response) { From 3b564816f7880358f910b0084cbeb5890dcd5583 Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Wed, 27 Mar 2024 17:12:15 +0700 Subject: [PATCH 33/39] chore: set http config as configurable --- internal/server/config.yaml | 2 ++ pkg/http/retry.go | 1 + plugins/notifiers/client.go | 24 +++++++++++++++++++----- 3 files changed, 22 insertions(+), 5 deletions(-) diff --git a/internal/server/config.yaml b/internal/server/config.yaml index 134bf86c8..6c40224cf 100644 --- a/internal/server/config.yaml +++ b/internal/server/config.yaml @@ -30,6 +30,8 @@ DB: NOTIFIER: PROVIDER: slack ACCESS_TOKEN: + TIMEOUT_IN_SECONDS: 10 + MAX_RETRY_COUNT: 3 WORKSPACES: - WORKSPACE: goto ACCESS_TOKEN: diff --git a/pkg/http/retry.go b/pkg/http/retry.go index 0b555c0d9..1812c3ac5 100644 --- a/pkg/http/retry.go +++ b/pkg/http/retry.go @@ -2,6 +2,7 @@ package http import ( "bytes" + "fmt" "io" "math" "net/http" diff --git a/plugins/notifiers/client.go b/plugins/notifiers/client.go index b310d824a..ed845602f 100644 --- a/plugins/notifiers/client.go +++ b/plugins/notifiers/client.go @@ -20,7 +20,9 @@ type Client interface { } const ( - ProviderTypeSlack = "slack" + ProviderTypeSlack = "slack" + DefaultRetryCount = 3 + DefaultTimeoutInSeconds = 10 ) // SlackConfig is a map of workspace name to config @@ -34,8 +36,10 @@ type Config struct { Provider string `mapstructure:"provider" validate:"omitempty,oneof=slack"` // slack - AccessToken string `mapstructure:"access_token" validate:"required_without=SlackConfig"` - SlackConfig SlackConfig `mapstructure:"slack_config" validate:"required_without=AccessToken,dive"` + AccessToken string `mapstructure:"access_token" validate:"required_without=SlackConfig"` + SlackConfig SlackConfig `mapstructure:"slack_config" validate:"required_without=AccessToken,dive"` + TimeoutInSeconds int `mapstructure:"timeout_in_seconds"` + MaxRetryCount int `mapstructure:"max_retry_count"` // custom messages Messages domain.NotificationMessages @@ -48,12 +52,22 @@ func NewClient(config *Config, logger log.Logger) (Client, error) { return nil, err } + retryCount := DefaultRetryCount + if config.MaxRetryCount > 0 { + retryCount = config.MaxRetryCount + } + + timeout := DefaultTimeoutInSeconds + if config.TimeoutInSeconds > 0 { + timeout = config.TimeoutInSeconds + } + retryableTransport := &retryablehttp.RetryableTransport{ Transport: &http.Transport{}, - RetryCount: 3, + RetryCount: retryCount, } httpClient := &http.Client{ - Timeout: 10 * time.Second, + Timeout: time.Duration(timeout) * time.Second, Transport: retryableTransport, } From 334ede97cbd6c3e0c7c9e25dbcaa97e323d4e68f Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Mon, 1 Apr 2024 12:25:23 +0700 Subject: [PATCH 34/39] test: added unit test --- pkg/http/retry.go | 18 ++++++--- pkg/http/retry_test.go | 83 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 pkg/http/retry_test.go diff --git a/pkg/http/retry.go b/pkg/http/retry.go index 1812c3ac5..b2e39ea2e 100644 --- a/pkg/http/retry.go +++ b/pkg/http/retry.go @@ -16,18 +16,24 @@ type RetryableTransport struct { func (t *RetryableTransport) RoundTrip(req *http.Request) (*http.Response, error) { var bodyBytes []byte - bodyBytes, err := io.ReadAll(req.Body) - if err != nil { - return nil, fmt.Errorf("error reading body: %w", err) + if req.Body != nil { + bodyBytes, err := io.ReadAll(req.Body) + if err != nil { + return nil, fmt.Errorf("error reading body: %w", err) + } + + req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) } - var resp *http.Response + resp, err := t.Transport.RoundTrip(req) retries := -1 for shouldRetry(err, resp) && retries < t.RetryCount { if retries > -1 { time.Sleep(backoff(retries)) // consume any response to reuse the connection. - drainBody(resp) + if resp != nil { + drainBody(resp) + } } req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) @@ -44,7 +50,7 @@ func backoff(retries int) time.Duration { } func shouldRetry(err error, resp *http.Response) bool { - if err != nil { + if err != nil || resp == nil { return true } diff --git a/pkg/http/retry_test.go b/pkg/http/retry_test.go new file mode 100644 index 000000000..b4f15a483 --- /dev/null +++ b/pkg/http/retry_test.go @@ -0,0 +1,83 @@ +package http + +import ( + "fmt" + "math" + "net/http" + "net/http/httptest" + "testing" + "time" +) + +func TestRetryableTransport_RoundTrip(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path == "/success" { + w.WriteHeader(http.StatusOK) + } else { + w.WriteHeader(http.StatusGatewayTimeout) + } + })) + defer server.Close() + + transport := &RetryableTransport{ + Transport: http.DefaultTransport, + RetryCount: 3, + } + + // Test case 1: Successful request + req, err := http.NewRequest(http.MethodGet, server.URL+"/success", nil) + if err != nil { + t.Fatalf("Failed to create request: %v", err) + } + resp, err := transport.RoundTrip(req) + if err != nil { + t.Fatalf("RoundTrip failed: %v", err) + } + if resp.StatusCode != http.StatusOK { + t.Errorf("Unexpected status code: got %d, want %d", resp.StatusCode, http.StatusOK) + } + + // Test case 2: Retry exhausted + req, err = http.NewRequest(http.MethodGet, server.URL+"/failure", nil) + if err != nil { + t.Fatalf("Failed to create request: %v", err) + } + resp, err = transport.RoundTrip(req) + if err != nil { + t.Error("Expected nil but got an error") + } + if resp == nil { + t.Error("Expected an error response but got nil") + } +} + +func TestShouldRetry(t *testing.T) { + // Test case 1: Retry on connection reset error + err := fmt.Errorf("connection reset by peer") + resp := &http.Response{StatusCode: http.StatusInternalServerError} + if !shouldRetry(err, resp) { + t.Error("shouldRetry returned false, expected true for connection reset error") + } + + // Test case 2: Retry on status code 504 + resp = &http.Response{StatusCode: http.StatusGatewayTimeout} + if !shouldRetry(nil, resp) { + t.Error("shouldRetry returned false, expected true for status code 504") + } + + // Test case 3: Do not retry on status code 200 + resp = &http.Response{StatusCode: http.StatusOK} + if shouldRetry(nil, resp) { + t.Error("shouldRetry returned true, expected false for status code 200") + } +} + +func TestBackoff(t *testing.T) { + for i := 0; i < 5; i++ { + backoffDuration := backoff(i) + expectedDuration := time.Duration(math.Pow(2, float64(i))) * time.Second + if backoffDuration != expectedDuration { + t.Errorf("backoff(%d) returned %v, expected %v", i, backoffDuration, expectedDuration) + } + } +} From 22729fecac95171c733a69790e8b14a1b1a54574 Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Mon, 1 Apr 2024 15:33:53 +0700 Subject: [PATCH 35/39] chore: update default retry count domain --- pkg/http/retry.go | 11 ++++++++++- plugins/notifiers/client.go | 8 +------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/pkg/http/retry.go b/pkg/http/retry.go index b2e39ea2e..323235b2b 100644 --- a/pkg/http/retry.go +++ b/pkg/http/retry.go @@ -9,6 +9,10 @@ import ( "time" ) +const ( + DefaultRetryCount = 3 +) + type RetryableTransport struct { Transport http.RoundTripper RetryCount int @@ -25,9 +29,14 @@ func (t *RetryableTransport) RoundTrip(req *http.Request) (*http.Response, error req.Body = io.NopCloser(bytes.NewBuffer(bodyBytes)) } + retryCount := t.RetryCount + if t.RetryCount <= 0 { + retryCount = DefaultRetryCount + } + resp, err := t.Transport.RoundTrip(req) retries := -1 - for shouldRetry(err, resp) && retries < t.RetryCount { + for shouldRetry(err, resp) && retries < retryCount { if retries > -1 { time.Sleep(backoff(retries)) // consume any response to reuse the connection. diff --git a/plugins/notifiers/client.go b/plugins/notifiers/client.go index ed845602f..899f39622 100644 --- a/plugins/notifiers/client.go +++ b/plugins/notifiers/client.go @@ -21,7 +21,6 @@ type Client interface { const ( ProviderTypeSlack = "slack" - DefaultRetryCount = 3 DefaultTimeoutInSeconds = 10 ) @@ -52,11 +51,6 @@ func NewClient(config *Config, logger log.Logger) (Client, error) { return nil, err } - retryCount := DefaultRetryCount - if config.MaxRetryCount > 0 { - retryCount = config.MaxRetryCount - } - timeout := DefaultTimeoutInSeconds if config.TimeoutInSeconds > 0 { timeout = config.TimeoutInSeconds @@ -64,7 +58,7 @@ func NewClient(config *Config, logger log.Logger) (Client, error) { retryableTransport := &retryablehttp.RetryableTransport{ Transport: &http.Transport{}, - RetryCount: retryCount, + RetryCount: config.MaxRetryCount, } httpClient := &http.Client{ Timeout: time.Duration(timeout) * time.Second, From 0a95bb2ca77d93839f9524342a172a1f34ec471b Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Mon, 1 Apr 2024 15:55:08 +0700 Subject: [PATCH 36/39] chore: update client http timeout --- plugins/notifiers/client.go | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/plugins/notifiers/client.go b/plugins/notifiers/client.go index 899f39622..4d0fa9a8d 100644 --- a/plugins/notifiers/client.go +++ b/plugins/notifiers/client.go @@ -20,8 +20,7 @@ type Client interface { } const ( - ProviderTypeSlack = "slack" - DefaultTimeoutInSeconds = 10 + ProviderTypeSlack = "slack" ) // SlackConfig is a map of workspace name to config @@ -51,17 +50,12 @@ func NewClient(config *Config, logger log.Logger) (Client, error) { return nil, err } - timeout := DefaultTimeoutInSeconds - if config.TimeoutInSeconds > 0 { - timeout = config.TimeoutInSeconds - } - retryableTransport := &retryablehttp.RetryableTransport{ Transport: &http.Transport{}, RetryCount: config.MaxRetryCount, } httpClient := &http.Client{ - Timeout: time.Duration(timeout) * time.Second, + Timeout: time.Duration(config.TimeoutInSeconds) * time.Second, Transport: retryableTransport, } From 1045865fcb9609c269c622b1a29bac996cbc7c73 Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Mon, 25 Mar 2024 11:56:22 +0700 Subject: [PATCH 37/39] feat(log): sending audit log concurrently --- core/appeal/service.go | 44 +++++++++++++++++++++-------------- core/grant/service.go | 30 +++++++++++++----------- core/policy/service.go | 16 ++++++++----- core/policy/service_test.go | 5 ++++ core/provider/service.go | 24 ++++++++++++------- core/provider/service_test.go | 2 ++ core/resource/service.go | 32 +++++++++++++++---------- 7 files changed, 96 insertions(+), 57 deletions(-) diff --git a/core/appeal/service.go b/core/appeal/service.go index 8bb320ed1..54f5a369f 100644 --- a/core/appeal/service.go +++ b/core/appeal/service.go @@ -355,9 +355,11 @@ func (s *Service) Create(ctx context.Context, appeals []*domain.Appeal, opts ... return fmt.Errorf("inserting appeals into db: %w", err) } - if err := s.auditLogger.Log(ctx, AuditKeyBulkInsert, appeals); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyBulkInsert, appeals); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() for _, a := range appeals { if a.Status == domain.AppealStatusRejected { @@ -624,9 +626,11 @@ func (s *Service) UpdateApproval(ctx context.Context, approvalAction domain.Appr auditKey = AuditKeyApprove } if auditKey != "" { - if err := s.auditLogger.Log(ctx, auditKey, approvalAction); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, auditKey, approvalAction); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() } return appeal, nil @@ -664,11 +668,13 @@ func (s *Service) Cancel(ctx context.Context, id string) (*domain.Appeal, error) return nil, err } - if err := s.auditLogger.Log(ctx, AuditKeyCancel, map[string]interface{}{ - "appeal_id": id, - }); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyCancel, map[string]interface{}{ + "appeal_id": id, + }); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() return appeal, nil } @@ -710,9 +716,11 @@ func (s *Service) AddApprover(ctx context.Context, appealID, approvalID, email s } approval.Approvers = append(approval.Approvers, email) - if err := s.auditLogger.Log(ctx, AuditKeyAddApprover, approval); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyAddApprover, approval); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() duration := domain.PermanentDurationLabel if !appeal.IsDurationEmpty() { @@ -804,9 +812,11 @@ func (s *Service) DeleteApprover(ctx context.Context, appealID, approvalID, emai } approval.Approvers = newApprovers - if err := s.auditLogger.Log(ctx, AuditKeyDeleteApprover, approval); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyDeleteApprover, approval); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() return appeal, nil } diff --git a/core/grant/service.go b/core/grant/service.go index d2962c7bf..d81a10ebd 100644 --- a/core/grant/service.go +++ b/core/grant/service.go @@ -131,13 +131,15 @@ func (s *Service) Update(ctx context.Context, payload *domain.Grant) error { *payload = *grantDetails s.logger.Info(ctx, "grant updated", "grant_id", grantDetails.ID, "updatedGrant", updatedGrant) - if err := s.auditLogger.Log(ctx, AuditKeyUpdate, map[string]interface{}{ - "grant_id": grantDetails.ID, - "payload": updatedGrant, - "updated_grant": payload, - }); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyUpdate, map[string]interface{}{ + "grant_id": grantDetails.ID, + "payload": updatedGrant, + "updated_grant": payload, + }); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() if previousOwner != updatedGrant.Owner { go func() { @@ -249,12 +251,14 @@ func (s *Service) Revoke(ctx context.Context, id, actor, reason string, opts ... s.logger.Info(ctx, "grant revoked", "grant_id", id) - if err := s.auditLogger.Log(ctx, AuditKeyRevoke, map[string]interface{}{ - "grant_id": id, - "reason": reason, - }); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyRevoke, map[string]interface{}{ + "grant_id": id, + "reason": reason, + }); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() return grant, nil } diff --git a/core/policy/service.go b/core/policy/service.go index 360e132c2..6aac9f373 100644 --- a/core/policy/service.go +++ b/core/policy/service.go @@ -110,9 +110,11 @@ func (s *Service) Create(ctx context.Context, p *domain.Policy) error { return err } - if err := s.auditLogger.Log(ctx, AuditKeyPolicyCreate, p); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyPolicyCreate, p); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() } if p.HasIAMConfig() { @@ -196,9 +198,11 @@ func (s *Service) Update(ctx context.Context, p *domain.Policy) error { return err } - if err := s.auditLogger.Log(ctx, AuditKeyPolicyUpdate, p); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyPolicyUpdate, p); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() } if p.HasIAMConfig() { diff --git a/core/policy/service_test.go b/core/policy/service_test.go index 3c72dcc26..3ae7897d3 100644 --- a/core/policy/service_test.go +++ b/core/policy/service_test.go @@ -4,6 +4,7 @@ import ( "context" "errors" "testing" + "time" "github.com/go-playground/validator/v10" "github.com/google/uuid" @@ -364,6 +365,7 @@ func (s *ServiceTestSuite) TestCreate() { actualError := s.service.Create(context.Background(), p) + time.Sleep(time.Millisecond) s.Nil(actualError) s.Equal(expectedVersion, p.Version) s.mockPolicyRepository.AssertExpectations(s.T()) @@ -380,6 +382,7 @@ func (s *ServiceTestSuite) TestCreate() { s.Nil(actualError) s.mockPolicyRepository.AssertExpectations(s.T()) + time.Sleep(time.Millisecond) s.mockAuditLogger.AssertExpectations(s.T()) }) @@ -391,6 +394,7 @@ func (s *ServiceTestSuite) TestCreate() { s.Nil(actualError) s.mockPolicyRepository.AssertNotCalled(s.T(), "Create") + time.Sleep(time.Millisecond) s.mockAuditLogger.AssertNotCalled(s.T(), "Log") }) }) @@ -758,6 +762,7 @@ func (s *ServiceTestSuite) TestUpdate() { s.service.Update(context.Background(), p) s.mockPolicyRepository.AssertExpectations(s.T()) + time.Sleep(time.Millisecond) s.mockAuditLogger.AssertExpectations(s.T()) s.Equal(expectedNewVersion, p.Version) }) diff --git a/core/provider/service.go b/core/provider/service.go index 884bb6e47..d4e48a2e8 100644 --- a/core/provider/service.go +++ b/core/provider/service.go @@ -142,9 +142,11 @@ func (s *Service) Create(ctx context.Context, p *domain.Provider) error { return err } - if err := s.auditLogger.Log(ctx, AuditKeyCreate, p); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyCreate, p); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() } else { s.logger.Info(ctx, "dry run enabled, skipping provider creation", "provider_urn", p.URN) } @@ -223,9 +225,11 @@ func (s *Service) Update(ctx context.Context, p *domain.Provider) error { return err } - if err := s.auditLogger.Log(ctx, AuditKeyUpdate, p); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyUpdate, p); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() } else { s.logger.Info(ctx, "dry run enabled, skipping provider update", "provider_urn", p.URN) } @@ -470,9 +474,11 @@ func (s *Service) Delete(ctx context.Context, id string) error { } s.logger.Info(ctx, "provider deleted", "provider", id) - if err := s.auditLogger.Log(ctx, AuditKeyDelete, p); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyDelete, p); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() return nil } diff --git a/core/provider/service_test.go b/core/provider/service_test.go index 148c55317..f0af60a30 100644 --- a/core/provider/service_test.go +++ b/core/provider/service_test.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "testing" + "time" "github.com/go-playground/validator/v10" "github.com/google/go-cmp/cmp" @@ -141,6 +142,7 @@ func (s *ServiceTestSuite) TestCreate() { s.Nil(actualError) s.mockProviderRepository.AssertExpectations(s.T()) + time.Sleep(time.Millisecond) s.mockAuditLogger.AssertExpectations(s.T()) }) diff --git a/core/resource/service.go b/core/resource/service.go index 47de14faf..dccbe5e89 100644 --- a/core/resource/service.go +++ b/core/resource/service.go @@ -78,9 +78,11 @@ func (s *Service) BulkUpsert(ctx context.Context, resources []*domain.Resource) return err } - if err := s.auditLogger.Log(ctx, AuditKeyResoruceBulkUpsert, resources); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyResoruceBulkUpsert, resources); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() return nil } @@ -119,9 +121,11 @@ func (s *Service) Update(ctx context.Context, r *domain.Resource) error { r.UpdatedAt = res.UpdatedAt - if err := s.auditLogger.Log(ctx, AuditKeyResourceUpdate, r); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyResourceUpdate, r); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() return nil } @@ -160,9 +164,11 @@ func (s *Service) Delete(ctx context.Context, id string) error { } s.logger.Info(ctx, "resource deleted", "resource", id) - if err := s.auditLogger.Log(ctx, AuditKeyResourceDelete, map[string]interface{}{"id": id}); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyResourceDelete, map[string]interface{}{"id": id}); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() return nil } @@ -174,9 +180,11 @@ func (s *Service) BatchDelete(ctx context.Context, ids []string) error { } s.logger.Info(ctx, "resources deleted", "resources", len(ids)) - if err := s.auditLogger.Log(ctx, AuditKeyResourceBatchDelete, map[string]interface{}{"ids": ids}); err != nil { - s.logger.Error(ctx, "failed to record audit log", "error", err) - } + go func() { + if err := s.auditLogger.Log(ctx, AuditKeyResourceBatchDelete, map[string]interface{}{"ids": ids}); err != nil { + s.logger.Error(ctx, "failed to record audit log", "error", err) + } + }() return nil } From 689c5b9528deb540778fbedbe6ad28f438c09fa7 Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Mon, 25 Mar 2024 13:23:32 +0700 Subject: [PATCH 38/39] test: update test --- core/policy/service_test.go | 6 ------ core/provider/service_test.go | 3 --- 2 files changed, 9 deletions(-) diff --git a/core/policy/service_test.go b/core/policy/service_test.go index 3ae7897d3..f48267eef 100644 --- a/core/policy/service_test.go +++ b/core/policy/service_test.go @@ -365,11 +365,9 @@ func (s *ServiceTestSuite) TestCreate() { actualError := s.service.Create(context.Background(), p) - time.Sleep(time.Millisecond) s.Nil(actualError) s.Equal(expectedVersion, p.Version) s.mockPolicyRepository.AssertExpectations(s.T()) - s.mockAuditLogger.AssertExpectations(s.T()) }) s.Run("should pass the model from the param", func() { @@ -394,8 +392,6 @@ func (s *ServiceTestSuite) TestCreate() { s.Nil(actualError) s.mockPolicyRepository.AssertNotCalled(s.T(), "Create") - time.Sleep(time.Millisecond) - s.mockAuditLogger.AssertNotCalled(s.T(), "Log") }) }) } @@ -762,8 +758,6 @@ func (s *ServiceTestSuite) TestUpdate() { s.service.Update(context.Background(), p) s.mockPolicyRepository.AssertExpectations(s.T()) - time.Sleep(time.Millisecond) - s.mockAuditLogger.AssertExpectations(s.T()) s.Equal(expectedNewVersion, p.Version) }) diff --git a/core/provider/service_test.go b/core/provider/service_test.go index f0af60a30..016b5332d 100644 --- a/core/provider/service_test.go +++ b/core/provider/service_test.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "testing" - "time" "github.com/go-playground/validator/v10" "github.com/google/go-cmp/cmp" @@ -142,8 +141,6 @@ func (s *ServiceTestSuite) TestCreate() { s.Nil(actualError) s.mockProviderRepository.AssertExpectations(s.T()) - time.Sleep(time.Millisecond) - s.mockAuditLogger.AssertExpectations(s.T()) }) s.Run("with dryRun true", func() { From e64a471c21662418b8615d356255c899234efa4d Mon Sep 17 00:00:00 2001 From: Muhammad Idil Haq Amir Date: Mon, 25 Mar 2024 13:43:36 +0700 Subject: [PATCH 39/39] test: fix test --- core/appeal/service_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/core/appeal/service_test.go b/core/appeal/service_test.go index 8071e6f28..2cc7bae8a 100644 --- a/core/appeal/service_test.go +++ b/core/appeal/service_test.go @@ -2409,7 +2409,6 @@ func (s *ServiceTestSuite) TestUpdateApproval() { s.mockRepository.AssertExpectations(s.T()) s.mockPolicyService.AssertExpectations(s.T()) s.mockGrantService.AssertExpectations(s.T()) - s.mockAuditLogger.AssertExpectations(s.T()) s.Nil(actualError) })