diff --git a/acl/authorizer.go b/acl/authorizer.go index b0e5326bc8..6842283b18 100644 --- a/acl/authorizer.go +++ b/acl/authorizer.go @@ -335,6 +335,24 @@ func (a AllowAuthorizer) MeshWriteAllowed(ctx *AuthorizerContext) error { return nil } +// PeeringReadAllowed determines if the read-only Consul peering functions +// can be used. +func (a AllowAuthorizer) PeeringReadAllowed(ctx *AuthorizerContext) error { + if a.Authorizer.PeeringRead(ctx) != Allow { + return PermissionDeniedByACLUnnamed(a, ctx, ResourcePeering, AccessRead) + } + return nil +} + +// PeeringWriteAllowed determines if the state-changing Consul peering +// functions can be used. +func (a AllowAuthorizer) PeeringWriteAllowed(ctx *AuthorizerContext) error { + if a.Authorizer.PeeringWrite(ctx) != Allow { + return PermissionDeniedByACLUnnamed(a, ctx, ResourcePeering, AccessWrite) + } + return nil +} + // NodeReadAllowed checks for permission to read (discover) a given node. func (a AllowAuthorizer) NodeReadAllowed(name string, ctx *AuthorizerContext) error { if a.Authorizer.NodeRead(name, ctx) != Allow { diff --git a/agent/cache-types/trust_bundle.go b/agent/cache-types/trust_bundle.go index 16b8f204bc..48dad64372 100644 --- a/agent/cache-types/trust_bundle.go +++ b/agent/cache-types/trust_bundle.go @@ -3,16 +3,53 @@ package cachetype import ( "context" "fmt" + "strconv" + "time" + "github.com/mitchellh/hashstructure" "google.golang.org/grpc" "github.com/hashicorp/consul/agent/cache" + external "github.com/hashicorp/consul/agent/grpc-external" + "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto/pbpeering" ) // Recommended name for registration. const TrustBundleReadName = "peer-trust-bundle" +type TrustBundleReadRequest struct { + Request *pbpeering.TrustBundleReadRequest + structs.QueryOptions +} + +func (r *TrustBundleReadRequest) CacheInfo() cache.RequestInfo { + info := cache.RequestInfo{ + Token: r.Token, + Datacenter: "", + MinIndex: 0, + Timeout: 0, + MustRevalidate: false, + + // OPTIMIZE(peering): Cache.notifyPollingQuery polls at this interval. We need to revisit how that polling works. + // Using an exponential backoff when the result hasn't changed may be preferable. + MaxAge: 1 * time.Second, + } + + v, err := hashstructure.Hash([]interface{}{ + r.Request.Partition, + r.Request.Name, + }, nil) + if err == nil { + // If there is an error, we don't set the key. A blank key forces + // no cache for this request so the request is forwarded directly + // to the server. + info.Key = strconv.FormatUint(v, 10) + } + + return info +} + // TrustBundle supports fetching discovering service instances via prepared // queries. type TrustBundle struct { @@ -33,14 +70,20 @@ func (t *TrustBundle) Fetch(_ cache.FetchOptions, req cache.Request) (cache.Fetc // The request should be a TrustBundleReadRequest. // We do not need to make a copy of this request type like in other cache types // because the RequestInfo is synthetic. - reqReal, ok := req.(*pbpeering.TrustBundleReadRequest) + reqReal, ok := req.(*TrustBundleReadRequest) if !ok { return result, fmt.Errorf( "Internal cache failure: request wrong type: %T", req) } + // Always allow stale - there's no point in hitting leader if the request is + // going to be served from cache and end up arbitrarily stale anyway. This + // allows cached service-discover to automatically read scale across all + // servers too. + reqReal.QueryOptions.SetAllowStale(true) + // Fetch - reply, err := t.Client.TrustBundleRead(context.Background(), reqReal) + reply, err := t.Client.TrustBundleRead(external.ContextWithToken(context.Background(), reqReal.Token), reqReal.Request) if err != nil { return result, err } diff --git a/agent/cache-types/trust_bundle_test.go b/agent/cache-types/trust_bundle_test.go index fa3d016a29..ee03838aaa 100644 --- a/agent/cache-types/trust_bundle_test.go +++ b/agent/cache-types/trust_bundle_test.go @@ -33,8 +33,10 @@ func TestTrustBundle(t *testing.T) { Return(resp, nil) // Fetch and assert against the result. - result, err := typ.Fetch(cache.FetchOptions{}, &pbpeering.TrustBundleReadRequest{ - Name: "foo", + result, err := typ.Fetch(cache.FetchOptions{}, &TrustBundleReadRequest{ + Request: &pbpeering.TrustBundleReadRequest{ + Name: "foo", + }, }) require.NoError(t, err) require.Equal(t, cache.FetchResult{ @@ -82,7 +84,9 @@ func TestTrustBundle_MultipleUpdates(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) t.Cleanup(cancel) - err := c.Notify(ctx, TrustBundleReadName, &pbpeering.TrustBundleReadRequest{Name: "foo"}, "updates", ch) + err := c.Notify(ctx, TrustBundleReadName, &TrustBundleReadRequest{ + Request: &pbpeering.TrustBundleReadRequest{Name: "foo"}, + }, "updates", ch) require.NoError(t, err) i := uint64(1) diff --git a/agent/cache-types/trust_bundles.go b/agent/cache-types/trust_bundles.go index 5b4bbcc136..70c63cb4be 100644 --- a/agent/cache-types/trust_bundles.go +++ b/agent/cache-types/trust_bundles.go @@ -3,16 +3,55 @@ package cachetype import ( "context" "fmt" + "strconv" + "time" + "github.com/mitchellh/hashstructure" "google.golang.org/grpc" "github.com/hashicorp/consul/agent/cache" + external "github.com/hashicorp/consul/agent/grpc-external" + "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto/pbpeering" ) // Recommended name for registration. const TrustBundleListName = "trust-bundles" +type TrustBundleListRequest struct { + Request *pbpeering.TrustBundleListByServiceRequest + structs.QueryOptions +} + +func (r *TrustBundleListRequest) CacheInfo() cache.RequestInfo { + info := cache.RequestInfo{ + Token: r.Token, + Datacenter: "", + MinIndex: 0, + Timeout: 0, + MustRevalidate: false, + + // OPTIMIZE(peering): Cache.notifyPollingQuery polls at this interval. We need to revisit how that polling works. + // Using an exponential backoff when the result hasn't changed may be preferable. + MaxAge: 1 * time.Second, + } + + v, err := hashstructure.Hash([]interface{}{ + r.Request.Partition, + r.Request.Namespace, + r.Request.ServiceName, + r.Request.Kind, + }, nil) + if err == nil { + // If there is an error, we don't set the key. A blank key forces + // no cache for this request so the request is forwarded directly + // to the server. + info.Key = strconv.FormatUint(v, 10) + } + + return info +} + // TrustBundles supports fetching discovering service instances via prepared // queries. type TrustBundles struct { @@ -30,17 +69,23 @@ type TrustBundleLister interface { func (t *TrustBundles) Fetch(_ cache.FetchOptions, req cache.Request) (cache.FetchResult, error) { var result cache.FetchResult - // The request should be a TrustBundleListByServiceRequest. + // The request should be a TrustBundleListRequest. // We do not need to make a copy of this request type like in other cache types // because the RequestInfo is synthetic. - reqReal, ok := req.(*pbpeering.TrustBundleListByServiceRequest) + reqReal, ok := req.(*TrustBundleListRequest) if !ok { return result, fmt.Errorf( "Internal cache failure: request wrong type: %T", req) } + // Always allow stale - there's no point in hitting leader if the request is + // going to be served from cache and end up arbitrarily stale anyway. This + // allows cached service-discover to automatically read scale across all + // servers too. + reqReal.QueryOptions.SetAllowStale(true) + // Fetch - reply, err := t.Client.TrustBundleListByService(context.Background(), reqReal) + reply, err := t.Client.TrustBundleListByService(external.ContextWithToken(context.Background(), reqReal.Token), reqReal.Request) if err != nil { return result, err } diff --git a/agent/cache-types/trust_bundles_test.go b/agent/cache-types/trust_bundles_test.go index d5fbd6f501..09d8a80bcb 100644 --- a/agent/cache-types/trust_bundles_test.go +++ b/agent/cache-types/trust_bundles_test.go @@ -36,8 +36,10 @@ func TestTrustBundles(t *testing.T) { Return(resp, nil) // Fetch and assert against the result. - result, err := typ.Fetch(cache.FetchOptions{}, &pbpeering.TrustBundleListByServiceRequest{ - ServiceName: "foo", + result, err := typ.Fetch(cache.FetchOptions{}, &TrustBundleListRequest{ + Request: &pbpeering.TrustBundleListByServiceRequest{ + ServiceName: "foo", + }, }) require.NoError(t, err) require.Equal(t, cache.FetchResult{ @@ -85,7 +87,9 @@ func TestTrustBundles_MultipleUpdates(t *testing.T) { ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) t.Cleanup(cancel) - err := c.Notify(ctx, TrustBundleListName, &pbpeering.TrustBundleListByServiceRequest{ServiceName: "foo"}, "updates", ch) + err := c.Notify(ctx, TrustBundleListName, &TrustBundleListRequest{ + Request: &pbpeering.TrustBundleListByServiceRequest{ServiceName: "foo"}, + }, "updates", ch) require.NoError(t, err) i := uint64(1) diff --git a/agent/consul/peering_backend.go b/agent/consul/peering_backend.go index 589b4e95be..1ab1b5c957 100644 --- a/agent/consul/peering_backend.go +++ b/agent/consul/peering_backend.go @@ -7,6 +7,8 @@ import ( "strconv" "sync" + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/acl/resolver" "github.com/hashicorp/consul/agent/consul/stream" "github.com/hashicorp/consul/agent/grpc-external/services/peerstream" "github.com/hashicorp/consul/agent/rpc/peering" @@ -160,3 +162,7 @@ func (b *PeeringBackend) CatalogDeregister(req *structs.DeregisterRequest) error _, err := b.srv.leaderRaftApply("Catalog.Deregister", structs.DeregisterRequestType, req) return err } + +func (b *PeeringBackend) ResolveTokenAndDefaultMeta(token string, entMeta *acl.EnterpriseMeta, authzCtx *acl.AuthorizerContext) (resolver.Result, error) { + return b.srv.ResolveTokenAndDefaultMeta(token, entMeta, authzCtx) +} diff --git a/agent/consul/peering_backend_oss_test.go b/agent/consul/peering_backend_oss_test.go index 5996690eae..3c120d26f7 100644 --- a/agent/consul/peering_backend_oss_test.go +++ b/agent/consul/peering_backend_oss_test.go @@ -42,8 +42,7 @@ func TestPeeringBackend_RejectsPartition(t *testing.T) { peeringClient := pbpeering.NewPeeringServiceClient(conn) req := pbpeering.GenerateTokenRequest{ - Datacenter: "dc1", - Partition: "test", + Partition: "test", } _, err = peeringClient.GenerateToken(ctx, &req) require.Error(t, err) @@ -77,9 +76,8 @@ func TestPeeringBackend_IgnoresDefaultPartition(t *testing.T) { peeringClient := pbpeering.NewPeeringServiceClient(conn) req := pbpeering.GenerateTokenRequest{ - Datacenter: "dc1", - PeerName: "my-peer", - Partition: "DeFaUlT", + PeerName: "my-peer", + Partition: "DeFaUlT", } _, err = peeringClient.GenerateToken(ctx, &req) require.NoError(t, err) diff --git a/agent/consul/peering_backend_test.go b/agent/consul/peering_backend_test.go index 6d6344a295..fc73ba53d0 100644 --- a/agent/consul/peering_backend_test.go +++ b/agent/consul/peering_backend_test.go @@ -15,43 +15,6 @@ import ( "github.com/hashicorp/consul/testrpc" ) -func TestPeeringBackend_DoesNotForwardToDifferentDC(t *testing.T) { - if testing.Short() { - t.Skip("too slow for testing.Short") - } - - t.Parallel() - _, s1 := testServerDC(t, "dc1") - _, s2 := testServerDC(t, "dc2") - - joinWAN(t, s2, s1) - - testrpc.WaitForLeader(t, s1.RPC, "dc1") - testrpc.WaitForLeader(t, s2.RPC, "dc2") - - // make a grpc client to dial s2 directly - ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second) - t.Cleanup(cancel) - - conn, err := gogrpc.DialContext(ctx, s2.config.RPCAddr.String(), - gogrpc.WithContextDialer(newServerDialer(s2.config.RPCAddr.String())), - gogrpc.WithInsecure(), - gogrpc.WithBlock()) - require.NoError(t, err) - t.Cleanup(func() { conn.Close() }) - - peeringClient := pbpeering.NewPeeringServiceClient(conn) - - // GenerateToken request should fail against dc1, because we are dialing dc2. The GenerateToken request should never be forwarded across datacenters. - req := pbpeering.GenerateTokenRequest{ - PeerName: "peer1-usw1", - Datacenter: "dc1", - } - _, err = peeringClient.GenerateToken(ctx, &req) - require.Error(t, err) - require.Contains(t, err.Error(), "requests to generate peering tokens cannot be forwarded to remote datacenters") -} - func TestPeeringBackend_ForwardToLeader(t *testing.T) { t.Parallel() @@ -86,8 +49,7 @@ func TestPeeringBackend_ForwardToLeader(t *testing.T) { testutil.RunStep(t, "forward a write", func(t *testing.T) { // Do the grpc Write call to server2 req := pbpeering.GenerateTokenRequest{ - Datacenter: "dc1", - PeerName: "foo", + PeerName: "foo", } _, err := peeringClient.GenerateToken(ctx, &req) require.NoError(t, err) diff --git a/agent/peering_endpoint.go b/agent/peering_endpoint.go index 0d120830e2..6ef7167b26 100644 --- a/agent/peering_endpoint.go +++ b/agent/peering_endpoint.go @@ -6,6 +6,7 @@ import ( "strings" "github.com/hashicorp/consul/acl" + external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/lib" "github.com/hashicorp/consul/proto/pbpeering" @@ -32,17 +33,20 @@ func (s *HTTPHandlers) PeeringEndpoint(resp http.ResponseWriter, req *http.Reque // peeringRead fetches a peering that matches the name and partition. // This assumes that the name and partition parameters are valid func (s *HTTPHandlers) peeringRead(resp http.ResponseWriter, req *http.Request, name string) (interface{}, error) { - args := pbpeering.PeeringReadRequest{ - Name: name, - Datacenter: s.agent.config.Datacenter, - } var entMeta acl.EnterpriseMeta if err := s.parseEntMetaPartition(req, &entMeta); err != nil { return nil, err } - args.Partition = entMeta.PartitionOrEmpty() + args := pbpeering.PeeringReadRequest{ + Name: name, + Partition: entMeta.PartitionOrEmpty(), + } - result, err := s.agent.rpcClientPeering.PeeringRead(req.Context(), &args) + var token string + s.parseToken(req, &token) + ctx := external.ContextWithToken(req.Context(), token) + + result, err := s.agent.rpcClientPeering.PeeringRead(ctx, &args) if err != nil { return nil, err } @@ -55,16 +59,19 @@ func (s *HTTPHandlers) peeringRead(resp http.ResponseWriter, req *http.Request, // PeeringList fetches all peerings in the datacenter in OSS or in a given partition in Consul Enterprise. func (s *HTTPHandlers) PeeringList(resp http.ResponseWriter, req *http.Request) (interface{}, error) { - args := pbpeering.PeeringListRequest{ - Datacenter: s.agent.config.Datacenter, - } var entMeta acl.EnterpriseMeta if err := s.parseEntMetaPartition(req, &entMeta); err != nil { return nil, err } - args.Partition = entMeta.PartitionOrEmpty() + args := pbpeering.PeeringListRequest{ + Partition: entMeta.PartitionOrEmpty(), + } - pbresp, err := s.agent.rpcClientPeering.PeeringList(req.Context(), &args) + var token string + s.parseToken(req, &token) + ctx := external.ContextWithToken(req.Context(), token) + + pbresp, err := s.agent.rpcClientPeering.PeeringList(ctx, &args) if err != nil { return nil, err } @@ -79,14 +86,12 @@ func (s *HTTPHandlers) PeeringGenerateToken(resp http.ResponseWriter, req *http. return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: "The peering arguments must be provided in the body"} } - apiRequest := &api.PeeringGenerateTokenRequest{ - Datacenter: s.agent.config.Datacenter, - } - if err := lib.DecodeJSON(req.Body, apiRequest); err != nil { + var apiRequest api.PeeringGenerateTokenRequest + if err := lib.DecodeJSON(req.Body, &apiRequest); err != nil { return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: fmt.Sprintf("Body decoding failed: %v", err)} } - args := pbpeering.NewGenerateTokenRequestFromAPI(apiRequest) + args := pbpeering.NewGenerateTokenRequestFromAPI(&apiRequest) if args.PeerName == "" { return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: "PeerName is required in the payload when generating a new peering token."} } @@ -99,7 +104,11 @@ func (s *HTTPHandlers) PeeringGenerateToken(resp http.ResponseWriter, req *http. args.Partition = entMeta.PartitionOrEmpty() } - out, err := s.agent.rpcClientPeering.GenerateToken(req.Context(), args) + var token string + s.parseToken(req, &token) + ctx := external.ContextWithToken(req.Context(), token) + + out, err := s.agent.rpcClientPeering.GenerateToken(ctx, args) if err != nil { return nil, err } @@ -114,18 +123,15 @@ func (s *HTTPHandlers) PeeringEstablish(resp http.ResponseWriter, req *http.Requ return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: "The peering arguments must be provided in the body"} } - apiRequest := &api.PeeringEstablishRequest{ - Datacenter: s.agent.config.Datacenter, - } - if err := lib.DecodeJSON(req.Body, apiRequest); err != nil { + var apiRequest api.PeeringEstablishRequest + if err := lib.DecodeJSON(req.Body, &apiRequest); err != nil { return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: fmt.Sprintf("Body decoding failed: %v", err)} } - args := pbpeering.NewEstablishRequestFromAPI(apiRequest) + args := pbpeering.NewEstablishRequestFromAPI(&apiRequest) if args.PeerName == "" { return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: "PeerName is required in the payload when establishing a peering."} } - if args.PeeringToken == "" { return nil, HTTPError{StatusCode: http.StatusBadRequest, Reason: "PeeringToken is required in the payload when establishing a peering."} } @@ -138,7 +144,11 @@ func (s *HTTPHandlers) PeeringEstablish(resp http.ResponseWriter, req *http.Requ args.Partition = entMeta.PartitionOrEmpty() } - out, err := s.agent.rpcClientPeering.Establish(req.Context(), args) + var token string + s.parseToken(req, &token) + ctx := external.ContextWithToken(req.Context(), token) + + out, err := s.agent.rpcClientPeering.Establish(ctx, args) if err != nil { return nil, err } @@ -149,17 +159,20 @@ func (s *HTTPHandlers) PeeringEstablish(resp http.ResponseWriter, req *http.Requ // peeringDelete initiates a deletion for a peering that matches the name and partition. // This assumes that the name and partition parameters are valid. func (s *HTTPHandlers) peeringDelete(resp http.ResponseWriter, req *http.Request, name string) (interface{}, error) { - args := pbpeering.PeeringDeleteRequest{ - Name: name, - Datacenter: s.agent.config.Datacenter, - } var entMeta acl.EnterpriseMeta if err := s.parseEntMetaPartition(req, &entMeta); err != nil { return nil, err } - args.Partition = entMeta.PartitionOrEmpty() + args := pbpeering.PeeringDeleteRequest{ + Name: name, + Partition: entMeta.PartitionOrEmpty(), + } - _, err := s.agent.rpcClientPeering.PeeringDelete(req.Context(), &args) + var token string + s.parseToken(req, &token) + ctx := external.ContextWithToken(req.Context(), token) + + _, err := s.agent.rpcClientPeering.PeeringDelete(ctx, &args) if err != nil { return nil, err } diff --git a/agent/proxycfg-glue/glue.go b/agent/proxycfg-glue/glue.go index 04451c3d20..86badf67e4 100644 --- a/agent/proxycfg-glue/glue.go +++ b/agent/proxycfg-glue/glue.go @@ -3,6 +3,7 @@ package proxycfgglue import ( "context" + "github.com/hashicorp/consul/proto/pbpeering" "github.com/hashicorp/go-memdb" "github.com/hashicorp/consul/acl" @@ -14,7 +15,6 @@ import ( "github.com/hashicorp/consul/agent/consul/watch" "github.com/hashicorp/consul/agent/proxycfg" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/proto/pbpeering" ) // Store is the state store interface required for server-local data sources. diff --git a/agent/proxycfg-glue/trust_bundle.go b/agent/proxycfg-glue/trust_bundle.go index 4ce42591b7..455d7dc9ff 100644 --- a/agent/proxycfg-glue/trust_bundle.go +++ b/agent/proxycfg-glue/trust_bundle.go @@ -19,7 +19,7 @@ import ( // CacheTrustBundle satisfies the proxycfg.TrustBundle interface by sourcing // data from the agent cache. func CacheTrustBundle(c *cache.Cache) proxycfg.TrustBundle { - return &cacheProxyDataSource[*pbpeering.TrustBundleReadRequest]{c, cachetype.TrustBundleReadName} + return &cacheProxyDataSource[*cachetype.TrustBundleReadRequest]{c, cachetype.TrustBundleReadName} } // ServerTrustBundle satisfies the proxycfg.TrustBundle interface by sourcing @@ -32,13 +32,13 @@ type serverTrustBundle struct { deps ServerDataSourceDeps } -func (s *serverTrustBundle) Notify(ctx context.Context, req *pbpeering.TrustBundleReadRequest, correlationID string, ch chan<- proxycfg.UpdateEvent) error { +func (s *serverTrustBundle) Notify(ctx context.Context, req *cachetype.TrustBundleReadRequest, correlationID string, ch chan<- proxycfg.UpdateEvent) error { // TODO(peering): ACL check. return watch.ServerLocalNotify(ctx, correlationID, s.deps.GetStore, func(ws memdb.WatchSet, store Store) (uint64, *pbpeering.TrustBundleReadResponse, error) { index, bundle, err := store.PeeringTrustBundleRead(ws, state.Query{ - Value: req.Name, - EnterpriseMeta: *structs.NodeEnterpriseMetaInPartition(req.Partition), + Value: req.Request.Name, + EnterpriseMeta: *structs.NodeEnterpriseMetaInPartition(req.Request.Partition), }) if err != nil { return 0, nil, err @@ -55,7 +55,7 @@ func (s *serverTrustBundle) Notify(ctx context.Context, req *pbpeering.TrustBund // CacheTrustBundleList satisfies the proxycfg.TrustBundleList interface by sourcing // data from the agent cache. func CacheTrustBundleList(c *cache.Cache) proxycfg.TrustBundleList { - return &cacheProxyDataSource[*pbpeering.TrustBundleListByServiceRequest]{c, cachetype.TrustBundleListName} + return &cacheProxyDataSource[*cachetype.TrustBundleListRequest]{c, cachetype.TrustBundleListName} } // ServerTrustBundleList satisfies the proxycfg.TrustBundle interface by @@ -68,8 +68,8 @@ type serverTrustBundleList struct { deps ServerDataSourceDeps } -func (s *serverTrustBundleList) Notify(ctx context.Context, req *pbpeering.TrustBundleListByServiceRequest, correlationID string, ch chan<- proxycfg.UpdateEvent) error { - entMeta := acl.NewEnterpriseMetaWithPartition(req.Partition, req.Namespace) +func (s *serverTrustBundleList) Notify(ctx context.Context, req *cachetype.TrustBundleListRequest, correlationID string, ch chan<- proxycfg.UpdateEvent) error { + entMeta := acl.NewEnterpriseMetaWithPartition(req.Request.Partition, req.Request.Namespace) // TODO(peering): ACL check. return watch.ServerLocalNotify(ctx, correlationID, s.deps.GetStore, @@ -80,11 +80,11 @@ func (s *serverTrustBundleList) Notify(ctx context.Context, req *pbpeering.Trust err error ) switch { - case req.ServiceName != "": - index, bundles, err = store.TrustBundleListByService(ws, req.ServiceName, s.deps.Datacenter, entMeta) - case req.Kind == string(structs.ServiceKindMeshGateway): + case req.Request.Kind == string(structs.ServiceKindMeshGateway): index, bundles, err = store.PeeringTrustBundleList(ws, entMeta) - case req.Kind != "": + case req.Request.ServiceName != "": + index, bundles, err = store.TrustBundleListByService(ws, req.Request.ServiceName, s.deps.Datacenter, entMeta) + case req.Request.Kind != "": err = errors.New("kind must be mesh-gateway if set") default: err = errors.New("one of service or kind is required") diff --git a/agent/proxycfg-glue/trust_bundle_test.go b/agent/proxycfg-glue/trust_bundle_test.go index 65c343a05c..910ffdcab0 100644 --- a/agent/proxycfg-glue/trust_bundle_test.go +++ b/agent/proxycfg-glue/trust_bundle_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + cachetype "github.com/hashicorp/consul/agent/cache-types" "github.com/stretchr/testify/require" "github.com/hashicorp/consul/agent/consul/state" @@ -32,8 +33,10 @@ func TestServerTrustBundle(t *testing.T) { }) eventCh := make(chan proxycfg.UpdateEvent) - err := dataSource.Notify(context.Background(), &pbpeering.TrustBundleReadRequest{ - Name: peerName, + err := dataSource.Notify(context.Background(), &cachetype.TrustBundleReadRequest{ + Request: &pbpeering.TrustBundleReadRequest{ + Name: peerName, + }, }, "", eventCh) require.NoError(t, err) @@ -96,9 +99,11 @@ func TestServerTrustBundleList(t *testing.T) { }) eventCh := make(chan proxycfg.UpdateEvent) - err := dataSource.Notify(context.Background(), &pbpeering.TrustBundleListByServiceRequest{ - ServiceName: serviceName, - Partition: us, + err := dataSource.Notify(context.Background(), &cachetype.TrustBundleListRequest{ + Request: &pbpeering.TrustBundleListByServiceRequest{ + ServiceName: serviceName, + Partition: us, + }, }, "", eventCh) require.NoError(t, err) @@ -134,9 +139,11 @@ func TestServerTrustBundleList(t *testing.T) { }) eventCh := make(chan proxycfg.UpdateEvent) - err := dataSource.Notify(context.Background(), &pbpeering.TrustBundleListByServiceRequest{ - Kind: string(structs.ServiceKindMeshGateway), - Partition: "default", + err := dataSource.Notify(context.Background(), &cachetype.TrustBundleListRequest{ + Request: &pbpeering.TrustBundleListByServiceRequest{ + Kind: string(structs.ServiceKindMeshGateway), + Partition: "default", + }, }, "", eventCh) require.NoError(t, err) diff --git a/agent/proxycfg/connect_proxy.go b/agent/proxycfg/connect_proxy.go index 9b0f3e54b6..15e3498f2f 100644 --- a/agent/proxycfg/connect_proxy.go +++ b/agent/proxycfg/connect_proxy.go @@ -46,11 +46,13 @@ func (s *handlerConnectProxy) initialize(ctx context.Context) (ConfigSnapshot, e return snap, err } - err = s.dataSources.TrustBundleList.Notify(ctx, &pbpeering.TrustBundleListByServiceRequest{ - // TODO(peering): Pass ACL token - ServiceName: s.proxyCfg.DestinationServiceName, - Namespace: s.proxyID.NamespaceOrDefault(), - Partition: s.proxyID.PartitionOrDefault(), + err = s.dataSources.TrustBundleList.Notify(ctx, &cachetype.TrustBundleListRequest{ + Request: &pbpeering.TrustBundleListByServiceRequest{ + ServiceName: s.proxyCfg.DestinationServiceName, + Namespace: s.proxyID.NamespaceOrDefault(), + Partition: s.proxyID.PartitionOrDefault(), + }, + QueryOptions: structs.QueryOptions{Token: s.token}, }, peeringTrustBundlesWatchID, s.ch) if err != nil { return snap, err @@ -226,9 +228,12 @@ func (s *handlerConnectProxy) initialize(ctx context.Context) (ConfigSnapshot, e // Check whether a watch for this peer exists to avoid duplicates. if ok := snap.ConnectProxy.UpstreamPeerTrustBundles.IsWatched(uid.Peer); !ok { peerCtx, cancel := context.WithCancel(ctx) - if err := s.dataSources.TrustBundle.Notify(peerCtx, &pbpeering.TrustBundleReadRequest{ - Name: uid.Peer, - Partition: uid.PartitionOrDefault(), + if err := s.dataSources.TrustBundle.Notify(peerCtx, &cachetype.TrustBundleReadRequest{ + Request: &pbpeering.TrustBundleReadRequest{ + Name: uid.Peer, + Partition: uid.PartitionOrDefault(), + }, + QueryOptions: structs.QueryOptions{Token: s.token}, }, peerTrustBundleIDPrefix+uid.Peer, s.ch); err != nil { cancel() return snap, fmt.Errorf("error while watching trust bundle for peer %q: %w", uid.Peer, err) @@ -344,9 +349,12 @@ func (s *handlerConnectProxy) handleUpdate(ctx context.Context, u UpdateEvent, s // Check whether a watch for this peer exists to avoid duplicates. if ok := snap.ConnectProxy.UpstreamPeerTrustBundles.IsWatched(uid.Peer); !ok { peerCtx, cancel := context.WithCancel(ctx) - if err := s.dataSources.TrustBundle.Notify(peerCtx, &pbpeering.TrustBundleReadRequest{ - Name: uid.Peer, - Partition: uid.PartitionOrDefault(), + if err := s.dataSources.TrustBundle.Notify(peerCtx, &cachetype.TrustBundleReadRequest{ + Request: &pbpeering.TrustBundleReadRequest{ + Name: uid.Peer, + Partition: uid.PartitionOrDefault(), + }, + QueryOptions: structs.QueryOptions{Token: s.token}, }, peerTrustBundleIDPrefix+uid.Peer, s.ch); err != nil { cancel() return fmt.Errorf("error while watching trust bundle for peer %q: %w", uid.Peer, err) diff --git a/agent/proxycfg/data_sources.go b/agent/proxycfg/data_sources.go index 3bef5e3478..bda0226ffb 100644 --- a/agent/proxycfg/data_sources.go +++ b/agent/proxycfg/data_sources.go @@ -5,7 +5,6 @@ import ( cachetype "github.com/hashicorp/consul/agent/cache-types" "github.com/hashicorp/consul/agent/structs" - "github.com/hashicorp/consul/proto/pbpeering" ) // UpdateEvent contains new data for a resource we are subscribed to (e.g. an @@ -220,13 +219,13 @@ type ServiceList interface { // TrustBundle is the interface used to consume updates about a single // peer's trust bundle. type TrustBundle interface { - Notify(ctx context.Context, req *pbpeering.TrustBundleReadRequest, correlationID string, ch chan<- UpdateEvent) error + Notify(ctx context.Context, req *cachetype.TrustBundleReadRequest, correlationID string, ch chan<- UpdateEvent) error } // TrustBundleList is the interface used to consume updates about trust bundles // for peered clusters that the given proxy is exported to. type TrustBundleList interface { - Notify(ctx context.Context, req *pbpeering.TrustBundleListByServiceRequest, correlationID string, ch chan<- UpdateEvent) error + Notify(ctx context.Context, req *cachetype.TrustBundleListRequest, correlationID string, ch chan<- UpdateEvent) error } // ExportedPeeredServices is the interface used to consume updates about the diff --git a/agent/proxycfg/mesh_gateway.go b/agent/proxycfg/mesh_gateway.go index b5c3f6755f..f80ee537ff 100644 --- a/agent/proxycfg/mesh_gateway.go +++ b/agent/proxycfg/mesh_gateway.go @@ -32,11 +32,14 @@ func (s *handlerMeshGateway) initialize(ctx context.Context) (ConfigSnapshot, er } // Watch for all peer trust bundles we may need. - err = s.dataSources.TrustBundleList.Notify(ctx, &pbpeering.TrustBundleListByServiceRequest{ - // TODO(peering): Pass ACL token - Kind: string(structs.ServiceKindMeshGateway), - Namespace: s.proxyID.NamespaceOrDefault(), - Partition: s.proxyID.PartitionOrDefault(), + err = s.dataSources.TrustBundleList.Notify(ctx, &cachetype.TrustBundleListRequest{ + Request: &pbpeering.TrustBundleListByServiceRequest{ + Kind: string(structs.ServiceKindMeshGateway), + ServiceName: s.service, + Namespace: s.proxyID.NamespaceOrDefault(), + Partition: s.proxyID.PartitionOrDefault(), + }, + QueryOptions: structs.QueryOptions{Token: s.token}, }, peeringTrustBundlesWatchID, s.ch) if err != nil { return snap, err diff --git a/agent/proxycfg/state_test.go b/agent/proxycfg/state_test.go index 662596b9be..855ded03d5 100644 --- a/agent/proxycfg/state_test.go +++ b/agent/proxycfg/state_test.go @@ -137,8 +137,8 @@ func recordWatches(sc *stateConfig) *watchRecorder { PreparedQuery: typedWatchRecorder[*structs.PreparedQueryExecuteRequest]{wr}, ResolvedServiceConfig: typedWatchRecorder[*structs.ServiceConfigRequest]{wr}, ServiceList: typedWatchRecorder[*structs.DCSpecificRequest]{wr}, - TrustBundle: typedWatchRecorder[*pbpeering.TrustBundleReadRequest]{wr}, - TrustBundleList: typedWatchRecorder[*pbpeering.TrustBundleListByServiceRequest]{wr}, + TrustBundle: typedWatchRecorder[*cachetype.TrustBundleReadRequest]{wr}, + TrustBundleList: typedWatchRecorder[*cachetype.TrustBundleListRequest]{wr}, ExportedPeeredServices: typedWatchRecorder[*structs.DCSpecificRequest]{wr}, } recordWatchesEnterprise(sc, wr) @@ -203,9 +203,9 @@ func verifyDatacentersWatch(t testing.TB, request any) { func genVerifyTrustBundleReadWatch(peer string) verifyWatchRequest { return func(t testing.TB, request any) { - reqReal, ok := request.(*pbpeering.TrustBundleReadRequest) + reqReal, ok := request.(*cachetype.TrustBundleReadRequest) require.True(t, ok) - require.Equal(t, peer, reqReal.Name) + require.Equal(t, peer, reqReal.Request.Name) } } @@ -225,19 +225,19 @@ func genVerifyLeafWatch(expectedService string, expectedDatacenter string) verif func genVerifyTrustBundleListWatch(service string) verifyWatchRequest { return func(t testing.TB, request any) { - reqReal, ok := request.(*pbpeering.TrustBundleListByServiceRequest) + reqReal, ok := request.(*cachetype.TrustBundleListRequest) require.True(t, ok) - require.Equal(t, service, reqReal.ServiceName) + require.Equal(t, service, reqReal.Request.ServiceName) } } func genVerifyTrustBundleListWatchForMeshGateway(partition string) verifyWatchRequest { return func(t testing.TB, request any) { - reqReal, ok := request.(*pbpeering.TrustBundleListByServiceRequest) + reqReal, ok := request.(*cachetype.TrustBundleListRequest) require.True(t, ok) - require.Equal(t, string(structs.ServiceKindMeshGateway), reqReal.Kind) - require.True(t, acl.EqualPartitions(partition, reqReal.Partition), "%q != %q", partition, reqReal.Partition) - require.Empty(t, reqReal.ServiceName) + require.Equal(t, string(structs.ServiceKindMeshGateway), reqReal.Request.Kind) + require.True(t, acl.EqualPartitions(partition, reqReal.Request.Partition), "%q != %q", partition, reqReal.Request.Partition) + require.NotEmpty(t, reqReal.Request.ServiceName) } } diff --git a/agent/proxycfg/testing.go b/agent/proxycfg/testing.go index dfde519d18..0493e30dae 100644 --- a/agent/proxycfg/testing.go +++ b/agent/proxycfg/testing.go @@ -751,8 +751,8 @@ func testConfigSnapshotFixture( PreparedQuery: &noopDataSource[*structs.PreparedQueryExecuteRequest]{}, ResolvedServiceConfig: &noopDataSource[*structs.ServiceConfigRequest]{}, ServiceList: &noopDataSource[*structs.DCSpecificRequest]{}, - TrustBundle: &noopDataSource[*pbpeering.TrustBundleReadRequest]{}, - TrustBundleList: &noopDataSource[*pbpeering.TrustBundleListByServiceRequest]{}, + TrustBundle: &noopDataSource[*cachetype.TrustBundleReadRequest]{}, + TrustBundleList: &noopDataSource[*cachetype.TrustBundleListRequest]{}, ExportedPeeredServices: &noopDataSource[*structs.DCSpecificRequest]{}, }, dnsConfig: DNSConfig{ // TODO: make configurable @@ -954,8 +954,8 @@ func NewTestDataSources() *TestDataSources { PreparedQuery: NewTestDataSource[*structs.PreparedQueryExecuteRequest, *structs.PreparedQueryExecuteResponse](), ResolvedServiceConfig: NewTestDataSource[*structs.ServiceConfigRequest, *structs.ServiceConfigResponse](), ServiceList: NewTestDataSource[*structs.DCSpecificRequest, *structs.IndexedServiceList](), - TrustBundle: NewTestDataSource[*pbpeering.TrustBundleReadRequest, *pbpeering.TrustBundleReadResponse](), - TrustBundleList: NewTestDataSource[*pbpeering.TrustBundleListByServiceRequest, *pbpeering.TrustBundleListByServiceResponse](), + TrustBundle: NewTestDataSource[*cachetype.TrustBundleReadRequest, *pbpeering.TrustBundleReadResponse](), + TrustBundleList: NewTestDataSource[*cachetype.TrustBundleListRequest, *pbpeering.TrustBundleListByServiceResponse](), } srcs.buildEnterpriseSources() return srcs @@ -981,8 +981,8 @@ type TestDataSources struct { PreparedQuery *TestDataSource[*structs.PreparedQueryExecuteRequest, *structs.PreparedQueryExecuteResponse] ResolvedServiceConfig *TestDataSource[*structs.ServiceConfigRequest, *structs.ServiceConfigResponse] ServiceList *TestDataSource[*structs.DCSpecificRequest, *structs.IndexedServiceList] - TrustBundle *TestDataSource[*pbpeering.TrustBundleReadRequest, *pbpeering.TrustBundleReadResponse] - TrustBundleList *TestDataSource[*pbpeering.TrustBundleListByServiceRequest, *pbpeering.TrustBundleListByServiceResponse] + TrustBundle *TestDataSource[*cachetype.TrustBundleReadRequest, *pbpeering.TrustBundleReadResponse] + TrustBundleList *TestDataSource[*cachetype.TrustBundleListRequest, *pbpeering.TrustBundleListByServiceResponse] TestDataSourcesEnterprise } diff --git a/agent/rpc/peering/service.go b/agent/rpc/peering/service.go index 8cb78e33ca..c7e0b861c3 100644 --- a/agent/rpc/peering/service.go +++ b/agent/rpc/peering/service.go @@ -16,9 +16,11 @@ import ( "google.golang.org/protobuf/proto" "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/acl/resolver" "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/consul/stream" "github.com/hashicorp/consul/agent/dns" + external "github.com/hashicorp/consul/agent/grpc-external" "github.com/hashicorp/consul/agent/grpc-external/services/peerstream" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/lib" @@ -43,6 +45,20 @@ func (e *errPeeringInvalidServerAddress) Error() string { return fmt.Sprintf("%s is not a valid peering server address", e.addr) } +// For private/internal gRPC handlers, protoc-gen-rpc-glue generates the +// requisite methods to satisfy the structs.RPCInfo interface using fields +// from the pbcommon package. This service is public, so we can't use those +// fields in our proto definition. Instead, we construct our RPCInfo manually. +var writeRequest struct { + structs.WriteRequest + structs.DCSpecificRequest +} + +var readRequest struct { + structs.QueryOptions + structs.DCSpecificRequest +} + // Server implements pbpeering.PeeringService to provide RPC operations for // managing peering relationships. type Server struct { @@ -90,6 +106,12 @@ func (s *Server) Register(grpcServer *grpc.Server) { // providing access to CA data and the RPC system for forwarding requests to // other servers. type Backend interface { + // ResolveTokenAndDefaultMeta returns an acl.Authorizer which authorizes + // actions based on the permissions granted to the token. + // If either entMeta or authzContext are non-nil they will be populated with the + // partition and namespace from the token. + ResolveTokenAndDefaultMeta(token string, entMeta *acl.EnterpriseMeta, authzCtx *acl.AuthorizerContext) (resolver.Result, error) + // GetAgentCACertificates returns the CA certificate to be returned in the peering token data GetAgentCACertificates() ([]string, error) @@ -165,11 +187,11 @@ func (s *Server) GenerateToken( return nil, fmt.Errorf("meta tags failed validation: %w", err) } - // TODO(peering): add metrics - // TODO(peering): add tracing + defer metrics.MeasureSince([]string{"peering", "generate_token"}, time.Now()) resp := &pbpeering.GenerateTokenResponse{} - handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(&writeRequest, func(conn *grpc.ClientConn) error { + ctx := external.ForwardMetadataContext(ctx) var err error resp, err = pbpeering.NewPeeringServiceClient(conn).GenerateToken(ctx, req) return err @@ -178,6 +200,17 @@ func (s *Server) GenerateToken( return resp, err } + var authzCtx acl.AuthorizerContext + entMeta := structs.DefaultEnterpriseMetaInPartition(req.Partition) + authz, err := s.Backend.ResolveTokenAndDefaultMeta(external.TokenFromContext(ctx), entMeta, &authzCtx) + if err != nil { + return nil, err + } + + if err := authz.ToAllowAuthorizer().PeeringWriteAllowed(&authzCtx); err != nil { + return nil, err + } + ca, err := s.Backend.GetAgentCACertificates() if err != nil { return nil, err @@ -194,7 +227,7 @@ func (s *Server) GenerateToken( } } - peeringOrNil, err := s.getExistingPeering(req.PeerName, req.Partition) + peeringOrNil, err := s.getExistingPeering(req.PeerName, entMeta.PartitionOrDefault()) if err != nil { return nil, err } @@ -206,7 +239,7 @@ func (s *Server) GenerateToken( canRetry := true RETRY_ONCE: - id, err := s.getExistingOrCreateNewPeerID(req.PeerName, req.Partition) + id, err := s.getExistingOrCreateNewPeerID(req.PeerName, entMeta.PartitionOrDefault()) if err != nil { return nil, err } @@ -214,9 +247,10 @@ RETRY_ONCE: Peering: &pbpeering.Peering{ ID: id, Name: req.PeerName, - // TODO(peering): Normalize from ACL token once this endpoint is guarded by ACLs. - Partition: req.PartitionOrDefault(), - Meta: req.Meta, + Meta: req.Meta, + + // PartitionOrEmpty is used to avoid writing "default" in OSS. + Partition: entMeta.PartitionOrEmpty(), }, } if err := s.Backend.PeeringWrite(&writeReq); err != nil { @@ -234,7 +268,7 @@ RETRY_ONCE: q := state.Query{ Value: strings.ToLower(req.PeerName), - EnterpriseMeta: *structs.NodeEnterpriseMetaInPartition(req.Partition), + EnterpriseMeta: *entMeta, } _, peering, err := s.Backend.Store().PeeringRead(nil, q) if err != nil { @@ -288,7 +322,8 @@ func (s *Server) Establish( } resp := &pbpeering.EstablishResponse{} - handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(&writeRequest, func(conn *grpc.ClientConn) error { + ctx := external.ForwardMetadataContext(ctx) var err error resp, err = pbpeering.NewPeeringServiceClient(conn).Establish(ctx, req) return err @@ -299,7 +334,18 @@ func (s *Server) Establish( defer metrics.MeasureSince([]string{"peering", "establish"}, time.Now()) - peeringOrNil, err := s.getExistingPeering(req.PeerName, req.Partition) + var authzCtx acl.AuthorizerContext + entMeta := structs.DefaultEnterpriseMetaInPartition(req.Partition) + authz, err := s.Backend.ResolveTokenAndDefaultMeta(external.TokenFromContext(ctx), entMeta, &authzCtx) + if err != nil { + return nil, err + } + + if err := authz.ToAllowAuthorizer().PeeringWriteAllowed(&authzCtx); err != nil { + return nil, err + } + + peeringOrNil, err := s.getExistingPeering(req.PeerName, entMeta.PartitionOrDefault()) if err != nil { return nil, err } @@ -341,6 +387,9 @@ func (s *Server) Establish( PeerID: tok.PeerID, Meta: req.Meta, State: pbpeering.PeeringState_ESTABLISHING, + + // PartitionOrEmpty is used to avoid writing "default" in OSS. + Partition: entMeta.PartitionOrEmpty(), }, } if err = s.Backend.PeeringWrite(writeReq); err != nil { @@ -350,6 +399,7 @@ func (s *Server) Establish( return resp, nil } +// OPTIMIZE: Handle blocking queries func (s *Server) PeeringRead(ctx context.Context, req *pbpeering.PeeringReadRequest) (*pbpeering.PeeringReadResponse, error) { if !s.Config.PeeringEnabled { return nil, peeringNotEnabledErr @@ -360,7 +410,8 @@ func (s *Server) PeeringRead(ctx context.Context, req *pbpeering.PeeringReadRequ } var resp *pbpeering.PeeringReadResponse - handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(&readRequest, func(conn *grpc.ClientConn) error { + ctx := external.ForwardMetadataContext(ctx) var err error resp, err = pbpeering.NewPeeringServiceClient(conn).PeeringRead(ctx, req) return err @@ -370,12 +421,22 @@ func (s *Server) PeeringRead(ctx context.Context, req *pbpeering.PeeringReadRequ } defer metrics.MeasureSince([]string{"peering", "read"}, time.Now()) - // TODO(peering): ACL check request token - // TODO(peering): handle blocking queries + var authzCtx acl.AuthorizerContext + entMeta := structs.DefaultEnterpriseMetaInPartition(req.Partition) + authz, err := s.Backend.ResolveTokenAndDefaultMeta(external.TokenFromContext(ctx), entMeta, &authzCtx) + if err != nil { + return nil, err + } + + if err := authz.ToAllowAuthorizer().PeeringReadAllowed(&authzCtx); err != nil { + return nil, err + } + q := state.Query{ Value: strings.ToLower(req.Name), - EnterpriseMeta: *structs.NodeEnterpriseMetaInPartition(req.Partition)} + EnterpriseMeta: *entMeta, + } _, peering, err := s.Backend.Store().PeeringRead(nil, q) if err != nil { return nil, err @@ -388,6 +449,7 @@ func (s *Server) PeeringRead(ctx context.Context, req *pbpeering.PeeringReadRequ return &pbpeering.PeeringReadResponse{Peering: cp}, nil } +// OPTIMIZE: Handle blocking queries func (s *Server) PeeringList(ctx context.Context, req *pbpeering.PeeringListRequest) (*pbpeering.PeeringListResponse, error) { if !s.Config.PeeringEnabled { return nil, peeringNotEnabledErr @@ -398,7 +460,8 @@ func (s *Server) PeeringList(ctx context.Context, req *pbpeering.PeeringListRequ } var resp *pbpeering.PeeringListResponse - handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(&readRequest, func(conn *grpc.ClientConn) error { + ctx := external.ForwardMetadataContext(ctx) var err error resp, err = pbpeering.NewPeeringServiceClient(conn).PeeringList(ctx, req) return err @@ -407,11 +470,20 @@ func (s *Server) PeeringList(ctx context.Context, req *pbpeering.PeeringListRequ return resp, err } - defer metrics.MeasureSince([]string{"peering", "list"}, time.Now()) - // TODO(peering): ACL check request token + var authzCtx acl.AuthorizerContext + entMeta := structs.DefaultEnterpriseMetaInPartition(req.Partition) + authz, err := s.Backend.ResolveTokenAndDefaultMeta(external.TokenFromContext(ctx), entMeta, &authzCtx) + if err != nil { + return nil, err + } - // TODO(peering): handle blocking queries - _, peerings, err := s.Backend.Store().PeeringList(nil, *structs.NodeEnterpriseMetaInPartition(req.Partition)) + if err := authz.ToAllowAuthorizer().PeeringReadAllowed(&authzCtx); err != nil { + return nil, err + } + + defer metrics.MeasureSince([]string{"peering", "list"}, time.Now()) + + _, peerings, err := s.Backend.Store().PeeringList(nil, *entMeta) if err != nil { return nil, err } @@ -465,7 +537,8 @@ func (s *Server) PeeringWrite(ctx context.Context, req *pbpeering.PeeringWriteRe } var resp *pbpeering.PeeringWriteResponse - handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(&writeRequest, func(conn *grpc.ClientConn) error { + ctx := external.ForwardMetadataContext(ctx) var err error resp, err = pbpeering.NewPeeringServiceClient(conn).PeeringWrite(ctx, req) return err @@ -475,19 +548,28 @@ func (s *Server) PeeringWrite(ctx context.Context, req *pbpeering.PeeringWriteRe } defer metrics.MeasureSince([]string{"peering", "write"}, time.Now()) - // TODO(peering): ACL check request token + + var authzCtx acl.AuthorizerContext + entMeta := structs.DefaultEnterpriseMetaInPartition(req.Peering.Partition) + authz, err := s.Backend.ResolveTokenAndDefaultMeta(external.TokenFromContext(ctx), entMeta, &authzCtx) + if err != nil { + return nil, err + } + + if err := authz.ToAllowAuthorizer().PeeringWriteAllowed(&authzCtx); err != nil { + return nil, err + } if req.Peering == nil { return nil, fmt.Errorf("missing required peering body") } - id, err := s.getExistingOrCreateNewPeerID(req.Peering.Name, req.Peering.Partition) + id, err := s.getExistingOrCreateNewPeerID(req.Peering.Name, entMeta.PartitionOrDefault()) if err != nil { return nil, err } req.Peering.ID = id - // TODO(peering): handle blocking queries err = s.Backend.PeeringWrite(req) if err != nil { return nil, err @@ -505,7 +587,8 @@ func (s *Server) PeeringDelete(ctx context.Context, req *pbpeering.PeeringDelete } var resp *pbpeering.PeeringDeleteResponse - handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(&writeRequest, func(conn *grpc.ClientConn) error { + ctx := external.ForwardMetadataContext(ctx) var err error resp, err = pbpeering.NewPeeringServiceClient(conn).PeeringDelete(ctx, req) return err @@ -515,13 +598,21 @@ func (s *Server) PeeringDelete(ctx context.Context, req *pbpeering.PeeringDelete } defer metrics.MeasureSince([]string{"peering", "delete"}, time.Now()) - // TODO(peering): ACL check request token - // TODO(peering): handle blocking queries + var authzCtx acl.AuthorizerContext + entMeta := structs.DefaultEnterpriseMetaInPartition(req.Partition) + authz, err := s.Backend.ResolveTokenAndDefaultMeta(external.TokenFromContext(ctx), entMeta, &authzCtx) + if err != nil { + return nil, err + } + + if err := authz.ToAllowAuthorizer().PeeringWriteAllowed(&authzCtx); err != nil { + return nil, err + } q := state.Query{ Value: strings.ToLower(req.Name), - EnterpriseMeta: *structs.NodeEnterpriseMetaInPartition(req.Partition), + EnterpriseMeta: *entMeta, } _, existing, err := s.Backend.Store().PeeringRead(nil, q) if err != nil { @@ -543,9 +634,11 @@ func (s *Server) PeeringDelete(ctx context.Context, req *pbpeering.PeeringDelete // for deletion the peering is effectively gone. ID: existing.ID, Name: req.Name, - Partition: req.Partition, State: pbpeering.PeeringState_DELETING, DeletedAt: structs.TimeToProto(time.Now().UTC()), + + // PartitionOrEmpty is used to avoid writing "default" in OSS. + Partition: entMeta.PartitionOrEmpty(), }, } err = s.Backend.PeeringWrite(writeReq) @@ -555,6 +648,7 @@ func (s *Server) PeeringDelete(ctx context.Context, req *pbpeering.PeeringDelete return &pbpeering.PeeringDeleteResponse{}, nil } +// OPTIMIZE: Handle blocking queries func (s *Server) TrustBundleRead(ctx context.Context, req *pbpeering.TrustBundleReadRequest) (*pbpeering.TrustBundleReadResponse, error) { if !s.Config.PeeringEnabled { return nil, peeringNotEnabledErr @@ -565,7 +659,8 @@ func (s *Server) TrustBundleRead(ctx context.Context, req *pbpeering.TrustBundle } var resp *pbpeering.TrustBundleReadResponse - handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(&readRequest, func(conn *grpc.ClientConn) error { + ctx := external.ForwardMetadataContext(ctx) var err error resp, err = pbpeering.NewPeeringServiceClient(conn).TrustBundleRead(ctx, req) return err @@ -575,13 +670,21 @@ func (s *Server) TrustBundleRead(ctx context.Context, req *pbpeering.TrustBundle } defer metrics.MeasureSince([]string{"peering", "trust_bundle_read"}, time.Now()) - // TODO(peering): ACL check request token - // TODO(peering): handle blocking queries + var authzCtx acl.AuthorizerContext + entMeta := structs.DefaultEnterpriseMetaInPartition(req.Partition) + authz, err := s.Backend.ResolveTokenAndDefaultMeta(external.TokenFromContext(ctx), entMeta, &authzCtx) + if err != nil { + return nil, err + } + + if err := authz.ToAllowAuthorizer().ServiceWriteAnyAllowed(&authzCtx); err != nil { + return nil, err + } idx, trustBundle, err := s.Backend.Store().PeeringTrustBundleRead(nil, state.Query{ Value: req.Name, - EnterpriseMeta: *structs.NodeEnterpriseMetaInPartition(req.Partition), + EnterpriseMeta: *entMeta, }) if err != nil { return nil, fmt.Errorf("failed to read trust bundle for peer %s: %w", req.Name, err) @@ -594,6 +697,7 @@ func (s *Server) TrustBundleRead(ctx context.Context, req *pbpeering.TrustBundle } // TODO(peering): rename rpc & request/response to drop the "service" part +// OPTIMIZE: Handle blocking queries func (s *Server) TrustBundleListByService(ctx context.Context, req *pbpeering.TrustBundleListByServiceRequest) (*pbpeering.TrustBundleListByServiceResponse, error) { if !s.Config.PeeringEnabled { return nil, peeringNotEnabledErr @@ -605,9 +709,13 @@ func (s *Server) TrustBundleListByService(ctx context.Context, req *pbpeering.Tr if err := s.Backend.EnterpriseCheckNamespaces(req.Namespace); err != nil { return nil, grpcstatus.Error(codes.InvalidArgument, err.Error()) } + if req.ServiceName == "" { + return nil, errors.New("missing service name") + } var resp *pbpeering.TrustBundleListByServiceResponse - handled, err := s.ForwardRPC(req, func(conn *grpc.ClientConn) error { + handled, err := s.ForwardRPC(&readRequest, func(conn *grpc.ClientConn) error { + ctx := external.ForwardMetadataContext(ctx) var err error resp, err = pbpeering.NewPeeringServiceClient(conn).TrustBundleListByService(ctx, req) return err @@ -617,11 +725,17 @@ func (s *Server) TrustBundleListByService(ctx context.Context, req *pbpeering.Tr } defer metrics.MeasureSince([]string{"peering", "trust_bundle_list_by_service"}, time.Now()) - // TODO(peering): ACL check request token for service:write on the service name - - // TODO(peering): handle blocking queries + var authzCtx acl.AuthorizerContext entMeta := acl.NewEnterpriseMetaWithPartition(req.Partition, req.Namespace) + authz, err := s.Backend.ResolveTokenAndDefaultMeta(external.TokenFromContext(ctx), &entMeta, &authzCtx) + if err != nil { + return nil, err + } + + if err := authz.ToAllowAuthorizer().ServiceWriteAllowed(req.ServiceName, &authzCtx); err != nil { + return nil, err + } var ( idx uint64 @@ -629,10 +743,10 @@ func (s *Server) TrustBundleListByService(ctx context.Context, req *pbpeering.Tr ) switch { - case req.ServiceName != "": - idx, bundles, err = s.Backend.Store().TrustBundleListByService(nil, req.ServiceName, s.Datacenter, entMeta) case req.Kind == string(structs.ServiceKindMeshGateway): idx, bundles, err = s.Backend.Store().PeeringTrustBundleList(nil, entMeta) + case req.ServiceName != "": + idx, bundles, err = s.Backend.Store().TrustBundleListByService(nil, req.ServiceName, s.Datacenter, entMeta) case req.Kind != "": return nil, grpcstatus.Error(codes.InvalidArgument, "kind must be mesh-gateway if set") default: diff --git a/agent/rpc/peering/service_test.go b/agent/rpc/peering/service_test.go index 47de64554d..ca3553a1bb 100644 --- a/agent/rpc/peering/service_test.go +++ b/agent/rpc/peering/service_test.go @@ -22,6 +22,7 @@ import ( "github.com/hashicorp/consul/agent/consul" "github.com/hashicorp/consul/agent/consul/state" "github.com/hashicorp/consul/agent/consul/stream" + external "github.com/hashicorp/consul/agent/grpc-external" grpc "github.com/hashicorp/consul/agent/grpc-internal" "github.com/hashicorp/consul/agent/grpc-internal/resolver" "github.com/hashicorp/consul/agent/pool" @@ -41,6 +42,13 @@ import ( "github.com/hashicorp/consul/types" ) +const ( + testTokenPeeringReadSecret = "9a83c138-a0c7-40f1-89fa-6acf9acd78f5" + testTokenPeeringWriteSecret = "91f90a41-0840-4afe-b615-68745f9e16c1" + testTokenServiceReadSecret = "1ef8e3cf-6e95-49aa-9f73-a0d3ad1a77d4" + testTokenServiceWriteSecret = "4a3dc05d-d86c-4f20-be43-8f4f8f045fea" +) + func generateTooManyMetaKeys() map[string]string { // todo -- modularize in structs.go or testing.go tooMuchMeta := make(map[string]string) @@ -70,12 +78,12 @@ func TestPeeringService_GenerateToken(t *testing.T) { // TODO(peering): for more failure cases, consider using a table test // check meta tags - reqE := pbpeering.GenerateTokenRequest{PeerName: "peerB", Datacenter: "dc1", Meta: generateTooManyMetaKeys()} + reqE := pbpeering.GenerateTokenRequest{PeerName: "peerB", Meta: generateTooManyMetaKeys()} _, errE := client.GenerateToken(ctx, &reqE) require.EqualError(t, errE, "rpc error: code = Unknown desc = meta tags failed validation: Node metadata cannot contain more than 64 key/value pairs") // happy path - req := pbpeering.GenerateTokenRequest{PeerName: "peerB", Datacenter: "dc1", Meta: map[string]string{"foo": "bar"}} + req := pbpeering.GenerateTokenRequest{PeerName: "peerB", Meta: map[string]string{"foo": "bar"}} resp, err := client.GenerateToken(ctx, &req) require.NoError(t, err) @@ -129,7 +137,7 @@ func TestPeeringService_GenerateTokenExternalAddress(t *testing.T) { externalAddress := "32.1.2.3:8502" // happy path - req := pbpeering.GenerateTokenRequest{PeerName: "peerB", Datacenter: "dc1", Meta: map[string]string{"foo": "bar"}, ServerExternalAddresses: []string{externalAddress}} + req := pbpeering.GenerateTokenRequest{PeerName: "peerB", Meta: map[string]string{"foo": "bar"}, ServerExternalAddresses: []string{externalAddress}} resp, err := client.GenerateToken(ctx, &req) require.NoError(t, err) @@ -144,6 +152,62 @@ func TestPeeringService_GenerateTokenExternalAddress(t *testing.T) { require.Equal(t, []string{ca}, token.CA) } +func TestPeeringService_GenerateToken_ACLEnforcement(t *testing.T) { + // TODO(peering): see note on newTestServer, refactor to not use this + s := newTestServer(t, func(conf *consul.Config) { + conf.ACLsEnabled = true + conf.ACLResolverSettings.ACLDefaultPolicy = acl.PolicyDeny + }) + upsertTestACLs(t, s.Server.FSM().State()) + + client := pbpeering.NewPeeringServiceClient(s.ClientConn(t)) + + type testcase struct { + name string + req *pbpeering.GenerateTokenRequest + token string + expectErr string + } + run := func(t *testing.T, tc testcase) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + t.Cleanup(cancel) + + _, err := client.GenerateToken(external.ContextWithToken(ctx, tc.token), tc.req) + if tc.expectErr != "" { + require.Contains(t, err.Error(), tc.expectErr) + return + } + require.NoError(t, err) + } + tcs := []testcase{ + { + name: "anonymous token lacks permissions", + req: &pbpeering.GenerateTokenRequest{PeerName: "foo"}, + expectErr: "lacks permission 'peering:write'", + }, + { + name: "read token lacks permissions", + req: &pbpeering.GenerateTokenRequest{ + PeerName: "foo", + }, + token: testTokenPeeringReadSecret, + expectErr: "lacks permission 'peering:write'", + }, + { + name: "write token grants permission", + req: &pbpeering.GenerateTokenRequest{ + PeerName: "foo", + }, + token: testTokenPeeringWriteSecret, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + run(t, tc) + }) + } +} + func TestPeeringService_Establish(t *testing.T) { validToken := peering.TestPeeringToken("83474a06-cca4-4ff4-99a4-4152929c8160") validTokenJSON, _ := json.Marshal(&validToken) @@ -250,6 +314,71 @@ func TestPeeringService_Establish(t *testing.T) { } } +func TestPeeringService_Establish_ACLEnforcement(t *testing.T) { + validToken := peering.TestPeeringToken("83474a06-cca4-4ff4-99a4-4152929c8160") + validTokenJSON, _ := json.Marshal(&validToken) + validTokenB64 := base64.StdEncoding.EncodeToString(validTokenJSON) + + // TODO(peering): see note on newTestServer, refactor to not use this + s := newTestServer(t, func(conf *consul.Config) { + conf.ACLsEnabled = true + conf.ACLResolverSettings.ACLDefaultPolicy = acl.PolicyDeny + }) + upsertTestACLs(t, s.Server.FSM().State()) + + client := pbpeering.NewPeeringServiceClient(s.ClientConn(t)) + + type testcase struct { + name string + req *pbpeering.EstablishRequest + token string + expectErr string + } + run := func(t *testing.T, tc testcase) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + t.Cleanup(cancel) + + _, err := client.Establish(external.ContextWithToken(ctx, tc.token), tc.req) + if tc.expectErr != "" { + require.Contains(t, err.Error(), tc.expectErr) + return + } + require.NoError(t, err) + } + tcs := []testcase{ + { + name: "anonymous token lacks permissions", + req: &pbpeering.EstablishRequest{ + PeerName: "foo", + PeeringToken: validTokenB64, + }, + expectErr: "lacks permission 'peering:write'", + }, + { + name: "read token lacks permissions", + req: &pbpeering.EstablishRequest{ + PeerName: "foo", + PeeringToken: validTokenB64, + }, + token: testTokenPeeringReadSecret, + expectErr: "lacks permission 'peering:write'", + }, + { + name: "write token grants permission", + req: &pbpeering.EstablishRequest{ + PeerName: "foo", + PeeringToken: validTokenB64, + }, + token: testTokenPeeringWriteSecret, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + run(t, tc) + }) + } +} + func TestPeeringService_Read(t *testing.T) { // TODO(peering): see note on newTestServer, refactor to not use this s := newTestServer(t, nil) @@ -309,6 +438,72 @@ func TestPeeringService_Read(t *testing.T) { } } +func TestPeeringService_Read_ACLEnforcement(t *testing.T) { + // TODO(peering): see note on newTestServer, refactor to not use this + s := newTestServer(t, func(conf *consul.Config) { + conf.ACLsEnabled = true + conf.ACLResolverSettings.ACLDefaultPolicy = acl.PolicyDeny + }) + upsertTestACLs(t, s.Server.FSM().State()) + + // insert peering directly to state store + p := &pbpeering.Peering{ + ID: testUUID(t), + Name: "foo", + State: pbpeering.PeeringState_ESTABLISHING, + PeerCAPems: nil, + PeerServerName: "test", + PeerServerAddresses: []string{"addr1"}, + ImportedServiceCount: 0, + ExportedServiceCount: 0, + } + err := s.Server.FSM().State().PeeringWrite(10, p) + require.NoError(t, err) + + client := pbpeering.NewPeeringServiceClient(s.ClientConn(t)) + + type testcase struct { + name string + req *pbpeering.PeeringReadRequest + expect *pbpeering.PeeringReadResponse + token string + expectErr string + } + run := func(t *testing.T, tc testcase) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + t.Cleanup(cancel) + + resp, err := client.PeeringRead(external.ContextWithToken(ctx, tc.token), tc.req) + if tc.expectErr != "" { + require.Contains(t, err.Error(), tc.expectErr) + return + } + require.NoError(t, err) + prototest.AssertDeepEqual(t, tc.expect, resp) + } + tcs := []testcase{ + { + name: "anonymous token lacks permissions", + req: &pbpeering.PeeringReadRequest{Name: "foo"}, + expect: &pbpeering.PeeringReadResponse{Peering: p}, + expectErr: "lacks permission 'peering:read'", + }, + { + name: "read token grants permission", + req: &pbpeering.PeeringReadRequest{ + Name: "foo", + }, + expect: &pbpeering.PeeringReadResponse{Peering: p}, + token: testTokenPeeringReadSecret, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + run(t, tc) + }) + } +} + func TestPeeringService_Delete(t *testing.T) { // TODO(peering): see note on newTestServer, refactor to not use this s := newTestServer(t, nil) @@ -344,6 +539,76 @@ func TestPeeringService_Delete(t *testing.T) { }) } +func TestPeeringService_Delete_ACLEnforcement(t *testing.T) { + // TODO(peering): see note on newTestServer, refactor to not use this + s := newTestServer(t, func(conf *consul.Config) { + conf.ACLsEnabled = true + conf.ACLResolverSettings.ACLDefaultPolicy = acl.PolicyDeny + }) + upsertTestACLs(t, s.Server.FSM().State()) + + p := &pbpeering.Peering{ + ID: testUUID(t), + Name: "foo", + State: pbpeering.PeeringState_ESTABLISHING, + PeerCAPems: nil, + PeerServerName: "test", + PeerServerAddresses: []string{"addr1"}, + } + err := s.Server.FSM().State().PeeringWrite(10, p) + require.NoError(t, err) + require.Nil(t, p.DeletedAt) + require.True(t, p.IsActive()) + + client := pbpeering.NewPeeringServiceClient(s.ClientConn(t)) + + type testcase struct { + name string + req *pbpeering.PeeringDeleteRequest + token string + expectErr string + } + run := func(t *testing.T, tc testcase) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + t.Cleanup(cancel) + + _, err = client.PeeringDelete(external.ContextWithToken(ctx, tc.token), tc.req) + if tc.expectErr != "" { + require.Contains(t, err.Error(), tc.expectErr) + return + } + require.NoError(t, err) + } + tcs := []testcase{ + { + name: "anonymous token lacks permissions", + req: &pbpeering.PeeringDeleteRequest{Name: "foo"}, + expectErr: "lacks permission 'peering:write'", + }, + { + name: "read token lacks permissions", + req: &pbpeering.PeeringDeleteRequest{ + Name: "foo", + }, + token: testTokenPeeringReadSecret, + expectErr: "lacks permission 'peering:write'", + }, + { + name: "write token grants permission", + req: &pbpeering.PeeringDeleteRequest{ + Name: "foo", + }, + token: testTokenPeeringWriteSecret, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + run(t, tc) + }) + } + +} + func TestPeeringService_List(t *testing.T) { // TODO(peering): see note on newTestServer, refactor to not use this s := newTestServer(t, nil) @@ -388,6 +653,78 @@ func TestPeeringService_List(t *testing.T) { prototest.AssertDeepEqual(t, expect, resp) } +func TestPeeringService_List_ACLEnforcement(t *testing.T) { + // TODO(peering): see note on newTestServer, refactor to not use this + s := newTestServer(t, func(conf *consul.Config) { + conf.ACLsEnabled = true + conf.ACLResolverSettings.ACLDefaultPolicy = acl.PolicyDeny + }) + upsertTestACLs(t, s.Server.FSM().State()) + + // insert peering directly to state store + foo := &pbpeering.Peering{ + ID: testUUID(t), + Name: "foo", + State: pbpeering.PeeringState_ESTABLISHING, + PeerCAPems: nil, + PeerServerName: "fooservername", + PeerServerAddresses: []string{"addr1"}, + ImportedServiceCount: 0, + ExportedServiceCount: 0, + } + require.NoError(t, s.Server.FSM().State().PeeringWrite(10, foo)) + bar := &pbpeering.Peering{ + ID: testUUID(t), + Name: "bar", + State: pbpeering.PeeringState_ACTIVE, + PeerCAPems: nil, + PeerServerName: "barservername", + PeerServerAddresses: []string{"addr1"}, + ImportedServiceCount: 0, + ExportedServiceCount: 0, + } + require.NoError(t, s.Server.FSM().State().PeeringWrite(15, bar)) + + client := pbpeering.NewPeeringServiceClient(s.ClientConn(t)) + + type testcase struct { + name string + token string + expect *pbpeering.PeeringListResponse + expectErr string + } + run := func(t *testing.T, tc testcase) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + t.Cleanup(cancel) + + resp, err := client.PeeringList(external.ContextWithToken(ctx, tc.token), &pbpeering.PeeringListRequest{}) + if tc.expectErr != "" { + require.Contains(t, err.Error(), tc.expectErr) + return + } + require.NoError(t, err) + prototest.AssertDeepEqual(t, tc.expect, resp) + } + tcs := []testcase{ + { + name: "anonymous token lacks permissions", + expectErr: "lacks permission 'peering:read'", + }, + { + name: "read token grants permission", + token: testTokenPeeringReadSecret, + expect: &pbpeering.PeeringListResponse{ + Peerings: []*pbpeering.Peering{bar, foo}, + }, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + run(t, tc) + }) + } +} + func TestPeeringService_TrustBundleRead(t *testing.T) { srv := newTestServer(t, nil) store := srv.Server.FSM().State() @@ -396,25 +733,6 @@ func TestPeeringService_TrustBundleRead(t *testing.T) { var lastIdx uint64 = 1 _ = setupTestPeering(t, store, "my-peering", lastIdx) - mysql := &structs.CheckServiceNode{ - Node: &structs.Node{ - Node: "node1", - Address: "10.0.0.1", - PeerName: "my-peering", - }, - Service: &structs.NodeService{ - ID: "mysql-1", - Service: "mysql", - Port: 5000, - PeerName: "my-peering", - }, - } - - lastIdx++ - require.NoError(t, store.EnsureNode(lastIdx, mysql.Node)) - lastIdx++ - require.NoError(t, store.EnsureService(lastIdx, mysql.Node.Node, mysql.Service)) - bundle := &pbpeering.PeeringTrustBundle{ TrustDomain: "peer1.com", PeerName: "my-peering", @@ -435,6 +753,76 @@ func TestPeeringService_TrustBundleRead(t *testing.T) { prototest.AssertDeepEqual(t, bundle, resp.Bundle) } +func TestPeeringService_TrustBundleRead_ACLEnforcement(t *testing.T) { + // TODO(peering): see note on newTestServer, refactor to not use this + s := newTestServer(t, func(conf *consul.Config) { + conf.ACLsEnabled = true + conf.ACLResolverSettings.ACLDefaultPolicy = acl.PolicyDeny + }) + store := s.Server.FSM().State() + upsertTestACLs(t, s.Server.FSM().State()) + + // Insert peering and trust bundle directly to state store. + _ = setupTestPeering(t, store, "my-peering", 10) + + bundle := &pbpeering.PeeringTrustBundle{ + TrustDomain: "peer1.com", + PeerName: "my-peering", + RootPEMs: []string{"peer1-root-1"}, + } + require.NoError(t, store.PeeringTrustBundleWrite(11, bundle)) + + client := pbpeering.NewPeeringServiceClient(s.ClientConn(t)) + + type testcase struct { + name string + req *pbpeering.TrustBundleReadRequest + token string + expect *pbpeering.PeeringTrustBundle + expectErr string + } + run := func(t *testing.T, tc testcase) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + t.Cleanup(cancel) + + resp, err := client.TrustBundleRead(external.ContextWithToken(ctx, tc.token), tc.req) + if tc.expectErr != "" { + require.Contains(t, err.Error(), tc.expectErr) + return + } + require.NoError(t, err) + prototest.AssertDeepEqual(t, tc.expect, resp.Bundle) + } + tcs := []testcase{ + { + name: "anonymous token lacks permissions", + req: &pbpeering.TrustBundleReadRequest{Name: "foo"}, + expectErr: "lacks permission 'service:write'", + }, + { + name: "service read token lacks permissions", + req: &pbpeering.TrustBundleReadRequest{ + Name: "my-peering", + }, + token: testTokenServiceReadSecret, + expectErr: "lacks permission 'service:write'", + }, + { + name: "with service write token", + req: &pbpeering.TrustBundleReadRequest{ + Name: "my-peering", + }, + token: testTokenServiceWriteSecret, + expect: bundle, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + run(t, tc) + }) + } +} + // Setup: // - Peerings "foo" and "bar" with trust bundles saved // - "api" service exported to both "foo" and "bar" @@ -667,6 +1055,116 @@ func TestPeeringService_PeeringDisabled(t *testing.T) { }) } +func TestPeeringService_TrustBundleListByService_ACLEnforcement(t *testing.T) { + // TODO(peering): see note on newTestServer, refactor to not use this + s := newTestServer(t, func(conf *consul.Config) { + conf.ACLsEnabled = true + conf.ACLResolverSettings.ACLDefaultPolicy = acl.PolicyDeny + }) + store := s.Server.FSM().State() + upsertTestACLs(t, s.Server.FSM().State()) + + var lastIdx uint64 = 10 + + lastIdx++ + require.NoError(t, s.Server.FSM().State().PeeringWrite(lastIdx, &pbpeering.Peering{ + ID: testUUID(t), + Name: "foo", + State: pbpeering.PeeringState_ESTABLISHING, + PeerServerName: "test", + PeerServerAddresses: []string{"addr1"}, + })) + + lastIdx++ + require.NoError(t, store.PeeringTrustBundleWrite(lastIdx, &pbpeering.PeeringTrustBundle{ + TrustDomain: "foo.com", + PeerName: "foo", + RootPEMs: []string{"foo-root-1"}, + })) + + lastIdx++ + require.NoError(t, store.EnsureNode(lastIdx, &structs.Node{ + Node: "my-node", Address: "127.0.0.1", + })) + + lastIdx++ + require.NoError(t, store.EnsureService(lastIdx, "my-node", &structs.NodeService{ + ID: "api", + Service: "api", + Port: 8000, + })) + + entry := structs.ExportedServicesConfigEntry{ + Name: "default", + Services: []structs.ExportedService{ + { + Name: "api", + Consumers: []structs.ServiceConsumer{ + { + PeerName: "foo", + }, + }, + }, + }, + } + require.NoError(t, entry.Normalize()) + require.NoError(t, entry.Validate()) + + lastIdx++ + require.NoError(t, store.EnsureConfigEntry(lastIdx, &entry)) + + client := pbpeering.NewPeeringServiceClient(s.ClientConn(t)) + + type testcase struct { + name string + req *pbpeering.TrustBundleListByServiceRequest + token string + expect []string + expectErr string + } + run := func(t *testing.T, tc testcase) { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + t.Cleanup(cancel) + + resp, err := client.TrustBundleListByService(external.ContextWithToken(ctx, tc.token), tc.req) + if tc.expectErr != "" { + require.Contains(t, err.Error(), tc.expectErr) + return + } + require.NoError(t, err) + require.Len(t, resp.Bundles, 1) + require.Equal(t, tc.expect, resp.Bundles[0].RootPEMs) + } + tcs := []testcase{ + { + name: "anonymous token lacks permissions", + req: &pbpeering.TrustBundleListByServiceRequest{ServiceName: "api"}, + expectErr: "lacks permission 'service:write'", + }, + { + name: "service read token lacks permission", + req: &pbpeering.TrustBundleListByServiceRequest{ + ServiceName: "api", + }, + token: testTokenServiceReadSecret, + expectErr: "lacks permission 'service:write'", + }, + { + name: "with service write token", + req: &pbpeering.TrustBundleListByServiceRequest{ + ServiceName: "api", + }, + token: testTokenServiceWriteSecret, + expect: []string{"foo-root-1"}, + }, + } + for _, tc := range tcs { + t.Run(tc.name, func(t *testing.T) { + run(t, tc) + }) + } +} + // newTestServer is copied from partition/service_test.go, with the addition of certs/cas. // TODO(peering): these are endpoint tests and should live in the agent/consul // package. Instead, these can be written around a mock client (see testing.go) @@ -831,6 +1329,87 @@ func newDefaultDeps(t *testing.T, c *consul.Config) consul.Deps { } } +func upsertTestACLs(t *testing.T, store *state.Store) { + var ( + testPolicyPeeringReadID = "43fed171-ad1d-4d3b-9df3-c99c1c835c37" + testPolicyPeeringWriteID = "cddb0821-e720-4411-bbdd-cc62ce417eac" + + testPolicyServiceReadID = "0e054136-f5d3-4627-a7e6-198f1df923d3" + testPolicyServiceWriteID = "b55e03f4-c9dd-4210-8d24-f7ea8e2a1918" + ) + policies := structs.ACLPolicies{ + { + ID: testPolicyPeeringReadID, + Name: "peering-read", + Rules: `peering = "read"`, + Syntax: acl.SyntaxCurrent, + }, + { + ID: testPolicyPeeringWriteID, + Name: "peering-write", + Rules: `peering = "write"`, + Syntax: acl.SyntaxCurrent, + }, + { + ID: testPolicyServiceReadID, + Name: "service-read", + Rules: `service "api" { policy = "read" }`, + Syntax: acl.SyntaxCurrent, + }, + { + ID: testPolicyServiceWriteID, + Name: "service-write", + Rules: `service "api" { policy = "write" }`, + Syntax: acl.SyntaxCurrent, + }, + } + require.NoError(t, store.ACLPolicyBatchSet(100, policies)) + + tokens := structs.ACLTokens{ + &structs.ACLToken{ + AccessorID: "22500c91-723c-4335-be8a-6697417dc35b", + SecretID: testTokenPeeringReadSecret, + Description: "peering read", + Policies: []structs.ACLTokenPolicyLink{ + { + ID: testPolicyPeeringReadID, + }, + }, + }, + &structs.ACLToken{ + AccessorID: "de924f93-cfec-404c-9a7e-c1c9b96b8cae", + SecretID: testTokenPeeringWriteSecret, + Description: "peering write", + Policies: []structs.ACLTokenPolicyLink{ + { + ID: testPolicyPeeringWriteID, + }, + }, + }, + &structs.ACLToken{ + AccessorID: "53c54f79-ffed-47d4-904e-e2e0e40c0a01", + SecretID: testTokenServiceReadSecret, + Description: "service read", + Policies: []structs.ACLTokenPolicyLink{ + { + ID: testPolicyServiceReadID, + }, + }, + }, + &structs.ACLToken{ + AccessorID: "a100fa5f-db72-49f0-8f61-aa1f9f92f657", + SecretID: testTokenServiceWriteSecret, + Description: "service write", + Policies: []structs.ACLTokenPolicyLink{ + { + ID: testPolicyServiceWriteID, + }, + }, + }, + } + require.NoError(t, store.ACLTokenBatchSet(101, tokens, state.ACLTokenSetOptions{})) +} + func setupTestPeering(t *testing.T, store *state.Store, name string, index uint64) string { t.Helper() err := store.PeeringWrite(index, &pbpeering.Peering{ diff --git a/agent/rpc/peering/testing.go b/agent/rpc/peering/testing.go index de64dda7a8..04f1bb2239 100644 --- a/agent/rpc/peering/testing.go +++ b/agent/rpc/peering/testing.go @@ -1,6 +1,7 @@ package peering import ( + "github.com/hashicorp/consul/acl" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/proto/pbpeering" ) @@ -53,6 +54,7 @@ func TestPeering(peerName string, state pbpeering.PeeringState, meta map[string] State: state, PeerID: validPeerID, Meta: meta, + Partition: acl.DefaultPartitionName, } } diff --git a/api/peering.go b/api/peering.go index bd24d98495..7a98ba9363 100644 --- a/api/peering.go +++ b/api/peering.go @@ -80,10 +80,8 @@ type PeeringGenerateTokenRequest struct { // PeerName is the name of the remote peer. PeerName string // Partition to be peered. - Partition string `json:",omitempty"` - Datacenter string `json:",omitempty"` - Token string `json:",omitempty"` - // Meta is a mapping of some string value to any other string value. + Partition string `json:",omitempty"` + // Meta is a mapping of some string value to any other string value Meta map[string]string `json:",omitempty"` // ServerExternalAddresses is a list of addresses to put into the generated token. This could be used to specify // load balancer(s) or external IPs to reach the servers from the dialing side, and will override any server @@ -103,9 +101,7 @@ type PeeringEstablishRequest struct { // The peering token returned from the peer's GenerateToken endpoint. PeeringToken string `json:",omitempty"` // Partition to be peered. - Partition string `json:",omitempty"` - Datacenter string `json:",omitempty"` - Token string `json:",omitempty"` + Partition string `json:",omitempty"` // Meta is a mapping of some string value to any other string value Meta map[string]string `json:",omitempty"` } diff --git a/api/peering_test.go b/api/peering_test.go index 8a42a454b6..79c8983ce7 100644 --- a/api/peering_test.go +++ b/api/peering_test.go @@ -37,6 +37,97 @@ func peerExistsInPeerListings(peer *Peering, peerings []*Peering) bool { return false } +func TestAPI_Peering_ACLDeny(t *testing.T) { + c, s := makeACLClient(t) + defer s.Stop() + + peerings := c.Peerings() + + testutil.RunStep(t, "generate token", func(t *testing.T) { + req := PeeringGenerateTokenRequest{PeerName: "peer1"} + + testutil.RunStep(t, "without ACL token", func(t *testing.T) { + _, _, err := peerings.GenerateToken(context.Background(), req, &WriteOptions{Token: "anonymous"}) + require.Error(t, err) + testutil.RequireErrorContains(t, err, "Permission denied") + }) + + testutil.RunStep(t, "with ACL token", func(t *testing.T) { + resp, wm, err := peerings.GenerateToken(context.Background(), req, &WriteOptions{Token: "root"}) + require.NoError(t, err) + require.NotNil(t, wm) + require.NotNil(t, resp) + }) + }) + + testutil.RunStep(t, "establish peering", func(t *testing.T) { + tokenJSON := `{"ServerAddresses":["127.0.0.1:8502"],"ServerName":"foo","PeerID":"716af65f-b844-f3bb-8aef-cfd7949f6873"}` + tokenB64 := base64.StdEncoding.EncodeToString([]byte(tokenJSON)) + + req := PeeringEstablishRequest{ + PeerName: "peer2", + PeeringToken: tokenB64, + } + testutil.RunStep(t, "without ACL token", func(t *testing.T) { + _, _, err := peerings.Establish(context.Background(), req, &WriteOptions{Token: "anonymous"}) + require.Error(t, err) + testutil.RequireErrorContains(t, err, "Permission denied") + }) + + testutil.RunStep(t, "with ACL token", func(t *testing.T) { + resp, wm, err := peerings.Establish(context.Background(), req, &WriteOptions{Token: "root"}) + require.NoError(t, err) + require.NotNil(t, wm) + require.NotNil(t, resp) + }) + }) + + testutil.RunStep(t, "read peering", func(t *testing.T) { + testutil.RunStep(t, "without ACL token", func(t *testing.T) { + _, _, err := peerings.Read(context.Background(), "peer1", &QueryOptions{Token: "anonymous"}) + require.Error(t, err) + testutil.RequireErrorContains(t, err, "Permission denied") + }) + + testutil.RunStep(t, "with ACL token", func(t *testing.T) { + resp, qm, err := peerings.Read(context.Background(), "peer1", &QueryOptions{Token: "root"}) + require.NoError(t, err) + require.NotNil(t, qm) + require.NotNil(t, resp) + }) + }) + + testutil.RunStep(t, "list peerings", func(t *testing.T) { + testutil.RunStep(t, "without ACL token", func(t *testing.T) { + _, _, err := peerings.List(context.Background(), &QueryOptions{Token: "anonymous"}) + require.Error(t, err) + testutil.RequireErrorContains(t, err, "Permission denied") + }) + + testutil.RunStep(t, "with ACL token", func(t *testing.T) { + resp, qm, err := peerings.List(context.Background(), &QueryOptions{Token: "root"}) + require.NoError(t, err) + require.NotNil(t, qm) + require.NotNil(t, resp) + require.Len(t, resp, 2) + }) + }) + + testutil.RunStep(t, "delete peering", func(t *testing.T) { + testutil.RunStep(t, "without ACL token", func(t *testing.T) { + _, err := peerings.Delete(context.Background(), "peer1", &WriteOptions{Token: "anonymous"}) + require.Error(t, err) + testutil.RequireErrorContains(t, err, "Permission denied") + }) + + testutil.RunStep(t, "with ACL token", func(t *testing.T) { + wm, err := peerings.Delete(context.Background(), "peer1", &WriteOptions{Token: "root"}) + require.NoError(t, err) + require.NotNil(t, wm) + }) + }) +} + func TestAPI_Peering_Read_ErrorHandling(t *testing.T) { t.Parallel() @@ -115,25 +206,6 @@ func TestAPI_Peering_List(t *testing.T) { }) } -func TestAPI_Peering_GenerateToken(t *testing.T) { - t.Parallel() - - c, s := makeClientWithCA(t) - defer s.Stop() - s.WaitForSerfCheck(t) - - ctx, cancel := context.WithTimeout(context.Background(), DefaultCtxDuration) - defer cancel() - - peerings := c.Peerings() - - t.Run("cannot have GenerateToken forward DC requests", func(t *testing.T) { - // Try to generate a token in dc2 - _, _, err := peerings.GenerateToken(ctx, PeeringGenerateTokenRequest{PeerName: "peer2", Datacenter: "dc2"}, nil) - require.Error(t, err) - }) -} - func TestAPI_Peering_GenerateToken_ExternalAddresses(t *testing.T) { t.Parallel() @@ -163,9 +235,6 @@ func TestAPI_Peering_GenerateToken_ExternalAddresses(t *testing.T) { require.Contains(t, string(tokenJSON), externalAddress) } -// TODO(peering): cover the following test cases: bad/ malformed input, peering with wrong token, -// peering with the wrong PeerName - // TestAPI_Peering_GenerateToken_Read_Establish_Delete tests the following use case: // a server creates a peering token, reads the token, then another server calls establish peering // finally, we delete the token on the first server @@ -217,7 +286,6 @@ func TestAPI_Peering_GenerateToken_Read_Establish_Delete(t *testing.T) { testutil.RunStep(t, "establish peering", func(t *testing.T) { i := PeeringEstablishRequest{ - Datacenter: c2.config.Datacenter, PeerName: "peer1", PeeringToken: token1, Meta: map[string]string{"foo": "bar"}, diff --git a/proto/pbpeering/peering.gen.go b/proto/pbpeering/peering.gen.go index b7afc6a4ce..5707e3b6c5 100644 --- a/proto/pbpeering/peering.gen.go +++ b/proto/pbpeering/peering.gen.go @@ -11,8 +11,6 @@ func EstablishRequestToAPI(s *EstablishRequest, t *api.PeeringEstablishRequest) t.PeerName = s.PeerName t.PeeringToken = s.PeeringToken t.Partition = s.Partition - t.Datacenter = s.Datacenter - t.Token = s.Token t.Meta = s.Meta } func EstablishRequestFromAPI(t *api.PeeringEstablishRequest, s *EstablishRequest) { @@ -22,8 +20,6 @@ func EstablishRequestFromAPI(t *api.PeeringEstablishRequest, s *EstablishRequest s.PeerName = t.PeerName s.PeeringToken = t.PeeringToken s.Partition = t.Partition - s.Datacenter = t.Datacenter - s.Token = t.Token s.Meta = t.Meta } func EstablishResponseToAPI(s *EstablishResponse, t *api.PeeringEstablishResponse) { @@ -42,8 +38,6 @@ func GenerateTokenRequestToAPI(s *GenerateTokenRequest, t *api.PeeringGenerateTo } t.PeerName = s.PeerName t.Partition = s.Partition - t.Datacenter = s.Datacenter - t.Token = s.Token t.Meta = s.Meta t.ServerExternalAddresses = s.ServerExternalAddresses } @@ -53,8 +47,6 @@ func GenerateTokenRequestFromAPI(t *api.PeeringGenerateTokenRequest, s *Generate } s.PeerName = t.PeerName s.Partition = t.Partition - s.Datacenter = t.Datacenter - s.Token = t.Token s.Meta = t.Meta s.ServerExternalAddresses = t.ServerExternalAddresses } diff --git a/proto/pbpeering/peering.go b/proto/pbpeering/peering.go index 5de1dc9bc0..f5092ded2e 100644 --- a/proto/pbpeering/peering.go +++ b/proto/pbpeering/peering.go @@ -1,86 +1,68 @@ package pbpeering import ( - "strconv" "time" "github.com/golang/protobuf/ptypes/timestamp" - "github.com/mitchellh/hashstructure" - - "github.com/hashicorp/consul/agent/cache" "github.com/hashicorp/consul/agent/structs" "github.com/hashicorp/consul/api" "github.com/hashicorp/consul/lib" ) -// TODO(peering): These are byproducts of not embedding -// types in our protobuf definitions and are temporary; -// Hoping to replace them with 1 or 2 methods per request -// using https://github.com/hashicorp/consul/pull/12507 - // RequestDatacenter implements structs.RPCInfo func (req *GenerateTokenRequest) RequestDatacenter() string { - return req.Datacenter + // Cross-datacenter requests are not allowed for peering actions because + // they rely on WAN-federation. + return "" } -// IsRead implements structs.RPCInfo -func (req *GenerateTokenRequest) IsRead() bool { - return false +// RequestDatacenter implements structs.RPCInfo +func (req *EstablishRequest) RequestDatacenter() string { + // Cross-datacenter requests are not allowed for peering actions because + // they rely on WAN-federation. + return "" } -// AllowStaleRead implements structs.RPCInfo -func (req *GenerateTokenRequest) AllowStaleRead() bool { - return false +// RequestDatacenter implements structs.RPCInfo +func (req *PeeringReadRequest) RequestDatacenter() string { + // Cross-datacenter requests are not allowed for peering actions because + // they rely on WAN-federation. + return "" } -// TokenSecret implements structs.RPCInfo -func (req *GenerateTokenRequest) TokenSecret() string { - return req.Token +// RequestDatacenter implements structs.RPCInfo +func (req *PeeringListRequest) RequestDatacenter() string { + // Cross-datacenter requests are not allowed for peering actions because + // they rely on WAN-federation. + return "" } -// SetTokenSecret implements structs.RPCInfo -func (req *GenerateTokenRequest) SetTokenSecret(token string) { - req.Token = token +// RequestDatacenter implements structs.RPCInfo +func (req *PeeringWriteRequest) RequestDatacenter() string { + // Cross-datacenter requests are not allowed for peering actions because + // they rely on WAN-federation. + return "" } -// HasTimedOut implements structs.RPCInfo -func (req *GenerateTokenRequest) HasTimedOut(start time.Time, rpcHoldTimeout, _, _ time.Duration) (bool, error) { - return time.Since(start) > rpcHoldTimeout, nil +// RequestDatacenter implements structs.RPCInfo +func (req *PeeringDeleteRequest) RequestDatacenter() string { + // Cross-datacenter requests are not allowed for peering actions because + // they rely on WAN-federation. + return "" } -// Timeout implements structs.RPCInfo -func (msg *GenerateTokenRequest) Timeout(rpcHoldTimeout time.Duration, maxQueryTime time.Duration, defaultQueryTime time.Duration) time.Duration { - return rpcHoldTimeout +// RequestDatacenter implements structs.RPCInfo +func (req *TrustBundleReadRequest) RequestDatacenter() string { + // Cross-datacenter requests are not allowed for peering actions because + // they rely on WAN-federation. + return "" } -// IsRead implements structs.RPCInfo -func (req *EstablishRequest) IsRead() bool { - return false -} - -// AllowStaleRead implements structs.RPCInfo -func (req *EstablishRequest) AllowStaleRead() bool { - return false -} - -// TokenSecret implements structs.RPCInfo -func (req *EstablishRequest) TokenSecret() string { - return req.Token -} - -// SetTokenSecret implements structs.RPCInfo -func (req *EstablishRequest) SetTokenSecret(token string) { - req.Token = token -} - -// HasTimedOut implements structs.RPCInfo -func (req *EstablishRequest) HasTimedOut(start time.Time, rpcHoldTimeout, _, _ time.Duration) (bool, error) { - return time.Since(start) > rpcHoldTimeout, nil -} - -// Timeout implements structs.RPCInfo -func (msg *EstablishRequest) Timeout(rpcHoldTimeout time.Duration, maxQueryTime time.Duration, defaultQueryTime time.Duration) time.Duration { - return rpcHoldTimeout +// RequestDatacenter implements structs.RPCInfo +func (req *TrustBundleListByServiceRequest) RequestDatacenter() string { + // Cross-datacenter requests are not allowed for peering actions because + // they rely on WAN-federation. + return "" } // ShouldDial returns true when the peering was stored via the peering initiation endpoint, @@ -95,34 +77,6 @@ func (x PeeringState) GoString() string { return x.String() } -func (r *TrustBundleReadRequest) CacheInfo() cache.RequestInfo { - info := cache.RequestInfo{ - // TODO(peering): Revisit whether this is the token to use once request types accept a token. - Token: r.Token(), - Datacenter: r.Datacenter, - MinIndex: 0, - Timeout: 0, - MustRevalidate: false, - - // TODO(peering): Cache.notifyPollingQuery polls at this interval. We need to revisit how that polling works. - // Using an exponential backoff when the result hasn't changed may be preferable. - MaxAge: 1 * time.Second, - } - - v, err := hashstructure.Hash([]interface{}{ - r.Partition, - r.Name, - }, nil) - if err == nil { - // If there is an error, we don't set the key. A blank key forces - // no cache for this request so the request is forwarded directly - // to the server. - info.Key = strconv.FormatUint(v, 10) - } - - return info -} - // ConcatenatedRootPEMs concatenates and returns all PEM-encoded public certificates // in a peer's trust bundle. func (b *PeeringTrustBundle) ConcatenatedRootPEMs() string { @@ -242,35 +196,6 @@ func NewEstablishRequestFromAPI(req *api.PeeringEstablishRequest) *EstablishRequ return t } -func (r *TrustBundleListByServiceRequest) CacheInfo() cache.RequestInfo { - info := cache.RequestInfo{ - // TODO(peering): Revisit whether this is the token to use once request types accept a token. - Token: r.Token(), - Datacenter: r.Datacenter, - MinIndex: 0, - Timeout: 0, - MustRevalidate: false, - - // TODO(peering): Cache.notifyPollingQuery polls at this interval. We need to revisit how that polling works. - // Using an exponential backoff when the result hasn't changed may be preferable. - MaxAge: 1 * time.Second, - } - - v, err := hashstructure.Hash([]interface{}{ - r.Partition, - r.Namespace, - r.ServiceName, - }, nil) - if err == nil { - // If there is an error, we don't set the key. A blank key forces - // no cache for this request so the request is forwarded directly - // to the server. - info.Key = strconv.FormatUint(v, 10) - } - - return info -} - func TimePtrFromProto(s *timestamp.Timestamp) *time.Time { if s == nil { return nil diff --git a/proto/pbpeering/peering.pb.go b/proto/pbpeering/peering.pb.go index a5e0f2cb51..7c2a8b478f 100644 --- a/proto/pbpeering/peering.pb.go +++ b/proto/pbpeering/peering.pb.go @@ -140,9 +140,11 @@ type Peering struct { // ExportedServiceCount is the count of how many services are exported to this peering. ExportedServiceCount uint64 `protobuf:"varint,14,opt,name=ExportedServiceCount,proto3" json:"ExportedServiceCount,omitempty"` // CreateIndex is the Raft index at which the Peering was created. - CreateIndex uint64 `protobuf:"varint,11,opt,name=CreateIndex,proto3" json:"CreateIndex,omitempty"` + // @gotags: bexpr:"-" + CreateIndex uint64 `protobuf:"varint,11,opt,name=CreateIndex,proto3" json:"CreateIndex,omitempty" bexpr:"-"` // ModifyIndex is the latest Raft index at which the Peering. was modified. - ModifyIndex uint64 `protobuf:"varint,12,opt,name=ModifyIndex,proto3" json:"ModifyIndex,omitempty"` + // @gotags: bexpr:"-" + ModifyIndex uint64 `protobuf:"varint,12,opt,name=ModifyIndex,proto3" json:"ModifyIndex,omitempty" bexpr:"-"` } func (x *Peering) Reset() { @@ -293,9 +295,11 @@ type PeeringTrustBundle struct { // which sent this trust bundle. Used for generating SpiffeIDs. ExportedPartition string `protobuf:"bytes,5,opt,name=ExportedPartition,proto3" json:"ExportedPartition,omitempty"` // CreateIndex is the Raft index at which the trust domain was created. - CreateIndex uint64 `protobuf:"varint,6,opt,name=CreateIndex,proto3" json:"CreateIndex,omitempty"` + // @gotags: bexpr:"-" + CreateIndex uint64 `protobuf:"varint,6,opt,name=CreateIndex,proto3" json:"CreateIndex,omitempty" bexpr:"-"` // ModifyIndex is the latest Raft index at which the trust bundle was modified. - ModifyIndex uint64 `protobuf:"varint,7,opt,name=ModifyIndex,proto3" json:"ModifyIndex,omitempty"` + // @gotags: bexpr:"-" + ModifyIndex uint64 `protobuf:"varint,7,opt,name=ModifyIndex,proto3" json:"ModifyIndex,omitempty" bexpr:"-"` } func (x *PeeringTrustBundle) Reset() { @@ -379,15 +383,14 @@ func (x *PeeringTrustBundle) GetModifyIndex() uint64 { return 0 } -// @consul-rpc-glue: Datacenter,LeaderReadTODO +// @consul-rpc-glue: LeaderReadTODO type PeeringReadRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` - Partition string `protobuf:"bytes,2,opt,name=Partition,proto3" json:"Partition,omitempty"` - Datacenter string `protobuf:"bytes,3,opt,name=Datacenter,proto3" json:"Datacenter,omitempty"` + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` + Partition string `protobuf:"bytes,2,opt,name=Partition,proto3" json:"Partition,omitempty"` } func (x *PeeringReadRequest) Reset() { @@ -436,13 +439,6 @@ func (x *PeeringReadRequest) GetPartition() string { return "" } -func (x *PeeringReadRequest) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - type PeeringReadResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -490,14 +486,13 @@ func (x *PeeringReadResponse) GetPeering() *Peering { return nil } -// @consul-rpc-glue: Datacenter,LeaderReadTODO +// @consul-rpc-glue: LeaderReadTODO type PeeringListRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Partition string `protobuf:"bytes,1,opt,name=Partition,proto3" json:"Partition,omitempty"` - Datacenter string `protobuf:"bytes,2,opt,name=Datacenter,proto3" json:"Datacenter,omitempty"` + Partition string `protobuf:"bytes,1,opt,name=Partition,proto3" json:"Partition,omitempty"` } func (x *PeeringListRequest) Reset() { @@ -539,13 +534,6 @@ func (x *PeeringListRequest) GetPartition() string { return "" } -func (x *PeeringListRequest) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - type PeeringListResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -593,17 +581,14 @@ func (x *PeeringListResponse) GetPeerings() []*Peering { return nil } -// @consul-rpc-glue: Datacenter,WriteTODO type PeeringWriteRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields Peering *Peering `protobuf:"bytes,1,opt,name=Peering,proto3" json:"Peering,omitempty"` - //TODO(peering): what to do with embedded write request? - Datacenter string `protobuf:"bytes,2,opt,name=Datacenter,proto3" json:"Datacenter,omitempty"` // Meta is a mapping of some string value to any other string value - Meta map[string]string `protobuf:"bytes,3,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Meta map[string]string `protobuf:"bytes,2,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *PeeringWriteRequest) Reset() { @@ -645,13 +630,6 @@ func (x *PeeringWriteRequest) GetPeering() *Peering { return nil } -func (x *PeeringWriteRequest) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - func (x *PeeringWriteRequest) GetMeta() map[string]string { if x != nil { return x.Meta @@ -698,7 +676,6 @@ func (*PeeringWriteResponse) Descriptor() ([]byte, []int) { return file_proto_pbpeering_peering_proto_rawDescGZIP(), []int{7} } -// @consul-rpc-glue: Datacenter,WriteTODO type PeeringDeleteRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -706,8 +683,6 @@ type PeeringDeleteRequest struct { Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` Partition string `protobuf:"bytes,2,opt,name=Partition,proto3" json:"Partition,omitempty"` - //TODO(peering): what to do with embedded write request? - Datacenter string `protobuf:"bytes,3,opt,name=Datacenter,proto3" json:"Datacenter,omitempty"` } func (x *PeeringDeleteRequest) Reset() { @@ -756,13 +731,6 @@ func (x *PeeringDeleteRequest) GetPartition() string { return "" } -func (x *PeeringDeleteRequest) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - type PeeringDeleteResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -801,7 +769,6 @@ func (*PeeringDeleteResponse) Descriptor() ([]byte, []int) { return file_proto_pbpeering_peering_proto_rawDescGZIP(), []int{9} } -// @consul-rpc-glue: Datacenter,ReadTODO type TrustBundleListByServiceRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -811,9 +778,6 @@ type TrustBundleListByServiceRequest struct { Namespace string `protobuf:"bytes,2,opt,name=Namespace,proto3" json:"Namespace,omitempty"` Partition string `protobuf:"bytes,3,opt,name=Partition,proto3" json:"Partition,omitempty"` Kind string `protobuf:"bytes,4,opt,name=Kind,proto3" json:"Kind,omitempty"` - // these are common fields required for implementing structs.RPCInfo methods - // that are used to forward requests - Datacenter string `protobuf:"bytes,5,opt,name=Datacenter,proto3" json:"Datacenter,omitempty"` } func (x *TrustBundleListByServiceRequest) Reset() { @@ -876,13 +840,6 @@ func (x *TrustBundleListByServiceRequest) GetKind() string { return "" } -func (x *TrustBundleListByServiceRequest) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - type TrustBundleListByServiceResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -938,7 +895,6 @@ func (x *TrustBundleListByServiceResponse) GetBundles() []*PeeringTrustBundle { return nil } -// @consul-rpc-glue: Datacenter,ReadTODO type TrustBundleReadRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -946,9 +902,6 @@ type TrustBundleReadRequest struct { Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` Partition string `protobuf:"bytes,2,opt,name=Partition,proto3" json:"Partition,omitempty"` - // these are common fields required for implementing structs.RPCInfo methods - // that are used to forward requests - Datacenter string `protobuf:"bytes,3,opt,name=Datacenter,proto3" json:"Datacenter,omitempty"` } func (x *TrustBundleReadRequest) Reset() { @@ -997,13 +950,6 @@ func (x *TrustBundleReadRequest) GetPartition() string { return "" } -func (x *TrustBundleReadRequest) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - type TrustBundleReadResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1059,6 +1005,7 @@ func (x *TrustBundleReadResponse) GetBundle() *PeeringTrustBundle { return nil } +// This is a purely internal type and does not require query metadata. type PeeringTerminateByIDRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1144,15 +1091,12 @@ func (*PeeringTerminateByIDResponse) Descriptor() ([]byte, []int) { return file_proto_pbpeering_peering_proto_rawDescGZIP(), []int{15} } -// @consul-rpc-glue: Datacenter type PeeringTrustBundleWriteRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields PeeringTrustBundle *PeeringTrustBundle `protobuf:"bytes,1,opt,name=PeeringTrustBundle,proto3" json:"PeeringTrustBundle,omitempty"` - //TODO(peering): what to do with embedded write request? - Datacenter string `protobuf:"bytes,2,opt,name=Datacenter,proto3" json:"Datacenter,omitempty"` } func (x *PeeringTrustBundleWriteRequest) Reset() { @@ -1194,13 +1138,6 @@ func (x *PeeringTrustBundleWriteRequest) GetPeeringTrustBundle() *PeeringTrustBu return nil } -func (x *PeeringTrustBundleWriteRequest) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - type PeeringTrustBundleWriteResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1239,7 +1176,6 @@ func (*PeeringTrustBundleWriteResponse) Descriptor() ([]byte, []int) { return file_proto_pbpeering_peering_proto_rawDescGZIP(), []int{17} } -// @consul-rpc-glue: Datacenter type PeeringTrustBundleDeleteRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1247,8 +1183,6 @@ type PeeringTrustBundleDeleteRequest struct { Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` Partition string `protobuf:"bytes,2,opt,name=Partition,proto3" json:"Partition,omitempty"` - //TODO(peering): what to do with embedded write request? - Datacenter string `protobuf:"bytes,3,opt,name=Datacenter,proto3" json:"Datacenter,omitempty"` } func (x *PeeringTrustBundleDeleteRequest) Reset() { @@ -1297,13 +1231,6 @@ func (x *PeeringTrustBundleDeleteRequest) GetPartition() string { return "" } -func (x *PeeringTrustBundleDeleteRequest) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - type PeeringTrustBundleDeleteResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1356,10 +1283,6 @@ type GenerateTokenRequest struct { PeerName string `protobuf:"bytes,1,opt,name=PeerName,proto3" json:"PeerName,omitempty"` // Partition is the local partition being peered. Partition string `protobuf:"bytes,2,opt,name=Partition,proto3" json:"Partition,omitempty"` - // these are common fields required for implementing structs.RPCInfo methods - // that are used to forward requests - Datacenter string `protobuf:"bytes,3,opt,name=Datacenter,proto3" json:"Datacenter,omitempty"` - Token string `protobuf:"bytes,4,opt,name=Token,proto3" json:"Token,omitempty"` // Meta is a mapping of some string value to any other string value Meta map[string]string `protobuf:"bytes,5,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` // ServerExternalAddresses is a list of addresses to put into the generated token. This could be used to specify @@ -1414,20 +1337,6 @@ func (x *GenerateTokenRequest) GetPartition() string { return "" } -func (x *GenerateTokenRequest) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - -func (x *GenerateTokenRequest) GetToken() string { - if x != nil { - return x.Token - } - return "" -} - func (x *GenerateTokenRequest) GetMeta() map[string]string { if x != nil { return x.Meta @@ -1496,8 +1405,6 @@ func (x *GenerateTokenResponse) GetPeeringToken() string { return "" } -// @consul-rpc-glue: Datacenter -// // mog annotation: // // target=github.com/hashicorp/consul/api.PeeringEstablishRequest @@ -1514,12 +1421,8 @@ type EstablishRequest struct { PeeringToken string `protobuf:"bytes,2,opt,name=PeeringToken,proto3" json:"PeeringToken,omitempty"` // Partition is the local partition being peered. Partition string `protobuf:"bytes,3,opt,name=Partition,proto3" json:"Partition,omitempty"` - // these are common fields required for implementing structs.RPCInfo methods - // that are used to forward requests - Datacenter string `protobuf:"bytes,4,opt,name=Datacenter,proto3" json:"Datacenter,omitempty"` - Token string `protobuf:"bytes,5,opt,name=Token,proto3" json:"Token,omitempty"` // Meta is a mapping of some string value to any other string value - Meta map[string]string `protobuf:"bytes,6,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Meta map[string]string `protobuf:"bytes,4,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` } func (x *EstablishRequest) Reset() { @@ -1575,20 +1478,6 @@ func (x *EstablishRequest) GetPartition() string { return "" } -func (x *EstablishRequest) GetDatacenter() string { - if x != nil { - return x.Datacenter - } - return "" -} - -func (x *EstablishRequest) GetToken() string { - if x != nil { - return x.Token - } - return "" -} - func (x *EstablishRequest) GetMeta() map[string]string { if x != nil { return x.Meta @@ -1596,7 +1485,6 @@ func (x *EstablishRequest) GetMeta() map[string]string { return nil } -// // mog annotation: // // target=github.com/hashicorp/consul/api.PeeringEstablishResponse @@ -1706,39 +1594,33 @@ var file_proto_pbpeering_peering_proto_rawDesc = []byte{ 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x20, 0x0a, 0x0b, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x79, 0x49, - 0x6e, 0x64, 0x65, 0x78, 0x22, 0x66, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, + 0x6e, 0x64, 0x65, 0x78, 0x22, 0x46, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, - 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x5b, 0x0a, 0x13, + 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x5b, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x44, 0x0a, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, - 0x52, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x52, 0x0a, 0x12, 0x50, 0x65, 0x65, + 0x52, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x22, 0x32, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, - 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x5d, 0x0a, + 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x5d, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, - 0x6e, 0x67, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x22, 0x8a, 0x02, 0x0a, + 0x6e, 0x67, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x73, 0x22, 0xea, 0x01, 0x0a, 0x13, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x44, 0x0a, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, - 0x67, 0x52, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, - 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, - 0x74, 0x61, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x67, 0x52, 0x07, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x54, 0x0a, 0x04, 0x4d, 0x65, + 0x74, 0x61, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, @@ -1748,15 +1630,13 @@ var file_proto_pbpeering_peering_proto_rawDesc = []byte{ 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, 0x16, 0x0a, 0x14, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0x68, 0x0a, 0x14, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, + 0x65, 0x22, 0x48, 0x0a, 0x14, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x44, - 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x17, 0x0a, 0x15, 0x50, + 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x17, 0x0a, 0x15, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xb3, 0x01, 0x0a, 0x1f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x93, 0x01, 0x0a, 0x1f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x53, @@ -1765,9 +1645,7 @@ var file_proto_pbpeering_peering_proto_rawDesc = []byte{ 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, - 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x89, 0x01, 0x0a, 0x20, 0x54, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x22, 0x89, 0x01, 0x0a, 0x20, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, @@ -1776,14 +1654,12 @@ var file_proto_pbpeering_peering_proto_rawDesc = []byte{ 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x07, 0x42, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x22, 0x6a, 0x0a, 0x16, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, + 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x73, 0x22, 0x4a, 0x0a, 0x16, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, - 0x65, 0x72, 0x22, 0x7e, 0x0a, 0x17, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, + 0x6f, 0x6e, 0x22, 0x7e, 0x0a, 0x17, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x4d, 0x0a, 0x06, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x02, 0x20, @@ -1796,7 +1672,7 @@ var file_proto_pbpeering_peering_proto_rawDesc = []byte{ 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x49, 0x44, 0x22, 0x1e, 0x0a, 0x1c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x42, 0x79, 0x49, 0x44, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x22, 0xa7, 0x01, 0x0a, 0x1e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, + 0x65, 0x22, 0x87, 0x01, 0x0a, 0x1e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x65, 0x0a, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, @@ -1804,159 +1680,149 @@ var file_proto_pbpeering_peering_proto_rawDesc = []byte{ 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x12, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, - 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x44, - 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x22, 0x21, 0x0a, 0x1f, 0x50, + 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x22, 0x21, 0x0a, 0x1f, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, - 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x73, + 0x65, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x53, 0x0a, 0x1f, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, - 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, - 0x74, 0x65, 0x72, 0x22, 0x22, 0x0a, 0x20, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, + 0x69, 0x6f, 0x6e, 0x22, 0x22, 0x0a, 0x20, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xd0, 0x02, 0x0a, 0x14, 0x47, 0x65, 0x6e, 0x65, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9a, 0x02, 0x0a, 0x14, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, - 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x12, 0x55, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, - 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x55, 0x0a, 0x04, 0x4d, 0x65, + 0x74, 0x61, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, + 0x61, 0x12, 0x38, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x17, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x4d, + 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 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, 0x3b, 0x0a, 0x15, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, + 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x22, 0xfc, 0x01, 0x0a, 0x10, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x6b, + 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, + 0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x51, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, + 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, - 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x38, 0x0a, 0x17, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, - 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x17, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, - 0x73, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, - 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, - 0x12, 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, 0x3b, 0x0a, 0x15, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, - 0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xb2, 0x02, 0x0a, 0x10, 0x45, 0x73, 0x74, 0x61, - 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, - 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, - 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1c, 0x0a, 0x09, - 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x44, 0x61, - 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x44, 0x61, 0x74, 0x61, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x12, 0x51, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, - 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, - 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, - 0x6e, 0x67, 0x2e, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, - 0x65, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, - 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, - 0x65, 0x79, 0x12, 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, 0x13, 0x0a, 0x11, - 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x2a, 0x73, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x00, - 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x01, 0x12, 0x10, 0x0a, - 0x0c, 0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, - 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x03, 0x12, 0x0b, 0x0a, 0x07, 0x46, - 0x41, 0x49, 0x4c, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x45, 0x4c, 0x45, - 0x54, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x45, 0x52, 0x4d, 0x49, 0x4e, - 0x41, 0x54, 0x45, 0x44, 0x10, 0x06, 0x32, 0xc0, 0x08, 0x0a, 0x0e, 0x50, 0x65, 0x65, 0x72, 0x69, - 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x0d, 0x47, 0x65, - 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x37, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, - 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, - 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x76, - 0x0a, 0x09, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x12, 0x33, 0x2e, 0x68, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, - 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, - 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x61, 0x64, 0x12, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, - 0x67, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, - 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, - 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, - 0x69, 0x73, 0x74, 0x12, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, - 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, - 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, - 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x68, 0x61, 0x73, - 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, - 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x0d, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x12, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, - 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, - 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7f, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, - 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, - 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x1a, 0x37, 0x0a, 0x09, 0x4d, 0x65, 0x74, 0x61, 0x45, + 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 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, 0x13, 0x0a, 0x11, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x73, 0x0a, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x44, 0x45, 0x46, 0x49, 0x4e, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x45, 0x4e, 0x44, 0x49, 0x4e, 0x47, 0x10, + 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x45, 0x53, 0x54, 0x41, 0x42, 0x4c, 0x49, 0x53, 0x48, 0x49, 0x4e, + 0x47, 0x10, 0x02, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x03, 0x12, + 0x0b, 0x0a, 0x07, 0x46, 0x41, 0x49, 0x4c, 0x49, 0x4e, 0x47, 0x10, 0x04, 0x12, 0x0c, 0x0a, 0x08, + 0x44, 0x45, 0x4c, 0x45, 0x54, 0x49, 0x4e, 0x47, 0x10, 0x05, 0x12, 0x0e, 0x0a, 0x0a, 0x54, 0x45, + 0x52, 0x4d, 0x49, 0x4e, 0x41, 0x54, 0x45, 0x44, 0x10, 0x06, 0x32, 0xc0, 0x08, 0x0a, 0x0e, 0x50, + 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x82, 0x01, + 0x0a, 0x0d, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, - 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0xa3, 0x01, 0x0a, 0x18, 0x54, 0x72, 0x75, - 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, - 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, - 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x76, 0x0a, 0x09, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x12, + 0x33, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, + 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, + 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, + 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x45, 0x73, 0x74, 0x61, 0x62, 0x6c, 0x69, + 0x73, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x0b, 0x50, 0x65, + 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x12, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, + 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, + 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x36, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, + 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, + 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7c, 0x0a, 0x0b, 0x50, 0x65, 0x65, 0x72, + 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x35, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, + 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, + 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, + 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, + 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, + 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x82, 0x01, 0x0a, 0x0d, 0x50, 0x65, 0x65, 0x72, 0x69, + 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, + 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, + 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, + 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7f, 0x0a, 0x0c, 0x50, + 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x36, 0x2e, 0x68, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, + 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x37, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x57, + 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0xa3, 0x01, 0x0a, + 0x18, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, + 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x42, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x42, 0x79, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x88, - 0x01, 0x0a, 0x0f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, - 0x61, 0x64, 0x12, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, - 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, - 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, - 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3a, 0x2e, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x43, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, - 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x8a, 0x02, 0x0a, 0x25, 0x63, 0x6f, - 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, - 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, - 0x69, 0x6e, 0x67, 0x42, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x6f, 0x74, - 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, - 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x50, 0xaa, 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, - 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0xca, 0x02, 0x21, 0x48, 0x61, - 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, - 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0xe2, - 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, + 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x4c, 0x69, 0x73, + 0x74, 0x42, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x88, 0x01, 0x0a, 0x0f, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, + 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x12, 0x39, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, + 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, + 0x61, 0x6c, 0x2e, 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, + 0x42, 0x75, 0x6e, 0x64, 0x6c, 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x3a, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x65, + 0x65, 0x72, 0x69, 0x6e, 0x67, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x42, 0x75, 0x6e, 0x64, 0x6c, + 0x65, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x8a, 0x02, + 0x0a, 0x25, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, + 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, + 0x70, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x42, 0x0c, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, + 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, + 0x6e, 0x73, 0x75, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x70, 0x62, 0x70, 0x65, 0x65, + 0x72, 0x69, 0x6e, 0x67, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, 0x50, 0xaa, 0x02, 0x21, 0x48, 0x61, + 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, + 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0xca, + 0x02, 0x21, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x50, 0x65, 0x65, 0x72, - 0x69, 0x6e, 0x67, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, - 0x02, 0x24, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, - 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x50, - 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x6e, 0x67, 0xe2, 0x02, 0x2d, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, + 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, + 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0xea, 0x02, 0x24, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, + 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x3a, 0x3a, 0x50, 0x65, 0x65, 0x72, 0x69, 0x6e, 0x67, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( diff --git a/proto/pbpeering/peering.proto b/proto/pbpeering/peering.proto index fc29d2458d..2f7c9858f4 100644 --- a/proto/pbpeering/peering.proto +++ b/proto/pbpeering/peering.proto @@ -105,9 +105,11 @@ message Peering { uint64 ExportedServiceCount = 14; // CreateIndex is the Raft index at which the Peering was created. + // @gotags: bexpr:"-" uint64 CreateIndex = 11; // ModifyIndex is the latest Raft index at which the Peering. was modified. + // @gotags: bexpr:"-" uint64 ModifyIndex = 12; } @@ -130,79 +132,56 @@ message PeeringTrustBundle { string ExportedPartition = 5; // CreateIndex is the Raft index at which the trust domain was created. + // @gotags: bexpr:"-" uint64 CreateIndex = 6; // ModifyIndex is the latest Raft index at which the trust bundle was modified. + // @gotags: bexpr:"-" uint64 ModifyIndex = 7; } -// @consul-rpc-glue: Datacenter,LeaderReadTODO +// @consul-rpc-glue: LeaderReadTODO message PeeringReadRequest { string Name = 1; string Partition = 2; - - string Datacenter = 3; - -//TODO(peering) query metadata } message PeeringReadResponse { Peering Peering = 1; - -//TODO(peering) query metadata } -// @consul-rpc-glue: Datacenter,LeaderReadTODO +// @consul-rpc-glue: LeaderReadTODO message PeeringListRequest { string Partition = 1; - - string Datacenter = 2; - -//TODO(peering) query metadata } message PeeringListResponse { repeated Peering Peerings = 1; - -//TODO(peering) query metadata } -// @consul-rpc-glue: Datacenter,WriteTODO message PeeringWriteRequest { Peering Peering = 1; - //TODO(peering): what to do with embedded write request? - string Datacenter = 2; - // Meta is a mapping of some string value to any other string value - map Meta = 3; + map Meta = 2; } // TODO(peering): Consider returning Peering if we keep this endpoint around message PeeringWriteResponse {} -// @consul-rpc-glue: Datacenter,WriteTODO message PeeringDeleteRequest { string Name = 1; string Partition = 2; - - //TODO(peering): what to do with embedded write request? - string Datacenter = 3; } message PeeringDeleteResponse {} -// @consul-rpc-glue: Datacenter,ReadTODO message TrustBundleListByServiceRequest { string ServiceName = 1; string Namespace = 2; string Partition = 3; string Kind = 4; - - // these are common fields required for implementing structs.RPCInfo methods - // that are used to forward requests - string Datacenter = 5; } message TrustBundleListByServiceResponse { @@ -210,14 +189,9 @@ message TrustBundleListByServiceResponse { repeated PeeringTrustBundle Bundles = 2; } -// @consul-rpc-glue: Datacenter,ReadTODO message TrustBundleReadRequest { string Name = 1; string Partition = 2; - - // these are common fields required for implementing structs.RPCInfo methods - // that are used to forward requests - string Datacenter = 3; } message TrustBundleReadResponse { @@ -225,30 +199,23 @@ message TrustBundleReadResponse { PeeringTrustBundle Bundle = 2; } +// This is a purely internal type and does not require query metadata. message PeeringTerminateByIDRequest { string ID = 1; } message PeeringTerminateByIDResponse {} -// @consul-rpc-glue: Datacenter message PeeringTrustBundleWriteRequest { PeeringTrustBundle PeeringTrustBundle = 1; - - //TODO(peering): what to do with embedded write request? - string Datacenter = 2; } message PeeringTrustBundleWriteResponse {} -// @consul-rpc-glue: Datacenter message PeeringTrustBundleDeleteRequest { string Name = 1; string Partition = 2; - - //TODO(peering): what to do with embedded write request? - string Datacenter = 3; } message PeeringTrustBundleDeleteResponse {} @@ -265,11 +232,6 @@ message GenerateTokenRequest { // Partition is the local partition being peered. string Partition = 2; - // these are common fields required for implementing structs.RPCInfo methods - // that are used to forward requests - string Datacenter = 3; - string Token = 4; - // Meta is a mapping of some string value to any other string value map Meta = 5; @@ -290,8 +252,6 @@ message GenerateTokenResponse { string PeeringToken = 1; } -// @consul-rpc-glue: Datacenter -// // mog annotation: // // target=github.com/hashicorp/consul/api.PeeringEstablishRequest @@ -307,16 +267,10 @@ message EstablishRequest { // Partition is the local partition being peered. string Partition = 3; - // these are common fields required for implementing structs.RPCInfo methods - // that are used to forward requests - string Datacenter = 4; - string Token = 5; - // Meta is a mapping of some string value to any other string value - map Meta = 6; + map Meta = 4; } -// // mog annotation: // // target=github.com/hashicorp/consul/api.PeeringEstablishResponse diff --git a/proto/pbpeering/peering.rpcglue.pb.go b/proto/pbpeering/peering.rpcglue.pb.go index 4c3c4dff0a..ca7498e0ba 100644 --- a/proto/pbpeering/peering.rpcglue.pb.go +++ b/proto/pbpeering/peering.rpcglue.pb.go @@ -12,14 +12,6 @@ import ( var _ structs.RPCInfo var _ time.Month -// RequestDatacenter implements structs.RPCInfo -func (msg *PeeringReadRequest) RequestDatacenter() string { - if msg == nil { - return "" - } - return msg.Datacenter -} - // IsRead implements structs.RPCInfo func (msg *PeeringReadRequest) IsRead() bool { // TODO(peering): figure out read semantics here @@ -64,14 +56,6 @@ func (msg *PeeringReadRequest) Token() string { return "" } -// RequestDatacenter implements structs.RPCInfo -func (msg *PeeringListRequest) RequestDatacenter() string { - if msg == nil { - return "" - } - return msg.Datacenter -} - // IsRead implements structs.RPCInfo func (msg *PeeringListRequest) IsRead() bool { // TODO(peering): figure out read semantics here @@ -115,211 +99,3 @@ func (msg *PeeringListRequest) Token() string { // TODO(peering): figure out read semantics here return "" } - -// RequestDatacenter implements structs.RPCInfo -func (msg *PeeringWriteRequest) RequestDatacenter() string { - if msg == nil { - return "" - } - return msg.Datacenter -} - -// IsRead implements structs.RPCInfo -func (msg *PeeringWriteRequest) IsRead() bool { - // TODO(peering): figure out write semantics here - return false -} - -// AllowStaleRead implements structs.RPCInfo -func (msg *PeeringWriteRequest) AllowStaleRead() bool { - // TODO(peering): figure out write semantics here - return false -} - -// HasTimedOut implements structs.RPCInfo -func (msg *PeeringWriteRequest) HasTimedOut(start time.Time, rpcHoldTimeout time.Duration, a time.Duration, b time.Duration) (bool, error) { - // TODO(peering): figure out write semantics here - return time.Since(start) > rpcHoldTimeout, nil -} - -// Timeout implements structs.RPCInfo -func (msg *PeeringWriteRequest) Timeout(rpcHoldTimeout time.Duration, a time.Duration, b time.Duration) time.Duration { - // TODO(peering): figure out write semantics here - return rpcHoldTimeout -} - -// SetTokenSecret implements structs.RPCInfo -func (msg *PeeringWriteRequest) SetTokenSecret(s string) { - // TODO(peering): figure out write semantics here -} - -// TokenSecret implements structs.RPCInfo -func (msg *PeeringWriteRequest) TokenSecret() string { - // TODO(peering): figure out write semantics here - return "" -} - -// RequestDatacenter implements structs.RPCInfo -func (msg *PeeringDeleteRequest) RequestDatacenter() string { - if msg == nil { - return "" - } - return msg.Datacenter -} - -// IsRead implements structs.RPCInfo -func (msg *PeeringDeleteRequest) IsRead() bool { - // TODO(peering): figure out write semantics here - return false -} - -// AllowStaleRead implements structs.RPCInfo -func (msg *PeeringDeleteRequest) AllowStaleRead() bool { - // TODO(peering): figure out write semantics here - return false -} - -// HasTimedOut implements structs.RPCInfo -func (msg *PeeringDeleteRequest) HasTimedOut(start time.Time, rpcHoldTimeout time.Duration, a time.Duration, b time.Duration) (bool, error) { - // TODO(peering): figure out write semantics here - return time.Since(start) > rpcHoldTimeout, nil -} - -// Timeout implements structs.RPCInfo -func (msg *PeeringDeleteRequest) Timeout(rpcHoldTimeout time.Duration, a time.Duration, b time.Duration) time.Duration { - // TODO(peering): figure out write semantics here - return rpcHoldTimeout -} - -// SetTokenSecret implements structs.RPCInfo -func (msg *PeeringDeleteRequest) SetTokenSecret(s string) { - // TODO(peering): figure out write semantics here -} - -// TokenSecret implements structs.RPCInfo -func (msg *PeeringDeleteRequest) TokenSecret() string { - // TODO(peering): figure out write semantics here - return "" -} - -// RequestDatacenter implements structs.RPCInfo -func (msg *TrustBundleListByServiceRequest) RequestDatacenter() string { - if msg == nil { - return "" - } - return msg.Datacenter -} - -// IsRead implements structs.RPCInfo -func (msg *TrustBundleListByServiceRequest) IsRead() bool { - // TODO(peering): figure out read semantics here - return true -} - -// AllowStaleRead implements structs.RPCInfo -func (msg *TrustBundleListByServiceRequest) AllowStaleRead() bool { - // TODO(peering): figure out read semantics here - return false -} - -// HasTimedOut implements structs.RPCInfo -func (msg *TrustBundleListByServiceRequest) HasTimedOut(start time.Time, rpcHoldTimeout time.Duration, a time.Duration, b time.Duration) (bool, error) { - // TODO(peering): figure out read semantics here - return time.Since(start) > rpcHoldTimeout, nil -} - -// Timeout implements structs.RPCInfo -func (msg *TrustBundleListByServiceRequest) Timeout(rpcHoldTimeout time.Duration, a time.Duration, b time.Duration) time.Duration { - // TODO(peering): figure out read semantics here - return rpcHoldTimeout -} - -// SetTokenSecret implements structs.RPCInfo -func (msg *TrustBundleListByServiceRequest) SetTokenSecret(s string) { - // TODO(peering): figure out read semantics here -} - -// TokenSecret implements structs.RPCInfo -func (msg *TrustBundleListByServiceRequest) TokenSecret() string { - // TODO(peering): figure out read semantics here - return "" -} - -// Token implements structs.RPCInfo -func (msg *TrustBundleListByServiceRequest) Token() string { - // TODO(peering): figure out read semantics here - return "" -} - -// RequestDatacenter implements structs.RPCInfo -func (msg *TrustBundleReadRequest) RequestDatacenter() string { - if msg == nil { - return "" - } - return msg.Datacenter -} - -// IsRead implements structs.RPCInfo -func (msg *TrustBundleReadRequest) IsRead() bool { - // TODO(peering): figure out read semantics here - return true -} - -// AllowStaleRead implements structs.RPCInfo -func (msg *TrustBundleReadRequest) AllowStaleRead() bool { - // TODO(peering): figure out read semantics here - return false -} - -// HasTimedOut implements structs.RPCInfo -func (msg *TrustBundleReadRequest) HasTimedOut(start time.Time, rpcHoldTimeout time.Duration, a time.Duration, b time.Duration) (bool, error) { - // TODO(peering): figure out read semantics here - return time.Since(start) > rpcHoldTimeout, nil -} - -// Timeout implements structs.RPCInfo -func (msg *TrustBundleReadRequest) Timeout(rpcHoldTimeout time.Duration, a time.Duration, b time.Duration) time.Duration { - // TODO(peering): figure out read semantics here - return rpcHoldTimeout -} - -// SetTokenSecret implements structs.RPCInfo -func (msg *TrustBundleReadRequest) SetTokenSecret(s string) { - // TODO(peering): figure out read semantics here -} - -// TokenSecret implements structs.RPCInfo -func (msg *TrustBundleReadRequest) TokenSecret() string { - // TODO(peering): figure out read semantics here - return "" -} - -// Token implements structs.RPCInfo -func (msg *TrustBundleReadRequest) Token() string { - // TODO(peering): figure out read semantics here - return "" -} - -// RequestDatacenter implements structs.RPCInfo -func (msg *PeeringTrustBundleWriteRequest) RequestDatacenter() string { - if msg == nil { - return "" - } - return msg.Datacenter -} - -// RequestDatacenter implements structs.RPCInfo -func (msg *PeeringTrustBundleDeleteRequest) RequestDatacenter() string { - if msg == nil { - return "" - } - return msg.Datacenter -} - -// RequestDatacenter implements structs.RPCInfo -func (msg *EstablishRequest) RequestDatacenter() string { - if msg == nil { - return "" - } - return msg.Datacenter -}