From 13da1a52853038902c84f387e350209b8709cf38 Mon Sep 17 00:00:00 2001 From: Thomas Eckert Date: Wed, 18 Jan 2023 17:14:34 -0500 Subject: [PATCH] Native API Gateway Config Entries (#15897) * Stub Config Entries for Consul Native API Gateway (#15644) * Add empty InlineCertificate struct and protobuf * apigateway stubs * Stub HTTPRoute in api pkg * Stub HTTPRoute in structs pkg * Simplify api.APIGatewayConfigEntry to be consistent w/ other entries * Update makeConfigEntry switch, add docstring for HTTPRouteConfigEntry * Add TCPRoute to MakeConfigEntry, return unique Kind * Stub BoundAPIGatewayConfigEntry in agent * Add RaftIndex to APIGatewayConfigEntry stub * Add new config entry kinds to validation allow-list * Add RaftIndex to other added config entry stubs * Update usage metrics assertions to include new cfg entries * Add Meta and acl.EnterpriseMeta to all new ConfigEntry types * Remove unnecessary Services field from added config entry types * Implement GetMeta(), GetEnterpriseMeta() for added config entry types * Add meta field to proto, name consistently w/ existing config entries * Format config_entry.proto * Add initial implementation of CanRead + CanWrite for new config entry types * Add unit tests for decoding of new config entry types * Add unit tests for parsing of new config entry types * Add unit tests for API Gateway config entry ACLs * Return typed PermissionDeniedError on BoundAPIGateway CanWrite * Add unit tests for added config entry ACLs * Add BoundAPIGateway type to AllConfigEntryKinds * Return proper kind from BoundAPIGateway * Add docstrings for new config entry types * Add missing config entry kinds to proto def * Update usagemetrics_oss_test.go * Use utility func for returning PermissionDeniedError * EventPublisher subscriptions for Consul Native API Gateway (#15757) * Create new event topics in subscribe proto * Add tests for PBSubscribe func * Make configs singular, add all configs to PBToStreamSubscribeRequest * Add snapshot methods * Add config_entry_events tests * Add config entry kind to topic for new configs * Add unit tests for snapshot methods * Start adding integration test * Test using the new controller code * Update agent/consul/state/config_entry_events.go * Check value of error * Add controller stubs for API Gateway (#15837) * update initial stub implementation * move files, clean up mutex references * Remove embed, use idiomatic names for constructors * Remove stray file introduced in merge * Add APIGateway validation (#15847) * Add APIGateway validation * Add additional validations * Add cert ref validation * Add protobuf definitions * Fix up field types * Add API structs * Move struct fields around a bit * APIGateway InlineCertificate validation (#15856) * Add APIGateway validation * Add additional validations * Add protobuf definitions * Tabs to spaces * Add API structs * Move struct fields around a bit * Add validation for InlineCertificate * Fix ACL test * APIGateway BoundAPIGateway validation (#15858) * Add APIGateway validation * Add additional validations * Add cert ref validation * Add protobuf definitions * Fix up field types * Add API structs * Move struct fields around a bit * Add validation for BoundAPIGateway * APIGateway TCPRoute validation (#15855) * Add APIGateway validation * Add additional validations * Add cert ref validation * Add protobuf definitions * Fix up field types * Add API structs * Add TCPRoute normalization and validation * Add forgotten Status * Add some more field docs in api package * Fix test * Format imports * Rename snapshot test variable names * Add plumbing for Native API GW Subscriptions (#16003) Co-authored-by: Sarah Alsmiller Co-authored-by: Nathan Coleman Co-authored-by: sarahalsmiller <100602640+sarahalsmiller@users.noreply.github.com> Co-authored-by: Andrew Stucki --- acl/errors.go | 2 +- agent/consul/controller/controller_test.go | 146 +- agent/consul/fsm/fsm.go | 35 + agent/consul/gateways/controller_gateways.go | 34 + agent/consul/gateways/controller_routes.go | 56 + agent/consul/state/config_entry.go | 5 + agent/consul/state/config_entry_events.go | 35 + .../consul/state/config_entry_events_test.go | 345 ++++ agent/consul/state/events.go | 9 +- agent/consul/state/events_test.go | 157 ++ agent/consul/state/memdb.go | 5 + .../usagemetrics/usagemetrics_oss_test.go | 160 ++ agent/proxycfg-glue/config_entry.go | 10 + agent/structs/config_entry.go | 20 + .../config_entry_discoverychain_test.go | 630 +++++++ agent/structs/config_entry_gateways.go | 302 ++- agent/structs/config_entry_gateways_test.go | 218 +++ .../config_entry_inline_certificate.go | 101 + .../config_entry_inline_certificate_test.go | 106 ++ agent/structs/config_entry_routes.go | 177 ++ agent/structs/config_entry_routes_test.go | 58 + agent/structs/config_entry_status.go | 51 + agent/structs/config_entry_test.go | 110 +- api/config_entry.go | 12 + api/config_entry_gateways.go | 79 + api/config_entry_inline_certificate.go | 75 + api/config_entry_routes.go | 132 ++ api/config_entry_status.go | 55 + command/helpers/helpers_test.go | 184 ++ proto/pbconfigentry/config_entry.gen.go | 350 ++++ proto/pbconfigentry/config_entry.go | 22 + proto/pbconfigentry/config_entry.pb.binary.go | 120 ++ proto/pbconfigentry/config_entry.pb.go | 1649 +++++++++++++++-- proto/pbconfigentry/config_entry.proto | 158 ++ proto/pbsubscribe/subscribe.pb.go | 87 +- proto/pbsubscribe/subscribe.proto | 15 + website/data/docs-nav-data.json | 9 +- 37 files changed, 5489 insertions(+), 230 deletions(-) create mode 100644 agent/consul/gateways/controller_gateways.go create mode 100644 agent/consul/gateways/controller_routes.go create mode 100644 agent/consul/state/events_test.go create mode 100644 agent/structs/config_entry_inline_certificate.go create mode 100644 agent/structs/config_entry_inline_certificate_test.go create mode 100644 agent/structs/config_entry_routes.go create mode 100644 agent/structs/config_entry_routes_test.go create mode 100644 agent/structs/config_entry_status.go create mode 100644 api/config_entry_inline_certificate.go create mode 100644 api/config_entry_routes.go create mode 100644 api/config_entry_status.go diff --git a/acl/errors.go b/acl/errors.go index 585bd12a06..e3eb6c7eaa 100644 --- a/acl/errors.go +++ b/acl/errors.go @@ -70,7 +70,7 @@ type PermissionDeniedError struct { Accessor string // Resource (e.g. Service) Resource Resource - // Access leve (e.g. Read) + // Access level (e.g. Read) AccessLevel AccessLevel // e.g. "sidecar-proxy-1" ResourceID ResourceDescriptor diff --git a/agent/consul/controller/controller_test.go b/agent/consul/controller/controller_test.go index d71b7403a7..fc270a6564 100644 --- a/agent/consul/controller/controller_test.go +++ b/agent/consul/controller/controller_test.go @@ -64,7 +64,7 @@ LOOP: } } - // since we only modified each entry once, we should have exactly 200 reconcliation calls + // since we only modified each entry once, we should have exactly 200 reconciliation calls require.Len(t, received, 200) for i := 0; i < 200; i++ { require.Contains(t, received, fmt.Sprintf("foo-%d", i)) @@ -271,3 +271,147 @@ func TestBasicController_RunPanicAssertions(t *testing.T) { controller.WithQueueFactory(RunWorkQueue) }) } + +func TestConfigEntrySubscriptions(t *testing.T) { + t.Parallel() + + cases := map[string]struct { + configEntry func(string) structs.ConfigEntry + topic stream.Topic + kind string + }{ + "Subscribe to Service Resolver Config Changes": { + configEntry: func(name string) structs.ConfigEntry { + return &structs.ServiceResolverConfigEntry{ + Kind: structs.ServiceResolver, + Name: name, + } + }, + topic: state.EventTopicServiceResolver, + kind: structs.ServiceResolver, + }, + "Subscribe to Ingress Gateway Changes": { + configEntry: func(name string) structs.ConfigEntry { + return &structs.IngressGatewayConfigEntry{ + Kind: structs.IngressGateway, + Name: name, + } + }, + topic: state.EventTopicIngressGateway, + kind: structs.IngressGateway, + }, + "Subscribe to Service Intentions Changes": { + configEntry: func(name string) structs.ConfigEntry { + return &structs.ServiceIntentionsConfigEntry{ + Kind: structs.ServiceIntentions, + Name: name, + } + }, + topic: state.EventTopicServiceIntentions, + kind: structs.ServiceIntentions, + }, + "Subscribe to API Gateway Changes": { + configEntry: func(name string) structs.ConfigEntry { + return &structs.APIGatewayConfigEntry{ + Kind: structs.APIGateway, + Name: name, + } + }, + topic: state.EventTopicAPIGateway, + kind: structs.APIGateway, + }, + "Subscribe to Inline Certificate Changes": { + configEntry: func(name string) structs.ConfigEntry { + return &structs.InlineCertificateConfigEntry{ + Kind: structs.InlineCertificate, + Name: name, + } + }, + topic: state.EventTopicInlineCertificate, + kind: structs.InlineCertificate, + }, + "Subscribe to HTTP Route Changes": { + configEntry: func(name string) structs.ConfigEntry { + return &structs.HTTPRouteConfigEntry{ + Kind: structs.HTTPRoute, + Name: name, + } + }, + topic: state.EventTopicHTTPRoute, + kind: structs.HTTPRoute, + }, + "Subscribe to TCP Route Changes": { + configEntry: func(name string) structs.ConfigEntry { + return &structs.TCPRouteConfigEntry{ + Kind: structs.TCPRoute, + Name: name, + } + }, + topic: state.EventTopicTCPRoute, + kind: structs.TCPRoute, + }, + "Subscribe to Bound API Gateway Changes": { + configEntry: func(name string) structs.ConfigEntry { + return &structs.BoundAPIGatewayConfigEntry{ + Kind: structs.BoundAPIGateway, + Name: name, + } + }, + topic: state.EventTopicBoundAPIGateway, + kind: structs.BoundAPIGateway, + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) + defer cancel() + + reconciler := newTestReconciler(false) + + publisher := stream.NewEventPublisher(1 * time.Millisecond) + go publisher.Run(ctx) + + // get the store through the FSM since the publisher handlers get registered through it + store := fsm.NewFromDeps(fsm.Deps{ + Logger: hclog.New(nil), + NewStateStore: func() *state.Store { + return state.NewStateStoreWithEventPublisher(nil, publisher) + }, + Publisher: publisher, + }).State() + + for i := 0; i < 200; i++ { + entryIndex := uint64(i + 1) + name := fmt.Sprintf("foo-%d", i) + require.NoError(t, store.EnsureConfigEntry(entryIndex, tc.configEntry(name))) + } + + go New(publisher, reconciler).Subscribe(&stream.SubscribeRequest{ + Topic: tc.topic, + Subject: stream.SubjectWildcard, + }).WithWorkers(10).Run(ctx) + + received := []string{} + LOOP: + for { + select { + case request := <-reconciler.received: + require.Equal(t, tc.kind, request.Kind) + received = append(received, request.Name) + if len(received) == 200 { + break LOOP + } + case <-ctx.Done(): + break LOOP + } + } + + // since we only modified each entry once, we should have exactly 200 reconciliation calls + require.Len(t, received, 200) + for i := 0; i < 200; i++ { + require.Contains(t, received, fmt.Sprintf("foo-%d", i)) + } + }) + } +} diff --git a/agent/consul/fsm/fsm.go b/agent/consul/fsm/fsm.go index 46d7d77310..87f761f154 100644 --- a/agent/consul/fsm/fsm.go +++ b/agent/consul/fsm/fsm.go @@ -342,4 +342,39 @@ func (c *FSM) registerStreamSnapshotHandlers() { if err != nil { panic(fmt.Errorf("fatal error encountered registering streaming snapshot handlers: %w", err)) } + + err = c.deps.Publisher.RegisterHandler(state.EventTopicAPIGateway, func(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { + return c.State().APIGatewaySnapshot(req, buf) + }, true) + if err != nil { + panic(fmt.Errorf("fatal error encountered registering streaming snapshot handlers: %w", err)) + } + + err = c.deps.Publisher.RegisterHandler(state.EventTopicInlineCertificate, func(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { + return c.State().InlineCertificateSnapshot(req, buf) + }, true) + if err != nil { + panic(fmt.Errorf("fatal error encountered registering streaming snapshot handlers: %w", err)) + } + + err = c.deps.Publisher.RegisterHandler(state.EventTopicHTTPRoute, func(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { + return c.State().HTTPRouteSnapshot(req, buf) + }, true) + if err != nil { + panic(fmt.Errorf("fatal error encountered registering streaming snapshot handlers: %w", err)) + } + + err = c.deps.Publisher.RegisterHandler(state.EventTopicTCPRoute, func(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { + return c.State().TCPRouteSnapshot(req, buf) + }, true) + if err != nil { + panic(fmt.Errorf("fatal error encountered registering streaming snapshot handlers: %w", err)) + } + + err = c.deps.Publisher.RegisterHandler(state.EventTopicBoundAPIGateway, func(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { + return c.State().BoundAPIGatewaySnapshot(req, buf) + }, true) + if err != nil { + panic(fmt.Errorf("fatal error encountered registering streaming snapshot handlers: %w", err)) + } } diff --git a/agent/consul/gateways/controller_gateways.go b/agent/consul/gateways/controller_gateways.go new file mode 100644 index 0000000000..fc2ae3ed0d --- /dev/null +++ b/agent/consul/gateways/controller_gateways.go @@ -0,0 +1,34 @@ +package gateways + +import ( + "context" + + "github.com/hashicorp/go-hclog" + + "github.com/hashicorp/consul/agent/consul/controller" + "github.com/hashicorp/consul/agent/consul/fsm" + "github.com/hashicorp/consul/agent/consul/state" + "github.com/hashicorp/consul/agent/consul/stream" +) + +type apiGatewayReconciler struct { + fsm *fsm.FSM + logger hclog.Logger +} + +func (r apiGatewayReconciler) Reconcile(ctx context.Context, req controller.Request) error { + return nil +} + +func NewAPIGatewayController(fsm *fsm.FSM, publisher state.EventPublisher, logger hclog.Logger) controller.Controller { + reconciler := apiGatewayReconciler{ + fsm: fsm, + logger: logger, + } + return controller.New(publisher, reconciler).Subscribe( + &stream.SubscribeRequest{ + Topic: state.EventTopicAPIGateway, + Subject: stream.SubjectWildcard, + }, + ) +} diff --git a/agent/consul/gateways/controller_routes.go b/agent/consul/gateways/controller_routes.go new file mode 100644 index 0000000000..96de0c982d --- /dev/null +++ b/agent/consul/gateways/controller_routes.go @@ -0,0 +1,56 @@ +package gateways + +import ( + "context" + + "github.com/hashicorp/go-hclog" + + "github.com/hashicorp/consul/agent/consul/controller" + "github.com/hashicorp/consul/agent/consul/fsm" + "github.com/hashicorp/consul/agent/consul/state" + "github.com/hashicorp/consul/agent/consul/stream" +) + +type tcpRouteReconciler struct { + fsm *fsm.FSM + logger hclog.Logger +} + +func (r tcpRouteReconciler) Reconcile(ctx context.Context, req controller.Request) error { + return nil +} + +func NewTCPRouteController(fsm *fsm.FSM, publisher state.EventPublisher, logger hclog.Logger) controller.Controller { + reconciler := tcpRouteReconciler{ + fsm: fsm, + logger: logger, + } + return controller.New(publisher, reconciler).Subscribe( + &stream.SubscribeRequest{ + Topic: state.EventTopicTCPRoute, + Subject: stream.SubjectWildcard, + }, + ) +} + +type httpRouteReconciler struct { + fsm *fsm.FSM + logger hclog.Logger +} + +func (r httpRouteReconciler) Reconcile(ctx context.Context, req controller.Request) error { + return nil +} + +func NewHTTPRouteController(fsm *fsm.FSM, publisher state.EventPublisher, logger hclog.Logger) controller.Controller { + reconciler := httpRouteReconciler{ + fsm: fsm, + logger: logger, + } + return controller.New(publisher, reconciler).Subscribe( + &stream.SubscribeRequest{ + Topic: state.EventTopicHTTPRoute, + Subject: stream.SubjectWildcard, + }, + ) +} diff --git a/agent/consul/state/config_entry.go b/agent/consul/state/config_entry.go index 97b7e3f281..929d963e31 100644 --- a/agent/consul/state/config_entry.go +++ b/agent/consul/state/config_entry.go @@ -496,6 +496,11 @@ func validateProposedConfigEntryInGraph( case structs.ServiceIntentions: case structs.MeshConfig: case structs.ExportedServices: + case structs.APIGateway: // TODO Consider checkGatewayClash + case structs.BoundAPIGateway: + case structs.InlineCertificate: + case structs.HTTPRoute: + case structs.TCPRoute: default: return fmt.Errorf("unhandled kind %q during validation of %q", kindName.Kind, kindName.Name) } diff --git a/agent/consul/state/config_entry_events.go b/agent/consul/state/config_entry_events.go index 5fc71f0275..c081d778b8 100644 --- a/agent/consul/state/config_entry_events.go +++ b/agent/consul/state/config_entry_events.go @@ -17,6 +17,11 @@ var configEntryKindToTopic = map[string]stream.Topic{ structs.IngressGateway: EventTopicIngressGateway, structs.ServiceIntentions: EventTopicServiceIntentions, structs.ServiceDefaults: EventTopicServiceDefaults, + structs.APIGateway: EventTopicAPIGateway, + structs.TCPRoute: EventTopicTCPRoute, + structs.HTTPRoute: EventTopicHTTPRoute, + structs.InlineCertificate: EventTopicInlineCertificate, + structs.BoundAPIGateway: EventTopicBoundAPIGateway, } // EventSubjectConfigEntry is a stream.Subject used to route and receive events @@ -117,6 +122,36 @@ func (s *Store) ServiceDefaultsSnapshot(req stream.SubscribeRequest, buf stream. return s.configEntrySnapshot(structs.ServiceDefaults, req, buf) } +// APIGatewaySnapshot is a stream.SnapshotFunc that returns a snapshot of +// api-gateway config entries. +func (s *Store) APIGatewaySnapshot(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { + return s.configEntrySnapshot(structs.APIGateway, req, buf) +} + +// TCPRouteSnapshot is a stream.SnapshotFunc that returns a snapshot of +// tcp-route config entries. +func (s *Store) TCPRouteSnapshot(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { + return s.configEntrySnapshot(structs.TCPRoute, req, buf) +} + +// HTTPRouteSnapshot is a stream.SnapshotFunc that retuns a snapshot of +// http-route config entries. +func (s *Store) HTTPRouteSnapshot(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { + return s.configEntrySnapshot(structs.HTTPRoute, req, buf) +} + +// InlineCertificateSnapshot is a stream.SnapshotFunc that returns a snapshot of +// inline-certificate config entries. +func (s *Store) InlineCertificateSnapshot(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { + return s.configEntrySnapshot(structs.InlineCertificate, req, buf) +} + +// BoundAPIGatewaySnapshot is a stream.SnapshotFunc that returns a snapshot of +// bound-api-gateway config entries. +func (s *Store) BoundAPIGatewaySnapshot(req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { + return s.configEntrySnapshot(structs.BoundAPIGateway, req, buf) +} + func (s *Store) configEntrySnapshot(kind string, req stream.SubscribeRequest, buf stream.SnapshotAppender) (uint64, error) { var ( idx uint64 diff --git a/agent/consul/state/config_entry_events_test.go b/agent/consul/state/config_entry_events_test.go index 2e50b677bd..a6c4ce3d62 100644 --- a/agent/consul/state/config_entry_events_test.go +++ b/agent/consul/state/config_entry_events_test.go @@ -547,3 +547,348 @@ func TestServiceDefaultsSnapshot(t *testing.T) { }) } } + +func TestAPIGatewaySnapshot(t *testing.T) { + const index uint64 = 123 + + gw1 := &structs.APIGatewayConfigEntry{ + Kind: structs.APIGateway, + Name: "agw1", + } + gw2 := &structs.APIGatewayConfigEntry{ + Kind: structs.APIGateway, + Name: "agw2", + } + + store := testStateStore(t) + require.NoError(t, store.EnsureConfigEntry(index, gw1)) + require.NoError(t, store.EnsureConfigEntry(index, gw2)) + + testCases := map[string]struct { + subject stream.Subject + events []stream.Event + }{ + "named entry": { + subject: EventSubjectConfigEntry{Name: gw1.Name}, + events: []stream.Event{ + { + Topic: EventTopicAPIGateway, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: gw1, + }, + }, + }, + }, + "wildcard": { + subject: stream.SubjectWildcard, + events: []stream.Event{ + { + Topic: EventTopicAPIGateway, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: gw1, + }, + }, + { + Topic: EventTopicAPIGateway, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: gw2, + }, + }, + }, + }, + } + + for desc, tc := range testCases { + t.Run(desc, func(t *testing.T) { + buf := &snapshotAppender{} + + idx, err := store.APIGatewaySnapshot(stream.SubscribeRequest{Subject: tc.subject}, buf) + require.NoError(t, err) + require.Equal(t, index, idx) + require.Len(t, buf.events, 1) + require.ElementsMatch(t, tc.events, buf.events[0]) + }) + } +} + +func TestTCPRouteSnapshot(t *testing.T) { + const index uint64 = 123 + + rt1 := &structs.TCPRouteConfigEntry{ + Kind: structs.TCPRoute, + Name: "tcprt1", + } + rt2 := &structs.TCPRouteConfigEntry{ + Kind: structs.TCPRoute, + Name: "tcprt2", + } + + store := testStateStore(t) + require.NoError(t, store.EnsureConfigEntry(index, rt1)) + require.NoError(t, store.EnsureConfigEntry(index, rt2)) + + testCases := map[string]struct { + subject stream.Subject + events []stream.Event + }{ + "named entry": { + subject: EventSubjectConfigEntry{Name: rt1.Name}, + events: []stream.Event{ + { + Topic: EventTopicTCPRoute, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: rt1, + }, + }, + }, + }, + "wildcard": { + subject: stream.SubjectWildcard, + events: []stream.Event{ + { + Topic: EventTopicTCPRoute, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: rt1, + }, + }, + { + Topic: EventTopicTCPRoute, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: rt2, + }, + }, + }, + }, + } + + for desc, tc := range testCases { + t.Run(desc, func(t *testing.T) { + buf := &snapshotAppender{} + + idx, err := store.TCPRouteSnapshot(stream.SubscribeRequest{Subject: tc.subject}, buf) + require.NoError(t, err) + require.Equal(t, index, idx) + require.Len(t, buf.events, 1) + require.ElementsMatch(t, tc.events, buf.events[0]) + }) + } +} + +func TestHTTPRouteSnapshot(t *testing.T) { + const index uint64 = 123 + + rt1 := &structs.HTTPRouteConfigEntry{ + Kind: structs.HTTPRoute, + Name: "httprt1", + } + gw2 := &structs.HTTPRouteConfigEntry{ + Kind: structs.HTTPRoute, + Name: "httprt2", + } + + store := testStateStore(t) + require.NoError(t, store.EnsureConfigEntry(index, rt1)) + require.NoError(t, store.EnsureConfigEntry(index, gw2)) + + testCases := map[string]struct { + subject stream.Subject + events []stream.Event + }{ + "named entry": { + subject: EventSubjectConfigEntry{Name: rt1.Name}, + events: []stream.Event{ + { + Topic: EventTopicHTTPRoute, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: rt1, + }, + }, + }, + }, + "wildcard": { + subject: stream.SubjectWildcard, + events: []stream.Event{ + { + Topic: EventTopicHTTPRoute, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: rt1, + }, + }, + { + Topic: EventTopicHTTPRoute, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: gw2, + }, + }, + }, + }, + } + + for desc, tc := range testCases { + t.Run(desc, func(t *testing.T) { + buf := &snapshotAppender{} + + idx, err := store.HTTPRouteSnapshot(stream.SubscribeRequest{Subject: tc.subject}, buf) + require.NoError(t, err) + require.Equal(t, index, idx) + require.Len(t, buf.events, 1) + require.ElementsMatch(t, tc.events, buf.events[0]) + }) + } +} + +func TestInlineCertificateSnapshot(t *testing.T) { + const index uint64 = 123 + + crt1 := &structs.InlineCertificateConfigEntry{ + Kind: structs.InlineCertificate, + Name: "inlinecert1", + } + crt2 := &structs.InlineCertificateConfigEntry{ + Kind: structs.InlineCertificate, + Name: "inlinecert2", + } + + store := testStateStore(t) + require.NoError(t, store.EnsureConfigEntry(index, crt1)) + require.NoError(t, store.EnsureConfigEntry(index, crt2)) + + testCases := map[string]struct { + subject stream.Subject + events []stream.Event + }{ + "named entry": { + subject: EventSubjectConfigEntry{Name: crt1.Name}, + events: []stream.Event{ + { + Topic: EventTopicInlineCertificate, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: crt1, + }, + }, + }, + }, + "wildcard": { + subject: stream.SubjectWildcard, + events: []stream.Event{ + { + Topic: EventTopicInlineCertificate, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: crt1, + }, + }, + { + Topic: EventTopicInlineCertificate, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: crt2, + }, + }, + }, + }, + } + + for desc, tc := range testCases { + t.Run(desc, func(t *testing.T) { + buf := &snapshotAppender{} + + idx, err := store.InlineCertificateSnapshot(stream.SubscribeRequest{Subject: tc.subject}, buf) + require.NoError(t, err) + require.Equal(t, index, idx) + require.Len(t, buf.events, 1) + require.ElementsMatch(t, tc.events, buf.events[0]) + }) + } +} + +func TestBoundAPIGatewaySnapshot(t *testing.T) { + const index uint64 = 123 + + gw1 := &structs.BoundAPIGatewayConfigEntry{ + Kind: structs.BoundAPIGateway, + Name: "boundapigw1", + } + gw2 := &structs.BoundAPIGatewayConfigEntry{ + Kind: structs.BoundAPIGateway, + Name: "boundapigw2", + } + + store := testStateStore(t) + require.NoError(t, store.EnsureConfigEntry(index, gw1)) + require.NoError(t, store.EnsureConfigEntry(index, gw2)) + + testCases := map[string]struct { + subject stream.Subject + events []stream.Event + }{ + "named entry": { + subject: EventSubjectConfigEntry{Name: gw1.Name}, + events: []stream.Event{ + { + Topic: EventTopicBoundAPIGateway, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: gw1, + }, + }, + }, + }, + "wildcard": { + subject: stream.SubjectWildcard, + events: []stream.Event{ + { + Topic: EventTopicBoundAPIGateway, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: gw1, + }, + }, + { + Topic: EventTopicBoundAPIGateway, + Index: index, + Payload: EventPayloadConfigEntry{ + Op: pbsubscribe.ConfigEntryUpdate_Upsert, + Value: gw2, + }, + }, + }, + }, + } + + for desc, tc := range testCases { + t.Run(desc, func(t *testing.T) { + buf := &snapshotAppender{} + + idx, err := store.BoundAPIGatewaySnapshot(stream.SubscribeRequest{Subject: tc.subject}, buf) + require.NoError(t, err) + require.Equal(t, index, idx) + require.Len(t, buf.events, 1) + require.ElementsMatch(t, tc.events, buf.events[0]) + }) + } +} diff --git a/agent/consul/state/events.go b/agent/consul/state/events.go index 93a4558f27..f17f38f657 100644 --- a/agent/consul/state/events.go +++ b/agent/consul/state/events.go @@ -9,6 +9,8 @@ import ( "github.com/hashicorp/consul/proto/pbsubscribe" ) +// PBToStreamSubscribeRequest takes a protobuf subscribe request and enterprise +// metadata to properly generate the matching stream subscribe request. func PBToStreamSubscribeRequest(req *pbsubscribe.SubscribeRequest, entMeta acl.EnterpriseMeta) (*stream.SubscribeRequest, error) { var subject stream.Subject @@ -17,7 +19,7 @@ func PBToStreamSubscribeRequest(req *pbsubscribe.SubscribeRequest, entMeta acl.E } else { named := req.GetNamedSubject() - // Support the (deprcated) top-level Key, Partition, Namespace, and PeerName fields. + // Support the (deprecated) top-level Key, Partition, Namespace, and PeerName fields. if named == nil { named = &pbsubscribe.NamedSubject{ Key: req.Key, // nolint:staticcheck // SA1019 intentional use of deprecated field @@ -38,7 +40,10 @@ func PBToStreamSubscribeRequest(req *pbsubscribe.SubscribeRequest, entMeta acl.E EnterpriseMeta: entMeta, PeerName: named.PeerName, } - case EventTopicMeshConfig, EventTopicServiceResolver, EventTopicIngressGateway, EventTopicServiceIntentions, EventTopicServiceDefaults: + case EventTopicMeshConfig, EventTopicServiceResolver, EventTopicIngressGateway, + EventTopicServiceIntentions, EventTopicServiceDefaults, EventTopicAPIGateway, + EventTopicTCPRoute, EventTopicHTTPRoute, EventTopicInlineCertificate, + EventTopicBoundAPIGateway: subject = EventSubjectConfigEntry{ Name: named.Key, EnterpriseMeta: &entMeta, diff --git a/agent/consul/state/events_test.go b/agent/consul/state/events_test.go new file mode 100644 index 0000000000..cf231148d5 --- /dev/null +++ b/agent/consul/state/events_test.go @@ -0,0 +1,157 @@ +package state + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/hashicorp/consul/acl" + "github.com/hashicorp/consul/agent/consul/stream" + "github.com/hashicorp/consul/proto/pbsubscribe" +) + +const aclToken = "67b04fbc-e35f-494a-ad43-739f1c8b839c" + +func TestPBToStreamSubscribeRequest(t *testing.T) { + cases := map[string]struct { + req *pbsubscribe.SubscribeRequest + entMeta acl.EnterpriseMeta + expectedSubscribeRequest *stream.SubscribeRequest + err error + }{ + "Wildcard subject": { + req: &pbsubscribe.SubscribeRequest{ + Topic: EventTopicServiceList, + Subject: &pbsubscribe.SubscribeRequest_WildcardSubject{WildcardSubject: true}, + Token: aclToken, + Index: 1, + }, + entMeta: acl.EnterpriseMeta{}, + expectedSubscribeRequest: &stream.SubscribeRequest{ + Topic: EventTopicServiceList, + Subject: stream.SubjectWildcard, + Token: aclToken, + Index: 1, + }, + err: nil, + }, + "Deprecated top level fields": { + req: &pbsubscribe.SubscribeRequest{ + Topic: EventTopicServiceDefaults, + Key: "key", + Partition: "partition", + Namespace: "consul", + PeerName: "peer", + }, + entMeta: acl.EnterpriseMeta{}, + expectedSubscribeRequest: &stream.SubscribeRequest{ + Topic: EventTopicServiceDefaults, + Subject: EventSubjectConfigEntry{ + Name: "key", + EnterpriseMeta: &acl.EnterpriseMeta{}, + }, + }, + err: nil, + }, + "Service health": { + req: &pbsubscribe.SubscribeRequest{ + Topic: EventTopicServiceHealth, + Subject: &pbsubscribe.SubscribeRequest_NamedSubject{ + NamedSubject: &pbsubscribe.NamedSubject{ + Key: "key", + Namespace: "consul", + Partition: "partition", + PeerName: "peer", + }, + }, + Token: aclToken, + Index: 2, + }, + entMeta: acl.EnterpriseMeta{}, + expectedSubscribeRequest: &stream.SubscribeRequest{ + Topic: EventTopicServiceHealth, + Subject: EventSubjectService{ + Key: "key", + EnterpriseMeta: acl.EnterpriseMeta{}, + PeerName: "peer", + }, + Token: aclToken, + Index: 2, + }, + err: nil, + }, + "Config": { + req: &pbsubscribe.SubscribeRequest{ + Topic: EventTopicAPIGateway, + Subject: &pbsubscribe.SubscribeRequest_NamedSubject{ + NamedSubject: &pbsubscribe.NamedSubject{ + Key: "key", + Namespace: "consul", + Partition: "partition", + PeerName: "peer", + }, + }, + Token: aclToken, + Index: 2, + }, + entMeta: acl.EnterpriseMeta{}, + expectedSubscribeRequest: &stream.SubscribeRequest{ + Topic: EventTopicAPIGateway, + Subject: EventSubjectConfigEntry{ + Name: "key", + EnterpriseMeta: &acl.EnterpriseMeta{}, + }, + Token: aclToken, + Index: 2, + }, + err: nil, + }, + "Service list without wildcard returns error": { + req: &pbsubscribe.SubscribeRequest{ + Topic: EventTopicServiceList, + Subject: &pbsubscribe.SubscribeRequest_NamedSubject{ + NamedSubject: &pbsubscribe.NamedSubject{ + Key: "key", + Namespace: "consul", + Partition: "partition", + PeerName: "peer", + }, + }, + }, + entMeta: acl.EnterpriseMeta{}, + expectedSubscribeRequest: nil, + err: fmt.Errorf("topic %s can only be consumed using WildcardSubject", EventTopicServiceList), + }, + "Unrecognized topic returns error": { + req: &pbsubscribe.SubscribeRequest{ + Topic: 99999, + Subject: &pbsubscribe.SubscribeRequest_NamedSubject{ + NamedSubject: &pbsubscribe.NamedSubject{ + Key: "key", + Namespace: "consul", + Partition: "partition", + PeerName: "peer", + }, + }, + }, + entMeta: acl.EnterpriseMeta{}, + expectedSubscribeRequest: nil, + err: fmt.Errorf("cannot construct subject for topic 99999"), + }, + } + + for name, tc := range cases { + t.Run(name, func(t *testing.T) { + actual, err := PBToStreamSubscribeRequest(tc.req, tc.entMeta) + + if tc.err != nil { + require.EqualError(t, err, tc.err.Error()) + } else { + require.NoError(t, err) + } + + require.Equal(t, tc.expectedSubscribeRequest, actual) + }) + } +} diff --git a/agent/consul/state/memdb.go b/agent/consul/state/memdb.go index 395325ee61..a0b2f116ac 100644 --- a/agent/consul/state/memdb.go +++ b/agent/consul/state/memdb.go @@ -186,6 +186,11 @@ var ( EventTopicServiceIntentions = pbsubscribe.Topic_ServiceIntentions EventTopicServiceDefaults = pbsubscribe.Topic_ServiceDefaults EventTopicServiceList = pbsubscribe.Topic_ServiceList + EventTopicAPIGateway = pbsubscribe.Topic_APIGateway + EventTopicTCPRoute = pbsubscribe.Topic_TCPRoute + EventTopicHTTPRoute = pbsubscribe.Topic_HTTPRoute + EventTopicInlineCertificate = pbsubscribe.Topic_InlineCertificate + EventTopicBoundAPIGateway = pbsubscribe.Topic_BoundAPIGateway ) func processDBChanges(tx ReadTxn, changes Changes) ([]stream.Event, error) { diff --git a/agent/consul/usagemetrics/usagemetrics_oss_test.go b/agent/consul/usagemetrics/usagemetrics_oss_test.go index add26bca69..951f1c3df4 100644 --- a/agent/consul/usagemetrics/usagemetrics_oss_test.go +++ b/agent/consul/usagemetrics/usagemetrics_oss_test.go @@ -350,6 +350,86 @@ var baseCases = map[string]testCase{ {Name: "kind", Value: "exported-services"}, }, }, + "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=api-gateway": { // Legacy + Name: "consul.usage.test.consul.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=api-gateway": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + }, + "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=bound-api-gateway": { // Legacy + Name: "consul.usage.test.consul.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "bound-api-gateway"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=bound-api-gateway": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "bound-api-gateway"}, + }, + }, + "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=inline-certificate": { // Legacy + Name: "consul.usage.test.consul.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "inline-certificate"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=inline-certificate": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "inline-certificate"}, + }, + }, + "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=http-route": { // Legacy + Name: "consul.usage.test.consul.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "http-route"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=http-route": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "http-route"}, + }, + }, + "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=tcp-route": { // Legacy + Name: "consul.usage.test.consul.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "tcp-route"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=tcp-route": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "tcp-route"}, + }, + }, }, getMembersFunc: func() []serf.Member { return []serf.Member{} }, }, @@ -690,6 +770,86 @@ var baseCases = map[string]testCase{ {Name: "kind", Value: "exported-services"}, }, }, + "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=api-gateway": { // Legacy + Name: "consul.usage.test.consul.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=api-gateway": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "api-gateway"}, + }, + }, + "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=bound-api-gateway": { // Legacy + Name: "consul.usage.test.consul.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "bound-api-gateway"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=bound-api-gateway": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "bound-api-gateway"}, + }, + }, + "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=inline-certificate": { // Legacy + Name: "consul.usage.test.consul.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "inline-certificate"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=inline-certificate": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "inline-certificate"}, + }, + }, + "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=http-route": { // Legacy + Name: "consul.usage.test.consul.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "http-route"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=http-route": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "http-route"}, + }, + }, + "consul.usage.test.consul.state.config_entries;datacenter=dc1;kind=tcp-route": { // Legacy + Name: "consul.usage.test.consul.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "tcp-route"}, + }, + }, + "consul.usage.test.state.config_entries;datacenter=dc1;kind=tcp-route": { + Name: "consul.usage.test.state.config_entries", + Value: 0, + Labels: []metrics.Label{ + {Name: "datacenter", Value: "dc1"}, + {Name: "kind", Value: "tcp-route"}, + }, + }, }, }, } diff --git a/agent/proxycfg-glue/config_entry.go b/agent/proxycfg-glue/config_entry.go index 76709a178f..022b9161ca 100644 --- a/agent/proxycfg-glue/config_entry.go +++ b/agent/proxycfg-glue/config_entry.go @@ -62,6 +62,16 @@ func newConfigEntryRequest(req *structs.ConfigEntryQuery, deps ServerDataSourceD topic = pbsubscribe.Topic_IngressGateway case structs.ServiceDefaults: topic = pbsubscribe.Topic_ServiceDefaults + case structs.APIGateway: + topic = pbsubscribe.Topic_APIGateway + case structs.HTTPRoute: + topic = pbsubscribe.Topic_HTTPRoute + case structs.TCPRoute: + topic = pbsubscribe.Topic_TCPRoute + case structs.InlineCertificate: + topic = pbsubscribe.Topic_InlineCertificate + case structs.BoundAPIGateway: + topic = pbsubscribe.Topic_BoundAPIGateway default: return nil, fmt.Errorf("cannot map config entry kind: %s to a topic", req.Kind) } diff --git a/agent/structs/config_entry.go b/agent/structs/config_entry.go index 65615103e9..6dd845023c 100644 --- a/agent/structs/config_entry.go +++ b/agent/structs/config_entry.go @@ -34,6 +34,11 @@ const ( ServiceIntentions string = "service-intentions" MeshConfig string = "mesh" ExportedServices string = "exported-services" + APIGateway string = "api-gateway" + BoundAPIGateway string = "bound-api-gateway" + InlineCertificate string = "inline-certificate" + HTTPRoute string = "http-route" + TCPRoute string = "tcp-route" ProxyConfigGlobal string = "global" MeshConfigMesh string = "mesh" @@ -54,6 +59,11 @@ var AllConfigEntryKinds = []string{ ServiceIntentions, MeshConfig, ExportedServices, + APIGateway, + BoundAPIGateway, + HTTPRoute, + TCPRoute, + InlineCertificate, } const ( @@ -698,6 +708,16 @@ func MakeConfigEntry(kind, name string) (ConfigEntry, error) { return &MeshConfigEntry{}, nil case ExportedServices: return &ExportedServicesConfigEntry{Name: name}, nil + case APIGateway: + return &APIGatewayConfigEntry{Name: name}, nil + case BoundAPIGateway: + return &BoundAPIGatewayConfigEntry{Name: name}, nil + case InlineCertificate: + return &InlineCertificateConfigEntry{Name: name}, nil + case HTTPRoute: + return &HTTPRouteConfigEntry{Name: name}, nil + case TCPRoute: + return &TCPRouteConfigEntry{Name: name}, nil default: return nil, fmt.Errorf("invalid config entry kind: %s", kind) } diff --git a/agent/structs/config_entry_discoverychain_test.go b/agent/structs/config_entry_discoverychain_test.go index dbd766744b..df1a5c5df1 100644 --- a/agent/structs/config_entry_discoverychain_test.go +++ b/agent/structs/config_entry_discoverychain_test.go @@ -409,6 +409,636 @@ func TestConfigEntries_ListRelatedServices_AndACLs(t *testing.T) { }, }, }, + { + name: "api-gateway", + entry: &APIGatewayConfigEntry{Name: "test"}, + expectACLs: []testACL{ + { + name: "no-authz", + authorizer: newAuthz(t, ``), + canRead: false, + canWrite: false, + }, + + { + name: "service deny and operator deny", + authorizer: newServiceAndOperatorACL(t, "deny", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service read and operator deny", + authorizer: newServiceAndOperatorACL(t, "read", "deny"), + canRead: true, + canWrite: false, + }, + { + name: "service write and operator deny", + authorizer: newServiceAndOperatorACL(t, "write", "deny"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and mesh deny", + authorizer: newServiceAndMeshACL(t, "deny", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service read and mesh deny", + authorizer: newServiceAndMeshACL(t, "read", "deny"), + canRead: true, + canWrite: false, + }, + { + name: "service write and mesh deny", + authorizer: newServiceAndMeshACL(t, "write", "deny"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and operator read", + authorizer: newServiceAndOperatorACL(t, "deny", "read"), + canRead: false, + canWrite: false, + }, + { + name: "service read and operator read", + authorizer: newServiceAndOperatorACL(t, "read", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service write and operator read", + authorizer: newServiceAndOperatorACL(t, "write", "read"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and operator write", + authorizer: newServiceAndOperatorACL(t, "deny", "write"), + canRead: false, + canWrite: true, + }, + { + name: "service read and operator write", + authorizer: newServiceAndOperatorACL(t, "read", "write"), + canRead: true, + canWrite: true, + }, + { + name: "service write and operator write", + authorizer: newServiceAndOperatorACL(t, "write", "write"), + canRead: true, + canWrite: true, + }, + + { + name: "service deny and mesh read", + authorizer: newServiceAndMeshACL(t, "deny", "read"), + canRead: false, + canWrite: false, + }, + { + name: "service read and mesh read", + authorizer: newServiceAndMeshACL(t, "read", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service write and mesh read", + authorizer: newServiceAndMeshACL(t, "write", "read"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and mesh write", + authorizer: newServiceAndMeshACL(t, "deny", "write"), + canRead: false, + canWrite: true, + }, + { + name: "service read and mesh write", + authorizer: newServiceAndMeshACL(t, "read", "write"), + canRead: true, + canWrite: true, + }, + { + name: "service write and mesh write", + authorizer: newServiceAndMeshACL(t, "write", "write"), + canRead: true, + canWrite: true, + }, + }, + }, + { + name: "inline-certificate", + entry: &InlineCertificateConfigEntry{Name: "test", Certificate: validCertificate, PrivateKey: validPrivateKey}, + expectACLs: []testACL{ + { + name: "no-authz", + authorizer: newAuthz(t, ``), + canRead: false, + canWrite: false, + }, + + { + name: "service deny and operator deny", + authorizer: newServiceAndOperatorACL(t, "deny", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service read and operator deny", + authorizer: newServiceAndOperatorACL(t, "read", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service write and operator deny", + authorizer: newServiceAndOperatorACL(t, "write", "deny"), + canRead: false, + canWrite: false, + }, + + { + name: "service deny and mesh deny", + authorizer: newServiceAndMeshACL(t, "deny", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service read and mesh deny", + authorizer: newServiceAndMeshACL(t, "read", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service write and mesh deny", + authorizer: newServiceAndMeshACL(t, "write", "deny"), + canRead: false, + canWrite: false, + }, + + { + name: "service deny and operator read", + authorizer: newServiceAndOperatorACL(t, "deny", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service read and operator read", + authorizer: newServiceAndOperatorACL(t, "read", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service write and operator read", + authorizer: newServiceAndOperatorACL(t, "write", "read"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and operator write", + authorizer: newServiceAndOperatorACL(t, "deny", "write"), + canRead: true, + canWrite: true, + }, + { + name: "service read and operator write", + authorizer: newServiceAndOperatorACL(t, "read", "write"), + canRead: true, + canWrite: true, + }, + { + name: "service write and operator write", + authorizer: newServiceAndOperatorACL(t, "write", "write"), + canRead: true, + canWrite: true, + }, + + { + name: "service deny and mesh read", + authorizer: newServiceAndMeshACL(t, "deny", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service read and mesh read", + authorizer: newServiceAndMeshACL(t, "read", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service write and mesh read", + authorizer: newServiceAndMeshACL(t, "write", "read"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and mesh write", + authorizer: newServiceAndMeshACL(t, "deny", "write"), + canRead: true, + canWrite: true, + }, + { + name: "service read and mesh write", + authorizer: newServiceAndMeshACL(t, "read", "write"), + canRead: true, + canWrite: true, + }, + { + name: "service write and mesh write", + authorizer: newServiceAndMeshACL(t, "write", "write"), + canRead: true, + canWrite: true, + }, + }, + }, + { + name: "http-route", + entry: &HTTPRouteConfigEntry{Name: "test"}, + expectACLs: []testACL{ + { + name: "no-authz", + authorizer: newAuthz(t, ``), + canRead: false, + canWrite: false, + }, + + { + name: "service deny and operator deny", + authorizer: newServiceAndOperatorACL(t, "deny", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service read and operator deny", + authorizer: newServiceAndOperatorACL(t, "read", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service write and operator deny", + authorizer: newServiceAndOperatorACL(t, "write", "deny"), + canRead: false, + canWrite: false, + }, + + { + name: "service deny and mesh deny", + authorizer: newServiceAndMeshACL(t, "deny", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service read and mesh deny", + authorizer: newServiceAndMeshACL(t, "read", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service write and mesh deny", + authorizer: newServiceAndMeshACL(t, "write", "deny"), + canRead: false, + canWrite: false, + }, + + { + name: "service deny and operator read", + authorizer: newServiceAndOperatorACL(t, "deny", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service read and operator read", + authorizer: newServiceAndOperatorACL(t, "read", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service write and operator read", + authorizer: newServiceAndOperatorACL(t, "write", "read"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and operator write", + authorizer: newServiceAndOperatorACL(t, "deny", "write"), + canRead: true, + canWrite: true, + }, + { + name: "service read and operator write", + authorizer: newServiceAndOperatorACL(t, "read", "write"), + canRead: true, + canWrite: true, + }, + { + name: "service write and operator write", + authorizer: newServiceAndOperatorACL(t, "write", "write"), + canRead: true, + canWrite: true, + }, + + { + name: "service deny and mesh read", + authorizer: newServiceAndMeshACL(t, "deny", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service read and mesh read", + authorizer: newServiceAndMeshACL(t, "read", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service write and mesh read", + authorizer: newServiceAndMeshACL(t, "write", "read"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and mesh write", + authorizer: newServiceAndMeshACL(t, "deny", "write"), + canRead: true, + canWrite: true, + }, + { + name: "service read and mesh write", + authorizer: newServiceAndMeshACL(t, "read", "write"), + canRead: true, + canWrite: true, + }, + { + name: "service write and mesh write", + authorizer: newServiceAndMeshACL(t, "write", "write"), + canRead: true, + canWrite: true, + }, + }, + }, + { + name: "tcp-route", + entry: &TCPRouteConfigEntry{Name: "test"}, + expectACLs: []testACL{ + { + name: "no-authz", + authorizer: newAuthz(t, ``), + canRead: false, + canWrite: false, + }, + + { + name: "service deny and operator deny", + authorizer: newServiceAndOperatorACL(t, "deny", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service read and operator deny", + authorizer: newServiceAndOperatorACL(t, "read", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service write and operator deny", + authorizer: newServiceAndOperatorACL(t, "write", "deny"), + canRead: false, + canWrite: false, + }, + + { + name: "service deny and mesh deny", + authorizer: newServiceAndMeshACL(t, "deny", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service read and mesh deny", + authorizer: newServiceAndMeshACL(t, "read", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service write and mesh deny", + authorizer: newServiceAndMeshACL(t, "write", "deny"), + canRead: false, + canWrite: false, + }, + + { + name: "service deny and operator read", + authorizer: newServiceAndOperatorACL(t, "deny", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service read and operator read", + authorizer: newServiceAndOperatorACL(t, "read", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service write and operator read", + authorizer: newServiceAndOperatorACL(t, "write", "read"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and operator write", + authorizer: newServiceAndOperatorACL(t, "deny", "write"), + canRead: true, + canWrite: true, + }, + { + name: "service read and operator write", + authorizer: newServiceAndOperatorACL(t, "read", "write"), + canRead: true, + canWrite: true, + }, + { + name: "service write and operator write", + authorizer: newServiceAndOperatorACL(t, "write", "write"), + canRead: true, + canWrite: true, + }, + + { + name: "service deny and mesh read", + authorizer: newServiceAndMeshACL(t, "deny", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service read and mesh read", + authorizer: newServiceAndMeshACL(t, "read", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service write and mesh read", + authorizer: newServiceAndMeshACL(t, "write", "read"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and mesh write", + authorizer: newServiceAndMeshACL(t, "deny", "write"), + canRead: true, + canWrite: true, + }, + { + name: "service read and mesh write", + authorizer: newServiceAndMeshACL(t, "read", "write"), + canRead: true, + canWrite: true, + }, + { + name: "service write and mesh write", + authorizer: newServiceAndMeshACL(t, "write", "write"), + canRead: true, + canWrite: true, + }, + }, + }, + { + name: "bound-api-gateway", + entry: &BoundAPIGatewayConfigEntry{Name: "test"}, + expectACLs: []testACL{ + { + name: "no-authz", + authorizer: newAuthz(t, ``), + canRead: false, + canWrite: false, + }, + + { + name: "service deny and operator deny", + authorizer: newServiceAndOperatorACL(t, "deny", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service read and operator deny", + authorizer: newServiceAndOperatorACL(t, "read", "deny"), + canRead: true, + canWrite: false, + }, + { + name: "service write and operator deny", + authorizer: newServiceAndOperatorACL(t, "write", "deny"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and mesh deny", + authorizer: newServiceAndMeshACL(t, "deny", "deny"), + canRead: false, + canWrite: false, + }, + { + name: "service read and mesh deny", + authorizer: newServiceAndMeshACL(t, "read", "deny"), + canRead: true, + canWrite: false, + }, + { + name: "service write and mesh deny", + authorizer: newServiceAndMeshACL(t, "write", "deny"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and operator read", + authorizer: newServiceAndOperatorACL(t, "deny", "read"), + canRead: false, + canWrite: false, + }, + { + name: "service read and operator read", + authorizer: newServiceAndOperatorACL(t, "read", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service write and operator read", + authorizer: newServiceAndOperatorACL(t, "write", "read"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and operator write", + authorizer: newServiceAndOperatorACL(t, "deny", "write"), + canRead: false, + canWrite: false, + }, + { + name: "service read and operator write", + authorizer: newServiceAndOperatorACL(t, "read", "write"), + canRead: true, + canWrite: false, + }, + { + name: "service write and operator write", + authorizer: newServiceAndOperatorACL(t, "write", "write"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and mesh read", + authorizer: newServiceAndMeshACL(t, "deny", "read"), + canRead: false, + canWrite: false, + }, + { + name: "service read and mesh read", + authorizer: newServiceAndMeshACL(t, "read", "read"), + canRead: true, + canWrite: false, + }, + { + name: "service write and mesh read", + authorizer: newServiceAndMeshACL(t, "write", "read"), + canRead: true, + canWrite: false, + }, + + { + name: "service deny and mesh write", + authorizer: newServiceAndMeshACL(t, "deny", "write"), + canRead: false, + canWrite: false, + }, + { + name: "service read and mesh write", + authorizer: newServiceAndMeshACL(t, "read", "write"), + canRead: true, + canWrite: false, + }, + { + name: "service write and mesh write", + authorizer: newServiceAndMeshACL(t, "write", "write"), + canRead: true, + canWrite: false, + }, + }, + }, { name: "terminating-gateway", entry: &TerminatingGatewayConfigEntry{Name: "test"}, diff --git a/agent/structs/config_entry_gateways.go b/agent/structs/config_entry_gateways.go index b023d00580..87a1588d94 100644 --- a/agent/structs/config_entry_gateways.go +++ b/agent/structs/config_entry_gateways.go @@ -12,6 +12,10 @@ import ( "github.com/hashicorp/consul/types" ) +const ( + wildcardPrefix = "*." +) + // IngressGatewayConfigEntry manages the configuration for an ingress service // with the given name. type IngressGatewayConfigEntry struct { @@ -371,7 +375,6 @@ func validateHost(tlsEnabled bool, host string) error { return nil } - wildcardPrefix := "*." if _, ok := dns.IsDomainName(host); !ok { return fmt.Errorf("Host %q must be a valid DNS hostname", host) } @@ -687,3 +690,300 @@ func (g *GatewayService) Clone() *GatewayService { ServiceKind: g.ServiceKind, } } + +// APIGatewayConfigEntry manages the configuration for an API gateway service +// with the given name. +type APIGatewayConfigEntry struct { + // Kind of the config entry. This will be set to structs.APIGateway. + Kind string + + // Name is used to match the config entry with its associated API gateway + // service. This should match the name provided in the service definition. + Name string + + // Listeners is the set of listener configuration to which an API Gateway + // might bind. + Listeners []APIGatewayListener + // Status is the asynchronous status which an APIGateway propagates to the user. + Status Status + + Meta map[string]string `json:",omitempty"` + acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` + RaftIndex +} + +func (e *APIGatewayConfigEntry) GetKind() string { + return APIGateway +} + +func (e *APIGatewayConfigEntry) GetName() string { + if e == nil { + return "" + } + return e.Name +} + +func (e *APIGatewayConfigEntry) GetMeta() map[string]string { + if e == nil { + return nil + } + return e.Meta +} + +func (e *APIGatewayConfigEntry) Normalize() error { + for i, listener := range e.Listeners { + protocol := strings.ToLower(string(listener.Protocol)) + listener.Protocol = APIGatewayListenerProtocol(protocol) + e.Listeners[i] = listener + } + return nil +} + +func (e *APIGatewayConfigEntry) Validate() error { + if err := e.validateListenerNames(); err != nil { + return err + } + if err := e.validateMergedListeners(); err != nil { + return err + } + + return e.validateListeners() +} + +func (e *APIGatewayConfigEntry) validateListenerNames() error { + listeners := make(map[string]struct{}) + for _, listener := range e.Listeners { + if _, found := listeners[listener.Name]; found { + return fmt.Errorf("found multiple listeners with the name %q", listener.Name) + } + listeners[listener.Name] = struct{}{} + } + return nil +} + +func (e *APIGatewayConfigEntry) validateMergedListeners() error { + listeners := make(map[int]APIGatewayListener) + for _, listener := range e.Listeners { + merged, found := listeners[listener.Port] + if found && (merged.Hostname != listener.Hostname || merged.Protocol != listener.Protocol) { + return fmt.Errorf("listeners %q and %q cannot be merged", merged.Name, listener.Name) + } + listeners[listener.Port] = listener + } + return nil +} + +func (e *APIGatewayConfigEntry) validateListeners() error { + validProtocols := map[APIGatewayListenerProtocol]bool{ + ListenerProtocolHTTP: true, + ListenerProtocolTCP: true, + } + allowedCertificateKinds := map[string]bool{ + InlineCertificate: true, + } + + for _, listener := range e.Listeners { + if !validProtocols[listener.Protocol] { + return fmt.Errorf("unsupported listener protocol %q, must be one of 'tcp', or 'http'", listener.Protocol) + } + if listener.Protocol == ListenerProtocolTCP && listener.Hostname != "" { + // TODO: once we have SNI matching we should be able to implement this + return fmt.Errorf("hostname specification is not supported when using TCP") + } + if listener.Port <= 0 || listener.Port > 65535 { + return fmt.Errorf("listener port %d not in the range 1-65535", listener.Port) + } + if strings.ContainsRune(strings.TrimPrefix(listener.Hostname, wildcardPrefix), '*') { + return fmt.Errorf("host %q is not valid, a wildcard specifier is only allowed as the left-most label", listener.Hostname) + } + for _, certificate := range listener.TLS.Certificates { + if !allowedCertificateKinds[certificate.Kind] { + return fmt.Errorf("unsupported certificate kind: %q, must be 'inline-certificate'", certificate.Kind) + } + if certificate.Name == "" { + return fmt.Errorf("certificate reference must have a name") + } + } + if err := validateTLSConfig(listener.TLS.MinVersion, listener.TLS.MaxVersion, listener.TLS.CipherSuites); err != nil { + return err + } + } + return nil +} + +func (e *APIGatewayConfigEntry) CanRead(authz acl.Authorizer) error { + var authzContext acl.AuthorizerContext + e.FillAuthzContext(&authzContext) + return authz.ToAllowAuthorizer().ServiceReadAllowed(e.Name, &authzContext) +} + +func (e *APIGatewayConfigEntry) CanWrite(authz acl.Authorizer) error { + var authzContext acl.AuthorizerContext + e.FillAuthzContext(&authzContext) + return authz.ToAllowAuthorizer().MeshWriteAllowed(&authzContext) +} + +func (e *APIGatewayConfigEntry) GetRaftIndex() *RaftIndex { + if e == nil { + return &RaftIndex{} + } + return &e.RaftIndex +} + +func (e *APIGatewayConfigEntry) GetEnterpriseMeta() *acl.EnterpriseMeta { + if e == nil { + return nil + } + return &e.EnterpriseMeta +} + +// APIGatewayListenerProtocol is the protocol that an APIGateway listener uses +type APIGatewayListenerProtocol string + +const ( + ListenerProtocolHTTP APIGatewayListenerProtocol = "http" + ListenerProtocolTCP APIGatewayListenerProtocol = "tcp" +) + +// APIGatewayListener represents an individual listener for an APIGateway +type APIGatewayListener struct { + // Name is the optional name of the listener in a given gateway. This is + // optional, however, it must be unique. Therefore, if a gateway has more + // than a single listener, all but one must specify a Name. + Name string + // Hostname is the host name that a listener should be bound to, if + // unspecified, the listener accepts requests for all hostnames. + Hostname string + // Port is the port at which this listener should bind. + Port int + // Protocol is the protocol that a listener should use, it must + // either be http or tcp + Protocol APIGatewayListenerProtocol + // TLS is the TLS settings for the listener. + TLS APIGatewayTLSConfiguration +} + +// APIGatewayTLSConfiguration specifies the configuration of a listener’s +// TLS settings. +type APIGatewayTLSConfiguration struct { + // Certificates is a set of references to certificates + // that a gateway listener uses for TLS termination. + Certificates []ResourceReference + // MaxVersion is the maximum TLS version that the listener + // should support. + MaxVersion types.TLSVersion + // MinVersion is the minimum TLS version that the listener + // should support. + MinVersion types.TLSVersion + // CipherSuites is the cipher suites that the listener should support. + CipherSuites []types.TLSCipherSuite +} + +// BoundAPIGatewayConfigEntry manages the configuration for a bound API +// gateway with the given name. This type is never written from the client. +// It is only written by the controller in order to represent an API gateway +// and the resources that are bound to it. +type BoundAPIGatewayConfigEntry struct { + // Kind of the config entry. This will be set to structs.BoundAPIGateway. + Kind string + + // Name is used to match the config entry with its associated API gateway + // service. This should match the name provided in the corresponding API + // gateway service definition. + Name string + + // Listeners are the valid listeners of an APIGateway with information about + // what certificates and routes have successfully bound to it. + Listeners []BoundAPIGatewayListener + + Meta map[string]string `json:",omitempty"` + acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` + RaftIndex +} + +func (e *BoundAPIGatewayConfigEntry) GetKind() string { + return BoundAPIGateway +} + +func (e *BoundAPIGatewayConfigEntry) GetName() string { + if e == nil { + return "" + } + return e.Name +} + +func (e *BoundAPIGatewayConfigEntry) GetMeta() map[string]string { + if e == nil { + return nil + } + return e.Meta +} + +func (e *BoundAPIGatewayConfigEntry) Normalize() error { + return nil +} + +func (e *BoundAPIGatewayConfigEntry) Validate() error { + allowedCertificateKinds := map[string]bool{ + InlineCertificate: true, + } + allowedRouteKinds := map[string]bool{ + HTTPRoute: true, + TCPRoute: true, + } + + // These should already be validated by upstream validation + // logic in the gateways/routes, but just in case we validate + // here as well. + for _, listener := range e.Listeners { + for _, certificate := range listener.Certificates { + if !allowedCertificateKinds[certificate.Kind] { + return fmt.Errorf("unsupported certificate kind: %q, must be 'inline-certificate'", certificate.Kind) + } + if certificate.Name == "" { + return fmt.Errorf("certificate reference must have a name") + } + } + for _, route := range listener.Routes { + if !allowedRouteKinds[route.Kind] { + return fmt.Errorf("unsupported route kind: %q, must be one of 'http-route', or 'tcp-route'", route.Kind) + } + if route.Name == "" { + return fmt.Errorf("route reference must have a name") + } + } + } + return nil +} + +func (e *BoundAPIGatewayConfigEntry) CanRead(authz acl.Authorizer) error { + var authzContext acl.AuthorizerContext + e.FillAuthzContext(&authzContext) + return authz.ToAllowAuthorizer().ServiceReadAllowed(e.Name, &authzContext) +} + +func (e *BoundAPIGatewayConfigEntry) CanWrite(_ acl.Authorizer) error { + return acl.PermissionDenied("only writeable by controller") +} + +func (e *BoundAPIGatewayConfigEntry) GetRaftIndex() *RaftIndex { + if e == nil { + return &RaftIndex{} + } + return &e.RaftIndex +} + +func (e *BoundAPIGatewayConfigEntry) GetEnterpriseMeta() *acl.EnterpriseMeta { + if e == nil { + return nil + } + return &e.EnterpriseMeta +} + +// BoundAPIGatewayListener is an API gateway listener with information +// about the routes and certificates that have successfully bound to it. +type BoundAPIGatewayListener struct { + Name string + Routes []ResourceReference + Certificates []ResourceReference +} diff --git a/agent/structs/config_entry_gateways_test.go b/agent/structs/config_entry_gateways_test.go index c494979c29..6e45e0b47b 100644 --- a/agent/structs/config_entry_gateways_test.go +++ b/agent/structs/config_entry_gateways_test.go @@ -1123,3 +1123,221 @@ func TestGatewayService_Addresses(t *testing.T) { }) } } + +func TestAPIGateway_Listeners(t *testing.T) { + cases := map[string]configEntryTestcase{ + "listener name conflict": { + entry: &APIGatewayConfigEntry{ + Kind: "api-gateway", + Name: "api-gw-one", + Listeners: []APIGatewayListener{ + { + Port: 80, + Name: "foo", + }, + { + Port: 80, + Name: "foo", + }, + }, + }, + validateErr: "multiple listeners with the name", + }, + "merged listener protocol conflict": { + entry: &APIGatewayConfigEntry{ + Kind: "api-gateway", + Name: "api-gw-two", + Listeners: []APIGatewayListener{ + { + Port: 80, + Protocol: ListenerProtocolHTTP, + }, + { + Name: "foo", + Port: 80, + Protocol: ListenerProtocolTCP, + }, + }, + }, + validateErr: "cannot be merged", + }, + "merged listener hostname conflict": { + entry: &APIGatewayConfigEntry{ + Kind: "api-gateway", + Name: "api-gw-three", + Listeners: []APIGatewayListener{ + { + Port: 80, + Hostname: "host.one", + }, + { + Name: "foo", + Port: 80, + Hostname: "host.two", + }, + }, + }, + validateErr: "cannot be merged", + }, + "invalid protocol": { + entry: &APIGatewayConfigEntry{ + Kind: "api-gateway", + Name: "api-gw-four", + Listeners: []APIGatewayListener{ + { + Port: 80, + Hostname: "host.one", + Protocol: APIGatewayListenerProtocol("UDP"), + }, + }, + }, + validateErr: "unsupported listener protocol", + }, + "hostname in unsupported protocol": { + entry: &APIGatewayConfigEntry{ + Kind: "api-gateway", + Name: "api-gw-five", + Listeners: []APIGatewayListener{ + { + Port: 80, + Hostname: "host.one", + Protocol: APIGatewayListenerProtocol("tcp"), + }, + }, + }, + validateErr: "hostname specification is not supported", + }, + "invalid port": { + entry: &APIGatewayConfigEntry{ + Kind: "api-gateway", + Name: "api-gw-six", + Listeners: []APIGatewayListener{ + { + Port: -1, + Protocol: APIGatewayListenerProtocol("tcp"), + }, + }, + }, + validateErr: "not in the range 1-65535", + }, + "invalid hostname": { + entry: &APIGatewayConfigEntry{ + Kind: "api-gateway", + Name: "api-gw-seven", + Listeners: []APIGatewayListener{ + { + Port: 80, + Hostname: "*.*.host.one", + Protocol: APIGatewayListenerProtocol("http"), + }, + }, + }, + validateErr: "only allowed as the left-most label", + }, + "unsupported certificate kind": { + entry: &APIGatewayConfigEntry{ + Kind: "api-gateway", + Name: "api-gw-eight", + Listeners: []APIGatewayListener{ + { + Port: 80, + Hostname: "host.one", + Protocol: APIGatewayListenerProtocol("http"), + TLS: APIGatewayTLSConfiguration{ + Certificates: []ResourceReference{{ + Kind: APIGateway, + }}, + }, + }, + }, + }, + validateErr: "unsupported certificate kind", + }, + "unnamed certificate": { + entry: &APIGatewayConfigEntry{ + Kind: "api-gateway", + Name: "api-gw-nine", + Listeners: []APIGatewayListener{ + { + Port: 80, + Hostname: "host.one", + Protocol: APIGatewayListenerProtocol("http"), + TLS: APIGatewayTLSConfiguration{ + Certificates: []ResourceReference{{ + Kind: InlineCertificate, + }}, + }, + }, + }, + }, + validateErr: "certificate reference must have a name", + }, + } + testConfigEntryNormalizeAndValidate(t, cases) +} + +func TestBoundAPIGateway(t *testing.T) { + cases := map[string]configEntryTestcase{ + "invalid certificate, no name": { + entry: &BoundAPIGatewayConfigEntry{ + Kind: BoundAPIGateway, + Name: "bound-api-gw-one", + Listeners: []BoundAPIGatewayListener{ + { + Name: "one", + Certificates: []ResourceReference{{ + Kind: InlineCertificate, + }}, + }, + }, + }, + validateErr: "certificate reference must have a name", + }, + "invalid certificate, no kind": { + entry: &BoundAPIGatewayConfigEntry{ + Kind: BoundAPIGateway, + Name: "bound-api-gw-two", + Listeners: []BoundAPIGatewayListener{ + { + Name: "one", + Certificates: []ResourceReference{{ + Name: "foo", + }}, + }, + }, + }, + validateErr: "unsupported certificate kind", + }, + "invalid route, no name": { + entry: &BoundAPIGatewayConfigEntry{ + Kind: BoundAPIGateway, + Name: "bound-api-gw-three", + Listeners: []BoundAPIGatewayListener{ + { + Name: "one", + Routes: []ResourceReference{{ + Kind: TCPRoute, + }}, + }, + }, + }, + validateErr: "route reference must have a name", + }, + "invalid route, no kind": { + entry: &BoundAPIGatewayConfigEntry{ + Kind: BoundAPIGateway, + Name: "bound-api-gw-four", + Listeners: []BoundAPIGatewayListener{ + { + Name: "one", + Routes: []ResourceReference{{ + Name: "foo", + }}, + }, + }, + }, + validateErr: "unsupported route kind", + }, + } + testConfigEntryNormalizeAndValidate(t, cases) +} diff --git a/agent/structs/config_entry_inline_certificate.go b/agent/structs/config_entry_inline_certificate.go new file mode 100644 index 0000000000..7cfc71a6b2 --- /dev/null +++ b/agent/structs/config_entry_inline_certificate.go @@ -0,0 +1,101 @@ +package structs + +import ( + "crypto/tls" + "crypto/x509" + "encoding/pem" + "errors" + "fmt" + + "github.com/hashicorp/consul/acl" +) + +// InlineCertificateConfigEntry manages the configuration for an inline certificate +// with the given name. +type InlineCertificateConfigEntry struct { + // Kind of config entry. This will be set to structs.InlineCertificate. + Kind string + + // Name is used to match the config entry with its associated inline certificate. + Name string + + // Certificate is the public certificate component of an x509 key pair encoded in raw PEM format. + Certificate string + // PrivateKey is the private key component of an x509 key pair encoded in raw PEM format. + PrivateKey string + + Meta map[string]string `json:",omitempty"` + acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` + RaftIndex +} + +func (e *InlineCertificateConfigEntry) GetKind() string { + return InlineCertificate +} + +func (e *InlineCertificateConfigEntry) GetName() string { + return e.Name +} + +func (e *InlineCertificateConfigEntry) Normalize() error { + return nil +} + +func (e *InlineCertificateConfigEntry) Validate() error { + privateKeyBlock, _ := pem.Decode([]byte(e.PrivateKey)) + if privateKeyBlock == nil { + return errors.New("failed to parse private key PEM") + } + + certificateBlock, _ := pem.Decode([]byte(e.Certificate)) + if certificateBlock == nil { + return errors.New("failed to parse certificate PEM") + } + + // make sure we have a valid x509 certificate + _, err := x509.ParseCertificate(certificateBlock.Bytes) + if err != nil { + return fmt.Errorf("failed to parse certificate: %w", err) + } + + // validate that the cert was generated with the given private key + _, err = tls.X509KeyPair([]byte(e.Certificate), []byte(e.PrivateKey)) + if err != nil { + return err + } + + return nil +} + +func (e *InlineCertificateConfigEntry) CanRead(authz acl.Authorizer) error { + var authzContext acl.AuthorizerContext + e.FillAuthzContext(&authzContext) + return authz.ToAllowAuthorizer().MeshReadAllowed(&authzContext) +} + +func (e *InlineCertificateConfigEntry) CanWrite(authz acl.Authorizer) error { + var authzContext acl.AuthorizerContext + e.FillAuthzContext(&authzContext) + return authz.ToAllowAuthorizer().MeshWriteAllowed(&authzContext) +} + +func (e *InlineCertificateConfigEntry) GetMeta() map[string]string { + if e == nil { + return nil + } + return e.Meta +} + +func (e *InlineCertificateConfigEntry) GetEnterpriseMeta() *acl.EnterpriseMeta { + if e == nil { + return nil + } + return &e.EnterpriseMeta +} + +func (e *InlineCertificateConfigEntry) GetRaftIndex() *RaftIndex { + if e == nil { + return &RaftIndex{} + } + return &e.RaftIndex +} diff --git a/agent/structs/config_entry_inline_certificate_test.go b/agent/structs/config_entry_inline_certificate_test.go new file mode 100644 index 0000000000..3e9d84e4f4 --- /dev/null +++ b/agent/structs/config_entry_inline_certificate_test.go @@ -0,0 +1,106 @@ +package structs + +import "testing" + +const ( + // generated via openssl req -x509 -sha256 -days 1825 -newkey rsa:2048 -keyout private.key -out certificate.crt + validPrivateKey = `-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAx95Opa6t4lGEpiTUogEBptqOdam2ch4BHQGhNhX/MrDwwuZQ +httBwMfngQ/wd9NmYEPAwj0dumUoAITIq6i2jQlhqTodElkbsd5vWY8R/bxJWQSo +NvVE12TlzECxGpJEiHt4W0r8pGffk+rvpljiUyCfnT1kGF3znOSjK1hRMTn6RKWC +yYaBvXQiB4SGilfLgJcEpOJKtISIxmZ+S409g9X5VU88/Bmmrz4cMyxce86Kc2ug +5/MOv0CjWDJwlrv8njneV2zvraQ61DDwQftrXOvuCbO5IBRHMOBHiHTZ4rtGuhMa +Ir21V4vb6n8c4YzXiFvhUYcyX7rltGZzVd+WmQIDAQABAoIBACYvceUzp2MK4gYA +GWPOP2uKbBdM0l+hHeNV0WAM+dHMfmMuL4pkT36ucqt0ySOLjw6rQyOZG5nmA6t9 +sv0g4ae2eCMlyDIeNi1Yavu4Wt6YX4cTXbQKThm83C6W2X9THKbauBbxD621bsDK +7PhiGPN60yPue7YwFQAPqqD4YaK+s22HFIzk9gwM/rkvAUNwRv7SyHMiFe4Igc1C +Eev7iHWzvj5Heoz6XfF+XNF9DU+TieSUAdjd56VyUb8XL4+uBTOhHwLiXvAmfaMR +HvpcxeKnYZusS6NaOxcUHiJnsLNWrxmJj9WEGgQzuLxcLjTe4vVmELVZD8t3QUKj +PAxu8tUCgYEA7KIWVn9dfVpokReorFym+J8FzLwSktP9RZYEMonJo00i8aii3K9s +u/aSwRWQSCzmON1ZcxZzWhwQF9usz6kGCk//9+4hlVW90GtNK0RD+j7sp4aT2JI8 +9eLEjTG+xSXa7XWe98QncjjL9lu/yrRncSTxHs13q/XP198nn2aYuQ8CgYEA2Dnt +sRBzv0fFEvzzFv7G/5f85mouN38TUYvxNRTjBLCXl9DeKjDkOVZ2b6qlfQnYXIru +H+W+v+AZEb6fySXc8FRab7lkgTMrwE+aeI4rkW7asVwtclv01QJ5wMnyT84AgDD/ +Dgt/RThFaHgtU9TW5GOZveL+l9fVPn7vKFdTJdcCgYEArJ99zjHxwJ1whNAOk1av +09UmRPm6TvRo4heTDk8oEoIWCNatoHI0z1YMLuENNSnT9Q280FFDayvnrY/qnD7A +kktT/sjwJOG8q8trKzIMqQS4XWm2dxoPcIyyOBJfCbEY6XuRsUuePxwh5qF942EB +yS9a2s6nC4Ix0lgPrqAIr48CgYBgS/Q6riwOXSU8nqCYdiEkBYlhCJrKpnJxF9T1 +ofa0yPzKZP/8ZEfP7VzTwHjxJehQ1qLUW9pG08P2biH1UEKEWdzo8vT6wVJT1F/k +HtTycR8+a+Hlk2SHVRHqNUYQGpuIe8mrdJ1as4Pd0d/F/P0zO9Rlh+mAsGPM8HUM +T0+9gwKBgHDoerX7NTskg0H0t8O+iSMevdxpEWp34ZYa9gHiftTQGyrRgERCa7Gj +nZPAxKb2JoWyfnu3v7G5gZ8fhDFsiOxLbZv6UZJBbUIh1MjJISpXrForDrC2QNLX +kHrHfwBFDB3KMudhQknsJzEJKCL/KmFH6o0MvsoaT9yzEl3K+ah/ +-----END RSA PRIVATE KEY-----` + validCertificate = `-----BEGIN CERTIFICATE----- +MIICljCCAX4CCQCQMDsYO8FrPjANBgkqhkiG9w0BAQsFADANMQswCQYDVQQGEwJV +UzAeFw0yMjEyMjAxNzUwMjVaFw0yNzEyMTkxNzUwMjVaMA0xCzAJBgNVBAYTAlVT +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx95Opa6t4lGEpiTUogEB +ptqOdam2ch4BHQGhNhX/MrDwwuZQhttBwMfngQ/wd9NmYEPAwj0dumUoAITIq6i2 +jQlhqTodElkbsd5vWY8R/bxJWQSoNvVE12TlzECxGpJEiHt4W0r8pGffk+rvplji +UyCfnT1kGF3znOSjK1hRMTn6RKWCyYaBvXQiB4SGilfLgJcEpOJKtISIxmZ+S409 +g9X5VU88/Bmmrz4cMyxce86Kc2ug5/MOv0CjWDJwlrv8njneV2zvraQ61DDwQftr +XOvuCbO5IBRHMOBHiHTZ4rtGuhMaIr21V4vb6n8c4YzXiFvhUYcyX7rltGZzVd+W +mQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQBfCqoUIdPf/HGSbOorPyZWbyizNtHJ +GL7x9cAeIYxpI5Y/WcO1o5v94lvrgm3FNfJoGKbV66+JxOge731FrfMpHplhar1Z +RahYIzNLRBTLrwadLAZkApUpZvB8qDK4knsTWFYujNsylCww2A6ajzIMFNU4GkUK +NtyHRuD+KYRmjXtyX1yHNqfGN3vOQmwavHq2R8wHYuBSc6LAHHV9vG+j0VsgMELO +qwxn8SmLkSKbf2+MsQVzLCXXN5u+D8Yv+4py+oKP4EQ5aFZuDEx+r/G/31rTthww +AAJAMaoXmoYVdgXV+CPuBb2M4XCpuzLu3bcA2PXm5ipSyIgntMKwXV7r +-----END CERTIFICATE-----` + mismatchedCertificate = `-----BEGIN CERTIFICATE----- +MIICljCCAX4CCQC49bq8e0QgLDANBgkqhkiG9w0BAQsFADANMQswCQYDVQQGEwJV +UzAeFw0yMjEyMjAxNzUyMzJaFw0yNzEyMTkxNzUyMzJaMA0xCzAJBgNVBAYTAlVT +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk7Are9ulVDY0IqaG5Pt/ +OVuS0kmDhgVUfQBM5JDGRfIsu1ebn68kn5JGCTQ+nC8nU9QXRJS7vG6As5GWm08W +FpkOyIbHLjOhWtYCYzQ+0R+sSSoMnczgl8l6wIUIkR3Vpoy6QUsSZbvo4/xDi3Uk +1CF+JMTM2oFDLD8PNrNzW/txRyTugK36W1G1ofUhvP6EHsTjmVcZwBcLOKToov6L +Ai758MLztl1/X/90DNdZwuHC9fGIgx52Ojz3+XIocXFttr+J8xZglMCtqL4n40bh +5b1DE+hC3NHQmA+7Chc99z28baj2cU1woNk/TO+ewqpyvj+WPWwGOQt3U63ZoPaw +yQIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCMF3JlrDdcSv2KYrxEp1tWB/GglI8a +JiSvrf3hePaRz59099bg4DoHzTn0ptOcOPOO9epDPbCJrUqLuPlwvrQRvll6GaW1 +y3TcbnE1AbwTAjbOTgpLhvuj6IVlyNNLoKbjZqs4A8N8i6UkQ7Y8qg77lwxD3QoH +pWLwGZKJifKPa7ObVWmKj727kbU59nA2Hx+Y4qa/MyiPWxJM9Y0JsFGxSBxp4kmQ +q4ikzSWaPv/TvtV+d4mO1H44aggdNMCYIQd/5BXQzG40l+ecHnBueJyG312ax/Zp +NsYUAKQT864cGlxrnWVgT4sW/tsl9Qen7g9iAdeBAPvLO7cQjAjtc7KZ +-----END CERTIFICATE-----` +) + +func TestInlineCertificate(t *testing.T) { + cases := map[string]configEntryTestcase{ + "invalid private key": { + entry: &InlineCertificateConfigEntry{ + Kind: InlineCertificate, + Name: "cert-one", + PrivateKey: "foo", + }, + validateErr: "failed to parse private key PEM", + }, + "invalid certificate": { + entry: &InlineCertificateConfigEntry{ + Kind: InlineCertificate, + Name: "cert-two", + PrivateKey: validPrivateKey, + Certificate: "foo", + }, + validateErr: "failed to parse certificate PEM", + }, + "mismatched certificate": { + entry: &InlineCertificateConfigEntry{ + Kind: InlineCertificate, + Name: "cert-three", + PrivateKey: validPrivateKey, + Certificate: mismatchedCertificate, + }, + validateErr: "private key does not match public key", + }, + "matched certificate": { + entry: &InlineCertificateConfigEntry{ + Kind: InlineCertificate, + Name: "cert-four", + PrivateKey: validPrivateKey, + Certificate: validCertificate, + }, + }, + } + testConfigEntryNormalizeAndValidate(t, cases) +} diff --git a/agent/structs/config_entry_routes.go b/agent/structs/config_entry_routes.go new file mode 100644 index 0000000000..19a2d70eda --- /dev/null +++ b/agent/structs/config_entry_routes.go @@ -0,0 +1,177 @@ +package structs + +import ( + "fmt" + + "github.com/hashicorp/consul/acl" +) + +// HTTPRouteConfigEntry manages the configuration for a HTTP route +// with the given name. +type HTTPRouteConfigEntry struct { + // Kind of the config entry. This will be set to structs.HTTPRoute. + Kind string + + // Name is used to match the config entry with its associated set + // of resources, which may include routers, splitters, filters, etc. + Name string + + Meta map[string]string `json:",omitempty"` + acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` + RaftIndex +} + +func (e *HTTPRouteConfigEntry) GetKind() string { + return HTTPRoute +} + +func (e *HTTPRouteConfigEntry) GetName() string { + if e == nil { + return "" + } + return e.Name +} + +func (e *HTTPRouteConfigEntry) Normalize() error { + return nil +} + +func (e *HTTPRouteConfigEntry) Validate() error { + return nil +} + +func (e *HTTPRouteConfigEntry) CanRead(authz acl.Authorizer) error { + var authzContext acl.AuthorizerContext + e.FillAuthzContext(&authzContext) + return authz.ToAllowAuthorizer().MeshReadAllowed(&authzContext) +} + +func (e *HTTPRouteConfigEntry) CanWrite(authz acl.Authorizer) error { + var authzContext acl.AuthorizerContext + e.FillAuthzContext(&authzContext) + return authz.ToAllowAuthorizer().MeshWriteAllowed(&authzContext) +} + +func (e *HTTPRouteConfigEntry) GetMeta() map[string]string { + if e == nil { + return nil + } + return e.Meta +} + +func (e *HTTPRouteConfigEntry) GetEnterpriseMeta() *acl.EnterpriseMeta { + if e == nil { + return nil + } + return &e.EnterpriseMeta +} + +func (e *HTTPRouteConfigEntry) GetRaftIndex() *RaftIndex { + if e == nil { + return &RaftIndex{} + } + return &e.RaftIndex +} + +// TCPRouteConfigEntry manages the configuration for a TCP route +// with the given name. +type TCPRouteConfigEntry struct { + // Kind of the config entry. This will be set to structs.TCPRoute. + Kind string + + // Name is used to match the config entry with its associated set + // of resources. + Name string + + // Parents is a list of gateways that this route should be bound to + Parents []ResourceReference + // Services is a list of TCP-based services that this should route to. + // Currently, this must specify at maximum one service. + Services []TCPService + + Meta map[string]string `json:",omitempty"` + // Status is the asynchronous status which a TCPRoute propagates to the user. + Status Status + acl.EnterpriseMeta `hcl:",squash" mapstructure:",squash"` + RaftIndex +} + +func (e *TCPRouteConfigEntry) GetKind() string { + return TCPRoute +} + +func (e *TCPRouteConfigEntry) GetName() string { + if e == nil { + return "" + } + return e.Name +} + +func (e *TCPRouteConfigEntry) GetMeta() map[string]string { + if e == nil { + return nil + } + return e.Meta +} + +func (e *TCPRouteConfigEntry) Normalize() error { + for i, parent := range e.Parents { + if parent.Kind == "" { + parent.Kind = APIGateway + e.Parents[i] = parent + } + } + return nil +} + +func (e *TCPRouteConfigEntry) Validate() error { + validParentKinds := map[string]bool{ + APIGateway: true, + } + + if len(e.Services) > 1 { + return fmt.Errorf("tcp-route currently only supports one service") + } + for _, parent := range e.Parents { + if !validParentKinds[parent.Kind] { + return fmt.Errorf("unsupported parent kind: %q, must be 'api-gateway'", parent.Kind) + } + } + return nil +} + +func (e *TCPRouteConfigEntry) CanRead(authz acl.Authorizer) error { + var authzContext acl.AuthorizerContext + e.FillAuthzContext(&authzContext) + return authz.ToAllowAuthorizer().MeshReadAllowed(&authzContext) +} + +func (e *TCPRouteConfigEntry) CanWrite(authz acl.Authorizer) error { + var authzContext acl.AuthorizerContext + e.FillAuthzContext(&authzContext) + return authz.ToAllowAuthorizer().MeshWriteAllowed(&authzContext) +} + +func (e *TCPRouteConfigEntry) GetRaftIndex() *RaftIndex { + if e == nil { + return &RaftIndex{} + } + return &e.RaftIndex +} + +func (e *TCPRouteConfigEntry) GetEnterpriseMeta() *acl.EnterpriseMeta { + if e == nil { + return nil + } + return &e.EnterpriseMeta +} + +// TCPService is a service reference for a TCPRoute +type TCPService struct { + Name string + // Weight specifies the proportion of requests forwarded to the referenced service. + // This is computed as weight/(sum of all weights in the list of services). + Weight int + + acl.EnterpriseMeta +} diff --git a/agent/structs/config_entry_routes_test.go b/agent/structs/config_entry_routes_test.go new file mode 100644 index 0000000000..dc89ca9e09 --- /dev/null +++ b/agent/structs/config_entry_routes_test.go @@ -0,0 +1,58 @@ +package structs + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestTCPRoute(t *testing.T) { + cases := map[string]configEntryTestcase{ + "multiple services": { + entry: &TCPRouteConfigEntry{ + Kind: TCPRoute, + Name: "route-one", + Services: []TCPService{{ + Name: "foo", + }, { + Name: "bar", + }}, + }, + validateErr: "tcp-route currently only supports one service", + }, + "normalize parent kind": { + entry: &TCPRouteConfigEntry{ + Kind: TCPRoute, + Name: "route-two", + Parents: []ResourceReference{{ + Name: "gateway", + }}, + Services: []TCPService{{ + Name: "foo", + }}, + }, + normalizeOnly: true, + check: func(t *testing.T, entry ConfigEntry) { + expectedParent := ResourceReference{ + Kind: APIGateway, + Name: "gateway", + } + route := entry.(*TCPRouteConfigEntry) + require.Len(t, route.Parents, 1) + require.Equal(t, expectedParent, route.Parents[0]) + }, + }, + "invalid parent kind": { + entry: &TCPRouteConfigEntry{ + Kind: TCPRoute, + Name: "route-two", + Parents: []ResourceReference{{ + Kind: "route", + Name: "gateway", + }}, + }, + validateErr: "unsupported parent kind", + }, + } + testConfigEntryNormalizeAndValidate(t, cases) +} diff --git a/agent/structs/config_entry_status.go b/agent/structs/config_entry_status.go new file mode 100644 index 0000000000..133555e9f2 --- /dev/null +++ b/agent/structs/config_entry_status.go @@ -0,0 +1,51 @@ +package structs + +import ( + "time" + + "github.com/hashicorp/consul/acl" +) + +// ResourceReference is a reference to a ConfigEntry +// with an optional reference to a subsection of that ConfigEntry +// that can be specified as SectionName +type ResourceReference struct { + // Kind is the kind of ConfigEntry that this resource refers to. + Kind string + // Name is the identifier for the ConfigEntry this resource refers to. + Name string + // SectionName is a generic subresource identifier that specifies + // a subset of the ConfigEntry to which this reference applies. Usage + // of this field should be up to the controller that leverages it. If + // unused, this should be blank. + SectionName string + + acl.EnterpriseMeta +} + +// Status is used for propagating back asynchronously calculated +// messages from control loops to a user +type Status struct { + // Conditions is the set of condition objects associated with + // a ConfigEntry status. + Conditions []Condition +} + +// Condition is used for a single message and state associated +// with an object. For example, a ConfigEntry that references +// multiple other resources may have different statuses with +// respect to each of those resources. +type Condition struct { + // Status is a value from a bounded set of statuses that an object might have + Status string + // Reason is a value from a bounded set of reasons for a given status + Reason string + // Message is a message that gives more detailed information about + // why a Condition has a given status and reason + Message string + // Resource is an optional reference to a resource for which this + // condition applies + Resource *ResourceReference + // LastTransitionTime is the time at which this Condition was created + LastTransitionTime *time.Time +} diff --git a/agent/structs/config_entry_test.go b/agent/structs/config_entry_test.go index 33cc9eb6f3..64ad4361ef 100644 --- a/agent/structs/config_entry_test.go +++ b/agent/structs/config_entry_test.go @@ -296,7 +296,7 @@ func TestDecodeConfigEntry_ServiceDefaults(t *testing.T) { } // TestDecodeConfigEntry is the 'structs' mirror image of -// command/config/write/config_write_test.go:TestParseConfigEntry +// command/helpers/helpers_test.go:TestParseConfigEntry func TestDecodeConfigEntry(t *testing.T) { for _, tc := range []struct { @@ -1899,6 +1899,114 @@ func TestDecodeConfigEntry(t *testing.T) { }, }, }, + { + name: "api-gateway", + snake: ` + kind = "api-gateway" + name = "foo" + meta { + "foo" = "bar" + "gir" = "zim" + } + `, + camel: ` + Kind = "api-gateway" + Name = "foo" + Meta { + "foo" = "bar" + "gir" = "zim" + } + `, + expect: &APIGatewayConfigEntry{ + Kind: "api-gateway", + Name: "foo", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + }, + }, + { + name: "inline-certificate", + snake: ` + kind = "inline-certificate" + name = "foo" + meta { + "foo" = "bar" + "gir" = "zim" + } + `, + camel: ` + Kind = "inline-certificate" + Name = "foo" + Meta { + "foo" = "bar" + "gir" = "zim" + } + `, + expect: &InlineCertificateConfigEntry{ + Kind: "inline-certificate", + Name: "foo", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + }, + }, + { + name: "http-route", + snake: ` + kind = "http-route" + name = "foo" + meta { + "foo" = "bar" + "gir" = "zim" + } + `, + camel: ` + Kind = "http-route" + Name = "foo" + Meta { + "foo" = "bar" + "gir" = "zim" + } + `, + expect: &HTTPRouteConfigEntry{ + Kind: "http-route", + Name: "foo", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + }, + }, + { + name: "tcp-route", + snake: ` + kind = "tcp-route" + name = "foo" + meta { + "foo" = "bar" + "gir" = "zim" + } + `, + camel: ` + Kind = "tcp-route" + Name = "foo" + Meta { + "foo" = "bar" + "gir" = "zim" + } + `, + expect: &TCPRouteConfigEntry{ + Kind: "tcp-route", + Name: "foo", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + }, + }, { name: "exported-services", snake: ` diff --git a/api/config_entry.go b/api/config_entry.go index 8649e16ea8..258d962422 100644 --- a/api/config_entry.go +++ b/api/config_entry.go @@ -26,6 +26,10 @@ const ( ProxyConfigGlobal string = "global" MeshConfigMesh string = "mesh" + APIGateway string = "api-gateway" + TCPRoute string = "tcp-route" + InlineCertificate string = "inline-certificate" + HTTPRoute string = "http-route" ) const ( @@ -347,6 +351,14 @@ func makeConfigEntry(kind, name string) (ConfigEntry, error) { return &MeshConfigEntry{}, nil case ExportedServices: return &ExportedServicesConfigEntry{Name: name}, nil + case APIGateway: + return &APIGatewayConfigEntry{Kind: kind, Name: name}, nil + case TCPRoute: + return &TCPRouteConfigEntry{Kind: kind, Name: name}, nil + case InlineCertificate: + return &InlineCertificateConfigEntry{Kind: kind, Name: name}, nil + case HTTPRoute: + return &HTTPRouteConfigEntry{Kind: kind, Name: name}, nil default: return nil, fmt.Errorf("invalid config entry kind: %s", kind) } diff --git a/api/config_entry_gateways.go b/api/config_entry_gateways.go index 44a3bbd0c3..209c7ae0df 100644 --- a/api/config_entry_gateways.go +++ b/api/config_entry_gateways.go @@ -221,3 +221,82 @@ func (g *TerminatingGatewayConfigEntry) GetNamespace() string { return g.N func (g *TerminatingGatewayConfigEntry) GetMeta() map[string]string { return g.Meta } func (g *TerminatingGatewayConfigEntry) GetCreateIndex() uint64 { return g.CreateIndex } func (g *TerminatingGatewayConfigEntry) GetModifyIndex() uint64 { return g.ModifyIndex } + +// APIGatewayConfigEntry manages the configuration for an API gateway +// with the given name. +type APIGatewayConfigEntry struct { + // Kind of the config entry. This should be set to api.APIGateway. + Kind string + + // Name is used to match the config entry with its associated api gateway + // service. This should match the name provided in the service definition. + Name string + + Meta map[string]string `json:",omitempty"` + + // Listeners is the set of listener configuration to which an API Gateway + // might bind. + Listeners []APIGatewayListener + // Status is the asynchronous status which an APIGateway propagates to the user. + Status ConfigEntryStatus + + // CreateIndex is the Raft index this entry was created at. This is a + // read-only field. + CreateIndex uint64 + + // ModifyIndex is used for the Check-And-Set operations and can also be fed + // back into the WaitIndex of the QueryOptions in order to perform blocking + // queries. + ModifyIndex uint64 + + // Partition is the partition the config entry is associated with. + // Partitioning is a Consul Enterprise feature. + Partition string `json:",omitempty"` + + // Namespace is the namespace the config entry is associated with. + // Namespacing is a Consul Enterprise feature. + Namespace string `json:",omitempty"` +} + +func (g *APIGatewayConfigEntry) GetKind() string { return g.Kind } +func (g *APIGatewayConfigEntry) GetName() string { return g.Name } +func (g *APIGatewayConfigEntry) GetPartition() string { return g.Partition } +func (g *APIGatewayConfigEntry) GetNamespace() string { return g.Namespace } +func (g *APIGatewayConfigEntry) GetMeta() map[string]string { return g.Meta } +func (g *APIGatewayConfigEntry) GetCreateIndex() uint64 { return g.CreateIndex } +func (g *APIGatewayConfigEntry) GetModifyIndex() uint64 { return g.ModifyIndex } + +// APIGatewayListener represents an individual listener for an APIGateway +type APIGatewayListener struct { + // Name is the optional name of the listener in a given gateway. This is + // optional, however, it must be unique. Therefore, if a gateway has more + // than a single listener, all but one must specify a Name. + Name string + // Hostname is the host name that a listener should be bound to, if + // unspecified, the listener accepts requests for all hostnames. + Hostname string + // Port is the port at which this listener should bind. + Port int + // Protocol is the protocol that a listener should use, it must + // either be "http" or "tcp" + Protocol string + // TLS is the TLS settings for the listener. + TLS APIGatewayTLSConfiguration +} + +// APIGatewayTLSConfiguration specifies the configuration of a listener’s +// TLS settings. +type APIGatewayTLSConfiguration struct { + // Certificates is a set of references to certificates + // that a gateway listener uses for TLS termination. + Certificates []ResourceReference + // MaxVersion is the maximum TLS version that the listener + // should support. + MaxVersion string `json:",omitempty" alias:"tls_max_version"` + // MinVersion is the minimum TLS version that the listener + // should support. + MinVersion string `json:",omitempty" alias:"tls_min_version"` + // Define a subset of cipher suites to restrict + // Only applicable to connections negotiated via TLS 1.2 or earlier + CipherSuites []string `json:",omitempty" alias:"cipher_suites"` +} diff --git a/api/config_entry_inline_certificate.go b/api/config_entry_inline_certificate.go new file mode 100644 index 0000000000..d2aa5115ea --- /dev/null +++ b/api/config_entry_inline_certificate.go @@ -0,0 +1,75 @@ +package api + +// InlineCertificateConfigEntry -- TODO stub +type InlineCertificateConfigEntry struct { + // Kind of the config entry. This should be set to api.InlineCertificate. + Kind string + + // Name is used to match the config entry with its associated tcp-route + // service. This should match the name provided in the service definition. + Name string + + // Certificate is the public certificate component of an x509 key pair encoded in raw PEM format. + Certificate string + // PrivateKey is the private key component of an x509 key pair encoded in raw PEM format. + PrivateKey string + + Meta map[string]string `json:",omitempty"` + + // CreateIndex is the Raft index this entry was created at. This is a + // read-only field. + CreateIndex uint64 + + // ModifyIndex is used for the Check-And-Set operations and can also be fed + // back into the WaitIndex of the QueryOptions in order to perform blocking + // queries. + ModifyIndex uint64 + + // Partition is the partition the config entry is associated with. + // Partitioning is a Consul Enterprise feature. + Partition string `json:",omitempty"` + + // Namespace is the namespace the config entry is associated with. + // Namespacing is a Consul Enterprise feature. + Namespace string `json:",omitempty"` +} + +func (a *InlineCertificateConfigEntry) GetKind() string { + return InlineCertificate +} + +func (a *InlineCertificateConfigEntry) GetName() string { + if a != nil { + return "" + } + return a.Name +} + +func (a *InlineCertificateConfigEntry) GetPartition() string { + if a != nil { + return "" + } + return a.Partition +} + +func (a *InlineCertificateConfigEntry) GetNamespace() string { + if a != nil { + return "" + } + return a.GetNamespace() +} + +func (a *InlineCertificateConfigEntry) GetMeta() map[string]string { + if a != nil { + return nil + } + return a.GetMeta() +} + +func (a *InlineCertificateConfigEntry) GetCreateIndex() uint64 { + return a.CreateIndex +} + +func (a *InlineCertificateConfigEntry) GetModifyIndex() uint64 { + return a.ModifyIndex +} diff --git a/api/config_entry_routes.go b/api/config_entry_routes.go new file mode 100644 index 0000000000..c8cec0c030 --- /dev/null +++ b/api/config_entry_routes.go @@ -0,0 +1,132 @@ +package api + +// TCPRouteConfigEntry -- TODO stub +type TCPRouteConfigEntry struct { + // Kind of the config entry. This should be set to api.TCPRoute. + Kind string + + // Name is used to match the config entry with its associated tcp-route + // service. This should match the name provided in the service definition. + Name string + + // Parents is a list of gateways that this route should be bound to. + Parents []ResourceReference + // Services is a list of TCP-based services that this should route to. + // Currently, this must specify at maximum one service. + Services []TCPService + + Meta map[string]string `json:",omitempty"` + + // Status is the asynchronous status which a TCPRoute propagates to the user. + Status ConfigEntryStatus + + // CreateIndex is the Raft index this entry was created at. This is a + // read-only field. + CreateIndex uint64 + + // ModifyIndex is used for the Check-And-Set operations and can also be fed + // back into the WaitIndex of the QueryOptions in order to perform blocking + // queries. + ModifyIndex uint64 + + // Partition is the partition the config entry is associated with. + // Partitioning is a Consul Enterprise feature. + Partition string `json:",omitempty"` + + // Namespace is the namespace the config entry is associated with. + // Namespacing is a Consul Enterprise feature. + Namespace string `json:",omitempty"` +} + +func (a *TCPRouteConfigEntry) GetKind() string { + return TCPRoute +} + +func (a *TCPRouteConfigEntry) GetName() string { + if a != nil { + return "" + } + return a.Name +} + +func (a *TCPRouteConfigEntry) GetPartition() string { + if a != nil { + return "" + } + return a.Partition +} + +func (a *TCPRouteConfigEntry) GetNamespace() string { + if a != nil { + return "" + } + return a.GetNamespace() +} + +func (a *TCPRouteConfigEntry) GetMeta() map[string]string { + if a != nil { + return nil + } + return a.GetMeta() +} + +func (a *TCPRouteConfigEntry) GetCreateIndex() uint64 { + return a.CreateIndex +} + +func (a *TCPRouteConfigEntry) GetModifyIndex() uint64 { + return a.ModifyIndex +} + +// TCPService is a service reference for a TCPRoute +type TCPService struct { + Name string + // Weight specifies the proportion of requests forwarded to the referenced service. + // This is computed as weight/(sum of all weights in the list of services). + Weight int + + // Partition is the partition the config entry is associated with. + // Partitioning is a Consul Enterprise feature. + Partition string `json:",omitempty"` + + // Namespace is the namespace the config entry is associated with. + // Namespacing is a Consul Enterprise feature. + Namespace string `json:",omitempty"` +} + +// HTTPRouteConfigEntry manages the configuration for a HTTP route +// with the given name. +type HTTPRouteConfigEntry struct { + // Kind of the config entry. This should be set to api.HTTPRoute. + Kind string + + // Name is used to match the config entry with its associated http-route. + Name string + + Meta map[string]string `json:",omitempty"` + + // CreateIndex is the Raft index this entry was created at. This is a + // read-only field. + CreateIndex uint64 + + // ModifyIndex is used for the Check-And-Set operations and can also be fed + // back into the WaitIndex of the QueryOptions in order to perform blocking + // queries. + ModifyIndex uint64 + + // Partition is the partition the config entry is associated with. + // Partitioning is a Consul Enterprise feature. + Partition string `json:",omitempty"` + + // Namespace is the namespace the config entry is associated with. + // Namespacing is a Consul Enterprise feature. + Namespace string `json:",omitempty"` +} + +func (r *HTTPRouteConfigEntry) GetKind() string { return HTTPRoute } +func (r *HTTPRouteConfigEntry) GetName() string { return r.Name } +func (r *HTTPRouteConfigEntry) GetPartition() string { return r.Partition } +func (r *HTTPRouteConfigEntry) GetNamespace() string { return r.Namespace } +func (r *HTTPRouteConfigEntry) GetMeta() map[string]string { return r.Meta } +func (r *HTTPRouteConfigEntry) GetCreateIndex() uint64 { return r.CreateIndex } +func (r *HTTPRouteConfigEntry) GetModifyIndex() uint64 { return r.ModifyIndex } diff --git a/api/config_entry_status.go b/api/config_entry_status.go new file mode 100644 index 0000000000..c0151ce2da --- /dev/null +++ b/api/config_entry_status.go @@ -0,0 +1,55 @@ +package api + +import ( + "time" +) + +// ResourceReference is a reference to a ConfigEntry +// with an optional reference to a subsection of that ConfigEntry +// that can be specified as SectionName +type ResourceReference struct { + // Kind is the kind of ConfigEntry that this resource refers to. + Kind string + // Name is the identifier for the ConfigEntry this resource refers to. + Name string + // SectionName is a generic subresource identifier that specifies + // a subset of the ConfigEntry to which this reference applies. Usage + // of this field should be up to the controller that leverages it. If + // unused, this should be blank. + SectionName string + + // Partition is the partition the config entry is associated with. + // Partitioning is a Consul Enterprise feature. + Partition string `json:",omitempty"` + + // Namespace is the namespace the config entry is associated with. + // Namespacing is a Consul Enterprise feature. + Namespace string `json:",omitempty"` +} + +// ConfigEntryStatus is used for propagating back asynchronously calculated +// messages from control loops to a user +type ConfigEntryStatus struct { + // Conditions is the set of condition objects associated with + // a ConfigEntry status. + Conditions []Condition +} + +// Condition is used for a single message and state associated +// with an object. For example, a ConfigEntry that references +// multiple other resources may have different statuses with +// respect to each of those resources. +type Condition struct { + // Status is a value from a bounded set of statuses that an object might have + Status string + // Reason is a value from a bounded set of reasons for a given status + Reason string + // Message is a message that gives more detailed information about + // why a Condition has a given status and reason + Message string + // Resource is an optional reference to a resource for which this + // condition applies + Resource *ResourceReference + // LastTransitionTime is the time at which this Condition was created + LastTransitionTime *time.Time +} diff --git a/command/helpers/helpers_test.go b/command/helpers/helpers_test.go index 4edc58349d..e9fbeb071a 100644 --- a/command/helpers/helpers_test.go +++ b/command/helpers/helpers_test.go @@ -3037,6 +3037,190 @@ func TestParseConfigEntry(t *testing.T) { }, }, }, + { + name: "api-gateway", + snake: ` + kind = "api-gateway" + name = "main" + meta { + "foo" = "bar" + "gir" = "zim" + } + `, + camel: ` + Kind = "api-gateway" + Name = "main" + Meta { + "foo" = "bar" + "gir" = "zim" + } + `, + snakeJSON: ` + { + "kind": "api-gateway", + "name": "main", + "meta": { + "foo": "bar", + "gir": "zim" + } + } + `, + camelJSON: ` + { + "Kind": "api-gateway", + "Name": "main", + "Meta": { + "foo": "bar", + "gir": "zim" + } + }`, + expect: &api.APIGatewayConfigEntry{ + Kind: "api-gateway", + Name: "main", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + }, + }, + { + name: "inline-certificate", + snake: ` + kind = "inline-certificate" + name = "main" + meta { + "foo" = "bar" + "gir" = "zim" + } + `, + camel: ` + Kind = "inline-certificate" + Name = "main" + Meta { + "foo" = "bar" + "gir" = "zim" + } + `, + snakeJSON: ` + { + "kind": "inline-certificate", + "name": "main", + "meta": { + "foo": "bar", + "gir": "zim" + } + } + `, + camelJSON: ` + { + "Kind": "inline-certificate", + "Name": "main", + "Meta": { + "foo": "bar", + "gir": "zim" + } + }`, + expect: &api.InlineCertificateConfigEntry{ + Kind: "inline-certificate", + Name: "main", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + }, + }, + { + name: "http-route", + snake: ` + kind = "http-route" + name = "main" + meta { + "foo" = "bar" + "gir" = "zim" + } + `, + camel: ` + Kind = "http-route" + Name = "main" + Meta { + "foo" = "bar" + "gir" = "zim" + } + `, + snakeJSON: ` + { + "kind": "http-route", + "name": "main", + "meta": { + "foo": "bar", + "gir": "zim" + } + } + `, + camelJSON: ` + { + "Kind": "http-route", + "Name": "main", + "Meta": { + "foo": "bar", + "gir": "zim" + } + }`, + expect: &api.HTTPRouteConfigEntry{ + Kind: "http-route", + Name: "main", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + }, + }, + { + name: "tcp-route", + snake: ` + kind = "tcp-route" + name = "main" + meta { + "foo" = "bar" + "gir" = "zim" + } + `, + camel: ` + Kind = "tcp-route" + Name = "main" + Meta { + "foo" = "bar" + "gir" = "zim" + } + `, + snakeJSON: ` + { + "kind": "tcp-route", + "name": "main", + "meta": { + "foo": "bar", + "gir": "zim" + } + } + `, + camelJSON: ` + { + "Kind": "tcp-route", + "Name": "main", + "Meta": { + "foo": "bar", + "gir": "zim" + } + }`, + expect: &api.TCPRouteConfigEntry{ + Kind: "tcp-route", + Name: "main", + Meta: map[string]string{ + "foo": "bar", + "gir": "zim", + }, + }, + }, } { tc := tc diff --git a/proto/pbconfigentry/config_entry.gen.go b/proto/pbconfigentry/config_entry.gen.go index b7bfc25d41..5835615fa9 100644 --- a/proto/pbconfigentry/config_entry.gen.go +++ b/proto/pbconfigentry/config_entry.gen.go @@ -4,6 +4,210 @@ package pbconfigentry import "github.com/hashicorp/consul/agent/structs" +func APIGatewayToStructs(s *APIGateway, t *structs.APIGatewayConfigEntry) { + if s == nil { + return + } + { + t.Listeners = make([]structs.APIGatewayListener, len(s.Listeners)) + for i := range s.Listeners { + if s.Listeners[i] != nil { + APIGatewayListenerToStructs(s.Listeners[i], &t.Listeners[i]) + } + } + } + if s.Status != nil { + StatusToStructs(s.Status, &t.Status) + } + t.Meta = s.Meta +} +func APIGatewayFromStructs(t *structs.APIGatewayConfigEntry, s *APIGateway) { + if s == nil { + return + } + { + s.Listeners = make([]*APIGatewayListener, len(t.Listeners)) + for i := range t.Listeners { + { + var x APIGatewayListener + APIGatewayListenerFromStructs(&t.Listeners[i], &x) + s.Listeners[i] = &x + } + } + } + { + var x Status + StatusFromStructs(&t.Status, &x) + s.Status = &x + } + s.Meta = t.Meta +} +func APIGatewayListenerToStructs(s *APIGatewayListener, t *structs.APIGatewayListener) { + if s == nil { + return + } + t.Name = s.Name + t.Hostname = s.Hostname + t.Port = int(s.Port) + t.Protocol = apiGatewayProtocolToStructs(s.Protocol) + if s.TLS != nil { + APIGatewayTLSConfigurationToStructs(s.TLS, &t.TLS) + } +} +func APIGatewayListenerFromStructs(t *structs.APIGatewayListener, s *APIGatewayListener) { + if s == nil { + return + } + s.Name = t.Name + s.Hostname = t.Hostname + s.Port = int32(t.Port) + s.Protocol = apiGatewayProtocolFromStructs(t.Protocol) + { + var x APIGatewayTLSConfiguration + APIGatewayTLSConfigurationFromStructs(&t.TLS, &x) + s.TLS = &x + } +} +func APIGatewayTLSConfigurationToStructs(s *APIGatewayTLSConfiguration, t *structs.APIGatewayTLSConfiguration) { + if s == nil { + return + } + { + t.Certificates = make([]structs.ResourceReference, len(s.Certificates)) + for i := range s.Certificates { + if s.Certificates[i] != nil { + ResourceReferenceToStructs(s.Certificates[i], &t.Certificates[i]) + } + } + } + t.MaxVersion = tlsVersionToStructs(s.MaxVersion) + t.MinVersion = tlsVersionToStructs(s.MinVersion) + t.CipherSuites = cipherSuitesToStructs(s.CipherSuites) +} +func APIGatewayTLSConfigurationFromStructs(t *structs.APIGatewayTLSConfiguration, s *APIGatewayTLSConfiguration) { + if s == nil { + return + } + { + s.Certificates = make([]*ResourceReference, len(t.Certificates)) + for i := range t.Certificates { + { + var x ResourceReference + ResourceReferenceFromStructs(&t.Certificates[i], &x) + s.Certificates[i] = &x + } + } + } + s.MaxVersion = tlsVersionFromStructs(t.MaxVersion) + s.MinVersion = tlsVersionFromStructs(t.MinVersion) + s.CipherSuites = cipherSuitesFromStructs(t.CipherSuites) +} +func BoundAPIGatewayToStructs(s *BoundAPIGateway, t *structs.BoundAPIGatewayConfigEntry) { + if s == nil { + return + } + { + t.Listeners = make([]structs.BoundAPIGatewayListener, len(s.Listeners)) + for i := range s.Listeners { + if s.Listeners[i] != nil { + BoundAPIGatewayListenerToStructs(s.Listeners[i], &t.Listeners[i]) + } + } + } + t.Meta = s.Meta +} +func BoundAPIGatewayFromStructs(t *structs.BoundAPIGatewayConfigEntry, s *BoundAPIGateway) { + if s == nil { + return + } + { + s.Listeners = make([]*BoundAPIGatewayListener, len(t.Listeners)) + for i := range t.Listeners { + { + var x BoundAPIGatewayListener + BoundAPIGatewayListenerFromStructs(&t.Listeners[i], &x) + s.Listeners[i] = &x + } + } + } + s.Meta = t.Meta +} +func BoundAPIGatewayListenerToStructs(s *BoundAPIGatewayListener, t *structs.BoundAPIGatewayListener) { + if s == nil { + return + } + t.Name = s.Name + { + t.Routes = make([]structs.ResourceReference, len(s.Routes)) + for i := range s.Routes { + if s.Routes[i] != nil { + ResourceReferenceToStructs(s.Routes[i], &t.Routes[i]) + } + } + } + { + t.Certificates = make([]structs.ResourceReference, len(s.Certificates)) + for i := range s.Certificates { + if s.Certificates[i] != nil { + ResourceReferenceToStructs(s.Certificates[i], &t.Certificates[i]) + } + } + } +} +func BoundAPIGatewayListenerFromStructs(t *structs.BoundAPIGatewayListener, s *BoundAPIGatewayListener) { + if s == nil { + return + } + s.Name = t.Name + { + s.Routes = make([]*ResourceReference, len(t.Routes)) + for i := range t.Routes { + { + var x ResourceReference + ResourceReferenceFromStructs(&t.Routes[i], &x) + s.Routes[i] = &x + } + } + } + { + s.Certificates = make([]*ResourceReference, len(t.Certificates)) + for i := range t.Certificates { + { + var x ResourceReference + ResourceReferenceFromStructs(&t.Certificates[i], &x) + s.Certificates[i] = &x + } + } + } +} +func ConditionToStructs(s *Condition, t *structs.Condition) { + if s == nil { + return + } + t.Status = s.Status + t.Reason = s.Reason + t.Message = s.Message + if s.Resource != nil { + var x structs.ResourceReference + ResourceReferenceToStructs(s.Resource, &x) + t.Resource = &x + } + t.LastTransitionTime = timeToStructs(s.LastTransitionTime) +} +func ConditionFromStructs(t *structs.Condition, s *Condition) { + if s == nil { + return + } + s.Status = t.Status + s.Reason = t.Reason + s.Message = t.Message + if t.Resource != nil { + var x ResourceReference + ResourceReferenceFromStructs(t.Resource, &x) + s.Resource = &x + } + s.LastTransitionTime = timeFromStructs(t.LastTransitionTime) +} func CookieConfigToStructs(s *CookieConfig, t *structs.CookieConfig) { if s == nil { return @@ -178,6 +382,18 @@ func HTTPHeaderModifiersFromStructs(t *structs.HTTPHeaderModifiers, s *HTTPHeade s.Set = t.Set s.Remove = t.Remove } +func HTTPRouteToStructs(s *HTTPRoute, t *structs.HTTPRouteConfigEntry) { + if s == nil { + return + } + t.Meta = s.Meta +} +func HTTPRouteFromStructs(t *structs.HTTPRouteConfigEntry, s *HTTPRoute) { + if s == nil { + return + } + s.Meta = t.Meta +} func HashPolicyToStructs(s *HashPolicy, t *structs.HashPolicy) { if s == nil { return @@ -386,6 +602,22 @@ func IngressServiceConfigFromStructs(t *structs.IngressServiceConfig, s *Ingress s.PassiveHealthCheck = &x } } +func InlineCertificateToStructs(s *InlineCertificate, t *structs.InlineCertificateConfigEntry) { + if s == nil { + return + } + t.Certificate = s.Certificate + t.PrivateKey = s.PrivateKey + t.Meta = s.Meta +} +func InlineCertificateFromStructs(t *structs.InlineCertificateConfigEntry, s *InlineCertificate) { + if s == nil { + return + } + s.Certificate = t.Certificate + s.PrivateKey = t.PrivateKey + s.Meta = t.Meta +} func IntentionHTTPHeaderPermissionToStructs(s *IntentionHTTPHeaderPermission, t *structs.IntentionHTTPHeaderPermission) { if s == nil { return @@ -678,6 +910,24 @@ func PeeringMeshConfigFromStructs(t *structs.PeeringMeshConfig, s *PeeringMeshCo } s.PeerThroughMeshGateways = t.PeerThroughMeshGateways } +func ResourceReferenceToStructs(s *ResourceReference, t *structs.ResourceReference) { + if s == nil { + return + } + t.Kind = s.Kind + t.Name = s.Name + t.SectionName = s.SectionName + t.EnterpriseMeta = enterpriseMetaToStructs(s.EnterpriseMeta) +} +func ResourceReferenceFromStructs(t *structs.ResourceReference, s *ResourceReference) { + if s == nil { + return + } + s.Kind = t.Kind + s.Name = t.Name + s.SectionName = t.SectionName + s.EnterpriseMeta = enterpriseMetaFromStructs(t.EnterpriseMeta) +} func RingHashConfigToStructs(s *RingHashConfig, t *structs.RingHashConfig) { if s == nil { return @@ -1038,6 +1288,106 @@ func SourceIntentionFromStructs(t *structs.SourceIntention, s *SourceIntention) s.EnterpriseMeta = enterpriseMetaFromStructs(t.EnterpriseMeta) s.Peer = t.Peer } +func StatusToStructs(s *Status, t *structs.Status) { + if s == nil { + return + } + { + t.Conditions = make([]structs.Condition, len(s.Conditions)) + for i := range s.Conditions { + if s.Conditions[i] != nil { + ConditionToStructs(s.Conditions[i], &t.Conditions[i]) + } + } + } +} +func StatusFromStructs(t *structs.Status, s *Status) { + if s == nil { + return + } + { + s.Conditions = make([]*Condition, len(t.Conditions)) + for i := range t.Conditions { + { + var x Condition + ConditionFromStructs(&t.Conditions[i], &x) + s.Conditions[i] = &x + } + } + } +} +func TCPRouteToStructs(s *TCPRoute, t *structs.TCPRouteConfigEntry) { + if s == nil { + return + } + { + t.Parents = make([]structs.ResourceReference, len(s.Parents)) + for i := range s.Parents { + if s.Parents[i] != nil { + ResourceReferenceToStructs(s.Parents[i], &t.Parents[i]) + } + } + } + { + t.Services = make([]structs.TCPService, len(s.Services)) + for i := range s.Services { + if s.Services[i] != nil { + TCPServiceToStructs(s.Services[i], &t.Services[i]) + } + } + } + t.Meta = s.Meta + if s.Status != nil { + StatusToStructs(s.Status, &t.Status) + } +} +func TCPRouteFromStructs(t *structs.TCPRouteConfigEntry, s *TCPRoute) { + if s == nil { + return + } + { + s.Parents = make([]*ResourceReference, len(t.Parents)) + for i := range t.Parents { + { + var x ResourceReference + ResourceReferenceFromStructs(&t.Parents[i], &x) + s.Parents[i] = &x + } + } + } + { + s.Services = make([]*TCPService, len(t.Services)) + for i := range t.Services { + { + var x TCPService + TCPServiceFromStructs(&t.Services[i], &x) + s.Services[i] = &x + } + } + } + s.Meta = t.Meta + { + var x Status + StatusFromStructs(&t.Status, &x) + s.Status = &x + } +} +func TCPServiceToStructs(s *TCPService, t *structs.TCPService) { + if s == nil { + return + } + t.Name = s.Name + t.Weight = int(s.Weight) + t.EnterpriseMeta = enterpriseMetaToStructs(s.EnterpriseMeta) +} +func TCPServiceFromStructs(t *structs.TCPService, s *TCPService) { + if s == nil { + return + } + s.Name = t.Name + s.Weight = int32(t.Weight) + s.EnterpriseMeta = enterpriseMetaFromStructs(t.EnterpriseMeta) +} func TransparentProxyConfigToStructs(s *TransparentProxyConfig, t *structs.TransparentProxyConfig) { if s == nil { return diff --git a/proto/pbconfigentry/config_entry.go b/proto/pbconfigentry/config_entry.go index 4a7c0e0c6a..301b97b870 100644 --- a/proto/pbconfigentry/config_entry.go +++ b/proto/pbconfigentry/config_entry.go @@ -314,3 +314,25 @@ func EnvoyExtensionsFromStructs(args []structs.EnvoyExtension) []*EnvoyExtension return o } + +func apiGatewayProtocolFromStructs(a structs.APIGatewayListenerProtocol) APIGatewayListenerProtocol { + switch a { + case structs.ListenerProtocolHTTP: + return APIGatewayListenerProtocol_ListenerProtocolHTTP + case structs.ListenerProtocolTCP: + return APIGatewayListenerProtocol_ListenerProtocolTCP + default: + return APIGatewayListenerProtocol_ListenerProtocolHTTP + } +} + +func apiGatewayProtocolToStructs(a APIGatewayListenerProtocol) structs.APIGatewayListenerProtocol { + switch a { + case APIGatewayListenerProtocol_ListenerProtocolHTTP: + return structs.ListenerProtocolHTTP + case APIGatewayListenerProtocol_ListenerProtocolTCP: + return structs.ListenerProtocolTCP + default: + return structs.ListenerProtocolHTTP + } +} diff --git a/proto/pbconfigentry/config_entry.pb.binary.go b/proto/pbconfigentry/config_entry.pb.binary.go index e03322294c..5595f16b90 100644 --- a/proto/pbconfigentry/config_entry.pb.binary.go +++ b/proto/pbconfigentry/config_entry.pb.binary.go @@ -416,3 +416,123 @@ func (msg *DestinationConfig) MarshalBinary() ([]byte, error) { func (msg *DestinationConfig) UnmarshalBinary(b []byte) error { return proto.Unmarshal(b, msg) } + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *APIGateway) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *APIGateway) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *Status) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *Status) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *Condition) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *Condition) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *APIGatewayListener) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *APIGatewayListener) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *APIGatewayTLSConfiguration) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *APIGatewayTLSConfiguration) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *ResourceReference) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *ResourceReference) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *BoundAPIGateway) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *BoundAPIGateway) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *BoundAPIGatewayListener) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *BoundAPIGatewayListener) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *InlineCertificate) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *InlineCertificate) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *HTTPRoute) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *HTTPRoute) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *TCPRoute) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *TCPRoute) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} + +// MarshalBinary implements encoding.BinaryMarshaler +func (msg *TCPService) MarshalBinary() ([]byte, error) { + return proto.Marshal(msg) +} + +// UnmarshalBinary implements encoding.BinaryUnmarshaler +func (msg *TCPService) UnmarshalBinary(b []byte) error { + return proto.Unmarshal(b, msg) +} diff --git a/proto/pbconfigentry/config_entry.pb.go b/proto/pbconfigentry/config_entry.pb.go index 3ce79dc075..9f7ca52e29 100644 --- a/proto/pbconfigentry/config_entry.pb.go +++ b/proto/pbconfigentry/config_entry.pb.go @@ -33,17 +33,27 @@ const ( Kind_KindIngressGateway Kind = 3 Kind_KindServiceIntentions Kind = 4 Kind_KindServiceDefaults Kind = 5 + Kind_KindInlineCertificate Kind = 6 + Kind_KindAPIGateway Kind = 7 + Kind_KindBoundAPIGateway Kind = 8 + Kind_KindHTTPRoute Kind = 9 + Kind_KindTCPRoute Kind = 10 ) // Enum value maps for Kind. var ( Kind_name = map[int32]string{ - 0: "KindUnknown", - 1: "KindMeshConfig", - 2: "KindServiceResolver", - 3: "KindIngressGateway", - 4: "KindServiceIntentions", - 5: "KindServiceDefaults", + 0: "KindUnknown", + 1: "KindMeshConfig", + 2: "KindServiceResolver", + 3: "KindIngressGateway", + 4: "KindServiceIntentions", + 5: "KindServiceDefaults", + 6: "KindInlineCertificate", + 7: "KindAPIGateway", + 8: "KindBoundAPIGateway", + 9: "KindHTTPRoute", + 10: "KindTCPRoute", } Kind_value = map[string]int32{ "KindUnknown": 0, @@ -52,6 +62,11 @@ var ( "KindIngressGateway": 3, "KindServiceIntentions": 4, "KindServiceDefaults": 5, + "KindInlineCertificate": 6, + "KindAPIGateway": 7, + "KindBoundAPIGateway": 8, + "KindHTTPRoute": 9, + "KindTCPRoute": 10, } ) @@ -272,6 +287,52 @@ func (MeshGatewayMode) EnumDescriptor() ([]byte, []int) { return file_proto_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{4} } +type APIGatewayListenerProtocol int32 + +const ( + APIGatewayListenerProtocol_ListenerProtocolHTTP APIGatewayListenerProtocol = 0 + APIGatewayListenerProtocol_ListenerProtocolTCP APIGatewayListenerProtocol = 1 +) + +// Enum value maps for APIGatewayListenerProtocol. +var ( + APIGatewayListenerProtocol_name = map[int32]string{ + 0: "ListenerProtocolHTTP", + 1: "ListenerProtocolTCP", + } + APIGatewayListenerProtocol_value = map[string]int32{ + "ListenerProtocolHTTP": 0, + "ListenerProtocolTCP": 1, + } +) + +func (x APIGatewayListenerProtocol) Enum() *APIGatewayListenerProtocol { + p := new(APIGatewayListenerProtocol) + *p = x + return p +} + +func (x APIGatewayListenerProtocol) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (APIGatewayListenerProtocol) Descriptor() protoreflect.EnumDescriptor { + return file_proto_pbconfigentry_config_entry_proto_enumTypes[5].Descriptor() +} + +func (APIGatewayListenerProtocol) Type() protoreflect.EnumType { + return &file_proto_pbconfigentry_config_entry_proto_enumTypes[5] +} + +func (x APIGatewayListenerProtocol) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use APIGatewayListenerProtocol.Descriptor instead. +func (APIGatewayListenerProtocol) EnumDescriptor() ([]byte, []int) { + return file_proto_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{5} +} + type ConfigEntry struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3530,6 +3591,852 @@ func (x *DestinationConfig) GetPort() int32 { return 0 } +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.APIGatewayConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +type APIGateway struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta map[string]string `protobuf:"bytes,1,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Listeners []*APIGatewayListener `protobuf:"bytes,2,rep,name=Listeners,proto3" json:"Listeners,omitempty"` + Status *Status `protobuf:"bytes,3,opt,name=Status,proto3" json:"Status,omitempty"` +} + +func (x *APIGateway) Reset() { + *x = APIGateway{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *APIGateway) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*APIGateway) ProtoMessage() {} + +func (x *APIGateway) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[41] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use APIGateway.ProtoReflect.Descriptor instead. +func (*APIGateway) Descriptor() ([]byte, []int) { + return file_proto_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{41} +} + +func (x *APIGateway) GetMeta() map[string]string { + if x != nil { + return x.Meta + } + return nil +} + +func (x *APIGateway) GetListeners() []*APIGatewayListener { + if x != nil { + return x.Listeners + } + return nil +} + +func (x *APIGateway) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.Status +// output=config_entry.gen.go +// name=Structs +type Status struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Conditions []*Condition `protobuf:"bytes,1,rep,name=Conditions,proto3" json:"Conditions,omitempty"` +} + +func (x *Status) Reset() { + *x = Status{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Status) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Status) ProtoMessage() {} + +func (x *Status) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[42] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Status.ProtoReflect.Descriptor instead. +func (*Status) Descriptor() ([]byte, []int) { + return file_proto_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{42} +} + +func (x *Status) GetConditions() []*Condition { + if x != nil { + return x.Conditions + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.Condition +// output=config_entry.gen.go +// name=Structs +type Condition struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Status string `protobuf:"bytes,1,opt,name=Status,proto3" json:"Status,omitempty"` + Reason string `protobuf:"bytes,2,opt,name=Reason,proto3" json:"Reason,omitempty"` + Message string `protobuf:"bytes,3,opt,name=Message,proto3" json:"Message,omitempty"` + Resource *ResourceReference `protobuf:"bytes,4,opt,name=Resource,proto3" json:"Resource,omitempty"` + // mog: func-to=timeToStructs func-from=timeFromStructs + LastTransitionTime *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=LastTransitionTime,proto3" json:"LastTransitionTime,omitempty"` +} + +func (x *Condition) Reset() { + *x = Condition{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[43] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Condition) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Condition) ProtoMessage() {} + +func (x *Condition) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[43] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Condition.ProtoReflect.Descriptor instead. +func (*Condition) Descriptor() ([]byte, []int) { + return file_proto_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{43} +} + +func (x *Condition) GetStatus() string { + if x != nil { + return x.Status + } + return "" +} + +func (x *Condition) GetReason() string { + if x != nil { + return x.Reason + } + return "" +} + +func (x *Condition) GetMessage() string { + if x != nil { + return x.Message + } + return "" +} + +func (x *Condition) GetResource() *ResourceReference { + if x != nil { + return x.Resource + } + return nil +} + +func (x *Condition) GetLastTransitionTime() *timestamppb.Timestamp { + if x != nil { + return x.LastTransitionTime + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.APIGatewayListener +// output=config_entry.gen.go +// name=Structs +type APIGatewayListener struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` + Hostname string `protobuf:"bytes,2,opt,name=Hostname,proto3" json:"Hostname,omitempty"` + // mog: func-to=int func-from=int32 + Port int32 `protobuf:"varint,3,opt,name=Port,proto3" json:"Port,omitempty"` + // mog: func-to=apiGatewayProtocolToStructs func-from=apiGatewayProtocolFromStructs + Protocol APIGatewayListenerProtocol `protobuf:"varint,4,opt,name=Protocol,proto3,enum=hashicorp.consul.internal.configentry.APIGatewayListenerProtocol" json:"Protocol,omitempty"` + TLS *APIGatewayTLSConfiguration `protobuf:"bytes,5,opt,name=TLS,proto3" json:"TLS,omitempty"` +} + +func (x *APIGatewayListener) Reset() { + *x = APIGatewayListener{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[44] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *APIGatewayListener) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*APIGatewayListener) ProtoMessage() {} + +func (x *APIGatewayListener) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[44] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use APIGatewayListener.ProtoReflect.Descriptor instead. +func (*APIGatewayListener) Descriptor() ([]byte, []int) { + return file_proto_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{44} +} + +func (x *APIGatewayListener) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *APIGatewayListener) GetHostname() string { + if x != nil { + return x.Hostname + } + return "" +} + +func (x *APIGatewayListener) GetPort() int32 { + if x != nil { + return x.Port + } + return 0 +} + +func (x *APIGatewayListener) GetProtocol() APIGatewayListenerProtocol { + if x != nil { + return x.Protocol + } + return APIGatewayListenerProtocol_ListenerProtocolHTTP +} + +func (x *APIGatewayListener) GetTLS() *APIGatewayTLSConfiguration { + if x != nil { + return x.TLS + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.APIGatewayTLSConfiguration +// output=config_entry.gen.go +// name=Structs +type APIGatewayTLSConfiguration struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Certificates []*ResourceReference `protobuf:"bytes,1,rep,name=Certificates,proto3" json:"Certificates,omitempty"` + // mog: func-from=tlsVersionFromStructs func-to=tlsVersionToStructs + MinVersion string `protobuf:"bytes,2,opt,name=MinVersion,proto3" json:"MinVersion,omitempty"` + // mog: func-from=tlsVersionFromStructs func-to=tlsVersionToStructs + MaxVersion string `protobuf:"bytes,3,opt,name=MaxVersion,proto3" json:"MaxVersion,omitempty"` + // mog: func-from=cipherSuitesFromStructs func-to=cipherSuitesToStructs + CipherSuites []string `protobuf:"bytes,4,rep,name=CipherSuites,proto3" json:"CipherSuites,omitempty"` +} + +func (x *APIGatewayTLSConfiguration) Reset() { + *x = APIGatewayTLSConfiguration{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[45] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *APIGatewayTLSConfiguration) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*APIGatewayTLSConfiguration) ProtoMessage() {} + +func (x *APIGatewayTLSConfiguration) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[45] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use APIGatewayTLSConfiguration.ProtoReflect.Descriptor instead. +func (*APIGatewayTLSConfiguration) Descriptor() ([]byte, []int) { + return file_proto_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{45} +} + +func (x *APIGatewayTLSConfiguration) GetCertificates() []*ResourceReference { + if x != nil { + return x.Certificates + } + return nil +} + +func (x *APIGatewayTLSConfiguration) GetMinVersion() string { + if x != nil { + return x.MinVersion + } + return "" +} + +func (x *APIGatewayTLSConfiguration) GetMaxVersion() string { + if x != nil { + return x.MaxVersion + } + return "" +} + +func (x *APIGatewayTLSConfiguration) GetCipherSuites() []string { + if x != nil { + return x.CipherSuites + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.ResourceReference +// output=config_entry.gen.go +// name=Structs +type ResourceReference struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Kind string `protobuf:"bytes,1,opt,name=Kind,proto3" json:"Kind,omitempty"` + Name string `protobuf:"bytes,2,opt,name=Name,proto3" json:"Name,omitempty"` + SectionName string `protobuf:"bytes,3,opt,name=SectionName,proto3" json:"SectionName,omitempty"` + // mog: func-to=enterpriseMetaToStructs func-from=enterpriseMetaFromStructs + EnterpriseMeta *pbcommon.EnterpriseMeta `protobuf:"bytes,4,opt,name=EnterpriseMeta,proto3" json:"EnterpriseMeta,omitempty"` +} + +func (x *ResourceReference) Reset() { + *x = ResourceReference{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[46] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ResourceReference) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ResourceReference) ProtoMessage() {} + +func (x *ResourceReference) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[46] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ResourceReference.ProtoReflect.Descriptor instead. +func (*ResourceReference) Descriptor() ([]byte, []int) { + return file_proto_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{46} +} + +func (x *ResourceReference) GetKind() string { + if x != nil { + return x.Kind + } + return "" +} + +func (x *ResourceReference) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ResourceReference) GetSectionName() string { + if x != nil { + return x.SectionName + } + return "" +} + +func (x *ResourceReference) GetEnterpriseMeta() *pbcommon.EnterpriseMeta { + if x != nil { + return x.EnterpriseMeta + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.BoundAPIGatewayConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +type BoundAPIGateway struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta map[string]string `protobuf:"bytes,1,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Listeners []*BoundAPIGatewayListener `protobuf:"bytes,2,rep,name=Listeners,proto3" json:"Listeners,omitempty"` +} + +func (x *BoundAPIGateway) Reset() { + *x = BoundAPIGateway{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[47] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BoundAPIGateway) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BoundAPIGateway) ProtoMessage() {} + +func (x *BoundAPIGateway) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[47] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BoundAPIGateway.ProtoReflect.Descriptor instead. +func (*BoundAPIGateway) Descriptor() ([]byte, []int) { + return file_proto_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{47} +} + +func (x *BoundAPIGateway) GetMeta() map[string]string { + if x != nil { + return x.Meta + } + return nil +} + +func (x *BoundAPIGateway) GetListeners() []*BoundAPIGatewayListener { + if x != nil { + return x.Listeners + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.BoundAPIGatewayListener +// output=config_entry.gen.go +// name=Structs +type BoundAPIGatewayListener struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` + Certificates []*ResourceReference `protobuf:"bytes,2,rep,name=Certificates,proto3" json:"Certificates,omitempty"` + Routes []*ResourceReference `protobuf:"bytes,3,rep,name=Routes,proto3" json:"Routes,omitempty"` +} + +func (x *BoundAPIGatewayListener) Reset() { + *x = BoundAPIGatewayListener{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[48] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *BoundAPIGatewayListener) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BoundAPIGatewayListener) ProtoMessage() {} + +func (x *BoundAPIGatewayListener) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[48] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BoundAPIGatewayListener.ProtoReflect.Descriptor instead. +func (*BoundAPIGatewayListener) Descriptor() ([]byte, []int) { + return file_proto_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{48} +} + +func (x *BoundAPIGatewayListener) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *BoundAPIGatewayListener) GetCertificates() []*ResourceReference { + if x != nil { + return x.Certificates + } + return nil +} + +func (x *BoundAPIGatewayListener) GetRoutes() []*ResourceReference { + if x != nil { + return x.Routes + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.InlineCertificateConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +type InlineCertificate struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta map[string]string `protobuf:"bytes,1,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Certificate string `protobuf:"bytes,2,opt,name=Certificate,proto3" json:"Certificate,omitempty"` + PrivateKey string `protobuf:"bytes,3,opt,name=PrivateKey,proto3" json:"PrivateKey,omitempty"` +} + +func (x *InlineCertificate) Reset() { + *x = InlineCertificate{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[49] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *InlineCertificate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InlineCertificate) ProtoMessage() {} + +func (x *InlineCertificate) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[49] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InlineCertificate.ProtoReflect.Descriptor instead. +func (*InlineCertificate) Descriptor() ([]byte, []int) { + return file_proto_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{49} +} + +func (x *InlineCertificate) GetMeta() map[string]string { + if x != nil { + return x.Meta + } + return nil +} + +func (x *InlineCertificate) GetCertificate() string { + if x != nil { + return x.Certificate + } + return "" +} + +func (x *InlineCertificate) GetPrivateKey() string { + if x != nil { + return x.PrivateKey + } + return "" +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.HTTPRouteConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +type HTTPRoute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta map[string]string `protobuf:"bytes,1,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 *HTTPRoute) Reset() { + *x = HTTPRoute{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[50] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *HTTPRoute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*HTTPRoute) ProtoMessage() {} + +func (x *HTTPRoute) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[50] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use HTTPRoute.ProtoReflect.Descriptor instead. +func (*HTTPRoute) Descriptor() ([]byte, []int) { + return file_proto_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{50} +} + +func (x *HTTPRoute) GetMeta() map[string]string { + if x != nil { + return x.Meta + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.TCPRouteConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +type TCPRoute struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Meta map[string]string `protobuf:"bytes,1,rep,name=Meta,proto3" json:"Meta,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` + Parents []*ResourceReference `protobuf:"bytes,2,rep,name=Parents,proto3" json:"Parents,omitempty"` + Services []*TCPService `protobuf:"bytes,3,rep,name=Services,proto3" json:"Services,omitempty"` + Status *Status `protobuf:"bytes,4,opt,name=Status,proto3" json:"Status,omitempty"` +} + +func (x *TCPRoute) Reset() { + *x = TCPRoute{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[51] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TCPRoute) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TCPRoute) ProtoMessage() {} + +func (x *TCPRoute) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[51] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TCPRoute.ProtoReflect.Descriptor instead. +func (*TCPRoute) Descriptor() ([]byte, []int) { + return file_proto_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{51} +} + +func (x *TCPRoute) GetMeta() map[string]string { + if x != nil { + return x.Meta + } + return nil +} + +func (x *TCPRoute) GetParents() []*ResourceReference { + if x != nil { + return x.Parents + } + return nil +} + +func (x *TCPRoute) GetServices() []*TCPService { + if x != nil { + return x.Services + } + return nil +} + +func (x *TCPRoute) GetStatus() *Status { + if x != nil { + return x.Status + } + return nil +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.TCPService +// output=config_entry.gen.go +// name=Structs +type TCPService struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` + // mog: func-to=int func-from=int32 + Weight int32 `protobuf:"varint,2,opt,name=Weight,proto3" json:"Weight,omitempty"` + // mog: func-to=enterpriseMetaToStructs func-from=enterpriseMetaFromStructs + EnterpriseMeta *pbcommon.EnterpriseMeta `protobuf:"bytes,4,opt,name=EnterpriseMeta,proto3" json:"EnterpriseMeta,omitempty"` +} + +func (x *TCPService) Reset() { + *x = TCPService{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[52] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *TCPService) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*TCPService) ProtoMessage() {} + +func (x *TCPService) ProtoReflect() protoreflect.Message { + mi := &file_proto_pbconfigentry_config_entry_proto_msgTypes[52] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use TCPService.ProtoReflect.Descriptor instead. +func (*TCPService) Descriptor() ([]byte, []int) { + return file_proto_pbconfigentry_config_entry_proto_rawDescGZIP(), []int{52} +} + +func (x *TCPService) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *TCPService) GetWeight() int32 { + if x != nil { + return x.Weight + } + return 0 +} + +func (x *TCPService) GetEnterpriseMeta() *pbcommon.EnterpriseMeta { + if x != nil { + return x.EnterpriseMeta + } + return nil +} + var File_proto_pbconfigentry_config_entry_proto protoreflect.FileDescriptor var file_proto_pbconfigentry_config_entry_proto_rawDesc = []byte{ @@ -4259,53 +5166,236 @@ var file_proto_pbconfigentry_config_entry_proto_rawDesc = []byte{ 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, - 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x2a, 0x90, - 0x01, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0f, 0x0a, 0x0b, 0x4b, 0x69, 0x6e, 0x64, 0x55, - 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4b, 0x69, 0x6e, 0x64, - 0x4d, 0x65, 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, - 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, - 0x76, 0x65, 0x72, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4b, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x67, - 0x72, 0x65, 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x03, 0x12, 0x19, 0x0a, - 0x15, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, - 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x04, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x10, - 0x05, 0x2a, 0x26, 0x0a, 0x0f, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x65, 0x6e, 0x79, 0x10, 0x00, 0x12, 0x09, - 0x0a, 0x05, 0x41, 0x6c, 0x6c, 0x6f, 0x77, 0x10, 0x01, 0x2a, 0x21, 0x0a, 0x13, 0x49, 0x6e, 0x74, - 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x10, 0x00, 0x2a, 0x50, 0x0a, 0x09, - 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, - 0x18, 0x0a, 0x14, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x50, 0x72, 0x6f, - 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x7b, - 0x0a, 0x0f, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, - 0x65, 0x12, 0x1a, 0x0a, 0x16, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, - 0x4d, 0x6f, 0x64, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, - 0x13, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, - 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, - 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x10, 0x02, - 0x12, 0x19, 0x0a, 0x15, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, - 0x6f, 0x64, 0x65, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x10, 0x03, 0x42, 0xa6, 0x02, 0x0a, 0x29, - 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, + 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x22, 0xb6, + 0x02, 0x0a, 0x0a, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x4f, 0x0a, + 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3b, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, + 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x2e, 0x4d, + 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x57, + 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 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, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x10, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2f, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xa2, 0x02, - 0x04, 0x48, 0x43, 0x49, 0x43, 0xaa, 0x02, 0x25, 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, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xca, 0x02, 0x25, - 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, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x65, 0x6e, 0x74, 0x72, 0x79, 0xe2, 0x02, 0x31, 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, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, - 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x28, 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, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, - 0x6e, 0x74, 0x72, 0x79, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, + 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 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, 0x5a, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x50, 0x0a, 0x0a, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, + 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x30, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x43, 0x6f, + 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0a, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x22, 0xf7, 0x01, 0x0a, 0x09, 0x43, 0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x52, 0x65, 0x61, + 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x52, 0x65, 0x61, 0x73, 0x6f, + 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x54, 0x0a, 0x08, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, + 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x4c, 0x61, 0x73, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x12, 0x4c, 0x61, 0x73, 0x74, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x8c, 0x02, + 0x0a, 0x12, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, + 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x48, 0x6f, 0x73, 0x74, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x5d, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, + 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x50, + 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x53, 0x0a, 0x03, 0x54, 0x4c, 0x53, 0x18, 0x05, + 0x20, 0x01, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x41, 0x50, 0x49, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x54, 0x4c, 0x53, 0x22, 0xde, 0x01, 0x0a, + 0x1a, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x54, 0x4c, 0x53, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5c, 0x0a, 0x0c, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 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, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x69, 0x6e, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4d, + 0x69, 0x6e, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x4d, 0x61, 0x78, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x4d, + 0x61, 0x78, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x43, 0x69, 0x70, + 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, + 0x0c, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x53, 0x75, 0x69, 0x74, 0x65, 0x73, 0x22, 0xb7, 0x01, + 0x0a, 0x11, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, + 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x53, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x58, 0x0a, + 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 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, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, + 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, + 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x22, 0xfe, 0x01, 0x0a, 0x0f, 0x42, 0x6f, 0x75, 0x6e, + 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x12, 0x54, 0x0a, 0x04, 0x4d, + 0x65, 0x74, 0x61, 0x18, 0x01, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0x2e, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, + 0x79, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, 0x4d, 0x65, 0x74, + 0x61, 0x12, 0x5c, 0x0a, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x73, 0x18, 0x02, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3e, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x42, 0x6f, 0x75, + 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, + 0x65, 0x6e, 0x65, 0x72, 0x52, 0x09, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 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, 0xdd, 0x01, 0x0a, 0x17, 0x42, 0x6f, 0x75, + 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, + 0x65, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x5c, 0x0a, 0x0c, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, + 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0c, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x50, 0x0a, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x52, 0x06, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x73, 0x22, 0xe6, 0x01, 0x0a, 0x11, 0x49, 0x6e, 0x6c, + 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x56, + 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, + 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x20, 0x0a, 0x0b, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x50, 0x72, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x50, 0x72, + 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 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, 0x94, 0x01, 0x0a, 0x09, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, + 0x4e, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 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, 0xfc, 0x02, 0x0a, 0x08, 0x54, 0x43, 0x50, + 0x52, 0x6f, 0x75, 0x74, 0x65, 0x12, 0x4d, 0x0a, 0x04, 0x4d, 0x65, 0x74, 0x61, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 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, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x54, 0x43, 0x50, 0x52, + 0x6f, 0x75, 0x74, 0x65, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x04, + 0x4d, 0x65, 0x74, 0x61, 0x12, 0x52, 0x0a, 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, + 0x07, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4d, 0x0a, 0x08, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x31, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, + 0x72, 0x79, 0x2e, 0x54, 0x43, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x08, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x12, 0x45, 0x0a, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x53, 0x74, 0x61, 0x74, 0x75, 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, 0x92, 0x01, 0x0a, 0x0a, 0x54, 0x43, 0x50, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x57, 0x65, + 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x57, 0x65, 0x69, 0x67, + 0x68, 0x74, 0x12, 0x58, 0x0a, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 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, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, + 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x2a, 0xfd, 0x01, 0x0a, + 0x04, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x0f, 0x0a, 0x0b, 0x4b, 0x69, 0x6e, 0x64, 0x55, 0x6e, 0x6b, + 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x4b, 0x69, 0x6e, 0x64, 0x4d, 0x65, + 0x73, 0x68, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, + 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x6f, 0x6c, 0x76, 0x65, + 0x72, 0x10, 0x02, 0x12, 0x16, 0x0a, 0x12, 0x4b, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x67, 0x72, 0x65, + 0x73, 0x73, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x4b, + 0x69, 0x6e, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x04, 0x12, 0x17, 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x10, 0x05, 0x12, + 0x19, 0x0a, 0x15, 0x4b, 0x69, 0x6e, 0x64, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x10, 0x06, 0x12, 0x12, 0x0a, 0x0e, 0x4b, 0x69, + 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x07, 0x12, 0x17, + 0x0a, 0x13, 0x4b, 0x69, 0x6e, 0x64, 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x08, 0x12, 0x11, 0x0a, 0x0d, 0x4b, 0x69, 0x6e, 0x64, 0x48, + 0x54, 0x54, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, 0x09, 0x12, 0x10, 0x0a, 0x0c, 0x4b, 0x69, + 0x6e, 0x64, 0x54, 0x43, 0x50, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x10, 0x0a, 0x2a, 0x26, 0x0a, 0x0f, + 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x08, 0x0a, 0x04, 0x44, 0x65, 0x6e, 0x79, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x6c, 0x6c, + 0x6f, 0x77, 0x10, 0x01, 0x2a, 0x21, 0x0a, 0x13, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, + 0x6e, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0a, 0x0a, 0x06, 0x43, + 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x10, 0x00, 0x2a, 0x50, 0x0a, 0x09, 0x50, 0x72, 0x6f, 0x78, 0x79, + 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x14, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, + 0x65, 0x44, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x50, 0x72, + 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, + 0x6e, 0x74, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x50, 0x72, 0x6f, 0x78, 0x79, 0x4d, 0x6f, 0x64, + 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x10, 0x02, 0x2a, 0x7b, 0x0a, 0x0f, 0x4d, 0x65, 0x73, + 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x16, + 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x44, + 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x10, 0x00, 0x12, 0x17, 0x0a, 0x13, 0x4d, 0x65, 0x73, 0x68, + 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x4e, 0x6f, 0x6e, 0x65, 0x10, + 0x01, 0x12, 0x18, 0x0a, 0x14, 0x4d, 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, + 0x4d, 0x6f, 0x64, 0x65, 0x4c, 0x6f, 0x63, 0x61, 0x6c, 0x10, 0x02, 0x12, 0x19, 0x0a, 0x15, 0x4d, + 0x65, 0x73, 0x68, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x10, 0x03, 0x2a, 0x4f, 0x0a, 0x1a, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, + 0x65, 0x77, 0x61, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x18, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, + 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x48, 0x54, 0x54, 0x50, 0x10, 0x00, 0x12, 0x17, + 0x0a, 0x13, 0x4c, 0x69, 0x73, 0x74, 0x65, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, + 0x6f, 0x6c, 0x54, 0x43, 0x50, 0x10, 0x01, 0x42, 0xa6, 0x02, 0x0a, 0x29, 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, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x65, 0x6e, 0x74, 0x72, 0x79, 0x42, 0x10, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2f, 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, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xa2, 0x02, 0x04, 0x48, 0x43, 0x49, + 0x43, 0xaa, 0x02, 0x25, 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, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0xca, 0x02, 0x25, 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, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, + 0x79, 0xe2, 0x02, 0x31, 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, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x28, 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, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4320,154 +5410,193 @@ func file_proto_pbconfigentry_config_entry_proto_rawDescGZIP() []byte { return file_proto_pbconfigentry_config_entry_proto_rawDescData } -var file_proto_pbconfigentry_config_entry_proto_enumTypes = make([]protoimpl.EnumInfo, 5) -var file_proto_pbconfigentry_config_entry_proto_msgTypes = make([]protoimpl.MessageInfo, 52) +var file_proto_pbconfigentry_config_entry_proto_enumTypes = make([]protoimpl.EnumInfo, 6) +var file_proto_pbconfigentry_config_entry_proto_msgTypes = make([]protoimpl.MessageInfo, 69) var file_proto_pbconfigentry_config_entry_proto_goTypes = []interface{}{ (Kind)(0), // 0: hashicorp.consul.internal.configentry.Kind (IntentionAction)(0), // 1: hashicorp.consul.internal.configentry.IntentionAction (IntentionSourceType)(0), // 2: hashicorp.consul.internal.configentry.IntentionSourceType (ProxyMode)(0), // 3: hashicorp.consul.internal.configentry.ProxyMode (MeshGatewayMode)(0), // 4: hashicorp.consul.internal.configentry.MeshGatewayMode - (*ConfigEntry)(nil), // 5: hashicorp.consul.internal.configentry.ConfigEntry - (*MeshConfig)(nil), // 6: hashicorp.consul.internal.configentry.MeshConfig - (*TransparentProxyMeshConfig)(nil), // 7: hashicorp.consul.internal.configentry.TransparentProxyMeshConfig - (*MeshTLSConfig)(nil), // 8: hashicorp.consul.internal.configentry.MeshTLSConfig - (*MeshDirectionalTLSConfig)(nil), // 9: hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig - (*MeshHTTPConfig)(nil), // 10: hashicorp.consul.internal.configentry.MeshHTTPConfig - (*PeeringMeshConfig)(nil), // 11: hashicorp.consul.internal.configentry.PeeringMeshConfig - (*ServiceResolver)(nil), // 12: hashicorp.consul.internal.configentry.ServiceResolver - (*ServiceResolverSubset)(nil), // 13: hashicorp.consul.internal.configentry.ServiceResolverSubset - (*ServiceResolverRedirect)(nil), // 14: hashicorp.consul.internal.configentry.ServiceResolverRedirect - (*ServiceResolverFailover)(nil), // 15: hashicorp.consul.internal.configentry.ServiceResolverFailover - (*ServiceResolverFailoverTarget)(nil), // 16: hashicorp.consul.internal.configentry.ServiceResolverFailoverTarget - (*LoadBalancer)(nil), // 17: hashicorp.consul.internal.configentry.LoadBalancer - (*RingHashConfig)(nil), // 18: hashicorp.consul.internal.configentry.RingHashConfig - (*LeastRequestConfig)(nil), // 19: hashicorp.consul.internal.configentry.LeastRequestConfig - (*HashPolicy)(nil), // 20: hashicorp.consul.internal.configentry.HashPolicy - (*CookieConfig)(nil), // 21: hashicorp.consul.internal.configentry.CookieConfig - (*IngressGateway)(nil), // 22: hashicorp.consul.internal.configentry.IngressGateway - (*IngressServiceConfig)(nil), // 23: hashicorp.consul.internal.configentry.IngressServiceConfig - (*GatewayTLSConfig)(nil), // 24: hashicorp.consul.internal.configentry.GatewayTLSConfig - (*GatewayTLSSDSConfig)(nil), // 25: hashicorp.consul.internal.configentry.GatewayTLSSDSConfig - (*IngressListener)(nil), // 26: hashicorp.consul.internal.configentry.IngressListener - (*IngressService)(nil), // 27: hashicorp.consul.internal.configentry.IngressService - (*GatewayServiceTLSConfig)(nil), // 28: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig - (*HTTPHeaderModifiers)(nil), // 29: hashicorp.consul.internal.configentry.HTTPHeaderModifiers - (*ServiceIntentions)(nil), // 30: hashicorp.consul.internal.configentry.ServiceIntentions - (*SourceIntention)(nil), // 31: hashicorp.consul.internal.configentry.SourceIntention - (*IntentionPermission)(nil), // 32: hashicorp.consul.internal.configentry.IntentionPermission - (*IntentionHTTPPermission)(nil), // 33: hashicorp.consul.internal.configentry.IntentionHTTPPermission - (*IntentionHTTPHeaderPermission)(nil), // 34: hashicorp.consul.internal.configentry.IntentionHTTPHeaderPermission - (*ServiceDefaults)(nil), // 35: hashicorp.consul.internal.configentry.ServiceDefaults - (*TransparentProxyConfig)(nil), // 36: hashicorp.consul.internal.configentry.TransparentProxyConfig - (*EnvoyExtension)(nil), // 37: hashicorp.consul.internal.configentry.EnvoyExtension - (*MeshGatewayConfig)(nil), // 38: hashicorp.consul.internal.configentry.MeshGatewayConfig - (*ExposeConfig)(nil), // 39: hashicorp.consul.internal.configentry.ExposeConfig - (*ExposePath)(nil), // 40: hashicorp.consul.internal.configentry.ExposePath - (*UpstreamConfiguration)(nil), // 41: hashicorp.consul.internal.configentry.UpstreamConfiguration - (*UpstreamConfig)(nil), // 42: hashicorp.consul.internal.configentry.UpstreamConfig - (*UpstreamLimits)(nil), // 43: hashicorp.consul.internal.configentry.UpstreamLimits - (*PassiveHealthCheck)(nil), // 44: hashicorp.consul.internal.configentry.PassiveHealthCheck - (*DestinationConfig)(nil), // 45: hashicorp.consul.internal.configentry.DestinationConfig - nil, // 46: hashicorp.consul.internal.configentry.MeshConfig.MetaEntry - nil, // 47: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry - nil, // 48: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry - nil, // 49: hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry - nil, // 50: hashicorp.consul.internal.configentry.IngressGateway.MetaEntry - nil, // 51: hashicorp.consul.internal.configentry.IngressService.MetaEntry - nil, // 52: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry - nil, // 53: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry - nil, // 54: hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry - nil, // 55: hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry - nil, // 56: hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry - (*pbcommon.EnterpriseMeta)(nil), // 57: hashicorp.consul.internal.common.EnterpriseMeta - (*pbcommon.RaftIndex)(nil), // 58: hashicorp.consul.internal.common.RaftIndex - (*durationpb.Duration)(nil), // 59: google.protobuf.Duration - (*timestamppb.Timestamp)(nil), // 60: google.protobuf.Timestamp - (*structpb.Value)(nil), // 61: google.protobuf.Value + (APIGatewayListenerProtocol)(0), // 5: hashicorp.consul.internal.configentry.APIGatewayListenerProtocol + (*ConfigEntry)(nil), // 6: hashicorp.consul.internal.configentry.ConfigEntry + (*MeshConfig)(nil), // 7: hashicorp.consul.internal.configentry.MeshConfig + (*TransparentProxyMeshConfig)(nil), // 8: hashicorp.consul.internal.configentry.TransparentProxyMeshConfig + (*MeshTLSConfig)(nil), // 9: hashicorp.consul.internal.configentry.MeshTLSConfig + (*MeshDirectionalTLSConfig)(nil), // 10: hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig + (*MeshHTTPConfig)(nil), // 11: hashicorp.consul.internal.configentry.MeshHTTPConfig + (*PeeringMeshConfig)(nil), // 12: hashicorp.consul.internal.configentry.PeeringMeshConfig + (*ServiceResolver)(nil), // 13: hashicorp.consul.internal.configentry.ServiceResolver + (*ServiceResolverSubset)(nil), // 14: hashicorp.consul.internal.configentry.ServiceResolverSubset + (*ServiceResolverRedirect)(nil), // 15: hashicorp.consul.internal.configentry.ServiceResolverRedirect + (*ServiceResolverFailover)(nil), // 16: hashicorp.consul.internal.configentry.ServiceResolverFailover + (*ServiceResolverFailoverTarget)(nil), // 17: hashicorp.consul.internal.configentry.ServiceResolverFailoverTarget + (*LoadBalancer)(nil), // 18: hashicorp.consul.internal.configentry.LoadBalancer + (*RingHashConfig)(nil), // 19: hashicorp.consul.internal.configentry.RingHashConfig + (*LeastRequestConfig)(nil), // 20: hashicorp.consul.internal.configentry.LeastRequestConfig + (*HashPolicy)(nil), // 21: hashicorp.consul.internal.configentry.HashPolicy + (*CookieConfig)(nil), // 22: hashicorp.consul.internal.configentry.CookieConfig + (*IngressGateway)(nil), // 23: hashicorp.consul.internal.configentry.IngressGateway + (*IngressServiceConfig)(nil), // 24: hashicorp.consul.internal.configentry.IngressServiceConfig + (*GatewayTLSConfig)(nil), // 25: hashicorp.consul.internal.configentry.GatewayTLSConfig + (*GatewayTLSSDSConfig)(nil), // 26: hashicorp.consul.internal.configentry.GatewayTLSSDSConfig + (*IngressListener)(nil), // 27: hashicorp.consul.internal.configentry.IngressListener + (*IngressService)(nil), // 28: hashicorp.consul.internal.configentry.IngressService + (*GatewayServiceTLSConfig)(nil), // 29: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig + (*HTTPHeaderModifiers)(nil), // 30: hashicorp.consul.internal.configentry.HTTPHeaderModifiers + (*ServiceIntentions)(nil), // 31: hashicorp.consul.internal.configentry.ServiceIntentions + (*SourceIntention)(nil), // 32: hashicorp.consul.internal.configentry.SourceIntention + (*IntentionPermission)(nil), // 33: hashicorp.consul.internal.configentry.IntentionPermission + (*IntentionHTTPPermission)(nil), // 34: hashicorp.consul.internal.configentry.IntentionHTTPPermission + (*IntentionHTTPHeaderPermission)(nil), // 35: hashicorp.consul.internal.configentry.IntentionHTTPHeaderPermission + (*ServiceDefaults)(nil), // 36: hashicorp.consul.internal.configentry.ServiceDefaults + (*TransparentProxyConfig)(nil), // 37: hashicorp.consul.internal.configentry.TransparentProxyConfig + (*EnvoyExtension)(nil), // 38: hashicorp.consul.internal.configentry.EnvoyExtension + (*MeshGatewayConfig)(nil), // 39: hashicorp.consul.internal.configentry.MeshGatewayConfig + (*ExposeConfig)(nil), // 40: hashicorp.consul.internal.configentry.ExposeConfig + (*ExposePath)(nil), // 41: hashicorp.consul.internal.configentry.ExposePath + (*UpstreamConfiguration)(nil), // 42: hashicorp.consul.internal.configentry.UpstreamConfiguration + (*UpstreamConfig)(nil), // 43: hashicorp.consul.internal.configentry.UpstreamConfig + (*UpstreamLimits)(nil), // 44: hashicorp.consul.internal.configentry.UpstreamLimits + (*PassiveHealthCheck)(nil), // 45: hashicorp.consul.internal.configentry.PassiveHealthCheck + (*DestinationConfig)(nil), // 46: hashicorp.consul.internal.configentry.DestinationConfig + (*APIGateway)(nil), // 47: hashicorp.consul.internal.configentry.APIGateway + (*Status)(nil), // 48: hashicorp.consul.internal.configentry.Status + (*Condition)(nil), // 49: hashicorp.consul.internal.configentry.Condition + (*APIGatewayListener)(nil), // 50: hashicorp.consul.internal.configentry.APIGatewayListener + (*APIGatewayTLSConfiguration)(nil), // 51: hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration + (*ResourceReference)(nil), // 52: hashicorp.consul.internal.configentry.ResourceReference + (*BoundAPIGateway)(nil), // 53: hashicorp.consul.internal.configentry.BoundAPIGateway + (*BoundAPIGatewayListener)(nil), // 54: hashicorp.consul.internal.configentry.BoundAPIGatewayListener + (*InlineCertificate)(nil), // 55: hashicorp.consul.internal.configentry.InlineCertificate + (*HTTPRoute)(nil), // 56: hashicorp.consul.internal.configentry.HTTPRoute + (*TCPRoute)(nil), // 57: hashicorp.consul.internal.configentry.TCPRoute + (*TCPService)(nil), // 58: hashicorp.consul.internal.configentry.TCPService + nil, // 59: hashicorp.consul.internal.configentry.MeshConfig.MetaEntry + nil, // 60: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry + nil, // 61: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry + nil, // 62: hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry + nil, // 63: hashicorp.consul.internal.configentry.IngressGateway.MetaEntry + nil, // 64: hashicorp.consul.internal.configentry.IngressService.MetaEntry + nil, // 65: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry + nil, // 66: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry + nil, // 67: hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry + nil, // 68: hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry + nil, // 69: hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry + nil, // 70: hashicorp.consul.internal.configentry.APIGateway.MetaEntry + nil, // 71: hashicorp.consul.internal.configentry.BoundAPIGateway.MetaEntry + nil, // 72: hashicorp.consul.internal.configentry.InlineCertificate.MetaEntry + nil, // 73: hashicorp.consul.internal.configentry.HTTPRoute.MetaEntry + nil, // 74: hashicorp.consul.internal.configentry.TCPRoute.MetaEntry + (*pbcommon.EnterpriseMeta)(nil), // 75: hashicorp.consul.internal.common.EnterpriseMeta + (*pbcommon.RaftIndex)(nil), // 76: hashicorp.consul.internal.common.RaftIndex + (*durationpb.Duration)(nil), // 77: google.protobuf.Duration + (*timestamppb.Timestamp)(nil), // 78: google.protobuf.Timestamp + (*structpb.Value)(nil), // 79: google.protobuf.Value } var file_proto_pbconfigentry_config_entry_proto_depIdxs = []int32{ 0, // 0: hashicorp.consul.internal.configentry.ConfigEntry.Kind:type_name -> hashicorp.consul.internal.configentry.Kind - 57, // 1: hashicorp.consul.internal.configentry.ConfigEntry.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 58, // 2: hashicorp.consul.internal.configentry.ConfigEntry.RaftIndex:type_name -> hashicorp.consul.internal.common.RaftIndex - 6, // 3: hashicorp.consul.internal.configentry.ConfigEntry.MeshConfig:type_name -> hashicorp.consul.internal.configentry.MeshConfig - 12, // 4: hashicorp.consul.internal.configentry.ConfigEntry.ServiceResolver:type_name -> hashicorp.consul.internal.configentry.ServiceResolver - 22, // 5: hashicorp.consul.internal.configentry.ConfigEntry.IngressGateway:type_name -> hashicorp.consul.internal.configentry.IngressGateway - 30, // 6: hashicorp.consul.internal.configentry.ConfigEntry.ServiceIntentions:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions - 35, // 7: hashicorp.consul.internal.configentry.ConfigEntry.ServiceDefaults:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults - 7, // 8: hashicorp.consul.internal.configentry.MeshConfig.TransparentProxy:type_name -> hashicorp.consul.internal.configentry.TransparentProxyMeshConfig - 8, // 9: hashicorp.consul.internal.configentry.MeshConfig.TLS:type_name -> hashicorp.consul.internal.configentry.MeshTLSConfig - 10, // 10: hashicorp.consul.internal.configentry.MeshConfig.HTTP:type_name -> hashicorp.consul.internal.configentry.MeshHTTPConfig - 46, // 11: hashicorp.consul.internal.configentry.MeshConfig.Meta:type_name -> hashicorp.consul.internal.configentry.MeshConfig.MetaEntry - 11, // 12: hashicorp.consul.internal.configentry.MeshConfig.Peering:type_name -> hashicorp.consul.internal.configentry.PeeringMeshConfig - 9, // 13: hashicorp.consul.internal.configentry.MeshTLSConfig.Incoming:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig - 9, // 14: hashicorp.consul.internal.configentry.MeshTLSConfig.Outgoing:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig - 47, // 15: hashicorp.consul.internal.configentry.ServiceResolver.Subsets:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry - 14, // 16: hashicorp.consul.internal.configentry.ServiceResolver.Redirect:type_name -> hashicorp.consul.internal.configentry.ServiceResolverRedirect - 48, // 17: hashicorp.consul.internal.configentry.ServiceResolver.Failover:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry - 59, // 18: hashicorp.consul.internal.configentry.ServiceResolver.ConnectTimeout:type_name -> google.protobuf.Duration - 17, // 19: hashicorp.consul.internal.configentry.ServiceResolver.LoadBalancer:type_name -> hashicorp.consul.internal.configentry.LoadBalancer - 49, // 20: hashicorp.consul.internal.configentry.ServiceResolver.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry - 16, // 21: hashicorp.consul.internal.configentry.ServiceResolverFailover.Targets:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailoverTarget - 18, // 22: hashicorp.consul.internal.configentry.LoadBalancer.RingHashConfig:type_name -> hashicorp.consul.internal.configentry.RingHashConfig - 19, // 23: hashicorp.consul.internal.configentry.LoadBalancer.LeastRequestConfig:type_name -> hashicorp.consul.internal.configentry.LeastRequestConfig - 20, // 24: hashicorp.consul.internal.configentry.LoadBalancer.HashPolicies:type_name -> hashicorp.consul.internal.configentry.HashPolicy - 21, // 25: hashicorp.consul.internal.configentry.HashPolicy.CookieConfig:type_name -> hashicorp.consul.internal.configentry.CookieConfig - 59, // 26: hashicorp.consul.internal.configentry.CookieConfig.TTL:type_name -> google.protobuf.Duration - 24, // 27: hashicorp.consul.internal.configentry.IngressGateway.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig - 26, // 28: hashicorp.consul.internal.configentry.IngressGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.IngressListener - 50, // 29: hashicorp.consul.internal.configentry.IngressGateway.Meta:type_name -> hashicorp.consul.internal.configentry.IngressGateway.MetaEntry - 23, // 30: hashicorp.consul.internal.configentry.IngressGateway.Defaults:type_name -> hashicorp.consul.internal.configentry.IngressServiceConfig - 44, // 31: hashicorp.consul.internal.configentry.IngressServiceConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck - 25, // 32: hashicorp.consul.internal.configentry.GatewayTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig - 27, // 33: hashicorp.consul.internal.configentry.IngressListener.Services:type_name -> hashicorp.consul.internal.configentry.IngressService - 24, // 34: hashicorp.consul.internal.configentry.IngressListener.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig - 28, // 35: hashicorp.consul.internal.configentry.IngressService.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayServiceTLSConfig - 29, // 36: hashicorp.consul.internal.configentry.IngressService.RequestHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers - 29, // 37: hashicorp.consul.internal.configentry.IngressService.ResponseHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers - 51, // 38: hashicorp.consul.internal.configentry.IngressService.Meta:type_name -> hashicorp.consul.internal.configentry.IngressService.MetaEntry - 57, // 39: hashicorp.consul.internal.configentry.IngressService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 44, // 40: hashicorp.consul.internal.configentry.IngressService.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck - 25, // 41: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig - 52, // 42: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry - 53, // 43: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry - 31, // 44: hashicorp.consul.internal.configentry.ServiceIntentions.Sources:type_name -> hashicorp.consul.internal.configentry.SourceIntention - 54, // 45: hashicorp.consul.internal.configentry.ServiceIntentions.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry + 75, // 1: hashicorp.consul.internal.configentry.ConfigEntry.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 76, // 2: hashicorp.consul.internal.configentry.ConfigEntry.RaftIndex:type_name -> hashicorp.consul.internal.common.RaftIndex + 7, // 3: hashicorp.consul.internal.configentry.ConfigEntry.MeshConfig:type_name -> hashicorp.consul.internal.configentry.MeshConfig + 13, // 4: hashicorp.consul.internal.configentry.ConfigEntry.ServiceResolver:type_name -> hashicorp.consul.internal.configentry.ServiceResolver + 23, // 5: hashicorp.consul.internal.configentry.ConfigEntry.IngressGateway:type_name -> hashicorp.consul.internal.configentry.IngressGateway + 31, // 6: hashicorp.consul.internal.configentry.ConfigEntry.ServiceIntentions:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions + 36, // 7: hashicorp.consul.internal.configentry.ConfigEntry.ServiceDefaults:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults + 8, // 8: hashicorp.consul.internal.configentry.MeshConfig.TransparentProxy:type_name -> hashicorp.consul.internal.configentry.TransparentProxyMeshConfig + 9, // 9: hashicorp.consul.internal.configentry.MeshConfig.TLS:type_name -> hashicorp.consul.internal.configentry.MeshTLSConfig + 11, // 10: hashicorp.consul.internal.configentry.MeshConfig.HTTP:type_name -> hashicorp.consul.internal.configentry.MeshHTTPConfig + 59, // 11: hashicorp.consul.internal.configentry.MeshConfig.Meta:type_name -> hashicorp.consul.internal.configentry.MeshConfig.MetaEntry + 12, // 12: hashicorp.consul.internal.configentry.MeshConfig.Peering:type_name -> hashicorp.consul.internal.configentry.PeeringMeshConfig + 10, // 13: hashicorp.consul.internal.configentry.MeshTLSConfig.Incoming:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig + 10, // 14: hashicorp.consul.internal.configentry.MeshTLSConfig.Outgoing:type_name -> hashicorp.consul.internal.configentry.MeshDirectionalTLSConfig + 60, // 15: hashicorp.consul.internal.configentry.ServiceResolver.Subsets:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry + 15, // 16: hashicorp.consul.internal.configentry.ServiceResolver.Redirect:type_name -> hashicorp.consul.internal.configentry.ServiceResolverRedirect + 61, // 17: hashicorp.consul.internal.configentry.ServiceResolver.Failover:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry + 77, // 18: hashicorp.consul.internal.configentry.ServiceResolver.ConnectTimeout:type_name -> google.protobuf.Duration + 18, // 19: hashicorp.consul.internal.configentry.ServiceResolver.LoadBalancer:type_name -> hashicorp.consul.internal.configentry.LoadBalancer + 62, // 20: hashicorp.consul.internal.configentry.ServiceResolver.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceResolver.MetaEntry + 17, // 21: hashicorp.consul.internal.configentry.ServiceResolverFailover.Targets:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailoverTarget + 19, // 22: hashicorp.consul.internal.configentry.LoadBalancer.RingHashConfig:type_name -> hashicorp.consul.internal.configentry.RingHashConfig + 20, // 23: hashicorp.consul.internal.configentry.LoadBalancer.LeastRequestConfig:type_name -> hashicorp.consul.internal.configentry.LeastRequestConfig + 21, // 24: hashicorp.consul.internal.configentry.LoadBalancer.HashPolicies:type_name -> hashicorp.consul.internal.configentry.HashPolicy + 22, // 25: hashicorp.consul.internal.configentry.HashPolicy.CookieConfig:type_name -> hashicorp.consul.internal.configentry.CookieConfig + 77, // 26: hashicorp.consul.internal.configentry.CookieConfig.TTL:type_name -> google.protobuf.Duration + 25, // 27: hashicorp.consul.internal.configentry.IngressGateway.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig + 27, // 28: hashicorp.consul.internal.configentry.IngressGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.IngressListener + 63, // 29: hashicorp.consul.internal.configentry.IngressGateway.Meta:type_name -> hashicorp.consul.internal.configentry.IngressGateway.MetaEntry + 24, // 30: hashicorp.consul.internal.configentry.IngressGateway.Defaults:type_name -> hashicorp.consul.internal.configentry.IngressServiceConfig + 45, // 31: hashicorp.consul.internal.configentry.IngressServiceConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck + 26, // 32: hashicorp.consul.internal.configentry.GatewayTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig + 28, // 33: hashicorp.consul.internal.configentry.IngressListener.Services:type_name -> hashicorp.consul.internal.configentry.IngressService + 25, // 34: hashicorp.consul.internal.configentry.IngressListener.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSConfig + 29, // 35: hashicorp.consul.internal.configentry.IngressService.TLS:type_name -> hashicorp.consul.internal.configentry.GatewayServiceTLSConfig + 30, // 36: hashicorp.consul.internal.configentry.IngressService.RequestHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers + 30, // 37: hashicorp.consul.internal.configentry.IngressService.ResponseHeaders:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers + 64, // 38: hashicorp.consul.internal.configentry.IngressService.Meta:type_name -> hashicorp.consul.internal.configentry.IngressService.MetaEntry + 75, // 39: hashicorp.consul.internal.configentry.IngressService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 45, // 40: hashicorp.consul.internal.configentry.IngressService.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck + 26, // 41: hashicorp.consul.internal.configentry.GatewayServiceTLSConfig.SDS:type_name -> hashicorp.consul.internal.configentry.GatewayTLSSDSConfig + 65, // 42: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Add:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.AddEntry + 66, // 43: hashicorp.consul.internal.configentry.HTTPHeaderModifiers.Set:type_name -> hashicorp.consul.internal.configentry.HTTPHeaderModifiers.SetEntry + 32, // 44: hashicorp.consul.internal.configentry.ServiceIntentions.Sources:type_name -> hashicorp.consul.internal.configentry.SourceIntention + 67, // 45: hashicorp.consul.internal.configentry.ServiceIntentions.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceIntentions.MetaEntry 1, // 46: hashicorp.consul.internal.configentry.SourceIntention.Action:type_name -> hashicorp.consul.internal.configentry.IntentionAction - 32, // 47: hashicorp.consul.internal.configentry.SourceIntention.Permissions:type_name -> hashicorp.consul.internal.configentry.IntentionPermission + 33, // 47: hashicorp.consul.internal.configentry.SourceIntention.Permissions:type_name -> hashicorp.consul.internal.configentry.IntentionPermission 2, // 48: hashicorp.consul.internal.configentry.SourceIntention.Type:type_name -> hashicorp.consul.internal.configentry.IntentionSourceType - 55, // 49: hashicorp.consul.internal.configentry.SourceIntention.LegacyMeta:type_name -> hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry - 60, // 50: hashicorp.consul.internal.configentry.SourceIntention.LegacyCreateTime:type_name -> google.protobuf.Timestamp - 60, // 51: hashicorp.consul.internal.configentry.SourceIntention.LegacyUpdateTime:type_name -> google.protobuf.Timestamp - 57, // 52: hashicorp.consul.internal.configentry.SourceIntention.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 68, // 49: hashicorp.consul.internal.configentry.SourceIntention.LegacyMeta:type_name -> hashicorp.consul.internal.configentry.SourceIntention.LegacyMetaEntry + 78, // 50: hashicorp.consul.internal.configentry.SourceIntention.LegacyCreateTime:type_name -> google.protobuf.Timestamp + 78, // 51: hashicorp.consul.internal.configentry.SourceIntention.LegacyUpdateTime:type_name -> google.protobuf.Timestamp + 75, // 52: hashicorp.consul.internal.configentry.SourceIntention.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta 1, // 53: hashicorp.consul.internal.configentry.IntentionPermission.Action:type_name -> hashicorp.consul.internal.configentry.IntentionAction - 33, // 54: hashicorp.consul.internal.configentry.IntentionPermission.HTTP:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPPermission - 34, // 55: hashicorp.consul.internal.configentry.IntentionHTTPPermission.Header:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPHeaderPermission + 34, // 54: hashicorp.consul.internal.configentry.IntentionPermission.HTTP:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPPermission + 35, // 55: hashicorp.consul.internal.configentry.IntentionHTTPPermission.Header:type_name -> hashicorp.consul.internal.configentry.IntentionHTTPHeaderPermission 3, // 56: hashicorp.consul.internal.configentry.ServiceDefaults.Mode:type_name -> hashicorp.consul.internal.configentry.ProxyMode - 36, // 57: hashicorp.consul.internal.configentry.ServiceDefaults.TransparentProxy:type_name -> hashicorp.consul.internal.configentry.TransparentProxyConfig - 38, // 58: hashicorp.consul.internal.configentry.ServiceDefaults.MeshGateway:type_name -> hashicorp.consul.internal.configentry.MeshGatewayConfig - 39, // 59: hashicorp.consul.internal.configentry.ServiceDefaults.Expose:type_name -> hashicorp.consul.internal.configentry.ExposeConfig - 41, // 60: hashicorp.consul.internal.configentry.ServiceDefaults.UpstreamConfig:type_name -> hashicorp.consul.internal.configentry.UpstreamConfiguration - 45, // 61: hashicorp.consul.internal.configentry.ServiceDefaults.Destination:type_name -> hashicorp.consul.internal.configentry.DestinationConfig - 56, // 62: hashicorp.consul.internal.configentry.ServiceDefaults.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry - 37, // 63: hashicorp.consul.internal.configentry.ServiceDefaults.EnvoyExtensions:type_name -> hashicorp.consul.internal.configentry.EnvoyExtension - 61, // 64: hashicorp.consul.internal.configentry.EnvoyExtension.Arguments:type_name -> google.protobuf.Value + 37, // 57: hashicorp.consul.internal.configentry.ServiceDefaults.TransparentProxy:type_name -> hashicorp.consul.internal.configentry.TransparentProxyConfig + 39, // 58: hashicorp.consul.internal.configentry.ServiceDefaults.MeshGateway:type_name -> hashicorp.consul.internal.configentry.MeshGatewayConfig + 40, // 59: hashicorp.consul.internal.configentry.ServiceDefaults.Expose:type_name -> hashicorp.consul.internal.configentry.ExposeConfig + 42, // 60: hashicorp.consul.internal.configentry.ServiceDefaults.UpstreamConfig:type_name -> hashicorp.consul.internal.configentry.UpstreamConfiguration + 46, // 61: hashicorp.consul.internal.configentry.ServiceDefaults.Destination:type_name -> hashicorp.consul.internal.configentry.DestinationConfig + 69, // 62: hashicorp.consul.internal.configentry.ServiceDefaults.Meta:type_name -> hashicorp.consul.internal.configentry.ServiceDefaults.MetaEntry + 38, // 63: hashicorp.consul.internal.configentry.ServiceDefaults.EnvoyExtensions:type_name -> hashicorp.consul.internal.configentry.EnvoyExtension + 79, // 64: hashicorp.consul.internal.configentry.EnvoyExtension.Arguments:type_name -> google.protobuf.Value 4, // 65: hashicorp.consul.internal.configentry.MeshGatewayConfig.Mode:type_name -> hashicorp.consul.internal.configentry.MeshGatewayMode - 40, // 66: hashicorp.consul.internal.configentry.ExposeConfig.Paths:type_name -> hashicorp.consul.internal.configentry.ExposePath - 42, // 67: hashicorp.consul.internal.configentry.UpstreamConfiguration.Overrides:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig - 42, // 68: hashicorp.consul.internal.configentry.UpstreamConfiguration.Defaults:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig - 57, // 69: hashicorp.consul.internal.configentry.UpstreamConfig.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta - 43, // 70: hashicorp.consul.internal.configentry.UpstreamConfig.Limits:type_name -> hashicorp.consul.internal.configentry.UpstreamLimits - 44, // 71: hashicorp.consul.internal.configentry.UpstreamConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck - 38, // 72: hashicorp.consul.internal.configentry.UpstreamConfig.MeshGateway:type_name -> hashicorp.consul.internal.configentry.MeshGatewayConfig - 59, // 73: hashicorp.consul.internal.configentry.PassiveHealthCheck.Interval:type_name -> google.protobuf.Duration - 13, // 74: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverSubset - 15, // 75: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailover - 76, // [76:76] is the sub-list for method output_type - 76, // [76:76] is the sub-list for method input_type - 76, // [76:76] is the sub-list for extension type_name - 76, // [76:76] is the sub-list for extension extendee - 0, // [0:76] is the sub-list for field type_name + 41, // 66: hashicorp.consul.internal.configentry.ExposeConfig.Paths:type_name -> hashicorp.consul.internal.configentry.ExposePath + 43, // 67: hashicorp.consul.internal.configentry.UpstreamConfiguration.Overrides:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig + 43, // 68: hashicorp.consul.internal.configentry.UpstreamConfiguration.Defaults:type_name -> hashicorp.consul.internal.configentry.UpstreamConfig + 75, // 69: hashicorp.consul.internal.configentry.UpstreamConfig.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 44, // 70: hashicorp.consul.internal.configentry.UpstreamConfig.Limits:type_name -> hashicorp.consul.internal.configentry.UpstreamLimits + 45, // 71: hashicorp.consul.internal.configentry.UpstreamConfig.PassiveHealthCheck:type_name -> hashicorp.consul.internal.configentry.PassiveHealthCheck + 39, // 72: hashicorp.consul.internal.configentry.UpstreamConfig.MeshGateway:type_name -> hashicorp.consul.internal.configentry.MeshGatewayConfig + 77, // 73: hashicorp.consul.internal.configentry.PassiveHealthCheck.Interval:type_name -> google.protobuf.Duration + 70, // 74: hashicorp.consul.internal.configentry.APIGateway.Meta:type_name -> hashicorp.consul.internal.configentry.APIGateway.MetaEntry + 50, // 75: hashicorp.consul.internal.configentry.APIGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.APIGatewayListener + 48, // 76: hashicorp.consul.internal.configentry.APIGateway.Status:type_name -> hashicorp.consul.internal.configentry.Status + 49, // 77: hashicorp.consul.internal.configentry.Status.Conditions:type_name -> hashicorp.consul.internal.configentry.Condition + 52, // 78: hashicorp.consul.internal.configentry.Condition.Resource:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 78, // 79: hashicorp.consul.internal.configentry.Condition.LastTransitionTime:type_name -> google.protobuf.Timestamp + 5, // 80: hashicorp.consul.internal.configentry.APIGatewayListener.Protocol:type_name -> hashicorp.consul.internal.configentry.APIGatewayListenerProtocol + 51, // 81: hashicorp.consul.internal.configentry.APIGatewayListener.TLS:type_name -> hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration + 52, // 82: hashicorp.consul.internal.configentry.APIGatewayTLSConfiguration.Certificates:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 75, // 83: hashicorp.consul.internal.configentry.ResourceReference.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 71, // 84: hashicorp.consul.internal.configentry.BoundAPIGateway.Meta:type_name -> hashicorp.consul.internal.configentry.BoundAPIGateway.MetaEntry + 54, // 85: hashicorp.consul.internal.configentry.BoundAPIGateway.Listeners:type_name -> hashicorp.consul.internal.configentry.BoundAPIGatewayListener + 52, // 86: hashicorp.consul.internal.configentry.BoundAPIGatewayListener.Certificates:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 52, // 87: hashicorp.consul.internal.configentry.BoundAPIGatewayListener.Routes:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 72, // 88: hashicorp.consul.internal.configentry.InlineCertificate.Meta:type_name -> hashicorp.consul.internal.configentry.InlineCertificate.MetaEntry + 73, // 89: hashicorp.consul.internal.configentry.HTTPRoute.Meta:type_name -> hashicorp.consul.internal.configentry.HTTPRoute.MetaEntry + 74, // 90: hashicorp.consul.internal.configentry.TCPRoute.Meta:type_name -> hashicorp.consul.internal.configentry.TCPRoute.MetaEntry + 52, // 91: hashicorp.consul.internal.configentry.TCPRoute.Parents:type_name -> hashicorp.consul.internal.configentry.ResourceReference + 58, // 92: hashicorp.consul.internal.configentry.TCPRoute.Services:type_name -> hashicorp.consul.internal.configentry.TCPService + 48, // 93: hashicorp.consul.internal.configentry.TCPRoute.Status:type_name -> hashicorp.consul.internal.configentry.Status + 75, // 94: hashicorp.consul.internal.configentry.TCPService.EnterpriseMeta:type_name -> hashicorp.consul.internal.common.EnterpriseMeta + 14, // 95: hashicorp.consul.internal.configentry.ServiceResolver.SubsetsEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverSubset + 16, // 96: hashicorp.consul.internal.configentry.ServiceResolver.FailoverEntry.value:type_name -> hashicorp.consul.internal.configentry.ServiceResolverFailover + 97, // [97:97] is the sub-list for method output_type + 97, // [97:97] is the sub-list for method input_type + 97, // [97:97] is the sub-list for extension type_name + 97, // [97:97] is the sub-list for extension extendee + 0, // [0:97] is the sub-list for field type_name } func init() { file_proto_pbconfigentry_config_entry_proto_init() } @@ -4968,6 +6097,150 @@ func file_proto_pbconfigentry_config_entry_proto_init() { return nil } } + file_proto_pbconfigentry_config_entry_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*APIGateway); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbconfigentry_config_entry_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Status); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbconfigentry_config_entry_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Condition); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbconfigentry_config_entry_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*APIGatewayListener); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbconfigentry_config_entry_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*APIGatewayTLSConfiguration); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbconfigentry_config_entry_proto_msgTypes[46].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ResourceReference); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbconfigentry_config_entry_proto_msgTypes[47].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BoundAPIGateway); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbconfigentry_config_entry_proto_msgTypes[48].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*BoundAPIGatewayListener); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbconfigentry_config_entry_proto_msgTypes[49].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*InlineCertificate); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbconfigentry_config_entry_proto_msgTypes[50].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*HTTPRoute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbconfigentry_config_entry_proto_msgTypes[51].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TCPRoute); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_pbconfigentry_config_entry_proto_msgTypes[52].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*TCPService); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_proto_pbconfigentry_config_entry_proto_msgTypes[0].OneofWrappers = []interface{}{ (*ConfigEntry_MeshConfig)(nil), @@ -4981,8 +6254,8 @@ func file_proto_pbconfigentry_config_entry_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_proto_pbconfigentry_config_entry_proto_rawDesc, - NumEnums: 5, - NumMessages: 52, + NumEnums: 6, + NumMessages: 69, NumExtensions: 0, NumServices: 0, }, diff --git a/proto/pbconfigentry/config_entry.proto b/proto/pbconfigentry/config_entry.proto index 2204efdb9d..97c8731d44 100644 --- a/proto/pbconfigentry/config_entry.proto +++ b/proto/pbconfigentry/config_entry.proto @@ -14,6 +14,11 @@ enum Kind { KindIngressGateway = 3; KindServiceIntentions = 4; KindServiceDefaults = 5; + KindInlineCertificate = 6; + KindAPIGateway = 7; + KindBoundAPIGateway = 8; + KindHTTPRoute = 9; + KindTCPRoute = 10; } message ConfigEntry { @@ -575,3 +580,156 @@ message DestinationConfig { // mog: func-to=int func-from=int32 int32 Port = 2; } + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.APIGatewayConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +message APIGateway { + map Meta = 1; + repeated APIGatewayListener Listeners = 2; + Status Status = 3; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.Status +// output=config_entry.gen.go +// name=Structs +message Status { + repeated Condition Conditions = 1; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.Condition +// output=config_entry.gen.go +// name=Structs +message Condition { + string Status = 1; + string Reason = 2; + string Message = 3; + ResourceReference Resource = 4; + // mog: func-to=timeToStructs func-from=timeFromStructs + google.protobuf.Timestamp LastTransitionTime = 5; +} + +enum APIGatewayListenerProtocol { + ListenerProtocolHTTP = 0; + ListenerProtocolTCP = 1; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.APIGatewayListener +// output=config_entry.gen.go +// name=Structs +message APIGatewayListener { + string Name = 1; + string Hostname = 2; + // mog: func-to=int func-from=int32 + int32 Port = 3; + // mog: func-to=apiGatewayProtocolToStructs func-from=apiGatewayProtocolFromStructs + APIGatewayListenerProtocol Protocol = 4; + APIGatewayTLSConfiguration TLS = 5; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.APIGatewayTLSConfiguration +// output=config_entry.gen.go +// name=Structs +message APIGatewayTLSConfiguration { + repeated ResourceReference Certificates = 1; + // mog: func-from=tlsVersionFromStructs func-to=tlsVersionToStructs + string MinVersion = 2; + // mog: func-from=tlsVersionFromStructs func-to=tlsVersionToStructs + string MaxVersion = 3; + // mog: func-from=cipherSuitesFromStructs func-to=cipherSuitesToStructs + repeated string CipherSuites = 4; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.ResourceReference +// output=config_entry.gen.go +// name=Structs +message ResourceReference { + string Kind = 1; + string Name = 2; + string SectionName = 3; + // mog: func-to=enterpriseMetaToStructs func-from=enterpriseMetaFromStructs + common.EnterpriseMeta EnterpriseMeta = 4; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.BoundAPIGatewayConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +message BoundAPIGateway { + map Meta = 1; + repeated BoundAPIGatewayListener Listeners = 2; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.BoundAPIGatewayListener +// output=config_entry.gen.go +// name=Structs +message BoundAPIGatewayListener { + string Name = 1; + repeated ResourceReference Certificates = 2; + repeated ResourceReference Routes = 3; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.InlineCertificateConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +message InlineCertificate { + map Meta = 1; + string Certificate = 2; + string PrivateKey = 3; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.HTTPRouteConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +message HTTPRoute { + map Meta = 1; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.TCPRouteConfigEntry +// output=config_entry.gen.go +// name=Structs +// ignore-fields=Kind,Name,RaftIndex,EnterpriseMeta +message TCPRoute { + map Meta = 1; + repeated ResourceReference Parents = 2; + repeated TCPService Services = 3; + Status Status = 4; +} + +// mog annotation: +// +// target=github.com/hashicorp/consul/agent/structs.TCPService +// output=config_entry.gen.go +// name=Structs +message TCPService { + string Name = 1; + // mog: func-to=int func-from=int32 + int32 Weight = 2; + // mog: func-to=enterpriseMetaToStructs func-from=enterpriseMetaFromStructs + common.EnterpriseMeta EnterpriseMeta = 4; +} diff --git a/proto/pbsubscribe/subscribe.pb.go b/proto/pbsubscribe/subscribe.pb.go index f24b252b75..b6f7b4eaec 100644 --- a/proto/pbsubscribe/subscribe.pb.go +++ b/proto/pbsubscribe/subscribe.pb.go @@ -59,20 +59,35 @@ const ( Topic_ServiceList Topic = 7 // ServiceDefaults topic contains events for changes to service-defaults. Topic_ServiceDefaults Topic = 8 + // APIGateway topic contains events for changes to api-gateways. + Topic_APIGateway Topic = 9 + // TCPRoute topic contains events for changes to tcp-routes. + Topic_TCPRoute Topic = 10 + // HTTPRoute topic contains events for changes to http-routes. + Topic_HTTPRoute Topic = 11 + // InlineCertificate topic contains events for changes to inline-certificates. + Topic_InlineCertificate Topic = 12 + // BoundAPIGateway topic contains events for changes to bound-api-gateways. + Topic_BoundAPIGateway Topic = 13 ) // Enum value maps for Topic. var ( Topic_name = map[int32]string{ - 0: "Unknown", - 1: "ServiceHealth", - 2: "ServiceHealthConnect", - 3: "MeshConfig", - 4: "ServiceResolver", - 5: "IngressGateway", - 6: "ServiceIntentions", - 7: "ServiceList", - 8: "ServiceDefaults", + 0: "Unknown", + 1: "ServiceHealth", + 2: "ServiceHealthConnect", + 3: "MeshConfig", + 4: "ServiceResolver", + 5: "IngressGateway", + 6: "ServiceIntentions", + 7: "ServiceList", + 8: "ServiceDefaults", + 9: "APIGateway", + 10: "TCPRoute", + 11: "HTTPRoute", + 12: "InlineCertificate", + 13: "BoundAPIGateway", } Topic_value = map[string]int32{ "Unknown": 0, @@ -84,6 +99,11 @@ var ( "ServiceIntentions": 6, "ServiceList": 7, "ServiceDefaults": 8, + "APIGateway": 9, + "TCPRoute": 10, + "HTTPRoute": 11, + "InlineCertificate": 12, + "BoundAPIGateway": 13, } ) @@ -965,8 +985,8 @@ var file_proto_pbsubscribe_subscribe_proto_rawDesc = []byte{ 0x6d, 0x6f, 0x6e, 0x2e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x0e, 0x45, 0x6e, 0x74, 0x65, 0x72, 0x70, 0x72, 0x69, 0x73, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x2a, 0xb7, - 0x01, 0x0a, 0x05, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x50, 0x65, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x2a, 0x90, + 0x02, 0x0a, 0x05, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, @@ -977,26 +997,31 @@ var file_proto_pbsubscribe_subscribe_proto_rawDesc = []byte{ 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x10, 0x06, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x4c, 0x69, 0x73, 0x74, 0x10, 0x07, 0x12, 0x13, 0x0a, 0x0f, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x44, 0x65, - 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x10, 0x08, 0x2a, 0x29, 0x0a, 0x09, 0x43, 0x61, 0x74, 0x61, - 0x6c, 0x6f, 0x67, 0x4f, 0x70, 0x12, 0x0c, 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x10, 0x01, 0x32, 0x5f, 0x0a, 0x17, 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, - 0x67, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, - 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x12, 0x1b, 0x2e, 0x73, 0x75, - 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x62, 0x65, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x06, 0xe2, 0x86, 0x04, 0x02, - 0x08, 0x02, 0x30, 0x01, 0x42, 0x92, 0x01, 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x42, 0x0e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2d, 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, 0x73, 0x75, - 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xa2, 0x02, 0x03, 0x53, 0x58, 0x58, 0xaa, 0x02, 0x09, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xca, 0x02, 0x09, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x62, 0x65, 0xe2, 0x02, 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, - 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, - 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x66, 0x61, 0x75, 0x6c, 0x74, 0x73, 0x10, 0x08, 0x12, 0x0e, 0x0a, 0x0a, 0x41, 0x50, 0x49, 0x47, + 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, 0x09, 0x12, 0x0c, 0x0a, 0x08, 0x54, 0x43, 0x50, 0x52, + 0x6f, 0x75, 0x74, 0x65, 0x10, 0x0a, 0x12, 0x0d, 0x0a, 0x09, 0x48, 0x54, 0x54, 0x50, 0x52, 0x6f, + 0x75, 0x74, 0x65, 0x10, 0x0b, 0x12, 0x15, 0x0a, 0x11, 0x49, 0x6e, 0x6c, 0x69, 0x6e, 0x65, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x10, 0x0c, 0x12, 0x13, 0x0a, 0x0f, + 0x42, 0x6f, 0x75, 0x6e, 0x64, 0x41, 0x50, 0x49, 0x47, 0x61, 0x74, 0x65, 0x77, 0x61, 0x79, 0x10, + 0x0d, 0x2a, 0x29, 0x0a, 0x09, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x4f, 0x70, 0x12, 0x0c, + 0x0a, 0x08, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0x00, 0x12, 0x0e, 0x0a, 0x0a, + 0x44, 0x65, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x10, 0x01, 0x32, 0x5f, 0x0a, 0x17, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x62, 0x65, 0x12, 0x1b, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0x2e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x10, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x2e, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x22, 0x06, 0xe2, 0x86, 0x04, 0x02, 0x08, 0x02, 0x30, 0x01, 0x42, 0x92, 0x01, + 0x0a, 0x0d, 0x63, 0x6f, 0x6d, 0x2e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x42, + 0x0e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, + 0x01, 0x5a, 0x2d, 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, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, + 0xa2, 0x02, 0x03, 0x53, 0x58, 0x58, 0xaa, 0x02, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x62, 0x65, 0xca, 0x02, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0xe2, 0x02, + 0x15, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x09, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x62, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/proto/pbsubscribe/subscribe.proto b/proto/pbsubscribe/subscribe.proto index f4031c169f..957388f33b 100644 --- a/proto/pbsubscribe/subscribe.proto +++ b/proto/pbsubscribe/subscribe.proto @@ -78,6 +78,21 @@ enum Topic { // ServiceDefaults topic contains events for changes to service-defaults. ServiceDefaults = 8; + + // APIGateway topic contains events for changes to api-gateways. + APIGateway = 9; + + // TCPRoute topic contains events for changes to tcp-routes. + TCPRoute = 10; + + // HTTPRoute topic contains events for changes to http-routes. + HTTPRoute = 11; + + // InlineCertificate topic contains events for changes to inline-certificates. + InlineCertificate = 12; + + // BoundAPIGateway topic contains events for changes to bound-api-gateways. + BoundAPIGateway = 13; } message NamedSubject { diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index 8b85e1cdd1..6fffa4fa0e 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -1255,7 +1255,7 @@ }, { "title": "Network Segments", - "routes":[ + "routes": [ { "title": "Network Segments Overview", "path": "enterprise/network-segments/network-segments-overview" @@ -1323,8 +1323,8 @@ "path": "api-gateway/usage/usage" }, { - "title": "Reroute HTTP Requests", - "path": "api-gateway/usage/reroute-http-requests" + "title": "Reroute HTTP Requests", + "path": "api-gateway/usage/reroute-http-requests" }, { "title": "Route Traffic to Peered Services", @@ -1333,8 +1333,7 @@ { "title": "Error Messages", "path": "api-gateway/usage/errors" - } - + } ] }, {