diff --git a/api/client/client.go b/api/client/client.go index 1610712da27ce..edffe12d00ff2 100644 --- a/api/client/client.go +++ b/api/client/client.go @@ -2286,12 +2286,56 @@ func (c *Client) GetTrustedClusters(ctx context.Context) ([]types.TrustedCluster } // UpsertTrustedCluster creates or updates a Trusted Cluster. -func (c *Client) UpsertTrustedCluster(ctx context.Context, trusedCluster types.TrustedCluster) (types.TrustedCluster, error) { - trustedCluster, ok := trusedCluster.(*types.TrustedClusterV2) +// +// Deprecated: Use [Client.UpsertTrustedClusterV2] instead. +func (c *Client) UpsertTrustedCluster(ctx context.Context, trustedCluster types.TrustedCluster) (types.TrustedCluster, error) { + trustedClusterV2, ok := trustedCluster.(*types.TrustedClusterV2) + if !ok { + return nil, trace.BadParameter("invalid type %T", trustedCluster) + } + resp, err := c.grpc.UpsertTrustedCluster(ctx, trustedClusterV2) + if err != nil { + return nil, trace.Wrap(err) + } + return resp, nil +} + +// UpsertTrustedClusterV2 creates or updates a Trusted Cluster. +func (c *Client) UpsertTrustedClusterV2(ctx context.Context, trustedCluster types.TrustedCluster) (types.TrustedCluster, error) { + trustedClusterV2, ok := trustedCluster.(*types.TrustedClusterV2) + if !ok { + return nil, trace.BadParameter("invalid type %T", trustedCluster) + } + req := &trustpb.UpsertTrustedClusterRequest{TrustedCluster: trustedClusterV2} + resp, err := c.TrustClient().UpsertTrustedCluster(ctx, req) + if err != nil { + return nil, trace.Wrap(err) + } + return resp, nil +} + +// CreateTrustedCluster creates a Trusted Cluster. +func (c *Client) CreateTrustedCluster(ctx context.Context, trustedCluster types.TrustedCluster) (types.TrustedCluster, error) { + trustedClusterV2, ok := trustedCluster.(*types.TrustedClusterV2) + if !ok { + return nil, trace.BadParameter("invalid type %T", trustedCluster) + } + req := &trustpb.CreateTrustedClusterRequest{TrustedCluster: trustedClusterV2} + resp, err := c.TrustClient().CreateTrustedCluster(ctx, req) + if err != nil { + return nil, trace.Wrap(err) + } + return resp, nil +} + +// UpdateTrustedCluster updates a Trusted Cluster. +func (c *Client) UpdateTrustedCluster(ctx context.Context, trustedCluster types.TrustedCluster) (types.TrustedCluster, error) { + trustedClusterV2, ok := trustedCluster.(*types.TrustedClusterV2) if !ok { - return nil, trace.BadParameter("invalid type %T", trusedCluster) + return nil, trace.BadParameter("invalid type %T", trustedCluster) } - resp, err := c.grpc.UpsertTrustedCluster(ctx, trustedCluster) + req := &trustpb.UpdateTrustedClusterRequest{TrustedCluster: trustedClusterV2} + resp, err := c.TrustClient().UpdateTrustedCluster(ctx, req) if err != nil { return nil, trace.Wrap(err) } diff --git a/api/client/proto/authservice.pb.go b/api/client/proto/authservice.pb.go index 2deb3d5ef03e1..f9099550a91f1 100644 --- a/api/client/proto/authservice.pb.go +++ b/api/client/proto/authservice.pb.go @@ -16255,12 +16255,12 @@ func init() { } var fileDescriptor_0ffcffcda38ae159 = []byte{ - // 15541 bytes of a gzipped FileDescriptorProto + // 15544 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0xbd, 0x5b, 0x6c, 0x5c, 0x49, 0x7a, 0x18, 0xac, 0x6e, 0xde, 0x3f, 0xde, 0x5a, 0x45, 0x52, 0x6c, 0x51, 0x97, 0x96, 0x8e, 0x46, 0x33, 0x1a, 0xed, 0xac, 0x2e, 0x9c, 0xcb, 0xce, 0x7d, 0xa6, 0x9b, 0xa4, 0x48, 0x4a, 0xbc, 0xcd, 0x69, 0x92, 0x9a, 0x9b, 0xb7, 0xf7, 0xb0, 0xbb, 0x44, 0x1e, 0xab, 0xd9, 0xa7, 0xf7, 0x9c, 0xd3, - 0xd2, 0x68, 0xfd, 0xaf, 0x7f, 0xd8, 0xfe, 0xff, 0xc4, 0x41, 0x90, 0xc4, 0x06, 0xec, 0xc0, 0x81, + 0xd2, 0x68, 0xfd, 0xaf, 0x7f, 0xd8, 0xfe, 0xff, 0xc4, 0x41, 0x90, 0xc4, 0x06, 0xe2, 0xc0, 0x86, 0x03, 0x38, 0x01, 0x1c, 0x20, 0x08, 0x10, 0xc0, 0x2f, 0x81, 0x9f, 0xfc, 0x90, 0xa7, 0x6c, 0x0c, 0x04, 0x89, 0x61, 0xfb, 0x25, 0x40, 0xe8, 0x64, 0x01, 0xbf, 0x10, 0xc9, 0x83, 0x11, 0x24, 0x40, 0x36, 0x30, 0x10, 0xd4, 0x57, 0x97, 0x53, 0x75, 0x2e, 0xdd, 0xa4, 0xa4, 0x59, 0xe7, 0x45, 0x62, @@ -16410,7 +16410,7 @@ var fileDescriptor_0ffcffcda38ae159 = []byte{ 0xfe, 0x27, 0x54, 0x79, 0xba, 0x04, 0x3e, 0xf9, 0xe0, 0xea, 0x6b, 0x73, 0x62, 0xf2, 0x36, 0x8c, 0x2c, 0xd2, 0x26, 0xdd, 0x77, 0x42, 0x4f, 0x4e, 0x27, 0xdc, 0x01, 0x26, 0x81, 0xda, 0x98, 0x8b, 0x28, 0x99, 0x39, 0x6c, 0x53, 0x27, 0xf0, 0x5a, 0xba, 0x39, 0xec, 0x23, 0x44, 0x37, 0x87, 0x39, - 0x0d, 0xf9, 0xed, 0x1c, 0x8c, 0x96, 0x5b, 0x2d, 0xe1, 0x58, 0x0a, 0x84, 0xd6, 0x67, 0x6e, 0x29, + 0x0d, 0xf9, 0xad, 0x1c, 0x8c, 0x96, 0x5b, 0x2d, 0xe1, 0x58, 0x0a, 0x84, 0xd6, 0x67, 0x6e, 0x29, 0x4f, 0xec, 0x9a, 0xb3, 0x47, 0x9b, 0xbb, 0x4e, 0xb3, 0x43, 0x83, 0xca, 0xd7, 0xcc, 0x42, 0xf9, 0x8f, 0x47, 0xa5, 0x0f, 0x4e, 0xe1, 0x2a, 0x8a, 0x7c, 0xba, 0xdb, 0xbe, 0xe3, 0x86, 0x01, 0xfb, 0x6a, 0x9d, 0xa8, 0x40, 0xfd, 0xbb, 0xd1, 0xea, 0x11, 0xad, 0x0d, 0x83, 0xbd, 0xd6, 0x06, 0x72, @@ -16495,7 +16495,7 @@ var fileDescriptor_0ffcffcda38ae159 = []byte{ 0xef, 0xe7, 0xdf, 0xcd, 0xdd, 0xef, 0x1f, 0x1e, 0x2d, 0x8c, 0xf1, 0x63, 0xf5, 0xfb, 0xfd, 0xc3, 0xe3, 0x85, 0x09, 0xab, 0x0c, 0x93, 0x31, 0x7a, 0x52, 0x84, 0x21, 0xda, 0x62, 0x9b, 0xff, 0x06, 0xdf, 0x10, 0xd9, 0xf2, 0x27, 0x99, 0x86, 0x81, 0xa6, 0x7b, 0xe8, 0x86, 0x58, 0xe0, 0x80, 0xcd, - 0x7f, 0x58, 0xbf, 0x93, 0x03, 0x92, 0x5c, 0x8f, 0xc8, 0xed, 0x98, 0x18, 0xbe, 0xf5, 0x15, 0x20, + 0x7f, 0x58, 0xbf, 0x9d, 0x03, 0x92, 0x5c, 0x8f, 0xc8, 0xed, 0x98, 0x18, 0xbe, 0xf5, 0x15, 0x20, 0xfd, 0xe0, 0x40, 0x4a, 0xff, 0x0c, 0xa6, 0xf8, 0x80, 0x90, 0x2b, 0xa7, 0x56, 0x16, 0x9f, 0xb1, 0x53, 0xd0, 0xba, 0xb3, 0x49, 0xa0, 0x71, 0x9d, 0x5d, 0xc3, 0xaa, 0x75, 0x60, 0x26, 0x75, 0x25, 0x22, 0xeb, 0x30, 0x73, 0xe8, 0xb5, 0xc2, 0x83, 0xe6, 0x33, 0xb9, 0x10, 0x89, 0xd2, 0x72, 0x58, @@ -16619,7 +16619,7 @@ var fileDescriptor_0ffcffcda38ae159 = []byte{ 0xaa, 0x57, 0xe9, 0xd3, 0x30, 0xa0, 0x7b, 0x29, 0xf9, 0x0f, 0xeb, 0x37, 0x73, 0x30, 0x8d, 0xc3, 0x60, 0xdf, 0x65, 0xcb, 0x43, 0xd4, 0x96, 0x79, 0xa3, 0xd3, 0x2e, 0x1a, 0x9d, 0x16, 0xa3, 0x55, 0xbd, 0xf7, 0x7e, 0xa2, 0xf7, 0x2e, 0xa6, 0xf5, 0x1e, 0x4e, 0x01, 0xae, 0xd7, 0xd2, 0x3b, 0x4d, - 0x3f, 0xae, 0xfb, 0x9d, 0x1c, 0x4c, 0x69, 0x75, 0x52, 0x0d, 0xbc, 0x6b, 0x54, 0xe9, 0x42, 0x4a, + 0x3f, 0xae, 0xfb, 0xed, 0x1c, 0x4c, 0x69, 0x75, 0x52, 0x0d, 0xbc, 0x6b, 0x54, 0xe9, 0x42, 0x4a, 0x95, 0x12, 0xe3, 0xa9, 0x92, 0xa8, 0xd1, 0x2b, 0xdd, 0x6a, 0x94, 0x36, 0x9c, 0x8c, 0x61, 0xf2, 0x97, 0x39, 0x98, 0x49, 0xd5, 0x01, 0x39, 0xc7, 0xf6, 0xff, 0x75, 0x9f, 0x86, 0x42, 0xf3, 0xe2, 0x17, 0x83, 0xaf, 0x06, 0x41, 0x87, 0xfa, 0x42, 0xef, 0xe2, 0x17, 0x79, 0x05, 0xc6, 0xb7, 0xa8, @@ -16705,7 +16705,7 @@ var fileDescriptor_0ffcffcda38ae159 = []byte{ 0x83, 0x21, 0x96, 0x93, 0x24, 0x7f, 0x92, 0x9c, 0x24, 0xbf, 0x04, 0x19, 0x2e, 0xab, 0x13, 0x78, 0x01, 0x5e, 0x3b, 0x3e, 0x2a, 0x5d, 0x8b, 0xbc, 0x00, 0x1c, 0x9b, 0xe6, 0x0e, 0xc8, 0x28, 0x22, 0xe9, 0xbf, 0xe8, 0x7f, 0x0e, 0xff, 0xc5, 0x1d, 0x18, 0x42, 0x63, 0x66, 0x75, 0x4b, 0x44, 0x7e, - 0xe2, 0xf0, 0xc4, 0x0c, 0x45, 0x35, 0x57, 0x4f, 0x07, 0x28, 0xc9, 0xac, 0x7f, 0x98, 0x87, 0x2b, + 0xe2, 0xf0, 0xc4, 0x0c, 0x45, 0x35, 0x57, 0x4f, 0x07, 0x28, 0xc9, 0xac, 0x7f, 0x94, 0x87, 0x2b, 0xd9, 0x3a, 0x17, 0x75, 0x5b, 0x04, 0x88, 0x22, 0x5c, 0xba, 0x45, 0xd4, 0xe0, 0xb7, 0xf3, 0x94, 0xee, 0xa9, 0x88, 0x36, 0x8d, 0x8f, 0xed, 0x7d, 0xe4, 0x4d, 0xeb, 0xd8, 0x71, 0x8a, 0x71, 0x01, 0x5b, 0x64, 0xb3, 0x15, 0x20, 0x23, 0x9b, 0xad, 0x80, 0x91, 0x3d, 0x98, 0xdd, 0xf2, 0xdd, 0x27, @@ -16743,127 +16743,127 @@ var fileDescriptor_0ffcffcda38ae159 = []byte{ 0x94, 0xca, 0xf4, 0xf0, 0x91, 0x73, 0xeb, 0xc9, 0xdd, 0x5b, 0x29, 0xb4, 0x3c, 0x11, 0x41, 0x5d, 0x22, 0xb4, 0xf8, 0x2c, 0xfd, 0xa0, 0x2b, 0x85, 0x91, 0x7c, 0x01, 0xd3, 0xd5, 0xea, 0x26, 0xbf, 0xcc, 0x61, 0xcb, 0x03, 0x7e, 0x7b, 0x4d, 0x04, 0x6c, 0x61, 0x77, 0x07, 0x81, 0x57, 0x13, 0x97, - 0x40, 0xf4, 0xb0, 0x00, 0x3d, 0x15, 0x43, 0x9a, 0x08, 0xfd, 0xa4, 0xfc, 0xb7, 0xd4, 0x5d, 0x05, - 0xb6, 0x15, 0x71, 0x9b, 0x54, 0x5c, 0x3a, 0x92, 0x03, 0x3b, 0xe3, 0x94, 0x2f, 0xf7, 0x2d, 0x9f, - 0xf2, 0xfd, 0x41, 0x5e, 0xde, 0xd0, 0x48, 0x1e, 0xb4, 0x9e, 0xfa, 0xb0, 0x2f, 0xb5, 0x05, 0x27, - 0x5a, 0xa7, 0x53, 0x2b, 0x47, 0x2a, 0xf2, 0xa8, 0x54, 0x25, 0x2b, 0x9b, 0x50, 0xc7, 0x0e, 0x11, - 0xc2, 0x38, 0x3d, 0xc5, 0x5d, 0x91, 0xc6, 0x15, 0x3f, 0x87, 0xeb, 0x7b, 0xf1, 0x73, 0xb8, 0x1f, - 0xc3, 0x8c, 0xbc, 0x1a, 0xb5, 0x40, 0x5b, 0x21, 0xf5, 0xe5, 0x89, 0xfd, 0x44, 0x94, 0xf4, 0x0d, - 0xd3, 0xfb, 0x15, 0xa0, 0xaf, 0x6c, 0x6f, 0x08, 0x8f, 0x0e, 0xfb, 0x93, 0x5c, 0x31, 0x03, 0xe2, - 0xf8, 0x9d, 0x37, 0x23, 0xfc, 0xed, 0x0a, 0xab, 0x2e, 0xf7, 0xb3, 0xb8, 0x32, 0x55, 0x9f, 0xad, - 0x83, 0xac, 0x05, 0xb8, 0x60, 0x16, 0xbf, 0x45, 0xfd, 0x43, 0x17, 0xf7, 0xde, 0x55, 0x1a, 0xca, - 0x42, 0x73, 0x51, 0xa1, 0x44, 0x0f, 0xa8, 0x16, 0x66, 0xe0, 0xff, 0xce, 0x43, 0x29, 0xb5, 0x11, - 0xe5, 0x20, 0x70, 0xf7, 0x5b, 0x98, 0x41, 0xe3, 0x22, 0xf4, 0x3f, 0x70, 0x5b, 0x0d, 0xdd, 0x90, - 0x7c, 0xec, 0xb6, 0x1a, 0x36, 0x42, 0x99, 0x0d, 0x52, 0xed, 0xec, 0x21, 0x81, 0x66, 0x22, 0x07, - 0x9d, 0xbd, 0x1a, 0x23, 0xd2, 0x6d, 0x10, 0x41, 0x46, 0xae, 0xc3, 0x90, 0xcc, 0xb6, 0xd6, 0x17, - 0x79, 0xcf, 0x64, 0x9a, 0x35, 0x89, 0x23, 0x1f, 0xc1, 0xf0, 0x3a, 0x0d, 0x9d, 0x86, 0x13, 0x3a, - 0x62, 0xec, 0xc8, 0x87, 0x30, 0x24, 0xb8, 0x52, 0x10, 0x2b, 0xf4, 0xf0, 0xa1, 0x80, 0xd8, 0x8a, - 0x05, 0x15, 0xe8, 0x06, 0xed, 0xa6, 0xf3, 0x4c, 0x05, 0x93, 0x32, 0x05, 0x46, 0x20, 0xf2, 0x8e, - 0x19, 0x72, 0x11, 0x1d, 0x9f, 0xa5, 0x2a, 0x24, 0x0a, 0xc8, 0x58, 0xc1, 0x30, 0x90, 0x48, 0xd5, - 0x22, 0x9b, 0xa0, 0x95, 0xca, 0x6d, 0x50, 0xda, 0x26, 0xa3, 0xf5, 0xdb, 0xa3, 0x70, 0x76, 0xcb, - 0xd9, 0x77, 0x5b, 0x6c, 0x47, 0x61, 0xd3, 0xc0, 0xeb, 0xf8, 0x75, 0x4a, 0xca, 0x30, 0x61, 0x06, - 0x70, 0xf7, 0x08, 0x4f, 0x67, 0x9b, 0x26, 0x13, 0x46, 0xe6, 0x61, 0x44, 0x5d, 0x1a, 0x17, 0x3b, - 0x9d, 0x94, 0xcb, 0xe4, 0x2b, 0x67, 0xec, 0x88, 0x8c, 0xbc, 0x67, 0x1c, 0x3e, 0x4e, 0xaa, 0xfc, - 0x07, 0x48, 0x3b, 0xcf, 0x23, 0x6c, 0x5b, 0x5e, 0xc3, 0xdc, 0xad, 0xf1, 0x13, 0xb6, 0x1f, 0x24, - 0xce, 0x23, 0x07, 0x8c, 0x1a, 0x27, 0x9c, 0xb2, 0xb8, 0x51, 0xcd, 0xcc, 0x5e, 0x9f, 0x72, 0x52, - 0xf9, 0x25, 0x8c, 0x3e, 0xe8, 0xec, 0x51, 0x79, 0xf2, 0x3a, 0x28, 0x36, 0x6f, 0xf1, 0x6b, 0x09, - 0x02, 0xbf, 0xfb, 0x26, 0xff, 0x8a, 0x1f, 0x77, 0xf6, 0x68, 0xf2, 0x59, 0x04, 0xb6, 0x6a, 0x6a, - 0xc2, 0xc8, 0x01, 0x14, 0xe2, 0x37, 0x08, 0x44, 0x97, 0x76, 0xb9, 0xf7, 0x80, 0x89, 0x7e, 0xb4, - 0xc7, 0x17, 0x78, 0x5c, 0xb3, 0x51, 0x48, 0x42, 0x2a, 0xf9, 0x31, 0xcc, 0xa4, 0xba, 0xc4, 0xd5, - 0x1d, 0xc8, 0xee, 0xde, 0x76, 0x5c, 0x82, 0x62, 0x5a, 0x93, 0x17, 0x2e, 0x8d, 0x92, 0xd3, 0x4b, - 0x21, 0x0d, 0x98, 0x8c, 0x45, 0xc6, 0x8b, 0x17, 0x66, 0xb2, 0x63, 0xed, 0x71, 0xd7, 0x24, 0x93, - 0x34, 0xa7, 0x96, 0x15, 0x17, 0x49, 0xd6, 0x60, 0x44, 0xf9, 0xa2, 0x44, 0x6e, 0xbe, 0x34, 0xbf, - 0x5b, 0xf1, 0xf8, 0xa8, 0x34, 0x1d, 0xf9, 0xdd, 0x0c, 0x99, 0x91, 0x00, 0xf2, 0xcb, 0x70, 0x55, - 0x0d, 0xd1, 0x4d, 0x3f, 0xdd, 0x43, 0x29, 0x1e, 0x77, 0xb8, 0x19, 0x1f, 0xe1, 0x59, 0xf4, 0xbb, - 0x77, 0x2b, 0xf9, 0x62, 0x6e, 0xe5, 0x8c, 0xdd, 0x5b, 0x34, 0xf9, 0xd5, 0x1c, 0x9c, 0xcb, 0x28, - 0x75, 0x0c, 0x4b, 0xed, 0xe9, 0x36, 0x46, 0xcb, 0x13, 0xef, 0xfd, 0xb9, 0x8d, 0xe8, 0x7e, 0xac, - 0xf4, 0x1f, 0x1b, 0xed, 0xce, 0x28, 0x89, 0xdc, 0x01, 0xd8, 0x77, 0x43, 0x31, 0xc6, 0x30, 0x4d, - 0x5d, 0xf2, 0x03, 0x65, 0x6a, 0xdb, 0x77, 0x43, 0x31, 0xd2, 0x7e, 0x3f, 0xd7, 0x73, 0x5e, 0xc7, - 0xec, 0x75, 0xa3, 0xf3, 0xaf, 0x76, 0x9b, 0xf4, 0x22, 0xea, 0xca, 0x9d, 0xe3, 0xa3, 0xd2, 0x1b, - 0x2a, 0x05, 0x5a, 0x1d, 0xa9, 0xe4, 0x2d, 0xdf, 0x9a, 0xa3, 0xe8, 0x8c, 0xf6, 0xf4, 0x5c, 0x5a, - 0xde, 0x80, 0x41, 0xf4, 0x4c, 0x05, 0xc5, 0x71, 0xb4, 0xdd, 0x30, 0x71, 0x17, 0xfa, 0xaf, 0xf4, - 0xdd, 0x9a, 0xa0, 0x21, 0x2b, 0xcc, 0x06, 0xc2, 0xdd, 0xa2, 0xb4, 0x59, 0x44, 0x9a, 0x3f, 0x61, - 0x47, 0x73, 0x94, 0xcc, 0xbf, 0x63, 0x3c, 0x4f, 0x62, 0xb2, 0x55, 0x00, 0x86, 0x7d, 0x31, 0xdd, - 0xde, 0xef, 0x1f, 0xee, 0x2f, 0x0c, 0xf0, 0x19, 0x41, 0xde, 0x25, 0xf9, 0xf5, 0x61, 0x7e, 0xf1, - 0x7c, 0xa7, 0xe5, 0x3e, 0x72, 0xa3, 0x99, 0x59, 0xf7, 0x69, 0x47, 0xef, 0x84, 0x09, 0x8b, 0x33, - 0xe3, 0x45, 0x30, 0xe5, 0xfe, 0xce, 0xf7, 0x74, 0x7f, 0xbf, 0xa9, 0x1d, 0x14, 0x6b, 0xe9, 0x7c, - 0xb9, 0x65, 0x61, 0xba, 0x9b, 0xa3, 0x13, 0xe4, 0xaf, 0x61, 0x10, 0x33, 0xf0, 0xf2, 0x53, 0xf8, - 0xd1, 0xf9, 0x5b, 0xa2, 0x3b, 0xbb, 0x54, 0x9f, 0xa7, 0xec, 0x15, 0xc9, 0x24, 0xb8, 0xc6, 0x11, - 0x60, 0x68, 0x1c, 0x21, 0x64, 0x1b, 0xa6, 0xb6, 0xd8, 0x46, 0x97, 0xdf, 0x68, 0x68, 0xfb, 0xc2, - 0x25, 0xc8, 0x9d, 0x8d, 0xb8, 0xd1, 0x6e, 0x4b, 0x74, 0x8d, 0x2a, 0xbc, 0xbe, 0xd7, 0x4c, 0x61, - 0x27, 0x4b, 0x30, 0x51, 0xa5, 0x8e, 0x5f, 0x3f, 0x78, 0x40, 0x9f, 0x31, 0x23, 0xc3, 0x78, 0x1a, - 0x27, 0x40, 0x0c, 0x6b, 0x2f, 0xa2, 0xf4, 0xc8, 0x2a, 0x93, 0x89, 0x7c, 0x0a, 0x83, 0x55, 0xcf, - 0x0f, 0x2b, 0xcf, 0xc4, 0x6c, 0x2d, 0xcf, 0x69, 0x39, 0xb0, 0x72, 0x5e, 0x3e, 0x0f, 0x14, 0x78, - 0x7e, 0x58, 0xdb, 0x33, 0x32, 0xc1, 0x71, 0x12, 0xf2, 0x0c, 0xa6, 0xcd, 0x99, 0x52, 0x04, 0xda, - 0x0f, 0x0b, 0xe3, 0x26, 0x6d, 0x3a, 0xe6, 0x24, 0x95, 0x1b, 0x42, 0xfa, 0x95, 0xf8, 0x7c, 0xfc, - 0x08, 0xf1, 0xba, 0x45, 0x90, 0xc6, 0x4f, 0xd6, 0xf1, 0x5d, 0x25, 0xde, 0xa2, 0x72, 0xc0, 0x03, - 0xf4, 0x47, 0xa2, 0x5c, 0x83, 0x1d, 0x9c, 0x6d, 0x51, 0x13, 0x4e, 0x10, 0x7f, 0x8c, 0xcb, 0x4e, - 0xb0, 0x92, 0x2d, 0x38, 0xbb, 0x13, 0xd0, 0x2d, 0x9f, 0x3e, 0x71, 0xe9, 0x53, 0x29, 0x0f, 0xa2, - 0xc4, 0x6c, 0x4c, 0x5e, 0x9b, 0x63, 0xd3, 0x04, 0x26, 0x99, 0xc9, 0x7b, 0x00, 0x5b, 0x6e, 0xab, - 0x45, 0x1b, 0x78, 0xd8, 0x3f, 0x8a, 0xa2, 0xf0, 0x20, 0xa3, 0x8d, 0xd0, 0x9a, 0xd7, 0x6a, 0xea, - 0x2a, 0xd5, 0x88, 0x49, 0x05, 0xc6, 0x57, 0x5b, 0xf5, 0x66, 0x47, 0x04, 0xe5, 0x04, 0x38, 0x53, - 0x8a, 0x84, 0x91, 0x2e, 0x47, 0xd4, 0x12, 0x1f, 0xb9, 0xc9, 0x42, 0x1e, 0x00, 0x11, 0x00, 0x31, - 0x6a, 0x9d, 0xbd, 0x26, 0x15, 0x9f, 0x3b, 0x3a, 0x28, 0xa5, 0x20, 0x1c, 0xee, 0x46, 0x1e, 0xc6, - 0x04, 0xdb, 0xdc, 0x7b, 0x30, 0xaa, 0x8d, 0xf9, 0x94, 0xec, 0x28, 0xd3, 0x7a, 0x76, 0x94, 0x11, - 0x3d, 0x0b, 0xca, 0x3f, 0xcd, 0xc1, 0xc5, 0xf4, 0x6f, 0x49, 0xd8, 0x26, 0x9b, 0x30, 0xa2, 0x80, - 0xea, 0x3e, 0x9c, 0x34, 0xb8, 0x63, 0x5b, 0x3b, 0xfe, 0x41, 0xcb, 0x99, 0x47, 0x6f, 0x7d, 0x24, - 0xe3, 0x39, 0x4e, 0xc1, 0xfe, 0xf6, 0x30, 0x4c, 0xe3, 0xbd, 0x8f, 0xf8, 0x3c, 0xf5, 0x09, 0x66, - 0x39, 0x42, 0x98, 0x76, 0xa8, 0x23, 0xfc, 0xbb, 0x1c, 0x1e, 0xcf, 0xf7, 0x67, 0x30, 0x90, 0xb7, - 0xf5, 0x48, 0xa4, 0xbc, 0xf6, 0x8e, 0x93, 0x04, 0xea, 0x4d, 0x88, 0x42, 0x94, 0x5e, 0x37, 0x02, - 0x61, 0x4e, 0x3c, 0xe9, 0xf5, 0x9f, 0x74, 0xd2, 0xdb, 0x51, 0x93, 0x1e, 0xcf, 0x9e, 0xf3, 0x9a, - 0x36, 0xe9, 0xbd, 0xfc, 0xd9, 0x6e, 0xf0, 0x65, 0xcf, 0x76, 0x43, 0x2f, 0x36, 0xdb, 0x0d, 0x3f, - 0xe7, 0x6c, 0x77, 0x0f, 0x26, 0x36, 0x28, 0x6d, 0x68, 0xc7, 0x93, 0x23, 0xd1, 0xea, 0xd9, 0xa2, - 0xe8, 0x78, 0x4e, 0x3b, 0xa3, 0x8c, 0x71, 0x65, 0xce, 0x9a, 0xf0, 0x37, 0x33, 0x6b, 0x8e, 0xbe, - 0xe4, 0x59, 0x73, 0xec, 0x45, 0x66, 0xcd, 0xc4, 0xd4, 0x37, 0x7e, 0xea, 0xa9, 0xef, 0x45, 0x66, - 0xab, 0x7f, 0x9c, 0x87, 0x59, 0xf6, 0x01, 0x34, 0x9f, 0xd0, 0x6a, 0x75, 0x45, 0x04, 0x70, 0x45, - 0x81, 0x52, 0x07, 0x5e, 0x20, 0xef, 0x3a, 0xe0, 0xdf, 0x0c, 0xd6, 0xf6, 0x7c, 0x19, 0x6c, 0x82, - 0x7f, 0x93, 0x0a, 0x0c, 0xf2, 0x2f, 0xa4, 0xd8, 0x67, 0xa4, 0xa6, 0xca, 0x90, 0xab, 0x7f, 0x5f, - 0xb6, 0xe0, 0x24, 0x77, 0x61, 0x3a, 0xed, 0x53, 0x11, 0x6e, 0x8c, 0xa9, 0x76, 0xca, 0x67, 0xf2, - 0x1a, 0x4c, 0xc6, 0x3e, 0x06, 0xfe, 0xec, 0x8b, 0x3d, 0x11, 0x18, 0x1f, 0xc2, 0x8b, 0xa8, 0x67, - 0x01, 0x8a, 0xc9, 0x56, 0x88, 0x79, 0xfc, 0x35, 0x10, 0x37, 0xbc, 0x85, 0xb5, 0x1d, 0xdf, 0x5f, - 0xdb, 0x02, 0x6d, 0x7d, 0x8c, 0xc1, 0xd2, 0x4a, 0x40, 0xa0, 0xe9, 0x77, 0x45, 0xd3, 0xef, 0x8a, - 0xd0, 0xef, 0x96, 0xa6, 0x5f, 0xf6, 0xb7, 0x55, 0xc1, 0x10, 0x69, 0x9d, 0x5f, 0xdd, 0xb9, 0x1a, - 0x12, 0x17, 0xb6, 0xc5, 0x3a, 0x92, 0xa8, 0x82, 0xc4, 0x5b, 0x7f, 0x9e, 0xe3, 0xe1, 0x16, 0xff, - 0x37, 0x2e, 0x47, 0x2f, 0x12, 0x02, 0xf1, 0x6b, 0x51, 0x22, 0x17, 0x91, 0x74, 0xc6, 0x77, 0xea, - 0x8f, 0xa3, 0x18, 0x94, 0xef, 0xb3, 0xb9, 0x54, 0x47, 0x08, 0x63, 0x68, 0x56, 0x69, 0x4a, 0x47, - 0xee, 0xde, 0x95, 0x93, 0xac, 0xc8, 0x67, 0xc3, 0xc1, 0xe6, 0x24, 0xab, 0x33, 0x60, 0x14, 0xf0, - 0xa4, 0x65, 0xf3, 0x3c, 0x24, 0xa9, 0x35, 0x78, 0x27, 0x99, 0x49, 0x03, 0x2d, 0xd9, 0x28, 0x93, - 0x86, 0xae, 0xc6, 0x28, 0xa7, 0xc6, 0x0e, 0x5c, 0xb0, 0xe9, 0xa1, 0xf7, 0x84, 0xbe, 0x5c, 0xb1, - 0x5f, 0xc1, 0x79, 0x53, 0x20, 0xbf, 0x73, 0xc9, 0x1f, 0x08, 0xf9, 0x38, 0xfd, 0x59, 0x11, 0xc1, - 0xc0, 0x9f, 0x15, 0xe1, 0xaf, 0x13, 0xb0, 0x3f, 0xf5, 0xb5, 0x19, 0x71, 0x96, 0x07, 0x17, 0x4d, - 0xe1, 0xe5, 0x46, 0x03, 0x5f, 0x26, 0xae, 0xbb, 0x6d, 0xa7, 0x15, 0x92, 0x4d, 0x18, 0xd5, 0x7e, - 0xc6, 0xfc, 0x4c, 0x1a, 0x46, 0xec, 0x1b, 0x23, 0x80, 0x91, 0xdd, 0x39, 0x02, 0x5b, 0x14, 0x4a, - 0x71, 0xf5, 0x30, 0x95, 0xe9, 0x65, 0x56, 0x60, 0x5c, 0xfb, 0xa9, 0x0e, 0x63, 0x70, 0x82, 0xd5, - 0x4a, 0x30, 0x15, 0x66, 0xb2, 0x58, 0x75, 0x98, 0x4b, 0x53, 0x1a, 0x7f, 0x06, 0x80, 0x2c, 0x45, - 0x59, 0xfe, 0x7a, 0xc7, 0x11, 0x4f, 0x66, 0x65, 0xf8, 0xb3, 0xfe, 0x41, 0x3f, 0x5c, 0x10, 0x9d, - 0xf1, 0x32, 0x7b, 0x9c, 0xfc, 0x00, 0x46, 0xb5, 0x3e, 0x16, 0x4a, 0xbf, 0x22, 0x6f, 0x4c, 0x66, - 0x8d, 0x05, 0xee, 0x0f, 0xeb, 0x20, 0xa0, 0x16, 0xeb, 0xee, 0x95, 0x33, 0xb6, 0x2e, 0x92, 0x34, - 0x61, 0xc2, 0xec, 0x68, 0xe1, 0x12, 0xbc, 0x96, 0x5a, 0x88, 0x49, 0x2a, 0xdf, 0x08, 0x68, 0xd4, - 0x52, 0xbb, 0x7b, 0xe5, 0x8c, 0x1d, 0x93, 0x4d, 0xbe, 0x81, 0xb3, 0x89, 0x5e, 0x16, 0xfe, 0xde, - 0x57, 0x53, 0x0b, 0x4c, 0x50, 0xf3, 0x83, 0x26, 0x1f, 0xc1, 0x99, 0xc5, 0x26, 0x0b, 0x21, 0x0d, - 0x18, 0xd3, 0x3b, 0x5e, 0xf8, 0x2c, 0xaf, 0x76, 0x51, 0x25, 0x27, 0xe4, 0x1b, 0x68, 0xa1, 0x4b, - 0xec, 0xfb, 0x67, 0xe6, 0xe1, 0x99, 0x41, 0x3c, 0x0c, 0x83, 0xfc, 0xb7, 0xf5, 0x07, 0x39, 0xb8, - 0xb0, 0xe5, 0xd3, 0x80, 0xb6, 0xea, 0xd4, 0xb8, 0x7b, 0xf2, 0x82, 0x23, 0x22, 0xeb, 0xdc, 0x2a, - 0xff, 0xc2, 0xe7, 0x56, 0xd6, 0xbf, 0xc9, 0x41, 0x31, 0xad, 0xca, 0x55, 0xda, 0x6a, 0x90, 0x2d, - 0x28, 0xc4, 0xdb, 0x20, 0xbe, 0x18, 0x4b, 0xa5, 0x78, 0xcf, 0x6c, 0xed, 0xca, 0x19, 0x3b, 0xc1, - 0x4d, 0x36, 0xe0, 0xac, 0x06, 0x13, 0xe7, 0x46, 0xf9, 0x93, 0x9c, 0x1b, 0xb1, 0x1e, 0x4e, 0xb0, - 0xea, 0xc7, 0x6e, 0x2b, 0xb8, 0xea, 0x2e, 0x7a, 0x87, 0x8e, 0xdb, 0x62, 0x86, 0x8a, 0x96, 0x44, - 0x10, 0x22, 0xa8, 0x50, 0x3b, 0x3f, 0x48, 0x42, 0xa8, 0xbc, 0x86, 0xa7, 0x48, 0xac, 0x0f, 0x71, - 0x75, 0x10, 0xce, 0x63, 0x9e, 0xf8, 0x40, 0x09, 0xbb, 0x02, 0x03, 0xdb, 0x6b, 0xd5, 0x85, 0xb2, - 0x48, 0xa3, 0xc0, 0x93, 0xef, 0x34, 0x83, 0x5a, 0xdd, 0xb1, 0x39, 0xc2, 0xfa, 0x00, 0xc8, 0x32, - 0x0d, 0xc5, 0x1b, 0x23, 0x8a, 0xef, 0x3a, 0x0c, 0x09, 0x90, 0xe0, 0xc4, 0x23, 0x11, 0xf1, 0x62, - 0x89, 0x2d, 0x71, 0xd6, 0x96, 0xb4, 0xf3, 0x9a, 0xd4, 0x09, 0xb4, 0x45, 0xff, 0x5d, 0x18, 0xf6, - 0x05, 0x4c, 0xac, 0xf9, 0x13, 0xea, 0x09, 0x29, 0x04, 0xf3, 0xa3, 0x3a, 0x49, 0x63, 0xab, 0xbf, - 0xac, 0x35, 0x4c, 0x94, 0xb5, 0xb9, 0xba, 0xb8, 0xc0, 0xb4, 0x2a, 0x94, 0x25, 0xbb, 0xe3, 0x36, - 0xde, 0xbc, 0x09, 0xa9, 0x9e, 0x44, 0x01, 0x55, 0x83, 0x13, 0x88, 0x48, 0x0f, 0xa7, 0x91, 0x58, - 0x6f, 0xaa, 0xb4, 0x5b, 0x29, 0xd2, 0xb2, 0x9e, 0x42, 0xda, 0xc0, 0x84, 0x62, 0xcb, 0x18, 0x64, - 0xf8, 0x32, 0x2a, 0xe1, 0xc0, 0x1c, 0xdf, 0x42, 0xb0, 0x56, 0x89, 0x87, 0x60, 0x3d, 0x35, 0xed, - 0x2e, 0xc0, 0x88, 0x82, 0xa9, 0x88, 0x01, 0xae, 0x2b, 0x83, 0x7e, 0xf7, 0x4d, 0x9e, 0x6f, 0xa2, - 0xae, 0x04, 0x44, 0x7c, 0xac, 0x08, 0xfe, 0x4d, 0x7f, 0xcb, 0x45, 0x04, 0xd4, 0x0f, 0xbf, 0xd5, - 0x22, 0xa2, 0x8c, 0x73, 0xa7, 0x29, 0xc2, 0xa0, 0xdf, 0x9d, 0x3f, 0x89, 0xa2, 0xbe, 0xe5, 0x22, - 0x98, 0xa2, 0xbe, 0xbd, 0x22, 0xa8, 0x4c, 0xcd, 0xc7, 0x07, 0x69, 0xa2, 0x90, 0xa5, 0x64, 0x21, - 0xf2, 0x44, 0x25, 0xc6, 0xd1, 0xb5, 0x3f, 0x28, 0x5c, 0xe4, 0xca, 0xfa, 0x39, 0x14, 0xc3, 0x14, - 0xf6, 0xed, 0x16, 0xf3, 0x8f, 0x72, 0x3c, 0x51, 0x60, 0x75, 0x53, 0x7b, 0x82, 0xb9, 0xf5, 0xc8, + 0x40, 0xf4, 0xb0, 0x00, 0x3d, 0x15, 0x43, 0x9a, 0x08, 0xfd, 0xa4, 0xfc, 0x1f, 0xaa, 0xbb, 0x0a, + 0x6c, 0x2b, 0xe2, 0x36, 0xa9, 0xb8, 0x74, 0x24, 0x07, 0x76, 0xc6, 0x29, 0x5f, 0xee, 0x5b, 0x3e, + 0xe5, 0xfb, 0x83, 0xbc, 0xbc, 0xa1, 0x91, 0x3c, 0x68, 0x3d, 0xf5, 0x61, 0x5f, 0x6a, 0x0b, 0x4e, + 0xb4, 0x4e, 0xa7, 0x56, 0x8e, 0x54, 0xe4, 0x51, 0xa9, 0x4a, 0x56, 0x36, 0xa1, 0x8e, 0x1d, 0x22, + 0x84, 0x71, 0x7a, 0x8a, 0xbb, 0x22, 0x8d, 0x2b, 0x7e, 0x0e, 0xd7, 0xf7, 0xe2, 0xe7, 0x70, 0x3f, + 0x86, 0x19, 0x79, 0x35, 0x6a, 0x81, 0xb6, 0x42, 0xea, 0xcb, 0x13, 0xfb, 0x89, 0x28, 0xe9, 0x1b, + 0xa6, 0xf7, 0x2b, 0x40, 0x5f, 0xd9, 0xde, 0x10, 0x1e, 0x1d, 0xf6, 0x27, 0xb9, 0x62, 0x06, 0xc4, + 0xf1, 0x3b, 0x6f, 0x46, 0xf8, 0xdb, 0x15, 0x56, 0x5d, 0xee, 0x67, 0x71, 0x65, 0xaa, 0x3e, 0x5b, + 0x07, 0x59, 0x0b, 0x70, 0xc1, 0x2c, 0x7e, 0x8b, 0xfa, 0x87, 0x2e, 0xee, 0xbd, 0xab, 0x34, 0x94, + 0x85, 0xe6, 0xa2, 0x42, 0x89, 0x1e, 0x50, 0x2d, 0xcc, 0xc0, 0xff, 0x9d, 0x87, 0x52, 0x6a, 0x23, + 0xca, 0x41, 0xe0, 0xee, 0xb7, 0x30, 0x83, 0xc6, 0x45, 0xe8, 0x7f, 0xe0, 0xb6, 0x1a, 0xba, 0x21, + 0xf9, 0xd8, 0x6d, 0x35, 0x6c, 0x84, 0x32, 0x1b, 0xa4, 0xda, 0xd9, 0x43, 0x02, 0xcd, 0x44, 0x0e, + 0x3a, 0x7b, 0x35, 0x46, 0xa4, 0xdb, 0x20, 0x82, 0x8c, 0x5c, 0x87, 0x21, 0x99, 0x6d, 0xad, 0x2f, + 0xf2, 0x9e, 0xc9, 0x34, 0x6b, 0x12, 0x47, 0x3e, 0x82, 0xe1, 0x75, 0x1a, 0x3a, 0x0d, 0x27, 0x74, + 0xc4, 0xd8, 0x91, 0x0f, 0x61, 0x48, 0x70, 0xa5, 0x20, 0x56, 0xe8, 0xe1, 0x43, 0x01, 0xb1, 0x15, + 0x0b, 0x2a, 0xd0, 0x0d, 0xda, 0x4d, 0xe7, 0x99, 0x0a, 0x26, 0x65, 0x0a, 0x8c, 0x40, 0xe4, 0x1d, + 0x33, 0xe4, 0x22, 0x3a, 0x3e, 0x4b, 0x55, 0x48, 0x14, 0x90, 0xb1, 0x82, 0x61, 0x20, 0x91, 0xaa, + 0x45, 0x36, 0x41, 0x2b, 0x95, 0xdb, 0xa0, 0xb4, 0x4d, 0x46, 0xeb, 0xb7, 0x46, 0xe1, 0xec, 0x96, + 0xb3, 0xef, 0xb6, 0xd8, 0x8e, 0xc2, 0xa6, 0x81, 0xd7, 0xf1, 0xeb, 0x94, 0x94, 0x61, 0xc2, 0x0c, + 0xe0, 0xee, 0x11, 0x9e, 0xce, 0x36, 0x4d, 0x26, 0x8c, 0xcc, 0xc3, 0x88, 0xba, 0x34, 0x2e, 0x76, + 0x3a, 0x29, 0x97, 0xc9, 0x57, 0xce, 0xd8, 0x11, 0x19, 0x79, 0xcf, 0x38, 0x7c, 0x9c, 0x54, 0xf9, + 0x0f, 0x90, 0x76, 0x9e, 0x47, 0xd8, 0xb6, 0xbc, 0x86, 0xb9, 0x5b, 0xe3, 0x27, 0x6c, 0x3f, 0x48, + 0x9c, 0x47, 0x0e, 0x18, 0x35, 0x4e, 0x38, 0x65, 0x71, 0xa3, 0x9a, 0x99, 0xbd, 0x3e, 0xe5, 0xa4, + 0xf2, 0x4b, 0x18, 0x7d, 0xd0, 0xd9, 0xa3, 0xf2, 0xe4, 0x75, 0x50, 0x6c, 0xde, 0xe2, 0xd7, 0x12, + 0x04, 0x7e, 0xf7, 0x4d, 0xfe, 0x15, 0x3f, 0xee, 0xec, 0xd1, 0xe4, 0xb3, 0x08, 0x6c, 0xd5, 0xd4, + 0x84, 0x91, 0x03, 0x28, 0xc4, 0x6f, 0x10, 0x88, 0x2e, 0xed, 0x72, 0xef, 0x01, 0x13, 0xfd, 0x68, + 0x8f, 0x2f, 0xf0, 0xb8, 0x66, 0xa3, 0x90, 0x84, 0x54, 0xf2, 0x63, 0x98, 0x49, 0x75, 0x89, 0xab, + 0x3b, 0x90, 0xdd, 0xbd, 0xed, 0xb8, 0x04, 0xc5, 0xb4, 0x26, 0x2f, 0x5c, 0x1a, 0x25, 0xa7, 0x97, + 0x42, 0x1a, 0x30, 0x19, 0x8b, 0x8c, 0x17, 0x2f, 0xcc, 0x64, 0xc7, 0xda, 0xe3, 0xae, 0x49, 0x26, + 0x69, 0x4e, 0x2d, 0x2b, 0x2e, 0x92, 0xac, 0xc1, 0x88, 0xf2, 0x45, 0x89, 0xdc, 0x7c, 0x69, 0x7e, + 0xb7, 0xe2, 0xf1, 0x51, 0x69, 0x3a, 0xf2, 0xbb, 0x19, 0x32, 0x23, 0x01, 0xe4, 0x97, 0xe1, 0xaa, + 0x1a, 0xa2, 0x9b, 0x7e, 0xba, 0x87, 0x52, 0x3c, 0xee, 0x70, 0x33, 0x3e, 0xc2, 0xb3, 0xe8, 0x77, + 0xef, 0x56, 0xf2, 0xc5, 0xdc, 0xca, 0x19, 0xbb, 0xb7, 0x68, 0xf2, 0xab, 0x39, 0x38, 0x97, 0x51, + 0xea, 0x18, 0x96, 0xda, 0xd3, 0x6d, 0x8c, 0x96, 0x27, 0xde, 0xfb, 0x73, 0x1b, 0xd1, 0xfd, 0x58, + 0xe9, 0x3f, 0x36, 0xda, 0x9d, 0x51, 0x12, 0xb9, 0x03, 0xb0, 0xef, 0x86, 0x62, 0x8c, 0x61, 0x9a, + 0xba, 0xe4, 0x07, 0xca, 0xd4, 0xb6, 0xef, 0x86, 0x62, 0xa4, 0xfd, 0x7e, 0xae, 0xe7, 0xbc, 0x8e, + 0xd9, 0xeb, 0x46, 0xe7, 0x5f, 0xed, 0x36, 0xe9, 0x45, 0xd4, 0x95, 0x3b, 0xc7, 0x47, 0xa5, 0x37, + 0x54, 0x0a, 0xb4, 0x3a, 0x52, 0xc9, 0x5b, 0xbe, 0x35, 0x47, 0xd1, 0x19, 0xed, 0xe9, 0xb9, 0xb4, + 0xbc, 0x01, 0x83, 0xe8, 0x99, 0x0a, 0x8a, 0xe3, 0x68, 0xbb, 0x61, 0xe2, 0x2e, 0xf4, 0x5f, 0xe9, + 0xbb, 0x35, 0x41, 0x43, 0x56, 0x98, 0x0d, 0x84, 0xbb, 0x45, 0x69, 0xb3, 0x88, 0x34, 0x7f, 0xc2, + 0x8e, 0xe6, 0x28, 0x99, 0x7f, 0xc7, 0x78, 0x9e, 0xc4, 0x64, 0xab, 0x00, 0x0c, 0xfb, 0x62, 0xba, + 0xbd, 0xdf, 0x3f, 0xdc, 0x5f, 0x18, 0xe0, 0x33, 0x82, 0xbc, 0x4b, 0xf2, 0xeb, 0xc3, 0xfc, 0xe2, + 0xf9, 0x4e, 0xcb, 0x7d, 0xe4, 0x46, 0x33, 0xb3, 0xee, 0xd3, 0x8e, 0xde, 0x09, 0x13, 0x16, 0x67, + 0xc6, 0x8b, 0x60, 0xca, 0xfd, 0x9d, 0xef, 0xe9, 0xfe, 0x7e, 0x53, 0x3b, 0x28, 0xd6, 0xd2, 0xf9, + 0x72, 0xcb, 0xc2, 0x74, 0x37, 0x47, 0x27, 0xc8, 0x5f, 0xc3, 0x20, 0x66, 0xe0, 0xe5, 0xa7, 0xf0, + 0xa3, 0xf3, 0xb7, 0x44, 0x77, 0x76, 0xa9, 0x3e, 0x4f, 0xd9, 0x2b, 0x92, 0x49, 0x70, 0x8d, 0x23, + 0xc0, 0xd0, 0x38, 0x42, 0xc8, 0x36, 0x4c, 0x6d, 0xb1, 0x8d, 0x2e, 0xbf, 0xd1, 0xd0, 0xf6, 0x85, + 0x4b, 0x90, 0x3b, 0x1b, 0x71, 0xa3, 0xdd, 0x96, 0xe8, 0x1a, 0x55, 0x78, 0x7d, 0xaf, 0x99, 0xc2, + 0x4e, 0x96, 0x60, 0xa2, 0x4a, 0x1d, 0xbf, 0x7e, 0xf0, 0x80, 0x3e, 0x63, 0x46, 0x86, 0xf1, 0x34, + 0x4e, 0x80, 0x18, 0xd6, 0x5e, 0x44, 0xe9, 0x91, 0x55, 0x26, 0x13, 0xf9, 0x14, 0x06, 0xab, 0x9e, + 0x1f, 0x56, 0x9e, 0x89, 0xd9, 0x5a, 0x9e, 0xd3, 0x72, 0x60, 0xe5, 0xbc, 0x7c, 0x1e, 0x28, 0xf0, + 0xfc, 0xb0, 0xb6, 0x67, 0x64, 0x82, 0xe3, 0x24, 0xe4, 0x19, 0x4c, 0x9b, 0x33, 0xa5, 0x08, 0xb4, + 0x1f, 0x16, 0xc6, 0x4d, 0xda, 0x74, 0xcc, 0x49, 0x2a, 0x37, 0x84, 0xf4, 0x2b, 0xf1, 0xf9, 0xf8, + 0x11, 0xe2, 0x75, 0x8b, 0x20, 0x8d, 0x9f, 0xac, 0xe3, 0xbb, 0x4a, 0xbc, 0x45, 0xe5, 0x80, 0x07, + 0xe8, 0x8f, 0x44, 0xb9, 0x06, 0x3b, 0x38, 0xdb, 0xa2, 0x26, 0x9c, 0x20, 0xfe, 0x18, 0x97, 0x9d, + 0x60, 0x25, 0x5b, 0x70, 0x76, 0x27, 0xa0, 0x5b, 0x3e, 0x7d, 0xe2, 0xd2, 0xa7, 0x52, 0x1e, 0x44, + 0x89, 0xd9, 0x98, 0xbc, 0x36, 0xc7, 0xa6, 0x09, 0x4c, 0x32, 0x93, 0xf7, 0x00, 0xb6, 0xdc, 0x56, + 0x8b, 0x36, 0xf0, 0xb0, 0x7f, 0x14, 0x45, 0xe1, 0x41, 0x46, 0x1b, 0xa1, 0x35, 0xaf, 0xd5, 0xd4, + 0x55, 0xaa, 0x11, 0x93, 0x0a, 0x8c, 0xaf, 0xb6, 0xea, 0xcd, 0x8e, 0x08, 0xca, 0x09, 0x70, 0xa6, + 0x14, 0x09, 0x23, 0x5d, 0x8e, 0xa8, 0x25, 0x3e, 0x72, 0x93, 0x85, 0x3c, 0x00, 0x22, 0x00, 0x62, + 0xd4, 0x3a, 0x7b, 0x4d, 0x2a, 0x3e, 0x77, 0x74, 0x50, 0x4a, 0x41, 0x38, 0xdc, 0x8d, 0x3c, 0x8c, + 0x09, 0xb6, 0xb9, 0xf7, 0x60, 0x54, 0x1b, 0xf3, 0x29, 0xd9, 0x51, 0xa6, 0xf5, 0xec, 0x28, 0x23, + 0x7a, 0x16, 0x94, 0x7f, 0x9a, 0x83, 0x8b, 0xe9, 0xdf, 0x92, 0xb0, 0x4d, 0x36, 0x61, 0x44, 0x01, + 0xd5, 0x7d, 0x38, 0x69, 0x70, 0xc7, 0xb6, 0x76, 0xfc, 0x83, 0x96, 0x33, 0x8f, 0xde, 0xfa, 0x48, + 0xc6, 0x73, 0x9c, 0x82, 0xfd, 0xed, 0x61, 0x98, 0xc6, 0x7b, 0x1f, 0xf1, 0x79, 0xea, 0x13, 0xcc, + 0x72, 0x84, 0x30, 0xed, 0x50, 0x47, 0xf8, 0x77, 0x39, 0x3c, 0x9e, 0xef, 0xcf, 0x60, 0x20, 0x6f, + 0xeb, 0x91, 0x48, 0x79, 0xed, 0x1d, 0x27, 0x09, 0xd4, 0x9b, 0x10, 0x85, 0x28, 0xbd, 0x6e, 0x04, + 0xc2, 0x9c, 0x78, 0xd2, 0xeb, 0x3f, 0xe9, 0xa4, 0xb7, 0xa3, 0x26, 0x3d, 0x9e, 0x3d, 0xe7, 0x35, + 0x6d, 0xd2, 0x7b, 0xf9, 0xb3, 0xdd, 0xe0, 0xcb, 0x9e, 0xed, 0x86, 0x5e, 0x6c, 0xb6, 0x1b, 0x7e, + 0xce, 0xd9, 0xee, 0x1e, 0x4c, 0x6c, 0x50, 0xda, 0xd0, 0x8e, 0x27, 0x47, 0xa2, 0xd5, 0xb3, 0x45, + 0xd1, 0xf1, 0x9c, 0x76, 0x46, 0x19, 0xe3, 0xca, 0x9c, 0x35, 0xe1, 0x6f, 0x66, 0xd6, 0x1c, 0x7d, + 0xc9, 0xb3, 0xe6, 0xd8, 0x8b, 0xcc, 0x9a, 0x89, 0xa9, 0x6f, 0xfc, 0xd4, 0x53, 0xdf, 0x8b, 0xcc, + 0x56, 0xff, 0x38, 0x0f, 0xb3, 0xec, 0x03, 0x68, 0x3e, 0xa1, 0xd5, 0xea, 0x8a, 0x08, 0xe0, 0x8a, + 0x02, 0xa5, 0x0e, 0xbc, 0x40, 0xde, 0x75, 0xc0, 0xbf, 0x19, 0xac, 0xed, 0xf9, 0x32, 0xd8, 0x04, + 0xff, 0x26, 0x15, 0x18, 0xe4, 0x5f, 0x48, 0xb1, 0xcf, 0x48, 0x4d, 0x95, 0x21, 0x57, 0xff, 0xbe, + 0x6c, 0xc1, 0x49, 0xee, 0xc2, 0x74, 0xda, 0xa7, 0x22, 0xdc, 0x18, 0x53, 0xed, 0x94, 0xcf, 0xe4, + 0x35, 0x98, 0x8c, 0x7d, 0x0c, 0xfc, 0xd9, 0x17, 0x7b, 0x22, 0x30, 0x3e, 0x84, 0x17, 0x51, 0xcf, + 0x02, 0x14, 0x93, 0xad, 0x10, 0xf3, 0xf8, 0x6b, 0x20, 0x6e, 0x78, 0x0b, 0x6b, 0x3b, 0xbe, 0xbf, + 0xb6, 0x05, 0xda, 0xfa, 0x18, 0x83, 0xa5, 0x95, 0x80, 0x40, 0xd3, 0xef, 0x8a, 0xa6, 0xdf, 0x15, + 0xa1, 0xdf, 0x2d, 0x4d, 0xbf, 0xec, 0x6f, 0xab, 0x82, 0x21, 0xd2, 0x3a, 0xbf, 0xba, 0x73, 0x35, + 0x24, 0x2e, 0x6c, 0x8b, 0x75, 0x24, 0x51, 0x05, 0x89, 0xb7, 0xfe, 0x3c, 0xc7, 0xc3, 0x2d, 0xfe, + 0x6f, 0x5c, 0x8e, 0x5e, 0x24, 0x04, 0xe2, 0xd7, 0xa2, 0x44, 0x2e, 0x22, 0xe9, 0x8c, 0xef, 0xd4, + 0x1f, 0x47, 0x31, 0x28, 0xdf, 0x67, 0x73, 0xa9, 0x8e, 0x10, 0xc6, 0xd0, 0xac, 0xd2, 0x94, 0x8e, + 0xdc, 0xbd, 0x2b, 0x27, 0x59, 0x91, 0xcf, 0x86, 0x83, 0xcd, 0x49, 0x56, 0x67, 0xc0, 0x28, 0xe0, + 0x49, 0xcb, 0xe6, 0x79, 0x48, 0x52, 0x6b, 0xf0, 0x4e, 0x32, 0x93, 0x06, 0x5a, 0xb2, 0x51, 0x26, + 0x0d, 0x5d, 0x8d, 0x51, 0x4e, 0x8d, 0x1d, 0xb8, 0x60, 0xd3, 0x43, 0xef, 0x09, 0x7d, 0xb9, 0x62, + 0xbf, 0x82, 0xf3, 0xa6, 0x40, 0x7e, 0xe7, 0x92, 0x3f, 0x10, 0xf2, 0x71, 0xfa, 0xb3, 0x22, 0x82, + 0x81, 0x3f, 0x2b, 0xc2, 0x5f, 0x27, 0x60, 0x7f, 0xea, 0x6b, 0x33, 0xe2, 0x2c, 0x0f, 0x2e, 0x9a, + 0xc2, 0xcb, 0x8d, 0x06, 0xbe, 0x4c, 0x5c, 0x77, 0xdb, 0x4e, 0x2b, 0x24, 0x9b, 0x30, 0xaa, 0xfd, + 0x8c, 0xf9, 0x99, 0x34, 0x8c, 0xd8, 0x37, 0x46, 0x00, 0x23, 0xbb, 0x73, 0x04, 0xb6, 0x28, 0x94, + 0xe2, 0xea, 0x61, 0x2a, 0xd3, 0xcb, 0xac, 0xc0, 0xb8, 0xf6, 0x53, 0x1d, 0xc6, 0xe0, 0x04, 0xab, + 0x95, 0x60, 0x2a, 0xcc, 0x64, 0xb1, 0xea, 0x30, 0x97, 0xa6, 0x34, 0xfe, 0x0c, 0x00, 0x59, 0x8a, + 0xb2, 0xfc, 0xf5, 0x8e, 0x23, 0x9e, 0xcc, 0xca, 0xf0, 0x67, 0xfd, 0x83, 0x7e, 0xb8, 0x20, 0x3a, + 0xe3, 0x65, 0xf6, 0x38, 0xf9, 0x01, 0x8c, 0x6a, 0x7d, 0x2c, 0x94, 0x7e, 0x45, 0xde, 0x98, 0xcc, + 0x1a, 0x0b, 0xdc, 0x1f, 0xd6, 0x41, 0x40, 0x2d, 0xd6, 0xdd, 0x2b, 0x67, 0x6c, 0x5d, 0x24, 0x69, + 0xc2, 0x84, 0xd9, 0xd1, 0xc2, 0x25, 0x78, 0x2d, 0xb5, 0x10, 0x93, 0x54, 0xbe, 0x11, 0xd0, 0xa8, + 0xa5, 0x76, 0xf7, 0xca, 0x19, 0x3b, 0x26, 0x9b, 0x7c, 0x03, 0x67, 0x13, 0xbd, 0x2c, 0xfc, 0xbd, + 0xaf, 0xa6, 0x16, 0x98, 0xa0, 0xe6, 0x07, 0x4d, 0x3e, 0x82, 0x33, 0x8b, 0x4d, 0x16, 0x42, 0x1a, + 0x30, 0xa6, 0x77, 0xbc, 0xf0, 0x59, 0x5e, 0xed, 0xa2, 0x4a, 0x4e, 0xc8, 0x37, 0xd0, 0x42, 0x97, + 0xd8, 0xf7, 0xcf, 0xcc, 0xc3, 0x33, 0x83, 0x78, 0x18, 0x06, 0xf9, 0x6f, 0xeb, 0x0f, 0x72, 0x70, + 0x61, 0xcb, 0xa7, 0x01, 0x6d, 0xd5, 0xa9, 0x71, 0xf7, 0xe4, 0x05, 0x47, 0x44, 0xd6, 0xb9, 0x55, + 0xfe, 0x85, 0xcf, 0xad, 0xac, 0x7f, 0x93, 0x83, 0x62, 0x5a, 0x95, 0xab, 0xb4, 0xd5, 0x20, 0x5b, + 0x50, 0x88, 0xb7, 0x41, 0x7c, 0x31, 0x96, 0x4a, 0xf1, 0x9e, 0xd9, 0xda, 0x95, 0x33, 0x76, 0x82, + 0x9b, 0x6c, 0xc0, 0x59, 0x0d, 0x26, 0xce, 0x8d, 0xf2, 0x27, 0x39, 0x37, 0x62, 0x3d, 0x9c, 0x60, + 0xd5, 0x8f, 0xdd, 0x56, 0x70, 0xd5, 0x5d, 0xf4, 0x0e, 0x1d, 0xb7, 0xc5, 0x0c, 0x15, 0x2d, 0x89, + 0x20, 0x44, 0x50, 0xa1, 0x76, 0x7e, 0x90, 0x84, 0x50, 0x79, 0x0d, 0x4f, 0x91, 0x58, 0x1f, 0xe2, + 0xea, 0x20, 0x9c, 0xc7, 0x3c, 0xf1, 0x81, 0x12, 0x76, 0x05, 0x06, 0xb6, 0xd7, 0xaa, 0x0b, 0x65, + 0x91, 0x46, 0x81, 0x27, 0xdf, 0x69, 0x06, 0xb5, 0xba, 0x63, 0x73, 0x84, 0xf5, 0x01, 0x90, 0x65, + 0x1a, 0x8a, 0x37, 0x46, 0x14, 0xdf, 0x75, 0x18, 0x12, 0x20, 0xc1, 0x89, 0x47, 0x22, 0xe2, 0xc5, + 0x12, 0x5b, 0xe2, 0xac, 0x2d, 0x69, 0xe7, 0x35, 0xa9, 0x13, 0x68, 0x8b, 0xfe, 0xbb, 0x30, 0xec, + 0x0b, 0x98, 0x58, 0xf3, 0x27, 0xd4, 0x13, 0x52, 0x08, 0xe6, 0x47, 0x75, 0x92, 0xc6, 0x56, 0x7f, + 0x59, 0x6b, 0x98, 0x28, 0x6b, 0x73, 0x75, 0x71, 0x81, 0x69, 0x55, 0x28, 0x4b, 0x76, 0xc7, 0x6d, + 0xbc, 0x79, 0x13, 0x52, 0x3d, 0x89, 0x02, 0xaa, 0x06, 0x27, 0x10, 0x91, 0x1e, 0x4e, 0x23, 0xb1, + 0xde, 0x54, 0x69, 0xb7, 0x52, 0xa4, 0x65, 0x3d, 0x85, 0xb4, 0x81, 0x09, 0xc5, 0x96, 0x31, 0xc8, + 0xf0, 0x65, 0x54, 0xc2, 0x81, 0x39, 0xbe, 0x85, 0x60, 0xad, 0x12, 0x0f, 0xc1, 0x7a, 0x6a, 0xda, + 0x5d, 0x80, 0x11, 0x05, 0x53, 0x11, 0x03, 0x5c, 0x57, 0x06, 0xfd, 0xee, 0x9b, 0x3c, 0xdf, 0x44, + 0x5d, 0x09, 0x88, 0xf8, 0x58, 0x11, 0xfc, 0x9b, 0xfe, 0x96, 0x8b, 0x08, 0xa8, 0x1f, 0x7e, 0xab, + 0x45, 0x44, 0x19, 0xe7, 0x4e, 0x53, 0x84, 0x41, 0xbf, 0x3b, 0x7f, 0x12, 0x45, 0x7d, 0xcb, 0x45, + 0x30, 0x45, 0x7d, 0x7b, 0x45, 0x50, 0x99, 0x9a, 0x8f, 0x0f, 0xd2, 0x44, 0x21, 0x4b, 0xc9, 0x42, + 0xe4, 0x89, 0x4a, 0x8c, 0xa3, 0x6b, 0x7f, 0x50, 0xb8, 0xc8, 0x95, 0xf5, 0x73, 0x28, 0x86, 0x29, + 0xec, 0xdb, 0x2d, 0xe6, 0x77, 0x72, 0x3c, 0x51, 0x60, 0x75, 0x53, 0x7b, 0x82, 0xb9, 0xf5, 0xc8, 0xd3, 0x02, 0x9a, 0xb4, 0xaf, 0x5d, 0x3b, 0x60, 0xc6, 0x80, 0x26, 0xa7, 0x13, 0x1e, 0xa8, 0x44, 0xfa, 0x78, 0xda, 0x1c, 0xa7, 0x26, 0xef, 0xc1, 0xb8, 0x06, 0x52, 0x3b, 0x41, 0xfe, 0xd4, 0x91, 0xce, 0xee, 0x36, 0x6c, 0x93, 0xd2, 0xfa, 0xeb, 0x1c, 0x4c, 0x55, 0x9f, 0x05, 0x21, 0x3d, 0xc4, @@ -16996,7 +16996,7 @@ var fileDescriptor_0ffcffcda38ae159 = []byte{ 0xe5, 0x96, 0x7a, 0x21, 0x77, 0xb3, 0x22, 0x1f, 0x11, 0xd7, 0xbe, 0x73, 0x32, 0x0a, 0x43, 0x8b, 0x4b, 0xf7, 0xca, 0x3b, 0x6b, 0xdb, 0x85, 0x33, 0xec, 0xc7, 0x82, 0xbd, 0x54, 0xde, 0x5e, 0x5a, 0x2c, 0xe4, 0xc8, 0x08, 0x0c, 0x54, 0xb7, 0xcb, 0xdb, 0x4b, 0x85, 0x3c, 0x19, 0x86, 0xfe, 0x9d, - 0xea, 0x92, 0x5d, 0xe8, 0x9b, 0xff, 0xad, 0xdf, 0xcd, 0x71, 0x47, 0xa3, 0xbc, 0xcc, 0xf7, 0xb5, + 0xea, 0x92, 0x5d, 0xe8, 0x9b, 0xff, 0x9d, 0xdf, 0xcd, 0x71, 0x47, 0xa3, 0xbc, 0xcc, 0xf7, 0xb5, 0x66, 0x50, 0x8a, 0x29, 0x4f, 0xbc, 0x98, 0x9c, 0x69, 0x3d, 0xe2, 0x2e, 0x60, 0xae, 0xcb, 0xe1, 0x0e, 0x12, 0xdc, 0xc8, 0xdd, 0xc9, 0x11, 0x1b, 0x83, 0x61, 0x62, 0xf6, 0x95, 0x92, 0x9c, 0x6e, 0x02, 0xcf, 0x5d, 0xea, 0x6a, 0x96, 0x91, 0x5f, 0x02, 0x4b, 0x97, 0x99, 0x61, 0x85, 0x7c, 0xf7, @@ -17134,100 +17134,100 @@ var fileDescriptor_0ffcffcda38ae159 = []byte{ 0x66, 0x76, 0x5d, 0x45, 0x3a, 0xdd, 0x4e, 0x50, 0x83, 0x93, 0x38, 0xdb, 0x4e, 0xa2, 0x89, 0x6c, 0xcf, 0x14, 0x5b, 0x0e, 0xb7, 0xfd, 0x4e, 0x10, 0xd2, 0x46, 0xd2, 0xa3, 0x64, 0x56, 0x46, 0x46, 0x46, 0x98, 0xe4, 0xbb, 0xf3, 0x64, 0x15, 0xe7, 0x36, 0x13, 0xdc, 0xcd, 0xe5, 0x96, 0x2e, 0x06, - 0xa7, 0x9e, 0x15, 0x75, 0xad, 0xc7, 0xac, 0x53, 0x56, 0xd9, 0xd9, 0x95, 0x52, 0x2a, 0x3a, 0x61, - 0xeb, 0xb2, 0x54, 0xf4, 0x01, 0x86, 0x01, 0x70, 0xf7, 0x5f, 0x2f, 0xcd, 0xc4, 0x2f, 0x1a, 0x91, - 0x4f, 0x61, 0x44, 0x32, 0xf7, 0x56, 0x48, 0x9c, 0x1b, 0x15, 0xb2, 0x08, 0xe3, 0xc6, 0x2d, 0x2a, - 0x65, 0xdd, 0xa4, 0xdd, 0xad, 0xea, 0xd2, 0xcf, 0xe3, 0xc6, 0x6d, 0x29, 0x25, 0x25, 0xed, 0x0e, - 0x55, 0xa6, 0x94, 0x8f, 0x60, 0x54, 0xa8, 0xb4, 0xab, 0x36, 0xb2, 0xfd, 0x6d, 0x33, 0x5a, 0x44, - 0x72, 0xa7, 0xe1, 0x86, 0x0b, 0x5e, 0xeb, 0x91, 0xbb, 0xdf, 0x53, 0x31, 0x49, 0x96, 0xdd, 0x79, - 0xf2, 0x15, 0x3e, 0x2b, 0x2f, 0x1f, 0xfb, 0xa7, 0xe1, 0x53, 0xcf, 0x7f, 0xec, 0xb6, 0xf6, 0x7b, - 0x88, 0xbc, 0x62, 0x8a, 0x8c, 0xf3, 0xc9, 0xd8, 0x91, 0xaf, 0x60, 0xae, 0x9a, 0x2d, 0xbc, 0xa7, - 0x90, 0xee, 0xcb, 0x4b, 0x15, 0x2e, 0x62, 0xf4, 0xcc, 0x69, 0xeb, 0xde, 0x55, 0xe8, 0x17, 0x3c, - 0x61, 0xa3, 0xf4, 0xd5, 0xd7, 0x3d, 0xbf, 0xd1, 0x5b, 0x62, 0xc9, 0x0c, 0xa4, 0x8d, 0xb1, 0x49, - 0x65, 0x7c, 0x01, 0xe7, 0xab, 0x99, 0xa2, 0x7b, 0x89, 0xe8, 0xb5, 0x93, 0xbc, 0x80, 0xaa, 0x38, - 0x65, 0xbd, 0xbb, 0xca, 0x5c, 0xc5, 0x39, 0x8d, 0xad, 0x43, 0x5b, 0x3e, 0x7d, 0x44, 0x7d, 0x0c, - 0xd7, 0xee, 0x15, 0xa8, 0x6c, 0x92, 0xcb, 0x96, 0xaf, 0xc2, 0xd9, 0x6a, 0x42, 0x54, 0x16, 0x4b, - 0xaf, 0xf3, 0x9f, 0x29, 0x6c, 0xe9, 0x09, 0xeb, 0xd5, 0x23, 0x4a, 0x68, 0x74, 0x99, 0x86, 0x3b, - 0xab, 0x3d, 0xb4, 0x24, 0xef, 0x13, 0x48, 0xc2, 0xdd, 0xbb, 0x8c, 0xb3, 0xaa, 0x71, 0x26, 0x29, - 0x32, 0x3f, 0xde, 0x4f, 0xe5, 0x59, 0x48, 0xcf, 0x62, 0xb3, 0x24, 0xbc, 0x89, 0x73, 0xa1, 0x08, - 0x59, 0x9e, 0x8d, 0xb6, 0x00, 0x1c, 0x12, 0xb9, 0xea, 0xb4, 0xe8, 0xe5, 0x80, 0x94, 0xb9, 0xf9, - 0xc7, 0x87, 0x87, 0x80, 0x5d, 0x4e, 0x84, 0xb2, 0x77, 0x15, 0xc1, 0xbd, 0xa0, 0x6b, 0x5e, 0xfd, - 0xb1, 0xee, 0x05, 0x65, 0xbf, 0xe3, 0xee, 0x41, 0x06, 0xdb, 0x9d, 0x17, 0x33, 0x3e, 0xfb, 0x61, - 0x04, 0x7e, 0x21, 0x20, 0x9a, 0xf1, 0xe3, 0x70, 0xe1, 0x41, 0x7a, 0x53, 0xfa, 0x16, 0xb1, 0x40, - 0x53, 0x72, 0xa6, 0x6a, 0x94, 0x5b, 0x11, 0x99, 0x4c, 0xb7, 0xa2, 0x5e, 0xd1, 0x6c, 0x5f, 0x3e, - 0xb1, 0x69, 0xbb, 0x89, 0x51, 0xd0, 0x87, 0x1e, 0xe7, 0x89, 0x02, 0x63, 0x93, 0xa8, 0xde, 0xf1, - 0x5b, 0x53, 0x22, 0xea, 0xc7, 0x50, 0xbc, 0x4a, 0xa8, 0x9c, 0xc4, 0x45, 0xaa, 0xd4, 0x83, 0x91, - 0xee, 0xe4, 0xc8, 0x06, 0x9c, 0x5b, 0xa6, 0xa1, 0x98, 0xe3, 0x6c, 0x1a, 0x84, 0xbe, 0x5b, 0x0f, - 0xbb, 0x1e, 0x0c, 0x4a, 0xdb, 0x24, 0x85, 0x67, 0xf7, 0x2d, 0x26, 0xaf, 0x9a, 0x2e, 0xaf, 0x2b, - 0x5f, 0x97, 0x10, 0x59, 0x71, 0xda, 0x70, 0x9a, 0x2a, 0x66, 0x0f, 0xf1, 0x21, 0x1e, 0x81, 0x93, - 0xcd, 0x5a, 0x88, 0xb2, 0x9f, 0x08, 0x6b, 0xeb, 0x16, 0x0c, 0x72, 0xa6, 0xcc, 0x05, 0x75, 0x4c, - 0xe7, 0x21, 0x77, 0x61, 0x44, 0x85, 0xd0, 0x10, 0x03, 0x95, 0x59, 0xaf, 0xbb, 0x30, 0xc2, 0x4d, - 0xab, 0x93, 0xb3, 0x7c, 0x00, 0x23, 0x2a, 0xe6, 0xe6, 0xd4, 0x2b, 0xfd, 0x27, 0x30, 0xae, 0x47, - 0xdf, 0x9c, 0x5e, 0x91, 0x1f, 0xe1, 0xf1, 0xad, 0x3c, 0x25, 0xc9, 0xe6, 0x9f, 0x89, 0x25, 0x85, - 0x11, 0x2a, 0xe5, 0x13, 0xa4, 0x04, 0x66, 0x56, 0xff, 0x6c, 0x82, 0x9b, 0x7c, 0x20, 0x6f, 0x32, - 0x29, 0xe6, 0x24, 0x51, 0x17, 0x9d, 0x4d, 0x70, 0x35, 0x3f, 0x0f, 0xb3, 0x9a, 0x60, 0x7b, 0x56, - 0xfb, 0x24, 0xc7, 0xcc, 0xbd, 0x55, 0x97, 0x25, 0x65, 0x13, 0x77, 0x69, 0x89, 0x87, 0x18, 0xb3, - 0x05, 0x5d, 0xce, 0x7e, 0xbb, 0x11, 0x3b, 0xe3, 0x3e, 0x5a, 0x81, 0x09, 0x6c, 0x66, 0xf3, 0xba, - 0xbc, 0x05, 0x19, 0x99, 0xbd, 0x49, 0x71, 0x5d, 0xd8, 0xba, 0x59, 0xd1, 0xe2, 0x7e, 0xe6, 0x4b, - 0x11, 0xb7, 0x2a, 0x83, 0x18, 0x4f, 0xde, 0xd8, 0xec, 0x9a, 0x5d, 0x48, 0x39, 0xd8, 0xee, 0xd9, - 0x17, 0x59, 0xe2, 0x7e, 0x01, 0x77, 0x87, 0xa9, 0x59, 0xc1, 0xb2, 0x85, 0xdd, 0xd0, 0x62, 0x23, - 0x52, 0x39, 0xd5, 0xa2, 0xf7, 0x18, 0xaf, 0x88, 0xa5, 0x3f, 0x55, 0xf9, 0x6a, 0x0f, 0x29, 0x52, - 0x13, 0xaf, 0xf5, 0xa4, 0x53, 0xc7, 0xa4, 0x17, 0xf8, 0x0a, 0x9b, 0x5e, 0x5e, 0x8f, 0xa7, 0x37, - 0x53, 0x4e, 0xae, 0x55, 0x84, 0x68, 0xba, 0x40, 0x33, 0x42, 0xb4, 0x6b, 0x1b, 0xb2, 0xd4, 0xff, - 0x19, 0x94, 0xa2, 0x00, 0x90, 0xd3, 0x75, 0x42, 0x76, 0x60, 0x22, 0x49, 0x68, 0x2a, 0x20, 0xdd, - 0x9e, 0x6c, 0x9a, 0xbb, 0x9a, 0xa5, 0x61, 0xfd, 0x1a, 0x8c, 0x08, 0x6c, 0x8b, 0x3d, 0xda, 0x9a, - 0xf5, 0xfc, 0x6b, 0x17, 0x3f, 0xac, 0xb8, 0x33, 0xf7, 0x52, 0x04, 0x25, 0x7b, 0xfb, 0xf4, 0x82, - 0x54, 0x7c, 0x46, 0x4c, 0x90, 0xd5, 0xa5, 0x7b, 0x7b, 0x1f, 0x3d, 0x16, 0x33, 0xfa, 0xf5, 0xf4, - 0x1d, 0xea, 0x44, 0xf7, 0xc4, 0x62, 0x49, 0x04, 0xf5, 0xbb, 0xb9, 0x49, 0x54, 0xfc, 0x92, 0x53, - 0x1a, 0x85, 0x0a, 0x8a, 0x2a, 0xca, 0x22, 0x18, 0x9c, 0x99, 0x22, 0x9e, 0xef, 0x86, 0xcf, 0x16, - 0xec, 0xb5, 0xc8, 0xad, 0xa0, 0x23, 0xa4, 0x6c, 0x90, 0x48, 0x7b, 0x8d, 0x7c, 0x89, 0x53, 0x89, - 0x10, 0x5f, 0xf1, 0xbc, 0x30, 0x08, 0x7d, 0xa7, 0x5d, 0xc5, 0xc7, 0xac, 0x33, 0x1b, 0x1d, 0xc5, - 0x70, 0xa7, 0xb1, 0x69, 0x21, 0xa5, 0x22, 0x8f, 0x7d, 0x5a, 0xe6, 0x1b, 0x75, 0xad, 0x26, 0x0d, - 0xd9, 0xc5, 0x72, 0xa9, 0xca, 0xcc, 0xf5, 0x2f, 0x53, 0x68, 0x0d, 0x66, 0x33, 0xf2, 0x05, 0xa9, - 0xd3, 0xdb, 0xee, 0xf9, 0x84, 0xe6, 0xba, 0x17, 0x4c, 0xbe, 0x82, 0x99, 0xd4, 0x84, 0x42, 0xca, - 0x03, 0xdd, 0x2d, 0xdd, 0x50, 0x2f, 0xe1, 0x8f, 0xa1, 0xc8, 0x2f, 0x74, 0x60, 0xdc, 0xb2, 0x91, - 0x5b, 0x26, 0xba, 0xe6, 0x93, 0x41, 0x10, 0x9f, 0xaf, 0xb3, 0xe9, 0xd4, 0x65, 0xf3, 0x69, 0x4c, - 0x2a, 0x22, 0x5f, 0xdf, 0xa6, 0x75, 0xef, 0x09, 0xf5, 0x9f, 0xa9, 0x0f, 0x2f, 0x0d, 0xd9, 0xed, - 0x2e, 0xd1, 0x16, 0xcc, 0xec, 0x52, 0xdf, 0x7d, 0xf4, 0x2c, 0x2e, 0x50, 0x6a, 0x26, 0x15, 0xdb, - 0x4d, 0xe2, 0xe7, 0x30, 0xbb, 0xe0, 0x1d, 0xb6, 0xc5, 0xad, 0x3d, 0x43, 0xa6, 0x3a, 0x8a, 0x4f, - 0xc7, 0xf7, 0x8e, 0x65, 0x9a, 0x53, 0xd7, 0x0a, 0x75, 0xbe, 0x05, 0xbc, 0xce, 0x7a, 0xc3, 0x0c, - 0x27, 0x48, 0x21, 0x89, 0x2e, 0x63, 0x48, 0x53, 0x4e, 0xe7, 0xdf, 0xc6, 0x41, 0x18, 0xe3, 0xe3, - 0xbe, 0x39, 0x6d, 0x10, 0xa6, 0xe1, 0xbb, 0xdf, 0x01, 0x4b, 0x91, 0xca, 0x0b, 0xcc, 0x96, 0x7a, - 0x82, 0xda, 0x6e, 0xc8, 0xb5, 0x65, 0xcb, 0x77, 0x9f, 0xb8, 0x4d, 0xba, 0x2f, 0xdc, 0x88, 0x66, - 0xd0, 0xb4, 0x89, 0xec, 0x56, 0x4f, 0x2d, 0xab, 0x42, 0xb3, 0xd9, 0x65, 0x8b, 0x45, 0xf4, 0xb4, - 0x0a, 0x8c, 0x12, 0x9d, 0xf8, 0xe3, 0x3a, 0x6f, 0xb7, 0xd9, 0x3a, 0xc1, 0x8c, 0x9b, 0xda, 0xf7, - 0x61, 0xac, 0xaa, 0x17, 0x9e, 0x52, 0x48, 0xe6, 0xa0, 0x50, 0xb7, 0x80, 0x7a, 0xd7, 0xbd, 0x4b, - 0x2c, 0xa8, 0x5a, 0x78, 0x4e, 0xd4, 0x8a, 0xcc, 0xd0, 0x19, 0xe3, 0xed, 0x39, 0xb5, 0x0a, 0xa4, - 0x3d, 0xbf, 0xa9, 0x42, 0x67, 0xd2, 0x9f, 0xab, 0xab, 0xf1, 0x17, 0x6d, 0xe2, 0xaf, 0xab, 0x12, - 0xab, 0xf7, 0x33, 0xc6, 0x2a, 0x26, 0xbe, 0xeb, 0xf3, 0xac, 0x3c, 0xce, 0x27, 0x7a, 0x6d, 0x4f, - 0x8f, 0xf3, 0x49, 0xbc, 0xe1, 0xa7, 0xc7, 0xf9, 0xa4, 0x3c, 0xd0, 0x57, 0x85, 0x42, 0xfc, 0xf9, - 0x40, 0xe5, 0x56, 0xca, 0x78, 0x1d, 0x51, 0x45, 0xf4, 0x64, 0xbe, 0x3b, 0xb8, 0x84, 0x15, 0x8c, - 0xde, 0x17, 0xea, 0xe2, 0xe1, 0x50, 0x75, 0x4b, 0x79, 0xc6, 0xe8, 0x81, 0x9e, 0xf1, 0x83, 0xbf, - 0x4a, 0xd4, 0xc5, 0x81, 0x1b, 0xcf, 0xf4, 0x11, 0x7b, 0xc6, 0xe8, 0x1e, 0x14, 0xf8, 0x03, 0x0d, - 0x51, 0xa2, 0xc4, 0x28, 0x9e, 0x30, 0xf9, 0x6e, 0x44, 0x97, 0x91, 0x52, 0x88, 0xa7, 0x97, 0x53, - 0x0a, 0xcb, 0xc8, 0x3b, 0xd7, 0x65, 0xfc, 0x43, 0x94, 0x44, 0x4e, 0x79, 0xbb, 0x12, 0x79, 0xe5, - 0xe6, 0xce, 0xa7, 0x60, 0xd4, 0x3e, 0x75, 0x4c, 0x4f, 0x39, 0xa7, 0x9a, 0x94, 0x92, 0x87, 0x6e, - 0xee, 0x42, 0x2a, 0x4e, 0x08, 0x0a, 0xf9, 0xf3, 0xe0, 0xe9, 0xaf, 0xb5, 0x47, 0xb7, 0xc3, 0xba, - 0xd0, 0xc8, 0x62, 0x6e, 0x9e, 0x84, 0x54, 0x94, 0x4a, 0xd5, 0xeb, 0x4a, 0x29, 0x4f, 0xc4, 0xbf, - 0x96, 0x72, 0x81, 0xc3, 0xa0, 0x88, 0x06, 0x64, 0xf7, 0xf7, 0xea, 0xc9, 0x43, 0xf9, 0xda, 0x4d, - 0x46, 0x49, 0xbd, 0x04, 0x64, 0xf6, 0xe0, 0x43, 0xf9, 0xbe, 0xcd, 0xcb, 0x16, 0xbc, 0x07, 0x17, - 0x63, 0xb7, 0x42, 0x4c, 0xc1, 0x37, 0xd3, 0xaf, 0x8e, 0xa4, 0xaa, 0x27, 0xdb, 0x10, 0xb8, 0x92, - 0xbc, 0x3d, 0x12, 0xeb, 0xf7, 0xd3, 0x4e, 0xa4, 0xeb, 0x30, 0x81, 0x73, 0x57, 0x40, 0xfd, 0x65, - 0xdf, 0xeb, 0xb4, 0xa3, 0x84, 0x33, 0x26, 0x38, 0x9e, 0xf9, 0x28, 0x8e, 0x55, 0x97, 0xd2, 0xc7, - 0xc4, 0x4d, 0x63, 0x44, 0xe8, 0x89, 0x70, 0x14, 0x30, 0x6d, 0x69, 0x44, 0xc4, 0xee, 0x5d, 0xf2, - 0x11, 0x4c, 0x46, 0x17, 0x90, 0xb9, 0x88, 0x14, 0xb2, 0x2e, 0xde, 0xb7, 0xc9, 0xe8, 0x16, 0xf2, - 0xe9, 0xd9, 0x57, 0xe4, 0xfa, 0x16, 0xb1, 0x5f, 0x4a, 0xdc, 0xa1, 0x31, 0xda, 0x70, 0x92, 0x65, - 0x4e, 0xd3, 0xed, 0x69, 0x7b, 0xa7, 0x8e, 0x9f, 0x5b, 0x7a, 0x2e, 0x45, 0xfd, 0x73, 0xeb, 0x9a, - 0xef, 0x51, 0xed, 0xa9, 0x33, 0xe4, 0xac, 0xc3, 0x35, 0xcc, 0xbf, 0xb2, 0xc5, 0x33, 0xee, 0xa5, - 0x53, 0x65, 0xd7, 0x3d, 0x9e, 0xb5, 0xa5, 0x09, 0x57, 0x7b, 0x26, 0x93, 0x24, 0xb7, 0x8d, 0xb8, - 0x99, 0xde, 0x69, 0x27, 0xbb, 0x98, 0x33, 0xd3, 0x69, 0x39, 0x19, 0xd5, 0xe2, 0xdd, 0x25, 0x3d, - 0xa4, 0x5a, 0xbc, 0xbb, 0x26, 0x75, 0xfc, 0x1c, 0x9f, 0x90, 0x12, 0x6b, 0x14, 0xe6, 0x54, 0xa2, - 0x2d, 0x9e, 0x69, 0xba, 0xeb, 0x59, 0xd2, 0x55, 0xf3, 0xa4, 0x35, 0xc1, 0x88, 0x86, 0xd2, 0x65, - 0x61, 0xde, 0x65, 0x09, 0xef, 0x2d, 0xa4, 0x4b, 0xbc, 0xf6, 0x65, 0x3e, 0x00, 0x4f, 0x5d, 0xf3, - 0x0c, 0x78, 0x65, 0xf1, 0x27, 0xff, 0xe5, 0x72, 0xee, 0x27, 0x3f, 0xbd, 0x9c, 0xfb, 0x0f, 0x3f, - 0xbd, 0x9c, 0xfb, 0xcf, 0x3f, 0xbd, 0x9c, 0xfb, 0x72, 0xfe, 0x64, 0xf9, 0x8e, 0xf9, 0xa3, 0x8f, - 0xb7, 0xb9, 0xb8, 0x41, 0xfc, 0xef, 0xcd, 0xff, 0x13, 0x00, 0x00, 0xff, 0xff, 0xa5, 0xf6, 0x2e, - 0x3b, 0xed, 0xf0, 0x00, 0x00, + 0xa7, 0x9e, 0x75, 0x75, 0xad, 0xc7, 0xac, 0x53, 0x56, 0xd9, 0x99, 0x95, 0x92, 0x07, 0xda, 0x42, + 0x4f, 0x27, 0x6c, 0x62, 0x96, 0x9e, 0x3e, 0xc0, 0x58, 0x00, 0xee, 0x03, 0xec, 0xa5, 0x9e, 0xf8, + 0x6d, 0x23, 0xf2, 0x29, 0x8c, 0x48, 0xe6, 0xde, 0x5a, 0x89, 0x73, 0xa3, 0x56, 0x16, 0x61, 0xdc, + 0xb8, 0x4a, 0xa5, 0x4c, 0x9c, 0xb4, 0x0b, 0x56, 0x5d, 0x3a, 0x7b, 0xdc, 0xb8, 0x32, 0xa5, 0xa4, + 0xa4, 0x5d, 0xa4, 0xca, 0x94, 0xf2, 0x11, 0x8c, 0x0a, 0x95, 0x76, 0xd5, 0x46, 0xb6, 0xd3, 0x6d, + 0x46, 0x0b, 0x4b, 0xee, 0x34, 0xdc, 0x70, 0xc1, 0x6b, 0x3d, 0x72, 0xf7, 0x7b, 0x2a, 0x26, 0xc9, + 0xb2, 0x3b, 0x4f, 0xbe, 0xc2, 0xb7, 0xe5, 0xe5, 0x8b, 0xff, 0x34, 0x7c, 0xea, 0xf9, 0x8f, 0xdd, + 0xd6, 0x7e, 0x0f, 0x91, 0x57, 0x4c, 0x91, 0x71, 0x3e, 0x39, 0x78, 0xbe, 0x82, 0xb9, 0x6a, 0xb6, + 0xf0, 0x9e, 0x42, 0xba, 0xaf, 0x31, 0x55, 0xb8, 0x88, 0x21, 0x34, 0xa7, 0xad, 0x7b, 0x57, 0xa1, + 0x5f, 0xf0, 0xac, 0x8d, 0xd2, 0x61, 0x5f, 0xf7, 0xfc, 0x46, 0x6f, 0x89, 0x25, 0x33, 0x9a, 0x36, + 0xc6, 0x26, 0x95, 0xf1, 0x05, 0x9c, 0xaf, 0x66, 0x8a, 0xee, 0x25, 0xa2, 0xd7, 0x76, 0xf2, 0x02, + 0xaa, 0xe2, 0x94, 0xf5, 0xee, 0x2a, 0x73, 0x15, 0x27, 0x36, 0xb6, 0x18, 0x6d, 0xf9, 0xf4, 0x11, + 0xf5, 0x31, 0x66, 0xbb, 0x57, 0xb4, 0xb2, 0x49, 0x2e, 0x5b, 0xbe, 0x0a, 0x67, 0xab, 0x09, 0x51, + 0x59, 0x2c, 0xbd, 0x0e, 0x81, 0xa6, 0xb0, 0xa5, 0x27, 0xac, 0x57, 0x8f, 0x50, 0xa1, 0xd1, 0x65, + 0x1a, 0xee, 0xac, 0xf6, 0xd0, 0x92, 0xbc, 0x54, 0x20, 0x09, 0x77, 0xef, 0x32, 0xce, 0xaa, 0xc6, + 0x99, 0xa4, 0xc8, 0xfc, 0x78, 0x3f, 0x95, 0x07, 0x22, 0x3d, 0x8b, 0xcd, 0x92, 0xf0, 0x26, 0xce, + 0x85, 0x22, 0x6e, 0x79, 0x36, 0xda, 0x07, 0x70, 0x48, 0xe4, 0xaf, 0xd3, 0x42, 0x98, 0x03, 0x52, + 0xe6, 0x36, 0x20, 0x1f, 0x1e, 0x02, 0x76, 0x39, 0x11, 0xcf, 0xde, 0x55, 0x04, 0x77, 0x85, 0xae, + 0x79, 0xf5, 0xc7, 0xba, 0x2b, 0x94, 0xfd, 0x8e, 0xfb, 0x08, 0x19, 0x6c, 0x77, 0x5e, 0xcc, 0xf8, + 0xec, 0x87, 0x11, 0xfd, 0x85, 0x80, 0x68, 0xc6, 0x8f, 0xc3, 0x85, 0x1b, 0xe9, 0x4d, 0xe9, 0x60, + 0xc4, 0x02, 0x4d, 0xc9, 0x99, 0xaa, 0x51, 0xbe, 0x45, 0x64, 0x32, 0x7d, 0x8b, 0x7a, 0x45, 0xb3, + 0x1d, 0xfa, 0xc4, 0xa6, 0xed, 0x26, 0x86, 0x42, 0x1f, 0x7a, 0x9c, 0x27, 0x8a, 0x8e, 0x4d, 0xa2, + 0x7a, 0x07, 0x71, 0x4d, 0x89, 0xd0, 0x1f, 0x43, 0xf1, 0x2a, 0xab, 0x72, 0x12, 0x17, 0xa9, 0x52, + 0x8f, 0x48, 0xba, 0x93, 0x23, 0x1b, 0x70, 0x6e, 0x99, 0x86, 0x62, 0x8e, 0xb3, 0x69, 0x10, 0xfa, + 0x6e, 0x3d, 0xec, 0x7a, 0x3a, 0x28, 0x0d, 0x94, 0x14, 0x9e, 0xdd, 0xb7, 0x98, 0xbc, 0x6a, 0xba, + 0xbc, 0xae, 0x7c, 0x5d, 0xe2, 0x64, 0xc5, 0x91, 0xc3, 0x69, 0xaa, 0x98, 0x3d, 0xc4, 0x87, 0x78, + 0x18, 0x4e, 0x36, 0x6b, 0x21, 0x4a, 0x81, 0x22, 0x4c, 0xae, 0x5b, 0x30, 0xc8, 0x99, 0x32, 0x17, + 0xd4, 0x31, 0x9d, 0x87, 0xdc, 0x85, 0x11, 0x15, 0x47, 0x43, 0x0c, 0x54, 0x66, 0xbd, 0xee, 0xc2, + 0x08, 0xb7, 0xaf, 0x4e, 0xce, 0xf2, 0x01, 0x8c, 0xa8, 0xc0, 0x9b, 0x53, 0xaf, 0xf4, 0x9f, 0xc0, + 0xb8, 0x1e, 0x82, 0x73, 0x7a, 0x45, 0x7e, 0x84, 0x67, 0xb8, 0xf2, 0xa8, 0x24, 0x9b, 0x7f, 0x26, + 0x96, 0x19, 0x46, 0xa8, 0x94, 0x4f, 0x90, 0x12, 0x98, 0x59, 0xfd, 0xb3, 0x09, 0x6e, 0xf2, 0x81, + 0xbc, 0xce, 0xa4, 0x98, 0x93, 0x44, 0x5d, 0x74, 0x36, 0xc1, 0xd5, 0xfc, 0x3c, 0xcc, 0x6a, 0x82, + 0xed, 0x59, 0xed, 0x93, 0x9c, 0x35, 0xf7, 0x56, 0x5d, 0x96, 0x94, 0x4d, 0xdc, 0xa5, 0x25, 0x5e, + 0x63, 0xcc, 0x16, 0x74, 0x39, 0xfb, 0x01, 0x47, 0xec, 0x8c, 0xfb, 0x68, 0x0a, 0x26, 0xb0, 0x99, + 0xcd, 0xeb, 0xf2, 0x20, 0x64, 0x64, 0xfb, 0x26, 0xc5, 0x75, 0x61, 0xeb, 0x66, 0x4a, 0x8b, 0x4b, + 0x9a, 0x2f, 0x45, 0xdc, 0xaa, 0x8c, 0x64, 0x3c, 0x79, 0x63, 0xb3, 0x6b, 0x76, 0x21, 0xe5, 0x74, + 0xbb, 0x67, 0x5f, 0x64, 0x89, 0xfb, 0x05, 0xdc, 0x1d, 0xa6, 0xa6, 0x06, 0xcb, 0x16, 0x76, 0x43, + 0x0b, 0x90, 0x48, 0xe5, 0x54, 0x8b, 0xde, 0x63, 0xbc, 0x27, 0x96, 0xfe, 0x5e, 0xe5, 0xab, 0x3d, + 0xa4, 0x48, 0x4d, 0xbc, 0xd6, 0x93, 0x4e, 0x9d, 0x95, 0x5e, 0xe0, 0x2b, 0x6c, 0x7a, 0x79, 0x3d, + 0xde, 0xdf, 0x4c, 0x39, 0xbe, 0x56, 0x61, 0xa2, 0xe9, 0x02, 0xcd, 0x30, 0xd1, 0xae, 0x6d, 0xc8, + 0x52, 0xff, 0x67, 0x50, 0x8a, 0xa2, 0x40, 0x4e, 0xd7, 0x09, 0xd9, 0xd1, 0x89, 0x24, 0xa1, 0xa9, + 0x80, 0x74, 0x7b, 0xb7, 0x69, 0xee, 0x6a, 0x96, 0x86, 0xf5, 0xbb, 0x30, 0x22, 0xba, 0x2d, 0xf6, + 0x72, 0x6b, 0xd6, 0x1b, 0xb0, 0x5d, 0x9c, 0xb1, 0xe2, 0xe2, 0xdc, 0x4b, 0x11, 0x94, 0xec, 0xed, + 0xd3, 0x0b, 0x52, 0x41, 0x1a, 0x31, 0x41, 0x56, 0x97, 0xee, 0xed, 0x7d, 0xfe, 0x58, 0xcc, 0xe8, + 0xd7, 0xd3, 0x77, 0xa8, 0x13, 0x5d, 0x16, 0x8b, 0x65, 0x12, 0xd4, 0x2f, 0xe8, 0x26, 0x51, 0xf1, + 0x9b, 0x4e, 0x69, 0x14, 0x2a, 0x32, 0xaa, 0x28, 0x8b, 0x60, 0x70, 0x66, 0x8a, 0x78, 0xbe, 0x1b, + 0x3e, 0x5b, 0xb0, 0xd7, 0x22, 0xb7, 0x82, 0x8e, 0x90, 0xb2, 0x41, 0x22, 0xed, 0x35, 0xf2, 0x25, + 0x4e, 0x25, 0x42, 0x7c, 0xc5, 0xf3, 0xc2, 0x20, 0xf4, 0x9d, 0x76, 0x15, 0x5f, 0xb4, 0xce, 0x6c, + 0x74, 0x14, 0xc8, 0x9d, 0xc6, 0xa6, 0xc5, 0x95, 0x8a, 0x64, 0xf6, 0x69, 0xe9, 0x6f, 0xd4, 0xdd, + 0x9a, 0x34, 0x64, 0x17, 0xcb, 0xa5, 0x2a, 0xd3, 0xd7, 0xbf, 0x4c, 0xa1, 0x35, 0x98, 0xcd, 0x48, + 0x1a, 0xa4, 0x8e, 0x70, 0xbb, 0x27, 0x15, 0x9a, 0xeb, 0x5e, 0x30, 0xf9, 0x0a, 0x66, 0x52, 0xb3, + 0x0a, 0x29, 0x37, 0x74, 0xb7, 0x9c, 0x43, 0xbd, 0x84, 0x3f, 0x86, 0x22, 0xbf, 0xd5, 0x81, 0xc1, + 0xcb, 0x46, 0x82, 0x99, 0xe8, 0xae, 0x4f, 0x06, 0x41, 0x7c, 0xbe, 0xce, 0xa6, 0x53, 0x37, 0xce, + 0xa7, 0x31, 0xb3, 0x88, 0x7c, 0x82, 0x9b, 0xd6, 0xbd, 0x27, 0xd4, 0x7f, 0xa6, 0x3e, 0xbc, 0x34, + 0x64, 0xb7, 0x0b, 0x45, 0x5b, 0x30, 0xb3, 0x4b, 0x7d, 0xf7, 0xd1, 0xb3, 0xb8, 0x40, 0xa9, 0x99, + 0x54, 0x6c, 0x37, 0x89, 0x9f, 0xc3, 0xec, 0x82, 0x77, 0xd8, 0x16, 0x57, 0xf7, 0x0c, 0x99, 0xea, + 0x3c, 0x3e, 0x1d, 0xdf, 0x3b, 0xa0, 0x69, 0x4e, 0xdd, 0x2d, 0xd4, 0xf9, 0x16, 0xf0, 0x4e, 0xeb, + 0x0d, 0x33, 0xa6, 0x20, 0x85, 0x24, 0xba, 0x91, 0x21, 0x4d, 0x39, 0x9d, 0x7f, 0x1b, 0x07, 0x61, + 0x8c, 0x8f, 0xfb, 0xe6, 0xb4, 0x41, 0x98, 0x86, 0xef, 0x7e, 0x11, 0x2c, 0x45, 0x2a, 0x2f, 0x30, + 0x5b, 0xea, 0x09, 0x6a, 0xbb, 0x21, 0xd7, 0x96, 0x2d, 0xdf, 0x7d, 0xe2, 0x36, 0xe9, 0xbe, 0x70, + 0x23, 0x9a, 0x91, 0xd3, 0x26, 0xb2, 0x5b, 0x3d, 0xb5, 0xd4, 0x0a, 0xcd, 0x66, 0x97, 0x2d, 0x16, + 0xd1, 0x73, 0x2b, 0x30, 0x4a, 0xf4, 0xe4, 0x8f, 0xeb, 0xbc, 0xdd, 0x66, 0xeb, 0x04, 0x33, 0x6e, + 0x6a, 0xdf, 0x87, 0xb1, 0xaa, 0x5e, 0x78, 0x4a, 0x21, 0x99, 0x83, 0x42, 0x5d, 0x05, 0xea, 0x5d, + 0xf7, 0x2e, 0x01, 0xa1, 0x6a, 0xe1, 0x39, 0x51, 0x2b, 0x32, 0xe3, 0x67, 0x8c, 0x07, 0xe8, 0xd4, + 0x2a, 0x90, 0xf6, 0x06, 0xa7, 0x8a, 0x9f, 0x49, 0x7f, 0xb3, 0xae, 0xc6, 0x9f, 0xb5, 0x89, 0x3f, + 0xb1, 0x4a, 0xac, 0xde, 0x6f, 0x19, 0xab, 0xc0, 0xf8, 0xae, 0x6f, 0xb4, 0xf2, 0x60, 0x9f, 0xe8, + 0xc9, 0x3d, 0x3d, 0xd8, 0x27, 0xf1, 0x90, 0x9f, 0x1e, 0xec, 0x93, 0xf2, 0x4a, 0x5f, 0x15, 0x0a, + 0xf1, 0x37, 0x04, 0x95, 0x5b, 0x29, 0xe3, 0x89, 0x44, 0x15, 0xd6, 0x93, 0xf9, 0xf8, 0xe0, 0x12, + 0x56, 0x30, 0x7a, 0x64, 0xa8, 0x8b, 0x87, 0x43, 0xd5, 0x2d, 0xe5, 0x2d, 0xa3, 0x07, 0x7a, 0xda, + 0x0f, 0xfe, 0x34, 0x51, 0x17, 0x07, 0x6e, 0x3c, 0xdd, 0x47, 0xec, 0x2d, 0xa3, 0x7b, 0x50, 0xe0, + 0xaf, 0x34, 0x44, 0xd9, 0x12, 0xa3, 0xa0, 0xc2, 0xe4, 0xe3, 0x11, 0x5d, 0x46, 0x4a, 0x21, 0x9e, + 0x63, 0x4e, 0x29, 0x2c, 0x23, 0xf9, 0x5c, 0x97, 0xf1, 0x0f, 0x51, 0x26, 0x39, 0xe5, 0xed, 0x4a, + 0x24, 0x97, 0x9b, 0x3b, 0x9f, 0x82, 0x51, 0xfb, 0xd4, 0x31, 0x3d, 0xef, 0x9c, 0x6a, 0x52, 0x4a, + 0x32, 0xba, 0xb9, 0x0b, 0xa9, 0x38, 0x21, 0x28, 0xe4, 0x6f, 0x84, 0xa7, 0x3f, 0xd9, 0x1e, 0x5d, + 0x11, 0xeb, 0x42, 0x23, 0x8b, 0xb9, 0x79, 0x12, 0x52, 0x51, 0x2a, 0x55, 0x4f, 0x2c, 0xa5, 0xbc, + 0x13, 0xff, 0x5a, 0xca, 0x2d, 0x0e, 0x83, 0x22, 0x1a, 0x90, 0xdd, 0x1f, 0xad, 0x27, 0x0f, 0xe5, + 0x93, 0x37, 0x19, 0x25, 0xf5, 0x12, 0x90, 0xd9, 0x83, 0x0f, 0xe5, 0x23, 0x37, 0x2f, 0x5b, 0xf0, + 0x1e, 0x5c, 0x8c, 0x5d, 0x0d, 0x31, 0x05, 0xdf, 0x4c, 0xbf, 0x3f, 0x92, 0xaa, 0x9e, 0x6c, 0x43, + 0xe0, 0x4a, 0xf2, 0x0a, 0x49, 0xac, 0xdf, 0x4f, 0x3b, 0x91, 0xae, 0xc3, 0x04, 0xce, 0x5d, 0x01, + 0xf5, 0x97, 0x7d, 0xaf, 0xd3, 0x8e, 0xb2, 0xce, 0x98, 0xe0, 0x78, 0xfa, 0xa3, 0x38, 0x56, 0xdd, + 0x4c, 0x1f, 0x13, 0xd7, 0x8d, 0x11, 0xa1, 0x67, 0xc3, 0x51, 0xc0, 0xb4, 0xa5, 0x11, 0x11, 0xbb, + 0x77, 0xc9, 0x47, 0x30, 0x19, 0xdd, 0x42, 0xe6, 0x22, 0x52, 0xc8, 0xba, 0x78, 0xdf, 0x26, 0xa3, + 0xab, 0xc8, 0xa7, 0x67, 0x5f, 0x91, 0xeb, 0x5b, 0xc4, 0x7e, 0x29, 0x71, 0x91, 0xc6, 0x68, 0xc3, + 0x49, 0x96, 0x39, 0x4d, 0xb7, 0xa7, 0xed, 0x9d, 0x3a, 0x7e, 0x6e, 0xe9, 0x09, 0x15, 0xf5, 0xcf, + 0xad, 0x6b, 0xd2, 0x47, 0xb5, 0xa7, 0xce, 0x90, 0xb3, 0x0e, 0xd7, 0x30, 0x09, 0xcb, 0x16, 0x4f, + 0xbb, 0x97, 0x4e, 0x95, 0x5d, 0xf7, 0x78, 0xea, 0x96, 0x26, 0x5c, 0xed, 0x99, 0x51, 0x92, 0xdc, + 0x36, 0x82, 0x67, 0x7a, 0xe7, 0x9e, 0xec, 0x62, 0xce, 0x4c, 0xa7, 0x25, 0x66, 0x54, 0x8b, 0x77, + 0x97, 0x1c, 0x91, 0x6a, 0xf1, 0xee, 0x9a, 0xd9, 0xf1, 0x73, 0x7c, 0x47, 0x4a, 0xac, 0x51, 0x98, + 0x58, 0x89, 0xb6, 0x78, 0xba, 0xe9, 0xae, 0x67, 0x49, 0x57, 0xcd, 0x93, 0xd6, 0x04, 0x23, 0x1a, + 0x4a, 0x97, 0x85, 0x79, 0x97, 0x25, 0xbc, 0xb7, 0x90, 0x2e, 0x41, 0xdb, 0x97, 0xf9, 0x00, 0x3c, + 0x75, 0xcd, 0x33, 0xe0, 0x95, 0xc5, 0x9f, 0xfc, 0x97, 0xcb, 0xb9, 0x9f, 0xfc, 0xf4, 0x72, 0xee, + 0x3f, 0xfc, 0xf4, 0x72, 0xee, 0x3f, 0xff, 0xf4, 0x72, 0xee, 0xcb, 0xf9, 0x93, 0x25, 0x3d, 0xe6, + 0x2f, 0x3f, 0xde, 0xe6, 0xe2, 0x06, 0xf1, 0xbf, 0x37, 0xff, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, + 0xf4, 0x4b, 0x4f, 0x24, 0xf2, 0xf0, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -17612,6 +17612,8 @@ type AuthServiceClient interface { // GetTrustedClusters gets all current Trusted Cluster resources. GetTrustedClusters(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*types.TrustedClusterV2List, error) // UpsertTrustedCluster upserts a Trusted Cluster in a backend. + // + // Deprecated: Use [teleport.trust.v1.UpsertTrustedCluster] instead. UpsertTrustedCluster(ctx context.Context, in *types.TrustedClusterV2, opts ...grpc.CallOption) (*types.TrustedClusterV2, error) // DeleteTrustedCluster deletes an existing Trusted Cluster in a backend by name. DeleteTrustedCluster(ctx context.Context, in *types.ResourceRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) @@ -19593,6 +19595,7 @@ func (c *authServiceClient) GetTrustedClusters(ctx context.Context, in *emptypb. return out, nil } +// Deprecated: Do not use. func (c *authServiceClient) UpsertTrustedCluster(ctx context.Context, in *types.TrustedClusterV2, opts ...grpc.CallOption) (*types.TrustedClusterV2, error) { out := new(types.TrustedClusterV2) err := c.cc.Invoke(ctx, "/proto.AuthService/UpsertTrustedCluster", in, out, opts...) @@ -21001,6 +21004,8 @@ type AuthServiceServer interface { // GetTrustedClusters gets all current Trusted Cluster resources. GetTrustedClusters(context.Context, *emptypb.Empty) (*types.TrustedClusterV2List, error) // UpsertTrustedCluster upserts a Trusted Cluster in a backend. + // + // Deprecated: Use [teleport.trust.v1.UpsertTrustedCluster] instead. UpsertTrustedCluster(context.Context, *types.TrustedClusterV2) (*types.TrustedClusterV2, error) // DeleteTrustedCluster deletes an existing Trusted Cluster in a backend by name. DeleteTrustedCluster(context.Context, *types.ResourceRequest) (*emptypb.Empty, error) diff --git a/api/gen/proto/go/teleport/trust/v1/trust_service.pb.go b/api/gen/proto/go/teleport/trust/v1/trust_service.pb.go index 349eb18c6ae9e..5f6c82ec9c41d 100644 --- a/api/gen/proto/go/teleport/trust/v1/trust_service.pb.go +++ b/api/gen/proto/go/teleport/trust/v1/trust_service.pb.go @@ -38,6 +38,144 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +// Request for UpsertTrustedCluster. +type UpsertTrustedClusterRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // TrustedCluster specifies a Trusted Cluster resource. + TrustedCluster *types.TrustedClusterV2 `protobuf:"bytes,1,opt,name=trusted_cluster,json=trustedCluster,proto3" json:"trusted_cluster,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpsertTrustedClusterRequest) Reset() { + *x = UpsertTrustedClusterRequest{} + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpsertTrustedClusterRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpsertTrustedClusterRequest) ProtoMessage() {} + +func (x *UpsertTrustedClusterRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpsertTrustedClusterRequest.ProtoReflect.Descriptor instead. +func (*UpsertTrustedClusterRequest) Descriptor() ([]byte, []int) { + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{0} +} + +func (x *UpsertTrustedClusterRequest) GetTrustedCluster() *types.TrustedClusterV2 { + if x != nil { + return x.TrustedCluster + } + return nil +} + +// Request for CreateTrustedCluster. +type CreateTrustedClusterRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // TrustedCluster specifies a Trusted Cluster resource. + TrustedCluster *types.TrustedClusterV2 `protobuf:"bytes,1,opt,name=trusted_cluster,json=trustedCluster,proto3" json:"trusted_cluster,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *CreateTrustedClusterRequest) Reset() { + *x = CreateTrustedClusterRequest{} + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *CreateTrustedClusterRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateTrustedClusterRequest) ProtoMessage() {} + +func (x *CreateTrustedClusterRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateTrustedClusterRequest.ProtoReflect.Descriptor instead. +func (*CreateTrustedClusterRequest) Descriptor() ([]byte, []int) { + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{1} +} + +func (x *CreateTrustedClusterRequest) GetTrustedCluster() *types.TrustedClusterV2 { + if x != nil { + return x.TrustedCluster + } + return nil +} + +// Request for UpdateTrustedCluster. +type UpdateTrustedClusterRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // TrustedCluster specifies a Trusted Cluster resource. + TrustedCluster *types.TrustedClusterV2 `protobuf:"bytes,1,opt,name=trusted_cluster,json=trustedCluster,proto3" json:"trusted_cluster,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *UpdateTrustedClusterRequest) Reset() { + *x = UpdateTrustedClusterRequest{} + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *UpdateTrustedClusterRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateTrustedClusterRequest) ProtoMessage() {} + +func (x *UpdateTrustedClusterRequest) ProtoReflect() protoreflect.Message { + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateTrustedClusterRequest.ProtoReflect.Descriptor instead. +func (*UpdateTrustedClusterRequest) Descriptor() ([]byte, []int) { + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{2} +} + +func (x *UpdateTrustedClusterRequest) GetTrustedCluster() *types.TrustedClusterV2 { + if x != nil { + return x.TrustedCluster + } + return nil +} + // Request for GetCertAuthority type GetCertAuthorityRequest struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -53,7 +191,7 @@ type GetCertAuthorityRequest struct { func (x *GetCertAuthorityRequest) Reset() { *x = GetCertAuthorityRequest{} - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[0] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -65,7 +203,7 @@ func (x *GetCertAuthorityRequest) String() string { func (*GetCertAuthorityRequest) ProtoMessage() {} func (x *GetCertAuthorityRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[0] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -78,7 +216,7 @@ func (x *GetCertAuthorityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCertAuthorityRequest.ProtoReflect.Descriptor instead. func (*GetCertAuthorityRequest) Descriptor() ([]byte, []int) { - return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{0} + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{3} } func (x *GetCertAuthorityRequest) GetType() string { @@ -115,7 +253,7 @@ type GetCertAuthoritiesRequest struct { func (x *GetCertAuthoritiesRequest) Reset() { *x = GetCertAuthoritiesRequest{} - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[1] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -127,7 +265,7 @@ func (x *GetCertAuthoritiesRequest) String() string { func (*GetCertAuthoritiesRequest) ProtoMessage() {} func (x *GetCertAuthoritiesRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[1] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -140,7 +278,7 @@ func (x *GetCertAuthoritiesRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCertAuthoritiesRequest.ProtoReflect.Descriptor instead. func (*GetCertAuthoritiesRequest) Descriptor() ([]byte, []int) { - return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{1} + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{4} } func (x *GetCertAuthoritiesRequest) GetType() string { @@ -168,7 +306,7 @@ type GetCertAuthoritiesResponse struct { func (x *GetCertAuthoritiesResponse) Reset() { *x = GetCertAuthoritiesResponse{} - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[2] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -180,7 +318,7 @@ func (x *GetCertAuthoritiesResponse) String() string { func (*GetCertAuthoritiesResponse) ProtoMessage() {} func (x *GetCertAuthoritiesResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[2] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -193,7 +331,7 @@ func (x *GetCertAuthoritiesResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCertAuthoritiesResponse.ProtoReflect.Descriptor instead. func (*GetCertAuthoritiesResponse) Descriptor() ([]byte, []int) { - return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{2} + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{5} } func (x *GetCertAuthoritiesResponse) GetCertAuthoritiesV2() []*types.CertAuthorityV2 { @@ -216,7 +354,7 @@ type DeleteCertAuthorityRequest struct { func (x *DeleteCertAuthorityRequest) Reset() { *x = DeleteCertAuthorityRequest{} - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[3] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -228,7 +366,7 @@ func (x *DeleteCertAuthorityRequest) String() string { func (*DeleteCertAuthorityRequest) ProtoMessage() {} func (x *DeleteCertAuthorityRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[3] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -241,7 +379,7 @@ func (x *DeleteCertAuthorityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use DeleteCertAuthorityRequest.ProtoReflect.Descriptor instead. func (*DeleteCertAuthorityRequest) Descriptor() ([]byte, []int) { - return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{3} + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{6} } func (x *DeleteCertAuthorityRequest) GetType() string { @@ -269,7 +407,7 @@ type UpsertCertAuthorityRequest struct { func (x *UpsertCertAuthorityRequest) Reset() { *x = UpsertCertAuthorityRequest{} - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[4] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -281,7 +419,7 @@ func (x *UpsertCertAuthorityRequest) String() string { func (*UpsertCertAuthorityRequest) ProtoMessage() {} func (x *UpsertCertAuthorityRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[4] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -294,7 +432,7 @@ func (x *UpsertCertAuthorityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use UpsertCertAuthorityRequest.ProtoReflect.Descriptor instead. func (*UpsertCertAuthorityRequest) Descriptor() ([]byte, []int) { - return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{4} + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{7} } func (x *UpsertCertAuthorityRequest) GetCertAuthority() *types.CertAuthorityV2 { @@ -333,7 +471,7 @@ type RotateCertAuthorityRequest struct { func (x *RotateCertAuthorityRequest) Reset() { *x = RotateCertAuthorityRequest{} - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[5] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -345,7 +483,7 @@ func (x *RotateCertAuthorityRequest) String() string { func (*RotateCertAuthorityRequest) ProtoMessage() {} func (x *RotateCertAuthorityRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[5] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -358,7 +496,7 @@ func (x *RotateCertAuthorityRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use RotateCertAuthorityRequest.ProtoReflect.Descriptor instead. func (*RotateCertAuthorityRequest) Descriptor() ([]byte, []int) { - return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{5} + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{8} } func (x *RotateCertAuthorityRequest) GetType() string { @@ -411,7 +549,7 @@ type RotationSchedule struct { func (x *RotationSchedule) Reset() { *x = RotationSchedule{} - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[6] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -423,7 +561,7 @@ func (x *RotationSchedule) String() string { func (*RotationSchedule) ProtoMessage() {} func (x *RotationSchedule) ProtoReflect() protoreflect.Message { - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[6] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -436,7 +574,7 @@ func (x *RotationSchedule) ProtoReflect() protoreflect.Message { // Deprecated: Use RotationSchedule.ProtoReflect.Descriptor instead. func (*RotationSchedule) Descriptor() ([]byte, []int) { - return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{6} + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{9} } func (x *RotationSchedule) GetUpdateClients() *timestamppb.Timestamp { @@ -469,7 +607,7 @@ type RotateCertAuthorityResponse struct { func (x *RotateCertAuthorityResponse) Reset() { *x = RotateCertAuthorityResponse{} - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[7] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -481,7 +619,7 @@ func (x *RotateCertAuthorityResponse) String() string { func (*RotateCertAuthorityResponse) ProtoMessage() {} func (x *RotateCertAuthorityResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[7] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -494,7 +632,7 @@ func (x *RotateCertAuthorityResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use RotateCertAuthorityResponse.ProtoReflect.Descriptor instead. func (*RotateCertAuthorityResponse) Descriptor() ([]byte, []int) { - return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{7} + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{10} } // Request for RotateExternalCertAuthority. @@ -508,7 +646,7 @@ type RotateExternalCertAuthorityRequest struct { func (x *RotateExternalCertAuthorityRequest) Reset() { *x = RotateExternalCertAuthorityRequest{} - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[8] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -520,7 +658,7 @@ func (x *RotateExternalCertAuthorityRequest) String() string { func (*RotateExternalCertAuthorityRequest) ProtoMessage() {} func (x *RotateExternalCertAuthorityRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[8] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -533,7 +671,7 @@ func (x *RotateExternalCertAuthorityRequest) ProtoReflect() protoreflect.Message // Deprecated: Use RotateExternalCertAuthorityRequest.ProtoReflect.Descriptor instead. func (*RotateExternalCertAuthorityRequest) Descriptor() ([]byte, []int) { - return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{8} + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{11} } func (x *RotateExternalCertAuthorityRequest) GetCertAuthority() *types.CertAuthorityV2 { @@ -552,7 +690,7 @@ type RotateExternalCertAuthorityResponse struct { func (x *RotateExternalCertAuthorityResponse) Reset() { *x = RotateExternalCertAuthorityResponse{} - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[9] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -564,7 +702,7 @@ func (x *RotateExternalCertAuthorityResponse) String() string { func (*RotateExternalCertAuthorityResponse) ProtoMessage() {} func (x *RotateExternalCertAuthorityResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[9] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -577,7 +715,7 @@ func (x *RotateExternalCertAuthorityResponse) ProtoReflect() protoreflect.Messag // Deprecated: Use RotateExternalCertAuthorityResponse.ProtoReflect.Descriptor instead. func (*RotateExternalCertAuthorityResponse) Descriptor() ([]byte, []int) { - return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{9} + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{12} } // GenerateHostCertRequest is the request for GenerateHostCert. @@ -603,7 +741,7 @@ type GenerateHostCertRequest struct { func (x *GenerateHostCertRequest) Reset() { *x = GenerateHostCertRequest{} - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[10] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -615,7 +753,7 @@ func (x *GenerateHostCertRequest) String() string { func (*GenerateHostCertRequest) ProtoMessage() {} func (x *GenerateHostCertRequest) ProtoReflect() protoreflect.Message { - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[10] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -628,7 +766,7 @@ func (x *GenerateHostCertRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GenerateHostCertRequest.ProtoReflect.Descriptor instead. func (*GenerateHostCertRequest) Descriptor() ([]byte, []int) { - return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{10} + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{13} } func (x *GenerateHostCertRequest) GetKey() []byte { @@ -691,7 +829,7 @@ type GenerateHostCertResponse struct { func (x *GenerateHostCertResponse) Reset() { *x = GenerateHostCertResponse{} - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[11] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -703,7 +841,7 @@ func (x *GenerateHostCertResponse) String() string { func (*GenerateHostCertResponse) ProtoMessage() {} func (x *GenerateHostCertResponse) ProtoReflect() protoreflect.Message { - mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[11] + mi := &file_teleport_trust_v1_trust_service_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -716,7 +854,7 @@ func (x *GenerateHostCertResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use GenerateHostCertResponse.ProtoReflect.Descriptor instead. func (*GenerateHostCertResponse) Descriptor() ([]byte, []int) { - return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{11} + return file_teleport_trust_v1_trust_service_proto_rawDescGZIP(), []int{14} } func (x *GenerateHostCertResponse) GetSshCertificate() []byte { @@ -740,147 +878,183 @@ var file_teleport_trust_v1_trust_service_proto_rawDesc = []byte{ 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x21, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6c, 0x65, 0x67, 0x61, 0x63, 0x79, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x66, 0x0a, 0x17, 0x47, - 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, - 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, - 0x69, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x6b, 0x65, - 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, - 0x4b, 0x65, 0x79, 0x22, 0x50, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, - 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x6e, 0x63, 0x6c, 0x75, - 0x64, 0x65, 0x4b, 0x65, 0x79, 0x22, 0x64, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, - 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x13, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x76, 0x32, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x56, 0x32, 0x52, 0x11, 0x63, 0x65, 0x72, 0x74, 0x41, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x56, 0x32, 0x22, 0x48, 0x0a, 0x1a, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x5f, 0x0a, 0x1b, 0x55, + 0x70, 0x73, 0x65, 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x0f, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x56, 0x32, 0x52, 0x0e, 0x74, 0x72, + 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x5f, 0x0a, 0x1b, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x0f, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x56, 0x32, 0x52, 0x0e, 0x74, + 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x5f, 0x0a, + 0x1b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x0f, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x54, 0x72, + 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x56, 0x32, 0x52, 0x0e, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x22, 0x66, + 0x0a, 0x17, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x64, - 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x5b, 0x0a, 0x1a, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, - 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x0e, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, - 0x79, 0x56, 0x32, 0x52, 0x0d, 0x63, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x22, 0xe6, 0x01, 0x0a, 0x1a, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x43, 0x65, 0x72, - 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3c, 0x0a, 0x0c, 0x67, 0x72, 0x61, 0x63, 0x65, 0x5f, 0x70, - 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x67, 0x72, 0x61, 0x63, 0x65, 0x50, 0x65, 0x72, - 0x69, 0x6f, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, 0x5f, 0x70, 0x68, - 0x61, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x61, 0x72, 0x67, 0x65, - 0x74, 0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x3f, 0x0a, 0x08, 0x73, 0x63, - 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, - 0x65, 0x52, 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x22, 0xce, 0x01, 0x0a, 0x10, - 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, - 0x12, 0x41, 0x0a, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, - 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x73, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, + 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x6e, 0x63, 0x6c, + 0x75, 0x64, 0x65, 0x4b, 0x65, 0x79, 0x22, 0x50, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, + 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x6e, 0x63, 0x6c, 0x75, + 0x64, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x6e, + 0x63, 0x6c, 0x75, 0x64, 0x65, 0x4b, 0x65, 0x79, 0x22, 0x64, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x43, + 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x46, 0x0a, 0x13, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x5f, 0x76, 0x32, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x65, 0x72, 0x74, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x56, 0x32, 0x52, 0x11, 0x63, 0x65, 0x72, + 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x56, 0x32, 0x22, 0x48, + 0x0a, 0x1a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x22, 0x5b, 0x0a, 0x1a, 0x55, 0x70, 0x73, 0x65, + 0x72, 0x74, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x0e, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x61, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x74, 0x79, 0x56, 0x32, 0x52, 0x0d, 0x63, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x22, 0xe6, 0x01, 0x0a, 0x1a, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, + 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x3c, 0x0a, 0x0c, 0x67, 0x72, 0x61, 0x63, + 0x65, 0x5f, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x67, 0x72, 0x61, 0x63, 0x65, + 0x50, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x74, 0x61, 0x72, 0x67, 0x65, 0x74, + 0x5f, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x61, + 0x72, 0x67, 0x65, 0x74, 0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, + 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x3f, 0x0a, + 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x23, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, + 0x64, 0x75, 0x6c, 0x65, 0x52, 0x08, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x22, 0xce, + 0x01, 0x0a, 0x10, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x63, 0x68, 0x65, 0x64, + 0x75, 0x6c, 0x65, 0x12, 0x41, 0x0a, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x34, 0x0a, 0x07, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x62, - 0x79, 0x18, 0x03, 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, 0x07, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x62, 0x79, 0x22, 0x1d, 0x0a, 0x1b, - 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x63, 0x0a, 0x22, 0x52, - 0x6f, 0x74, 0x61, 0x74, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x43, 0x65, 0x72, - 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x3d, 0x0a, 0x0e, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x56, - 0x32, 0x52, 0x0d, 0x63, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x22, 0x25, 0x0a, 0x23, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, - 0x61, 0x6c, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xe5, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x6e, 0x65, - 0x72, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, - 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1b, - 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, 0x0a, 0x0a, 0x70, - 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x0a, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x12, - 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, - 0x6c, 0x65, 0x12, 0x2b, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x74, 0x74, 0x6c, 0x22, - 0x43, 0x0a, 0x18, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, - 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x73, - 0x73, 0x68, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x73, 0x73, 0x68, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x65, 0x32, 0x87, 0x06, 0x0a, 0x0c, 0x54, 0x72, 0x75, 0x73, 0x74, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x56, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, - 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, - 0x74, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x65, - 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x56, 0x32, 0x12, 0x71, 0x0a, - 0x12, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, - 0x69, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, - 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x41, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, - 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x5c, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, - 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, - 0x74, 0x65, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x5c, - 0x0a, 0x13, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x41, 0x0a, 0x0e, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x18, 0x02, 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, 0x0d, 0x75, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x73, 0x12, 0x34, 0x0a, 0x07, 0x73, 0x74, 0x61, + 0x6e, 0x64, 0x62, 0x79, 0x18, 0x03, 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, 0x07, 0x73, 0x74, 0x61, 0x6e, 0x64, 0x62, 0x79, 0x22, + 0x1d, 0x0a, 0x1b, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x63, + 0x0a, 0x22, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x65, 0x72, - 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x56, 0x32, 0x12, 0x74, 0x0a, 0x13, - 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x74, 0x79, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, - 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x43, 0x65, - 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, - 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x43, 0x65, 0x72, - 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x45, 0x78, 0x74, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x3d, 0x0a, 0x0e, 0x63, 0x65, 0x72, 0x74, 0x5f, 0x61, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x56, 0x32, 0x52, 0x0d, 0x63, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x74, 0x79, 0x22, 0x25, 0x0a, 0x23, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x12, 0x35, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, - 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x45, 0x78, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, - 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, - 0x74, 0x61, 0x74, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x43, 0x65, 0x72, 0x74, - 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x6b, 0x0a, 0x10, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, - 0x74, 0x43, 0x65, 0x72, 0x74, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, - 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, - 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x48, 0x6f, - 0x73, 0x74, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x4e, - 0x5a, 0x4c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, - 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x74, 0x72, - 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x74, 0x72, 0x75, 0x73, 0x74, 0x76, 0x31, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xe5, 0x01, 0x0a, 0x17, 0x47, + 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x65, 0x72, 0x74, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x17, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x6f, 0x73, 0x74, 0x49, + 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6e, 0x6f, 0x64, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1e, + 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x18, 0x04, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x12, 0x21, + 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x05, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x2b, 0x0a, 0x03, 0x74, 0x74, 0x6c, 0x18, 0x07, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x03, 0x74, + 0x74, 0x6c, 0x22, 0x43, 0x0a, 0x18, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, 0x48, 0x6f, + 0x73, 0x74, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x27, + 0x0a, 0x0f, 0x73, 0x73, 0x68, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0e, 0x73, 0x73, 0x68, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x32, 0xaa, 0x08, 0x0a, 0x0c, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x56, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x43, + 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2a, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x56, 0x32, + 0x12, 0x71, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x12, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, + 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x65, 0x72, 0x74, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x69, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x65, 0x72, + 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x5c, 0x0a, 0x13, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x43, 0x65, 0x72, 0x74, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x73, + 0x65, 0x72, 0x74, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, + 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x56, 0x32, 0x12, + 0x74, 0x0a, 0x13, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, + 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x74, 0x61, 0x74, + 0x65, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, + 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x8c, 0x01, 0x0a, 0x1b, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, + 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x35, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, + 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, + 0x2e, 0x52, 0x6f, 0x74, 0x61, 0x74, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x43, + 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6b, 0x0a, 0x10, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, 0x65, + 0x48, 0x6f, 0x73, 0x74, 0x43, 0x65, 0x72, 0x74, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, + 0x65, 0x72, 0x61, 0x74, 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x61, 0x74, + 0x65, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x65, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x5f, 0x0a, 0x14, 0x55, 0x70, 0x73, 0x65, 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, + 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, + 0x73, 0x65, 0x72, 0x74, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x56, 0x32, 0x12, 0x5f, 0x0a, 0x14, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x72, 0x75, 0x73, + 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x2e, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, + 0x72, 0x56, 0x32, 0x12, 0x5f, 0x0a, 0x14, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x72, 0x75, + 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x2e, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x54, 0x72, 0x75, 0x73, 0x74, 0x65, 0x64, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x56, 0x32, 0x42, 0x4e, 0x5a, 0x4c, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, + 0x6f, 0x6d, 0x2f, 0x67, 0x72, 0x61, 0x76, 0x69, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, + 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x65, + 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2f, 0x74, 0x72, 0x75, 0x73, 0x74, 0x2f, 0x76, 0x31, 0x3b, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -895,54 +1069,67 @@ func file_teleport_trust_v1_trust_service_proto_rawDescGZIP() []byte { return file_teleport_trust_v1_trust_service_proto_rawDescData } -var file_teleport_trust_v1_trust_service_proto_msgTypes = make([]protoimpl.MessageInfo, 12) +var file_teleport_trust_v1_trust_service_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_teleport_trust_v1_trust_service_proto_goTypes = []any{ - (*GetCertAuthorityRequest)(nil), // 0: teleport.trust.v1.GetCertAuthorityRequest - (*GetCertAuthoritiesRequest)(nil), // 1: teleport.trust.v1.GetCertAuthoritiesRequest - (*GetCertAuthoritiesResponse)(nil), // 2: teleport.trust.v1.GetCertAuthoritiesResponse - (*DeleteCertAuthorityRequest)(nil), // 3: teleport.trust.v1.DeleteCertAuthorityRequest - (*UpsertCertAuthorityRequest)(nil), // 4: teleport.trust.v1.UpsertCertAuthorityRequest - (*RotateCertAuthorityRequest)(nil), // 5: teleport.trust.v1.RotateCertAuthorityRequest - (*RotationSchedule)(nil), // 6: teleport.trust.v1.RotationSchedule - (*RotateCertAuthorityResponse)(nil), // 7: teleport.trust.v1.RotateCertAuthorityResponse - (*RotateExternalCertAuthorityRequest)(nil), // 8: teleport.trust.v1.RotateExternalCertAuthorityRequest - (*RotateExternalCertAuthorityResponse)(nil), // 9: teleport.trust.v1.RotateExternalCertAuthorityResponse - (*GenerateHostCertRequest)(nil), // 10: teleport.trust.v1.GenerateHostCertRequest - (*GenerateHostCertResponse)(nil), // 11: teleport.trust.v1.GenerateHostCertResponse - (*types.CertAuthorityV2)(nil), // 12: types.CertAuthorityV2 - (*durationpb.Duration)(nil), // 13: google.protobuf.Duration - (*timestamppb.Timestamp)(nil), // 14: google.protobuf.Timestamp - (*emptypb.Empty)(nil), // 15: google.protobuf.Empty + (*UpsertTrustedClusterRequest)(nil), // 0: teleport.trust.v1.UpsertTrustedClusterRequest + (*CreateTrustedClusterRequest)(nil), // 1: teleport.trust.v1.CreateTrustedClusterRequest + (*UpdateTrustedClusterRequest)(nil), // 2: teleport.trust.v1.UpdateTrustedClusterRequest + (*GetCertAuthorityRequest)(nil), // 3: teleport.trust.v1.GetCertAuthorityRequest + (*GetCertAuthoritiesRequest)(nil), // 4: teleport.trust.v1.GetCertAuthoritiesRequest + (*GetCertAuthoritiesResponse)(nil), // 5: teleport.trust.v1.GetCertAuthoritiesResponse + (*DeleteCertAuthorityRequest)(nil), // 6: teleport.trust.v1.DeleteCertAuthorityRequest + (*UpsertCertAuthorityRequest)(nil), // 7: teleport.trust.v1.UpsertCertAuthorityRequest + (*RotateCertAuthorityRequest)(nil), // 8: teleport.trust.v1.RotateCertAuthorityRequest + (*RotationSchedule)(nil), // 9: teleport.trust.v1.RotationSchedule + (*RotateCertAuthorityResponse)(nil), // 10: teleport.trust.v1.RotateCertAuthorityResponse + (*RotateExternalCertAuthorityRequest)(nil), // 11: teleport.trust.v1.RotateExternalCertAuthorityRequest + (*RotateExternalCertAuthorityResponse)(nil), // 12: teleport.trust.v1.RotateExternalCertAuthorityResponse + (*GenerateHostCertRequest)(nil), // 13: teleport.trust.v1.GenerateHostCertRequest + (*GenerateHostCertResponse)(nil), // 14: teleport.trust.v1.GenerateHostCertResponse + (*types.TrustedClusterV2)(nil), // 15: types.TrustedClusterV2 + (*types.CertAuthorityV2)(nil), // 16: types.CertAuthorityV2 + (*durationpb.Duration)(nil), // 17: google.protobuf.Duration + (*timestamppb.Timestamp)(nil), // 18: google.protobuf.Timestamp + (*emptypb.Empty)(nil), // 19: google.protobuf.Empty } var file_teleport_trust_v1_trust_service_proto_depIdxs = []int32{ - 12, // 0: teleport.trust.v1.GetCertAuthoritiesResponse.cert_authorities_v2:type_name -> types.CertAuthorityV2 - 12, // 1: teleport.trust.v1.UpsertCertAuthorityRequest.cert_authority:type_name -> types.CertAuthorityV2 - 13, // 2: teleport.trust.v1.RotateCertAuthorityRequest.grace_period:type_name -> google.protobuf.Duration - 6, // 3: teleport.trust.v1.RotateCertAuthorityRequest.schedule:type_name -> teleport.trust.v1.RotationSchedule - 14, // 4: teleport.trust.v1.RotationSchedule.update_clients:type_name -> google.protobuf.Timestamp - 14, // 5: teleport.trust.v1.RotationSchedule.update_servers:type_name -> google.protobuf.Timestamp - 14, // 6: teleport.trust.v1.RotationSchedule.standby:type_name -> google.protobuf.Timestamp - 12, // 7: teleport.trust.v1.RotateExternalCertAuthorityRequest.cert_authority:type_name -> types.CertAuthorityV2 - 13, // 8: teleport.trust.v1.GenerateHostCertRequest.ttl:type_name -> google.protobuf.Duration - 0, // 9: teleport.trust.v1.TrustService.GetCertAuthority:input_type -> teleport.trust.v1.GetCertAuthorityRequest - 1, // 10: teleport.trust.v1.TrustService.GetCertAuthorities:input_type -> teleport.trust.v1.GetCertAuthoritiesRequest - 3, // 11: teleport.trust.v1.TrustService.DeleteCertAuthority:input_type -> teleport.trust.v1.DeleteCertAuthorityRequest - 4, // 12: teleport.trust.v1.TrustService.UpsertCertAuthority:input_type -> teleport.trust.v1.UpsertCertAuthorityRequest - 5, // 13: teleport.trust.v1.TrustService.RotateCertAuthority:input_type -> teleport.trust.v1.RotateCertAuthorityRequest - 8, // 14: teleport.trust.v1.TrustService.RotateExternalCertAuthority:input_type -> teleport.trust.v1.RotateExternalCertAuthorityRequest - 10, // 15: teleport.trust.v1.TrustService.GenerateHostCert:input_type -> teleport.trust.v1.GenerateHostCertRequest - 12, // 16: teleport.trust.v1.TrustService.GetCertAuthority:output_type -> types.CertAuthorityV2 - 2, // 17: teleport.trust.v1.TrustService.GetCertAuthorities:output_type -> teleport.trust.v1.GetCertAuthoritiesResponse - 15, // 18: teleport.trust.v1.TrustService.DeleteCertAuthority:output_type -> google.protobuf.Empty - 12, // 19: teleport.trust.v1.TrustService.UpsertCertAuthority:output_type -> types.CertAuthorityV2 - 7, // 20: teleport.trust.v1.TrustService.RotateCertAuthority:output_type -> teleport.trust.v1.RotateCertAuthorityResponse - 9, // 21: teleport.trust.v1.TrustService.RotateExternalCertAuthority:output_type -> teleport.trust.v1.RotateExternalCertAuthorityResponse - 11, // 22: teleport.trust.v1.TrustService.GenerateHostCert:output_type -> teleport.trust.v1.GenerateHostCertResponse - 16, // [16:23] is the sub-list for method output_type - 9, // [9:16] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 15, // 0: teleport.trust.v1.UpsertTrustedClusterRequest.trusted_cluster:type_name -> types.TrustedClusterV2 + 15, // 1: teleport.trust.v1.CreateTrustedClusterRequest.trusted_cluster:type_name -> types.TrustedClusterV2 + 15, // 2: teleport.trust.v1.UpdateTrustedClusterRequest.trusted_cluster:type_name -> types.TrustedClusterV2 + 16, // 3: teleport.trust.v1.GetCertAuthoritiesResponse.cert_authorities_v2:type_name -> types.CertAuthorityV2 + 16, // 4: teleport.trust.v1.UpsertCertAuthorityRequest.cert_authority:type_name -> types.CertAuthorityV2 + 17, // 5: teleport.trust.v1.RotateCertAuthorityRequest.grace_period:type_name -> google.protobuf.Duration + 9, // 6: teleport.trust.v1.RotateCertAuthorityRequest.schedule:type_name -> teleport.trust.v1.RotationSchedule + 18, // 7: teleport.trust.v1.RotationSchedule.update_clients:type_name -> google.protobuf.Timestamp + 18, // 8: teleport.trust.v1.RotationSchedule.update_servers:type_name -> google.protobuf.Timestamp + 18, // 9: teleport.trust.v1.RotationSchedule.standby:type_name -> google.protobuf.Timestamp + 16, // 10: teleport.trust.v1.RotateExternalCertAuthorityRequest.cert_authority:type_name -> types.CertAuthorityV2 + 17, // 11: teleport.trust.v1.GenerateHostCertRequest.ttl:type_name -> google.protobuf.Duration + 3, // 12: teleport.trust.v1.TrustService.GetCertAuthority:input_type -> teleport.trust.v1.GetCertAuthorityRequest + 4, // 13: teleport.trust.v1.TrustService.GetCertAuthorities:input_type -> teleport.trust.v1.GetCertAuthoritiesRequest + 6, // 14: teleport.trust.v1.TrustService.DeleteCertAuthority:input_type -> teleport.trust.v1.DeleteCertAuthorityRequest + 7, // 15: teleport.trust.v1.TrustService.UpsertCertAuthority:input_type -> teleport.trust.v1.UpsertCertAuthorityRequest + 8, // 16: teleport.trust.v1.TrustService.RotateCertAuthority:input_type -> teleport.trust.v1.RotateCertAuthorityRequest + 11, // 17: teleport.trust.v1.TrustService.RotateExternalCertAuthority:input_type -> teleport.trust.v1.RotateExternalCertAuthorityRequest + 13, // 18: teleport.trust.v1.TrustService.GenerateHostCert:input_type -> teleport.trust.v1.GenerateHostCertRequest + 0, // 19: teleport.trust.v1.TrustService.UpsertTrustedCluster:input_type -> teleport.trust.v1.UpsertTrustedClusterRequest + 1, // 20: teleport.trust.v1.TrustService.CreateTrustedCluster:input_type -> teleport.trust.v1.CreateTrustedClusterRequest + 2, // 21: teleport.trust.v1.TrustService.UpdateTrustedCluster:input_type -> teleport.trust.v1.UpdateTrustedClusterRequest + 16, // 22: teleport.trust.v1.TrustService.GetCertAuthority:output_type -> types.CertAuthorityV2 + 5, // 23: teleport.trust.v1.TrustService.GetCertAuthorities:output_type -> teleport.trust.v1.GetCertAuthoritiesResponse + 19, // 24: teleport.trust.v1.TrustService.DeleteCertAuthority:output_type -> google.protobuf.Empty + 16, // 25: teleport.trust.v1.TrustService.UpsertCertAuthority:output_type -> types.CertAuthorityV2 + 10, // 26: teleport.trust.v1.TrustService.RotateCertAuthority:output_type -> teleport.trust.v1.RotateCertAuthorityResponse + 12, // 27: teleport.trust.v1.TrustService.RotateExternalCertAuthority:output_type -> teleport.trust.v1.RotateExternalCertAuthorityResponse + 14, // 28: teleport.trust.v1.TrustService.GenerateHostCert:output_type -> teleport.trust.v1.GenerateHostCertResponse + 15, // 29: teleport.trust.v1.TrustService.UpsertTrustedCluster:output_type -> types.TrustedClusterV2 + 15, // 30: teleport.trust.v1.TrustService.CreateTrustedCluster:output_type -> types.TrustedClusterV2 + 15, // 31: teleport.trust.v1.TrustService.UpdateTrustedCluster:output_type -> types.TrustedClusterV2 + 22, // [22:32] is the sub-list for method output_type + 12, // [12:22] is the sub-list for method input_type + 12, // [12:12] is the sub-list for extension type_name + 12, // [12:12] is the sub-list for extension extendee + 0, // [0:12] is the sub-list for field type_name } func init() { file_teleport_trust_v1_trust_service_proto_init() } @@ -956,7 +1143,7 @@ func file_teleport_trust_v1_trust_service_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_teleport_trust_v1_trust_service_proto_rawDesc, NumEnums: 0, - NumMessages: 12, + NumMessages: 15, NumExtensions: 0, NumServices: 1, }, diff --git a/api/gen/proto/go/teleport/trust/v1/trust_service_grpc.pb.go b/api/gen/proto/go/teleport/trust/v1/trust_service_grpc.pb.go index 5a91787708411..4cdc57fe369e1 100644 --- a/api/gen/proto/go/teleport/trust/v1/trust_service_grpc.pb.go +++ b/api/gen/proto/go/teleport/trust/v1/trust_service_grpc.pb.go @@ -42,6 +42,9 @@ const ( TrustService_RotateCertAuthority_FullMethodName = "/teleport.trust.v1.TrustService/RotateCertAuthority" TrustService_RotateExternalCertAuthority_FullMethodName = "/teleport.trust.v1.TrustService/RotateExternalCertAuthority" TrustService_GenerateHostCert_FullMethodName = "/teleport.trust.v1.TrustService/GenerateHostCert" + TrustService_UpsertTrustedCluster_FullMethodName = "/teleport.trust.v1.TrustService/UpsertTrustedCluster" + TrustService_CreateTrustedCluster_FullMethodName = "/teleport.trust.v1.TrustService/CreateTrustedCluster" + TrustService_UpdateTrustedCluster_FullMethodName = "/teleport.trust.v1.TrustService/UpdateTrustedCluster" ) // TrustServiceClient is the client API for TrustService service. @@ -65,6 +68,12 @@ type TrustServiceClient interface { // GenerateHostCert takes a public key in the OpenSSH `authorized_keys` format and returns // a SSH certificate signed by the Host CA. GenerateHostCert(ctx context.Context, in *GenerateHostCertRequest, opts ...grpc.CallOption) (*GenerateHostCertResponse, error) + // UpsertTrustedCluster upserts a Trusted Cluster in a backend. + UpsertTrustedCluster(ctx context.Context, in *UpsertTrustedClusterRequest, opts ...grpc.CallOption) (*types.TrustedClusterV2, error) + // CreateTrustedCluster creates a Trusted Cluster in a backend. + CreateTrustedCluster(ctx context.Context, in *CreateTrustedClusterRequest, opts ...grpc.CallOption) (*types.TrustedClusterV2, error) + // UpdateTrustedCluster updates a Trusted Cluster in a backend. + UpdateTrustedCluster(ctx context.Context, in *UpdateTrustedClusterRequest, opts ...grpc.CallOption) (*types.TrustedClusterV2, error) } type trustServiceClient struct { @@ -145,6 +154,36 @@ func (c *trustServiceClient) GenerateHostCert(ctx context.Context, in *GenerateH return out, nil } +func (c *trustServiceClient) UpsertTrustedCluster(ctx context.Context, in *UpsertTrustedClusterRequest, opts ...grpc.CallOption) (*types.TrustedClusterV2, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(types.TrustedClusterV2) + err := c.cc.Invoke(ctx, TrustService_UpsertTrustedCluster_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *trustServiceClient) CreateTrustedCluster(ctx context.Context, in *CreateTrustedClusterRequest, opts ...grpc.CallOption) (*types.TrustedClusterV2, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(types.TrustedClusterV2) + err := c.cc.Invoke(ctx, TrustService_CreateTrustedCluster_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *trustServiceClient) UpdateTrustedCluster(ctx context.Context, in *UpdateTrustedClusterRequest, opts ...grpc.CallOption) (*types.TrustedClusterV2, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(types.TrustedClusterV2) + err := c.cc.Invoke(ctx, TrustService_UpdateTrustedCluster_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + // TrustServiceServer is the server API for TrustService service. // All implementations must embed UnimplementedTrustServiceServer // for forward compatibility. @@ -166,6 +205,12 @@ type TrustServiceServer interface { // GenerateHostCert takes a public key in the OpenSSH `authorized_keys` format and returns // a SSH certificate signed by the Host CA. GenerateHostCert(context.Context, *GenerateHostCertRequest) (*GenerateHostCertResponse, error) + // UpsertTrustedCluster upserts a Trusted Cluster in a backend. + UpsertTrustedCluster(context.Context, *UpsertTrustedClusterRequest) (*types.TrustedClusterV2, error) + // CreateTrustedCluster creates a Trusted Cluster in a backend. + CreateTrustedCluster(context.Context, *CreateTrustedClusterRequest) (*types.TrustedClusterV2, error) + // UpdateTrustedCluster updates a Trusted Cluster in a backend. + UpdateTrustedCluster(context.Context, *UpdateTrustedClusterRequest) (*types.TrustedClusterV2, error) mustEmbedUnimplementedTrustServiceServer() } @@ -197,6 +242,15 @@ func (UnimplementedTrustServiceServer) RotateExternalCertAuthority(context.Conte func (UnimplementedTrustServiceServer) GenerateHostCert(context.Context, *GenerateHostCertRequest) (*GenerateHostCertResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method GenerateHostCert not implemented") } +func (UnimplementedTrustServiceServer) UpsertTrustedCluster(context.Context, *UpsertTrustedClusterRequest) (*types.TrustedClusterV2, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpsertTrustedCluster not implemented") +} +func (UnimplementedTrustServiceServer) CreateTrustedCluster(context.Context, *CreateTrustedClusterRequest) (*types.TrustedClusterV2, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateTrustedCluster not implemented") +} +func (UnimplementedTrustServiceServer) UpdateTrustedCluster(context.Context, *UpdateTrustedClusterRequest) (*types.TrustedClusterV2, error) { + return nil, status.Errorf(codes.Unimplemented, "method UpdateTrustedCluster not implemented") +} func (UnimplementedTrustServiceServer) mustEmbedUnimplementedTrustServiceServer() {} func (UnimplementedTrustServiceServer) testEmbeddedByValue() {} @@ -344,6 +398,60 @@ func _TrustService_GenerateHostCert_Handler(srv interface{}, ctx context.Context return interceptor(ctx, in, info, handler) } +func _TrustService_UpsertTrustedCluster_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpsertTrustedClusterRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TrustServiceServer).UpsertTrustedCluster(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TrustService_UpsertTrustedCluster_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TrustServiceServer).UpsertTrustedCluster(ctx, req.(*UpsertTrustedClusterRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TrustService_CreateTrustedCluster_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateTrustedClusterRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TrustServiceServer).CreateTrustedCluster(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TrustService_CreateTrustedCluster_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TrustServiceServer).CreateTrustedCluster(ctx, req.(*CreateTrustedClusterRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _TrustService_UpdateTrustedCluster_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateTrustedClusterRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(TrustServiceServer).UpdateTrustedCluster(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: TrustService_UpdateTrustedCluster_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(TrustServiceServer).UpdateTrustedCluster(ctx, req.(*UpdateTrustedClusterRequest)) + } + return interceptor(ctx, in, info, handler) +} + // TrustService_ServiceDesc is the grpc.ServiceDesc for TrustService service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -379,6 +487,18 @@ var TrustService_ServiceDesc = grpc.ServiceDesc{ MethodName: "GenerateHostCert", Handler: _TrustService_GenerateHostCert_Handler, }, + { + MethodName: "UpsertTrustedCluster", + Handler: _TrustService_UpsertTrustedCluster_Handler, + }, + { + MethodName: "CreateTrustedCluster", + Handler: _TrustService_CreateTrustedCluster_Handler, + }, + { + MethodName: "UpdateTrustedCluster", + Handler: _TrustService_UpdateTrustedCluster_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "teleport/trust/v1/trust_service.proto", diff --git a/api/proto/teleport/legacy/client/proto/authservice.proto b/api/proto/teleport/legacy/client/proto/authservice.proto index d5852268b27e2..fc6dc146ff248 100644 --- a/api/proto/teleport/legacy/client/proto/authservice.proto +++ b/api/proto/teleport/legacy/client/proto/authservice.proto @@ -3308,7 +3308,11 @@ service AuthService { // GetTrustedClusters gets all current Trusted Cluster resources. rpc GetTrustedClusters(google.protobuf.Empty) returns (types.TrustedClusterV2List); // UpsertTrustedCluster upserts a Trusted Cluster in a backend. - rpc UpsertTrustedCluster(types.TrustedClusterV2) returns (types.TrustedClusterV2); + // + // Deprecated: Use [teleport.trust.v1.UpsertTrustedCluster] instead. + rpc UpsertTrustedCluster(types.TrustedClusterV2) returns (types.TrustedClusterV2) { + option deprecated = true; + } // DeleteTrustedCluster deletes an existing Trusted Cluster in a backend by name. rpc DeleteTrustedCluster(types.ResourceRequest) returns (google.protobuf.Empty); diff --git a/api/proto/teleport/trust/v1/trust_service.proto b/api/proto/teleport/trust/v1/trust_service.proto index a6b3fc3282c44..7d8748f2375f7 100644 --- a/api/proto/teleport/trust/v1/trust_service.proto +++ b/api/proto/teleport/trust/v1/trust_service.proto @@ -40,6 +40,31 @@ service TrustService { // GenerateHostCert takes a public key in the OpenSSH `authorized_keys` format and returns // a SSH certificate signed by the Host CA. rpc GenerateHostCert(GenerateHostCertRequest) returns (GenerateHostCertResponse); + + // UpsertTrustedCluster upserts a Trusted Cluster in a backend. + rpc UpsertTrustedCluster(UpsertTrustedClusterRequest) returns (types.TrustedClusterV2); + // CreateTrustedCluster creates a Trusted Cluster in a backend. + rpc CreateTrustedCluster(CreateTrustedClusterRequest) returns (types.TrustedClusterV2); + // UpdateTrustedCluster updates a Trusted Cluster in a backend. + rpc UpdateTrustedCluster(UpdateTrustedClusterRequest) returns (types.TrustedClusterV2); +} + +// Request for UpsertTrustedCluster. +message UpsertTrustedClusterRequest { + // TrustedCluster specifies a Trusted Cluster resource. + types.TrustedClusterV2 trusted_cluster = 1; +} + +// Request for CreateTrustedCluster. +message CreateTrustedClusterRequest { + // TrustedCluster specifies a Trusted Cluster resource. + types.TrustedClusterV2 trusted_cluster = 1; +} + +// Request for UpdateTrustedCluster. +message UpdateTrustedClusterRequest { + // TrustedCluster specifies a Trusted Cluster resource. + types.TrustedClusterV2 trusted_cluster = 1; } // Request for GetCertAuthority diff --git a/api/types/trustedcluster.go b/api/types/trustedcluster.go index 27d8129f70cfe..17d397525a7df 100644 --- a/api/types/trustedcluster.go +++ b/api/types/trustedcluster.go @@ -29,8 +29,8 @@ import ( // TrustedCluster holds information needed for a cluster that can not be directly // accessed (maybe be behind firewall without any open ports) to join a parent cluster. type TrustedCluster interface { - // Resource provides common resource properties - Resource + // ResourceWithOrigin provides common resource properties + ResourceWithOrigin // SetMetadata sets object metadata SetMetadata(meta Metadata) // GetEnabled returns the state of the TrustedCluster. @@ -184,6 +184,16 @@ func (c *TrustedClusterV2) SetName(e string) { c.Metadata.Name = e } +// Origin returns the origin value of the resource. +func (c *TrustedClusterV2) Origin() string { + return c.Metadata.Origin() +} + +// SetOrigin sets the origin value of the resource. +func (c *TrustedClusterV2) SetOrigin(origin string) { + c.Metadata.SetOrigin(origin) +} + // GetEnabled returns the state of the TrustedCluster. func (c *TrustedClusterV2) GetEnabled() bool { return c.Spec.Enabled @@ -252,14 +262,6 @@ func (c *TrustedClusterV2) CanChangeStateTo(t TrustedCluster) error { if !slices.Equal(c.GetRoles(), t.GetRoles()) { return immutableFieldErr("roles") } - - if c.GetEnabled() == t.GetEnabled() && c.GetRoleMap().IsEqual(t.GetRoleMap()) { - if t.GetEnabled() { - return trace.AlreadyExists("leaf cluster is already enabled, this update would have no effect") - } - return trace.AlreadyExists("leaf cluster is already disabled, this update would have no effect") - } - return nil } diff --git a/integration/helpers/trustedclusters.go b/integration/helpers/trustedclusters.go index 1b3f43b61507c..cfc68f571ce5d 100644 --- a/integration/helpers/trustedclusters.go +++ b/integration/helpers/trustedclusters.go @@ -61,7 +61,66 @@ func TryCreateTrustedCluster(t *testing.T, authServer *auth.Server, trustedClust ctx := context.TODO() for i := 0; i < 10; i++ { log.Debugf("Will create trusted cluster %v, attempt %v.", trustedCluster, i) - _, err := authServer.UpsertTrustedCluster(ctx, trustedCluster) + _, err := authServer.CreateTrustedCluster(ctx, trustedCluster) + if err == nil { + return + } + if trace.IsConnectionProblem(err) { + log.Debugf("Retrying on connection problem: %v.", err) + time.Sleep(500 * time.Millisecond) + continue + } + if trace.IsAccessDenied(err) { + log.Debugf("Retrying on access denied: %v.", err) + time.Sleep(500 * time.Millisecond) + continue + } + require.FailNow(t, "Terminating on unexpected problem", "%v.", err) + } + require.FailNow(t, "Timeout creating trusted cluster") +} + +// TryUpdateTrustedCluster performs several attempts to update a trusted cluster, +// retries on connection problems and access denied errors to let caches +// propagate and services to start +func TryUpdateTrustedCluster(t *testing.T, authServer *auth.Server, trustedCluster types.TrustedCluster) { + t.Helper() + ctx := context.TODO() + for i := 0; i < 10; i++ { + log.Debugf("Will create trusted cluster %v, attempt %v.", trustedCluster, i) + _, err := authServer.UpdateTrustedCluster(ctx, trustedCluster) + if err == nil { + return + } + if trace.IsConnectionProblem(err) { + log.Debugf("Retrying on connection problem: %v.", err) + time.Sleep(500 * time.Millisecond) + continue + } + if trace.IsAccessDenied(err) { + log.Debugf("Retrying on access denied: %v.", err) + time.Sleep(500 * time.Millisecond) + continue + } + require.FailNow(t, "Terminating on unexpected problem", "%v.", err) + } + require.FailNow(t, "Timeout creating trusted cluster") +} + +// TryUpdateTrustedCluster performs several attempts to upsert a trusted cluster, +// retries on connection problems and access denied errors to let caches +// propagate and services to start +func TryUpsertTrustedCluster(t *testing.T, authServer *auth.Server, trustedCluster types.TrustedCluster, skipNameValidation bool) { + t.Helper() + ctx := context.TODO() + for i := 0; i < 10; i++ { + log.Debugf("Will create trusted cluster %v, attempt %v.", trustedCluster, i) + var err error + if skipNameValidation { + _, err = authServer.UpsertTrustedCluster(ctx, trustedCluster) + } else { + _, err = authServer.UpsertTrustedClusterV2(ctx, trustedCluster) + } if err == nil { return } diff --git a/integration/integration_test.go b/integration/integration_test.go index 9b5ff50af1f85..9dcb2332b44e6 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -196,6 +196,8 @@ func TestIntegrations(t *testing.T) { t.Run("TrustedDisabledClusters", suite.bind(testDisabledTrustedClusters)) t.Run("TrustedClustersRoleMapChanges", suite.bind(testTrustedClustersRoleMapChanges)) t.Run("TrustedClustersWithLabels", suite.bind(testTrustedClustersWithLabels)) + t.Run("TrustedClustersSkipNameValidation", suite.bind(testTrustedClustersSkipNameValidation)) + t.Run("CreateAndUpdateTrustedClusters", suite.bind(testCreateAndUpdateTrustedClusters)) t.Run("TrustedTunnelNode", suite.bind(testTrustedTunnelNode)) t.Run("TwoClustersProxy", suite.bind(testTwoClustersProxy)) t.Run("TwoClustersTunnel", suite.bind(testTwoClustersTunnel)) @@ -2744,17 +2746,14 @@ func testMapRoles(t *testing.T, suite *integrationTestSuite) { {Remote: mainDevs, Local: []string{auxDevs}}, }) - // modify trusted cluster resource name so it would not - // match the cluster name to check that it does not matter - trustedCluster.SetName(main.Secrets.SiteName + "-cluster") - require.NoError(t, main.Start()) require.NoError(t, aux.Start()) require.NoError(t, services.CheckAndSetDefaults(trustedCluster)) // try and upsert a trusted cluster - helpers.TryCreateTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster) + const skipNameValidation = false + helpers.TryUpsertTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster, skipNameValidation) helpers.WaitForTunnelConnections(t, main.Process.GetAuthServer(), clusterAux, 1) sshPort, _, _ := aux.StartNodeAndProxy(t, "aux-node") @@ -2904,6 +2903,9 @@ type trustedClusterTest struct { // useLabels turns on trusted cluster labels and // verifies RBAC useLabels bool + // skipNameValidation uses the deprecated UpsertTrustedCluster and skips + // cluster name validation. + skipNameValidation bool } // TestTrustedClusters tests remote clusters scenarios @@ -2940,6 +2942,15 @@ func testTrustedClustersWithLabels(t *testing.T, suite *integrationTestSuite) { trustedClusters(t, suite, trustedClusterTest{multiplex: false, useLabels: true}) } +// TestTrustedClustersSkipNameValidation tests remote clusters scenarios +// skipping name validation. +func testTrustedClustersSkipNameValidation(t *testing.T, suite *integrationTestSuite) { + tr := utils.NewTracer(utils.ThisFunction()).Start() + defer tr.Stop() + + trustedClusters(t, suite, trustedClusterTest{skipNameValidation: true}) +} + // TestJumpTrustedClusters tests remote clusters scenarios // using trusted clusters feature using jumphost connection func testJumpTrustedClusters(t *testing.T, suite *integrationTestSuite) { @@ -2967,6 +2978,15 @@ func testMultiplexingTrustedClusters(t *testing.T, suite *integrationTestSuite) trustedClusters(t, suite, trustedClusterTest{multiplex: true}) } +// TestCreateAndUpdateTrustedClusters tests the basic create and update +// operations for a trusted cluster. +func testCreateAndUpdateTrustedClusters(t *testing.T, suite *integrationTestSuite) { + tr := utils.NewTracer(utils.ThisFunction()).Start() + defer tr.Stop() + + createAndUpdateTrustedClusters(t, suite, trustedClusterTest{}) +} + func standardPortsOrMuxSetup(t *testing.T, mux bool, fds *[]*servicecfg.FileDescriptor) *helpers.InstanceListeners { if mux { return helpers.WebReverseTunnelMuxPortSetup(t, fds) @@ -2974,6 +2994,116 @@ func standardPortsOrMuxSetup(t *testing.T, mux bool, fds *[]*servicecfg.FileDesc return helpers.StandardListenerSetup(t, fds) } +func createAndUpdateTrustedClusters(t *testing.T, suite *integrationTestSuite, test trustedClusterTest) { + ctx := context.Background() + username := suite.Me.Username + + clusterMain := "cluster-main" + clusterAux := "cluster-aux" + mainCfg := helpers.InstanceConfig{ + ClusterName: clusterMain, + HostID: helpers.HostID, + NodeName: Host, + Priv: suite.Priv, + Pub: suite.Pub, + Log: suite.Log, + } + mainCfg.Listeners = standardPortsOrMuxSetup(t, test.multiplex, &mainCfg.Fds) + main := helpers.NewInstance(t, mainCfg) + aux := suite.newNamedTeleportInstance(t, clusterAux) + + // main cluster has a local user and belongs to role "main-devs" and "main-admins" + mainDevs := "main-devs" + mainRole, err := types.NewRole(mainDevs, types.RoleSpecV6{ + Allow: types.RoleConditions{ + Logins: []string{username}, + NodeLabels: types.Labels{types.Wildcard: []string{types.Wildcard}}, + }, + }) + require.NoError(t, err) + + mainAdmins := "main-admins" + adminsRole, err := types.NewRole(mainAdmins, types.RoleSpecV6{ + Allow: types.RoleConditions{ + Logins: []string{"superuser"}, + NodeLabels: types.Labels{types.Wildcard: []string{types.Wildcard}}, + }, + }) + require.NoError(t, err) + + main.AddUserWithRole(username, mainRole, adminsRole) + + // for role mapping test we turn on Web API on the main cluster + // as it's used + makeConfig := func(instance *helpers.TeleInstance, enableSSH bool) (*testing.T, *servicecfg.Config) { + tconf := suite.defaultServiceConfig() + tconf.Proxy.DisableWebService = false + tconf.Proxy.DisableWebInterface = true + tconf.SSH.Enabled = enableSSH + tconf, err := instance.GenerateConfig(t, nil, tconf) + require.NoError(t, err) + + tconf.CachePolicy.Enabled = false + return t, tconf + } + lib.SetInsecureDevMode(true) + defer lib.SetInsecureDevMode(false) + + require.NoError(t, main.CreateWithConf(makeConfig(main, false))) + require.NoError(t, aux.CreateWithConf(makeConfig(aux, true))) + + // auxiliary cluster has only a role aux-devs + // connect aux cluster to main cluster + // using trusted clusters, so remote user will be allowed to assume + // role specified by mapping remote role "devs" to local role "local-devs" + auxDevs := "aux-devs" + auxRole, err := types.NewRole(auxDevs, types.RoleSpecV6{ + Allow: types.RoleConditions{ + Logins: []string{username}, + NodeLabels: types.Labels{types.Wildcard: []string{types.Wildcard}}, + }, + }) + require.NoError(t, err) + _, err = aux.Process.GetAuthServer().UpsertRole(ctx, auxRole) + require.NoError(t, err) + + trustedClusterToken := "trusted-cluster-token" + tokenResource, err := types.NewProvisionToken(trustedClusterToken, []types.SystemRole{types.RoleTrustedCluster}, time.Time{}) + require.NoError(t, err) + err = main.Process.GetAuthServer().UpsertToken(ctx, tokenResource) + require.NoError(t, err) + + trustedCluster := main.AsTrustedCluster(trustedClusterToken, types.RoleMap{ + {Remote: mainDevs, Local: []string{auxDevs}}, + }) + + require.NoError(t, main.Start()) + require.NoError(t, aux.Start()) + + require.NoError(t, services.CheckAndSetDefaults(trustedCluster)) + + // Note that the trusted cluster resource name must match the cluster name. + // Modify the trusted cluster resource name and expect the create to fail. + trustedCluster.SetName(main.Secrets.SiteName + "-cluster") + _, err = aux.Process.GetAuthServer().CreateTrustedCluster(ctx, trustedCluster) + require.ErrorContains(t, err, "trusted cluster resource name must be the same as the remote cluster name", "expected failure due to tc name mismatch") + + // Modify the trusted cluster resource name back to what it was originally. + // Try and create a trusted cluster + trustedCluster.SetName(main.Secrets.SiteName) + helpers.TryCreateTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster) + + // Update the trusted cluster resource with new role mappings. + trustedCluster.SetRoleMap(types.RoleMap{ + {Remote: mainAdmins, Local: []string{auxDevs}}, + }) + helpers.TryUpdateTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster) + + // stop clusters and remaining nodes + require.NoError(t, main.StopAll()) + require.NoError(t, aux.StopAll()) +} + func trustedClusters(t *testing.T, suite *integrationTestSuite, test trustedClusterTest) { ctx := context.Background() username := suite.Me.Username @@ -3077,17 +3207,25 @@ func trustedClusters(t *testing.T, suite *integrationTestSuite, test trustedClus {Remote: mainOps, Local: []string{auxDevs}}, }) - // modify trusted cluster resource name, so it would not - // match the cluster name to check that it does not matter - trustedCluster.SetName(main.Secrets.SiteName + "-cluster") - require.NoError(t, main.Start()) require.NoError(t, aux.Start()) require.NoError(t, services.CheckAndSetDefaults(trustedCluster)) + // Note that the trusted cluster resource name must match the cluster name. + // Modify the trusted cluster resource name and expect the upsert to fail. + trustedCluster.SetName(main.Secrets.SiteName + "-cluster") + + _, err = aux.Process.GetAuthServer().UpsertTrustedClusterV2(ctx, trustedCluster) + require.ErrorContains(t, err, "trusted cluster resource name must be the same as the remote cluster name", "expected failure due to tc name mismatch") + + if !test.skipNameValidation { + // Modify the trusted cluster resource name back to what it was originally. + trustedCluster.SetName(main.Secrets.SiteName) + } + // try and upsert a trusted cluster - helpers.TryCreateTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster) + helpers.TryUpsertTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster, test.skipNameValidation) helpers.WaitForTunnelConnections(t, main.Process.GetAuthServer(), clusterAux, 1) sshPort, _, _ := aux.StartNodeAndProxy(t, "aux-node") @@ -3174,7 +3312,7 @@ func trustedClusters(t *testing.T, suite *integrationTestSuite, test trustedClus require.Error(t, err, "expected tunnel to close and SSH client to start failing") // recreating the trusted cluster should re-establish connection - _, err = aux.Process.GetAuthServer().UpsertTrustedCluster(ctx, trustedCluster) + _, err = aux.Process.GetAuthServer().UpsertTrustedClusterV2(ctx, trustedCluster) require.NoError(t, err) // check that remote cluster has been re-provisioned @@ -3320,9 +3458,6 @@ func trustedDisabledCluster(t *testing.T, suite *integrationTestSuite, test trus {Remote: mainOps, Local: []string{auxDevs}}, }) - // modify trusted cluster resource name, so it would not - // match the cluster name to check that it does not matter - trustedCluster.SetName(main.Secrets.SiteName + "-cluster") // disable cluster trustedCluster.SetEnabled(false) @@ -3332,11 +3467,11 @@ func trustedDisabledCluster(t *testing.T, suite *integrationTestSuite, test trus require.NoError(t, services.CheckAndSetDefaults(trustedCluster)) // try and upsert a trusted cluster while disabled - helpers.TryCreateTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster) + helpers.TryUpsertTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster, test.skipNameValidation) // try to enable disabled cluster trustedCluster.SetEnabled(true) - helpers.TryCreateTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster) + helpers.TryUpsertTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster, test.skipNameValidation) helpers.WaitForTunnelConnections(t, main.Process.GetAuthServer(), clusterAux, 1) helpers.CheckTrustedClustersCanConnect(ctx, t, helpers.TrustedClusterSetup{ @@ -3460,16 +3595,12 @@ func trustedClustersRoleMapChanges(t *testing.T, suite *integrationTestSuite, te {Remote: mainOps, Local: []string{auxDevs}}, }) - // modify trusted cluster resource name, so it would not - // match the cluster name to check that it does not matter - trustedCluster.SetName(main.Secrets.SiteName + "-cluster") - require.NoError(t, main.Start()) require.NoError(t, aux.Start()) require.NoError(t, services.CheckAndSetDefaults(trustedCluster)) - helpers.TryCreateTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster) + helpers.TryUpsertTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster, test.skipNameValidation) helpers.WaitForTunnelConnections(t, main.Process.GetAuthServer(), clusterAux, 1) // change role mapping to ensure updating works @@ -3477,7 +3608,7 @@ func trustedClustersRoleMapChanges(t *testing.T, suite *integrationTestSuite, te {Remote: mainDevs, Local: []string{auxDevs}}, }) - helpers.TryCreateTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster) + helpers.TryUpsertTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster, test.skipNameValidation) helpers.WaitForTunnelConnections(t, main.Process.GetAuthServer(), clusterAux, 1) helpers.CheckTrustedClustersCanConnect(ctx, t, helpers.TrustedClusterSetup{ @@ -3490,7 +3621,7 @@ func trustedClustersRoleMapChanges(t *testing.T, suite *integrationTestSuite, te // disable the enabled trusted cluster and ensure it no longer works trustedCluster.SetEnabled(false) - helpers.TryCreateTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster) + helpers.TryUpsertTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster, test.skipNameValidation) // Wait for both cluster to no longer see each other via reverse tunnels. require.Eventually(t, helpers.WaitForClusters(main.Tunnel, 0), 10*time.Second, 1*time.Second, @@ -3561,17 +3692,14 @@ func testTrustedTunnelNode(t *testing.T, suite *integrationTestSuite) { {Remote: mainDevs, Local: []string{auxDevs}}, }) - // modify trusted cluster resource name, so it would not - // match the cluster name to check that it does not matter - trustedCluster.SetName(main.Secrets.SiteName + "-cluster") - require.NoError(t, main.Start()) require.NoError(t, aux.Start()) require.NoError(t, services.CheckAndSetDefaults(trustedCluster)) // try and upsert a trusted cluster - helpers.TryCreateTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster) + const skipNameValidation = false + helpers.TryUpsertTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster, skipNameValidation) helpers.WaitForTunnelConnections(t, main.Process.GetAuthServer(), clusterAux, 1) // Create a Teleport instance with a node that dials back to the aux cluster. @@ -3745,17 +3873,14 @@ func testTrustedClusterAgentless(t *testing.T, suite *integrationTestSuite) { {Remote: devsRoleName, Local: []string{devsRoleName}}, }) - // modify trusted cluster resource name, so it would not - // match the cluster name to check that it does not matter - trustedCluster.SetName(main.Secrets.SiteName + "-cluster") - require.NoError(t, main.Start()) require.NoError(t, leaf.Start()) require.NoError(t, services.CheckAndSetDefaults(trustedCluster)) // try and upsert a trusted cluster - helpers.TryCreateTrustedCluster(t, leaf.Process.GetAuthServer(), trustedCluster) + const skipNameValidation = false + helpers.TryUpsertTrustedCluster(t, leaf.Process.GetAuthServer(), trustedCluster, skipNameValidation) helpers.WaitForTunnelConnections(t, main.Process.GetAuthServer(), clusterAux, 1) // Wait for both cluster to see each other via reverse tunnels. @@ -5583,7 +5708,8 @@ func testRotateTrustedClusters(t *testing.T, suite *integrationTestSuite) { lib.SetInsecureDevMode(true) defer lib.SetInsecureDevMode(false) - helpers.TryCreateTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster) + const skipNameValidation = false + helpers.TryUpsertTrustedCluster(t, aux.Process.GetAuthServer(), trustedCluster, skipNameValidation) helpers.WaitForTunnelConnections(t, svc.GetAuthServer(), aux.Secrets.SiteName, 1) // capture credentials before reload has started to simulate old client @@ -7482,7 +7608,9 @@ func createTrustedClusterPair(t *testing.T, suite *integrationTestSuite, extraSe t.Cleanup(func() { leaf.StopAll() }) require.NoError(t, services.CheckAndSetDefaults(trustedCluster)) - helpers.TryCreateTrustedCluster(t, leaf.Process.GetAuthServer(), trustedCluster) + + const skipNameValidation = false + helpers.TryUpsertTrustedCluster(t, leaf.Process.GetAuthServer(), trustedCluster, skipNameValidation) helpers.WaitForTunnelConnections(t, root.Process.GetAuthServer(), leafName, 1) _, _, rootProxySSHPort := root.StartNodeAndProxy(t, "root-zero") diff --git a/integration/kube_integration_test.go b/integration/kube_integration_test.go index c9fd5ff21efdb..2127486ff7a7f 100644 --- a/integration/kube_integration_test.go +++ b/integration/kube_integration_test.go @@ -695,7 +695,7 @@ func testKubeTrustedClustersClientCert(t *testing.T, suite *KubeSuite) { var upsertSuccess bool for i := 0; i < 10; i++ { log.Debugf("Will create trusted cluster %v, attempt %v", trustedCluster, i) - _, err = aux.Process.GetAuthServer().UpsertTrustedCluster(ctx, trustedCluster) + _, err = aux.Process.GetAuthServer().UpsertTrustedClusterV2(ctx, trustedCluster) if err != nil { if trace.IsConnectionProblem(err) { log.Debugf("retrying on connection problem: %v", err) @@ -971,7 +971,7 @@ func testKubeTrustedClustersSNI(t *testing.T, suite *KubeSuite) { var upsertSuccess bool for i := 0; i < 10; i++ { log.Debugf("Will create trusted cluster %v, attempt %v", trustedCluster, i) - _, err = aux.Process.GetAuthServer().UpsertTrustedCluster(ctx, trustedCluster) + _, err = aux.Process.GetAuthServer().UpsertTrustedClusterV2(ctx, trustedCluster) if err != nil { if trace.IsConnectionProblem(err) { log.Debugf("retrying on connection problem: %v", err) diff --git a/integration/proxy/proxy_helpers.go b/integration/proxy/proxy_helpers.go index e0e3c7b587224..9de514caf73e1 100644 --- a/integration/proxy/proxy_helpers.go +++ b/integration/proxy/proxy_helpers.go @@ -184,7 +184,8 @@ func newSuite(t *testing.T, opts ...proxySuiteOptionsFunc) *Suite { } if options.trustedCluster != nil { - helpers.TryCreateTrustedCluster(t, suite.leaf.Process.GetAuthServer(), options.trustedCluster) + const skipNameValidation = false + helpers.TryUpsertTrustedCluster(t, suite.leaf.Process.GetAuthServer(), options.trustedCluster, skipNameValidation) helpers.WaitForTunnelConnections(t, suite.root.Process.GetAuthServer(), suite.leaf.Secrets.SiteName, 1) } diff --git a/lib/auth/auth_test.go b/lib/auth/auth_test.go index 8f535a1727588..b9e9eb0a5aa8b 100644 --- a/lib/auth/auth_test.go +++ b/lib/auth/auth_test.go @@ -1262,7 +1262,7 @@ func TestTrustedClusterCRUDEventEmitted(t *testing.T) { // test create event for switch case: when tc exists but enabled is false tc.SetEnabled(false) - _, err = s.a.UpsertTrustedCluster(ctx, tc) + _, err = s.a.UpsertTrustedClusterV2(ctx, tc) require.NoError(t, err) require.Equal(t, events.TrustedClusterCreateEvent, s.mockEmitter.LastEvent().GetType()) createEvt := s.mockEmitter.LastEvent().(*apievents.TrustedClusterCreate) @@ -1272,7 +1272,7 @@ func TestTrustedClusterCRUDEventEmitted(t *testing.T) { // test create event for switch case: when tc exists but enabled is true tc.SetEnabled(true) - _, err = s.a.UpsertTrustedCluster(ctx, tc) + _, err = s.a.UpsertTrustedClusterV2(ctx, tc) require.NoError(t, err) require.Equal(t, events.TrustedClusterCreateEvent, s.mockEmitter.LastEvent().GetType()) createEvt = s.mockEmitter.LastEvent().(*apievents.TrustedClusterCreate) diff --git a/lib/auth/grpcserver.go b/lib/auth/grpcserver.go index 2699035c0b211..5d13991dfbc4a 100644 --- a/lib/auth/grpcserver.go +++ b/lib/auth/grpcserver.go @@ -3014,6 +3014,8 @@ func (g *GRPCServer) GetTrustedClusters(ctx context.Context, _ *emptypb.Empty) ( } // UpsertTrustedCluster upserts a Trusted Cluster. +// +// Deprecated: Use UpsertTrustedClusterV2 instead. func (g *GRPCServer) UpsertTrustedCluster(ctx context.Context, cluster *types.TrustedClusterV2) (*types.TrustedClusterV2, error) { auth, err := g.authenticate(ctx) if err != nil { diff --git a/lib/auth/trust/trustv1/service.go b/lib/auth/trust/trustv1/service.go index 91f99a4819be9..c0dfd564ea4a7 100644 --- a/lib/auth/trust/trustv1/service.go +++ b/lib/auth/trust/trustv1/service.go @@ -44,6 +44,13 @@ type authServer interface { // RotateCertAuthority starts or restarts certificate authority rotation process. RotateCertAuthority(ctx context.Context, req types.RotateRequest) error + + // UpsertTrustedClusterV2 upserts a Trusted Cluster. + UpsertTrustedClusterV2(ctx context.Context, tc types.TrustedCluster) (types.TrustedCluster, error) + // CreateTrustedCluster creates a Trusted Cluster. + CreateTrustedCluster(ctx context.Context, tc types.TrustedCluster) (types.TrustedCluster, error) + // UpdateTrustedCluster updates a Trusted Cluster. + UpdateTrustedCluster(ctx context.Context, tc types.TrustedCluster) (types.TrustedCluster, error) } // ServiceConfig holds configuration options for diff --git a/lib/auth/trust/trustv1/service_test.go b/lib/auth/trust/trustv1/service_test.go index 152c2558c22b3..23ae66a5149b5 100644 --- a/lib/auth/trust/trustv1/service_test.go +++ b/lib/auth/trust/trustv1/service_test.go @@ -100,6 +100,18 @@ func (f *fakeAuthServer) RotateCertAuthority(ctx context.Context, req types.Rota return f.rotateCertAuthorityData[string(req.Type)] } +func (f *fakeAuthServer) UpsertTrustedClusterV2(ctx context.Context, tc types.TrustedCluster) (types.TrustedCluster, error) { + return tc, nil +} + +func (f *fakeAuthServer) CreateTrustedCluster(ctx context.Context, tc types.TrustedCluster) (types.TrustedCluster, error) { + return tc, nil +} + +func (f *fakeAuthServer) UpdateTrustedCluster(ctx context.Context, tc types.TrustedCluster) (types.TrustedCluster, error) { + return tc, nil +} + type fakeChecker struct { services.AccessChecker allow map[check]bool diff --git a/lib/auth/trust/trustv1/trustedcluster.go b/lib/auth/trust/trustv1/trustedcluster.go new file mode 100644 index 0000000000000..48f57a43ba0ec --- /dev/null +++ b/lib/auth/trust/trustv1/trustedcluster.go @@ -0,0 +1,126 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package trustv1 + +import ( + "context" + + "github.com/gravitational/trace" + + trustpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/trust/v1" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/modules" + "github.com/gravitational/teleport/lib/services" +) + +// UpsertTrustedCluster upserts a Trusted Cluster. +func (s *Service) UpsertTrustedCluster(ctx context.Context, req *trustpb.UpsertTrustedClusterRequest) (*types.TrustedClusterV2, error) { + // Don't allow a Cloud tenant to be a leaf cluster. + if modules.GetModules().Features().Cloud { + return nil, trace.NotImplemented("cloud tenants cannot be leaf clusters") + } + + authCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + if err := authCtx.CheckAccessToKind(types.KindTrustedCluster, types.VerbCreate, types.VerbUpdate); err != nil { + return nil, trace.Wrap(err) + } + if err := authCtx.AuthorizeAdminActionAllowReusedMFA(); err != nil { + return nil, trace.Wrap(err) + } + + if err = services.ValidateTrustedCluster(req.GetTrustedCluster()); err != nil { + return nil, trace.Wrap(err) + } + tc, err := s.authServer.UpsertTrustedClusterV2(ctx, req.GetTrustedCluster()) + if err != nil { + return nil, trace.Wrap(err) + } + trustedClusterV2, ok := tc.(*types.TrustedClusterV2) + if !ok { + return nil, trace.Errorf("encountered unexpected Trusted Cluster type: %T", tc) + } + return trustedClusterV2, nil +} + +// CreateTrustedCluster creates a Trusted Cluster. +func (s *Service) CreateTrustedCluster(ctx context.Context, req *trustpb.CreateTrustedClusterRequest) (*types.TrustedClusterV2, error) { + // Don't allow a Cloud tenant to be a leaf cluster. + if modules.GetModules().Features().Cloud { + return nil, trace.NotImplemented("cloud tenants cannot be leaf clusters") + } + + authCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + if err := authCtx.CheckAccessToKind(types.KindTrustedCluster, types.VerbCreate); err != nil { + return nil, trace.Wrap(err) + } + if err := authCtx.AuthorizeAdminActionAllowReusedMFA(); err != nil { + return nil, trace.Wrap(err) + } + + if err = services.ValidateTrustedCluster(req.GetTrustedCluster()); err != nil { + return nil, trace.Wrap(err) + } + tc, err := s.authServer.CreateTrustedCluster(ctx, req.GetTrustedCluster()) + if err != nil { + return nil, trace.Wrap(err) + } + trustedClusterV2, ok := tc.(*types.TrustedClusterV2) + if !ok { + return nil, trace.Errorf("encountered unexpected Trusted Cluster type: %T", tc) + } + return trustedClusterV2, nil +} + +// UpdateTrustedCluster updates a Trusted Cluster. +func (s *Service) UpdateTrustedCluster(ctx context.Context, req *trustpb.UpdateTrustedClusterRequest) (*types.TrustedClusterV2, error) { + // Don't allow a Cloud tenant to be a leaf cluster. + if modules.GetModules().Features().Cloud { + return nil, trace.NotImplemented("cloud tenants cannot be leaf clusters") + } + + authCtx, err := s.authorizer.Authorize(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + if err := authCtx.CheckAccessToKind(types.KindTrustedCluster, types.VerbUpdate); err != nil { + return nil, trace.Wrap(err) + } + if err := authCtx.AuthorizeAdminActionAllowReusedMFA(); err != nil { + return nil, trace.Wrap(err) + } + + if err = services.ValidateTrustedCluster(req.GetTrustedCluster()); err != nil { + return nil, trace.Wrap(err) + } + tc, err := s.authServer.UpdateTrustedCluster(ctx, req.GetTrustedCluster()) + if err != nil { + return nil, trace.Wrap(err) + } + trustedClusterV2, ok := tc.(*types.TrustedClusterV2) + if !ok { + return nil, trace.Errorf("encountered unexpected Trusted Cluster type: %T", tc) + } + return trustedClusterV2, nil +} diff --git a/lib/auth/trust/trustv1/trustedcluster_test.go b/lib/auth/trust/trustv1/trustedcluster_test.go new file mode 100644 index 0000000000000..d4aea850fedc4 --- /dev/null +++ b/lib/auth/trust/trustv1/trustedcluster_test.go @@ -0,0 +1,281 @@ +/* + * Teleport + * Copyright (C) 2024 Gravitational, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package trustv1 + +import ( + "context" + "testing" + + "github.com/gravitational/trace" + "github.com/stretchr/testify/require" + + "github.com/gravitational/teleport" + trustpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/trust/v1" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/modules" + "github.com/gravitational/teleport/lib/services/local" +) + +// TestCloudProhibited verifies that Trusted Clusters cannot be created or updated +// in a Cloud hosted environment. +// Tests cannot be run in parallel because it relies on environment variables. +func TestCloudProhibited(t *testing.T) { + ctx := context.Background() + p := newTestPack(t) + + trust := local.NewCAService(p.mem) + cfg := &ServiceConfig{ + Cache: trust, + Backend: trust, + Authorizer: &fakeAuthorizer{}, + AuthServer: &fakeAuthServer{}, + } + + service, err := NewService(cfg) + require.NoError(t, err) + + modules.SetTestModules(t, &modules.TestModules{ + TestFeatures: modules.Features{Cloud: true}, + }) + + tc, err := types.NewTrustedCluster("test", types.TrustedClusterSpecV2{ + RoleMap: []types.RoleMapping{ + {Remote: teleport.PresetAccessRoleName, Local: []string{teleport.PresetAccessRoleName}}, + }, + }) + require.NoError(t, err, "creating trusted cluster resource") + + trustedClusterV2, ok := tc.(*types.TrustedClusterV2) + require.True(t, ok) + + t.Run("Cloud prohibits being a leaf cluster (UpsertTrustedCluster)", func(t *testing.T) { + _, err = service.UpsertTrustedCluster(ctx, &trustpb.UpsertTrustedClusterRequest{ + TrustedCluster: trustedClusterV2, + }) + require.True(t, trace.IsNotImplemented(err), "UpsertTrustedClusterV2 returned an unexpected error, got = %v (%T), want trace.NotImplementedError", err, err) + }) + + t.Run("Cloud prohibits being a leaf cluster (CreateTrustedCluster)", func(t *testing.T) { + _, err = service.CreateTrustedCluster(ctx, &trustpb.CreateTrustedClusterRequest{ + TrustedCluster: trustedClusterV2, + }) + require.True(t, trace.IsNotImplemented(err), "CreateTrustedCluster returned an unexpected error, got = %v (%T), want trace.NotImplementedError", err, err) + }) + + t.Run("Cloud prohibits being a leaf cluster (UpdateTrustedCluster)", func(t *testing.T) { + _, err = service.UpdateTrustedCluster(ctx, &trustpb.UpdateTrustedClusterRequest{ + TrustedCluster: trustedClusterV2, + }) + require.True(t, trace.IsNotImplemented(err), "UpdateTrustedCluster returned an unexpected error, got = %v (%T), want trace.NotImplementedError", err, err) + }) +} + +func TestTrustedClusterRBAC(t *testing.T) { + t.Parallel() + ctx := context.Background() + p := newTestPack(t) + + tc, err := types.NewTrustedCluster("test", types.TrustedClusterSpecV2{ + RoleMap: []types.RoleMapping{ + {Remote: teleport.PresetAccessRoleName, Local: []string{teleport.PresetAccessRoleName}}, + }, + }) + require.NoError(t, err, "creating trusted cluster resource") + + trustedClusterV2, ok := tc.(*types.TrustedClusterV2) + require.True(t, ok) + + tests := []struct { + desc string + f func(t *testing.T, service *Service) + authorizer fakeAuthorizer + expectChecks []check + }{ + { + desc: "upsert no access", + f: func(t *testing.T, service *Service) { + _, err := service.UpsertTrustedCluster(ctx, &trustpb.UpsertTrustedClusterRequest{ + TrustedCluster: trustedClusterV2, + }) + require.True(t, trace.IsAccessDenied(err), "expected AccessDenied error, got %v", err) + }, + authorizer: fakeAuthorizer{ + checker: &fakeChecker{ + allow: map[check]bool{}, + }, + }, + expectChecks: []check{ + {types.KindTrustedCluster, types.VerbCreate}, + {types.KindTrustedCluster, types.VerbUpdate}, + }, + }, + { + desc: "upsert no create access", + f: func(t *testing.T, service *Service) { + _, err := service.UpsertTrustedCluster(ctx, &trustpb.UpsertTrustedClusterRequest{ + TrustedCluster: trustedClusterV2, + }) + require.True(t, trace.IsAccessDenied(err), "expected AccessDenied error, got %v", err) + }, + authorizer: fakeAuthorizer{ + checker: &fakeChecker{ + allow: map[check]bool{ + {types.KindTrustedCluster, types.VerbCreate}: false, + {types.KindTrustedCluster, types.VerbUpdate}: true, + }, + }, + }, + expectChecks: []check{ + {types.KindTrustedCluster, types.VerbCreate}, + {types.KindTrustedCluster, types.VerbUpdate}, + }, + }, + { + desc: "upsert no update access", + f: func(t *testing.T, service *Service) { + _, err := service.UpsertTrustedCluster(ctx, &trustpb.UpsertTrustedClusterRequest{ + TrustedCluster: trustedClusterV2, + }) + require.True(t, trace.IsAccessDenied(err), "expected AccessDenied error, got %v", err) + }, + authorizer: fakeAuthorizer{ + checker: &fakeChecker{ + allow: map[check]bool{ + {types.KindTrustedCluster, types.VerbCreate}: true, + {types.KindTrustedCluster, types.VerbUpdate}: false, + }, + }, + }, + expectChecks: []check{ + {types.KindTrustedCluster, types.VerbCreate}, + {types.KindTrustedCluster, types.VerbUpdate}, + }, + }, + { + desc: "upsert ok", + f: func(t *testing.T, service *Service) { + _, err := service.UpsertTrustedCluster(ctx, &trustpb.UpsertTrustedClusterRequest{ + TrustedCluster: trustedClusterV2, + }) + require.NoError(t, err) + }, + authorizer: fakeAuthorizer{ + checker: &fakeChecker{ + allow: map[check]bool{ + {types.KindTrustedCluster, types.VerbCreate}: true, + {types.KindTrustedCluster, types.VerbUpdate}: true, + }, + }, + }, + expectChecks: []check{ + {types.KindTrustedCluster, types.VerbCreate}, + {types.KindTrustedCluster, types.VerbUpdate}, + }, + }, + { + desc: "create no access", + f: func(t *testing.T, service *Service) { + _, err := service.CreateTrustedCluster(ctx, &trustpb.CreateTrustedClusterRequest{ + TrustedCluster: trustedClusterV2, + }) + require.True(t, trace.IsAccessDenied(err), "expected AccessDenied error, got %v", err) + }, + authorizer: fakeAuthorizer{ + checker: &fakeChecker{ + allow: map[check]bool{}, + }, + }, + expectChecks: []check{ + {types.KindTrustedCluster, types.VerbCreate}, + }, + }, + { + desc: "create ok", + f: func(t *testing.T, service *Service) { + _, err := service.CreateTrustedCluster(ctx, &trustpb.CreateTrustedClusterRequest{ + TrustedCluster: trustedClusterV2, + }) + require.NoError(t, err) + }, + authorizer: fakeAuthorizer{ + checker: &fakeChecker{ + allow: map[check]bool{ + {types.KindTrustedCluster, types.VerbCreate}: true, + }, + }, + }, + expectChecks: []check{ + {types.KindTrustedCluster, types.VerbCreate}, + }, + }, + { + desc: "update no access", + f: func(t *testing.T, service *Service) { + _, err := service.UpdateTrustedCluster(ctx, &trustpb.UpdateTrustedClusterRequest{ + TrustedCluster: trustedClusterV2, + }) + require.True(t, trace.IsAccessDenied(err), "expected AccessDenied error, got %v", err) + }, + authorizer: fakeAuthorizer{ + checker: &fakeChecker{ + allow: map[check]bool{}, + }, + }, + expectChecks: []check{ + {types.KindTrustedCluster, types.VerbUpdate}, + }, + }, + { + desc: "update ok", + f: func(t *testing.T, service *Service) { + _, err := service.UpdateTrustedCluster(ctx, &trustpb.UpdateTrustedClusterRequest{ + TrustedCluster: trustedClusterV2, + }) + require.NoError(t, err) + }, + authorizer: fakeAuthorizer{ + checker: &fakeChecker{ + allow: map[check]bool{ + {types.KindTrustedCluster, types.VerbUpdate}: true, + }, + }, + }, + expectChecks: []check{ + {types.KindTrustedCluster, types.VerbUpdate}, + }, + }, + } + + for _, test := range tests { + t.Run(test.desc, func(t *testing.T) { + trust := local.NewCAService(p.mem) + cfg := &ServiceConfig{ + Cache: trust, + Backend: trust, + Authorizer: &test.authorizer, + AuthServer: &fakeAuthServer{}, + } + + service, err := NewService(cfg) + require.NoError(t, err) + test.f(t, service) + require.ElementsMatch(t, test.expectChecks, test.authorizer.checker.checks) + }) + } +} diff --git a/lib/auth/trustedcluster.go b/lib/auth/trustedcluster.go index 784d6aad010dc..e86008679d31e 100644 --- a/lib/auth/trustedcluster.go +++ b/lib/auth/trustedcluster.go @@ -30,6 +30,7 @@ import ( "github.com/gravitational/trace" "github.com/gravitational/teleport" + "github.com/gravitational/teleport/api/client/webclient" tracehttp "github.com/gravitational/teleport/api/observability/tracing/http" "github.com/gravitational/teleport/api/types" apievents "github.com/gravitational/teleport/api/types/events" @@ -45,7 +46,53 @@ import ( ) // UpsertTrustedCluster creates or toggles a Trusted Cluster relationship. +// Deprecated: UpsertTrustedClusterV2 should be preferred instead. func (a *Server) UpsertTrustedCluster(ctx context.Context, tc types.TrustedCluster) (newTrustedCluster types.TrustedCluster, returnErr error) { + const validateNameFalse = false + upserted, err := a.upsertTrustedCluster(ctx, tc, validateNameFalse) + return upserted, trace.Wrap(err) +} + +// UpsertTrustedClusterV2 creates or toggles a Trusted Cluster relationship. +// The trusted cluster resource name must match the cluster name. +func (a *Server) UpsertTrustedClusterV2(ctx context.Context, tc types.TrustedCluster) (newTrustedCluster types.TrustedCluster, returnErr error) { + const validateNameTrue = true + upserted, err := a.upsertTrustedCluster(ctx, tc, validateNameTrue) + return upserted, trace.Wrap(err) +} + +// CreateTrustedCluster creates a Trusted Cluster relationship. +func (a *Server) CreateTrustedCluster(ctx context.Context, tc types.TrustedCluster) (newTrustedCluster types.TrustedCluster, returnErr error) { + // verify that trusted cluster role map does not reference non-existent roles + if err := a.checkLocalRoles(ctx, tc.GetRoleMap()); err != nil { + return nil, trace.Wrap(err) + } + + const validateNameTrue = true + created, err := a.createTrustedCluster(ctx, tc, validateNameTrue) + return created, trace.Wrap(err) +} + +// UpdateTrustedCluster updates a Trusted Cluster relationship. +func (a *Server) UpdateTrustedCluster(ctx context.Context, tc types.TrustedCluster) (newTrustedCluster types.TrustedCluster, returnErr error) { + // verify that trusted cluster role map does not reference non-existent roles + if err := a.checkLocalRoles(ctx, tc.GetRoleMap()); err != nil { + return nil, trace.Wrap(err) + } + + existingCluster, err := a.GetTrustedCluster(ctx, tc.GetName()) + if err != nil { + return nil, trace.Wrap(err) + } + + updated, err := a.updateTrustedCluster(ctx, tc, existingCluster) + return updated, trace.Wrap(err) +} + +// upsertTrustedCluster upserts the trusted cluster. +// If validateName is true, the trusted cluster resource name must be validated +// before the trusted cluster is created. +func (a *Server) upsertTrustedCluster(ctx context.Context, tc types.TrustedCluster, validateName bool) (types.TrustedCluster, error) { // verify that trusted cluster role map does not reference non-existent roles if err := a.checkLocalRoles(ctx, tc.GetRoleMap()); err != nil { return nil, trace.Wrap(err) @@ -67,7 +114,7 @@ func (a *Server) UpsertTrustedCluster(ctx context.Context, tc types.TrustedClust // if there is no existing cluster, switch to the create case if existingCluster == nil { - return a.createTrustedCluster(ctx, tc) + return a.createTrustedCluster(ctx, tc, validateName) } if err := existingCluster.CanChangeStateTo(tc); err != nil { @@ -103,8 +150,11 @@ func (a *Server) UpsertTrustedCluster(ctx context.Context, tc types.TrustedClust return tc, nil } -func (a *Server) createTrustedCluster(ctx context.Context, tc types.TrustedCluster) (types.TrustedCluster, error) { - remoteCAs, err := a.establishTrust(ctx, tc) +// createTrustedCluster creates the trusted cluster. +// If validateName is true, the trusted cluster resource name must be validated +// before the trusted cluster is created. +func (a *Server) createTrustedCluster(ctx context.Context, tc types.TrustedCluster, validateName bool) (types.TrustedCluster, error) { + remoteCAs, err := a.establishTrust(ctx, tc, validateName) if err != nil { return nil, trace.Wrap(err) } @@ -130,6 +180,38 @@ func (a *Server) createTrustedCluster(ctx context.Context, tc types.TrustedClust return tc, nil } +// updateTrustedCluster updates the trusted cluster. +func (a *Server) updateTrustedCluster(ctx context.Context, tc types.TrustedCluster, existingCluster types.TrustedCluster) (types.TrustedCluster, error) { + if err := existingCluster.CanChangeStateTo(tc); err != nil { + return nil, trace.Wrap(err) + } + + // always load all current CAs. even if we aren't changing them as part of + // this function, Services.UpdateTrustedCluster will only correctly activate/deactivate + // CAs that are explicitly passed to it. note that we pass in the existing cluster state + // since where CAs are stored depends on the current state of the trusted cluster. + cas, err := a.getCAsForTrustedCluster(ctx, existingCluster) + if err != nil { + return nil, trace.Wrap(err) + } + + // propagate any role map changes to cas + configureCAsForTrustedCluster(tc, cas) + + revision, err := a.Services.UpdateTrustedCluster(ctx, tc, cas) + if err != nil { + return nil, trace.Wrap(err) + } + + tc.SetRevision(revision) + + if err := a.onTrustedClusterWrite(ctx, tc); err != nil { + return nil, trace.Wrap(err) + } + + return tc, nil +} + // configureCAsForTrustedCluster modifies remote CAs for use as trusted cluster CAs. func configureCAsForTrustedCluster(tc types.TrustedCluster, cas []types.CertAuthority) { // modify the remote CAs for use as tc cas. @@ -267,7 +349,7 @@ func (a *Server) DeleteTrustedCluster(ctx context.Context, name string) error { return nil } -func (a *Server) establishTrust(ctx context.Context, trustedCluster types.TrustedCluster) ([]types.CertAuthority, error) { +func (a *Server) establishTrust(ctx context.Context, trustedCluster types.TrustedCluster, validateName bool) ([]types.CertAuthority, error) { var localCertAuthorities []types.CertAuthority domainName, err := a.GetDomainName() @@ -286,6 +368,14 @@ func (a *Server) establishTrust(ctx context.Context, trustedCluster types.Truste } } + // Validate cluster names before establishing trust to avoid unnecessarily + // creating a remote_cluster resource on the root cluster. + if validateName { + if err := a.validateTrustedClusterName(ctx, trustedCluster); err != nil { + return nil, trace.Wrap(err) + } + } + // create a request to validate a trusted cluster (token and local certificate authorities) validateRequest := authclient.ValidateTrustedClusterRequest{ Token: trustedCluster.GetToken(), @@ -322,9 +412,10 @@ func (a *Server) establishTrust(ctx context.Context, trustedCluster types.Truste if remoteClusterName == domainName { return nil, trace.BadParameter("remote cluster name can not be the same as local cluster name") } - // TODO(klizhentas) in 2.5.0 prohibit adding trusted cluster resource name - // different from cluster name (we had no way of checking this before x509, - // because SSH CA was a public key, not a cert with metadata) + if validateName && trustedCluster.GetName() != remoteClusterName { + return nil, trace.BadParameter("trusted cluster resource name must be the same as the remote cluster name. got: %q", + trustedCluster.GetName()) + } } } @@ -586,7 +677,6 @@ func (a *Server) sendValidateRequestToProxy(host string, validateRequest *authcl if err != nil { return nil, trace.Wrap(err) } - validateRequestRaw, err := validateRequest.ToRaw() if err != nil { return nil, trace.Wrap(err) @@ -611,6 +701,24 @@ func (a *Server) sendValidateRequestToProxy(host string, validateRequest *authcl return validateResponse, nil } +// validateTrustedClusterName validates that the trusted cluster resource name +// matches the cluster name. +func (a *Server) validateTrustedClusterName(ctx context.Context, trustedCluster types.TrustedCluster) error { + resp, err := webclient.Find(&webclient.Config{ + Context: ctx, + ProxyAddr: trustedCluster.GetProxyAddress(), + Insecure: lib.IsInsecureDevMode(), + }) + if err != nil { + return trace.Wrap(err) + } + if trustedCluster.GetName() != resp.ClusterName { + return trace.BadParameter("trusted cluster resource name must be the same as the remote cluster name. got: %q", + trustedCluster.GetName()) + } + return nil +} + // createReverseTunnel will create a services.ReverseTunnel givenin the // services.TrustedCluster resource. func (a *Server) createReverseTunnel(ctx context.Context, t types.TrustedCluster) error { diff --git a/lib/auth/trustedcluster_test.go b/lib/auth/trustedcluster_test.go index c65287c5064ff..aca02a7dc4943 100644 --- a/lib/auth/trustedcluster_test.go +++ b/lib/auth/trustedcluster_test.go @@ -453,17 +453,23 @@ func TestUpsertTrustedCluster(t *testing.T) { err = a.SetStaticTokens(tks) require.NoError(t, err) - trustedCluster, err := types.NewTrustedCluster("trustedcluster", - types.TrustedClusterSpecV2{ - Enabled: true, - RoleMap: []types.RoleMapping{ - { - Local: []string{"someRole"}, - Remote: "someRole", - }, + role, err := types.NewRole("test-role", types.RoleSpecV6{}) + require.NoError(t, err) + _, err = a.UpsertRole(ctx, role) + require.NoError(t, err) + + trustedClusterSpec := types.TrustedClusterSpecV2{ + Enabled: true, + RoleMap: []types.RoleMapping{ + { + Local: []string{"test-role"}, + Remote: "someRole", }, - ProxyAddress: "localhost", - }) + }, + ProxyAddress: "localhost", + } + + trustedCluster, err := types.NewTrustedCluster("trustedcluster", trustedClusterSpec) require.NoError(t, err) ca := suite.NewTestCA(types.UserCA, "trustedcluster") @@ -489,7 +495,7 @@ func TestUpsertTrustedCluster(t *testing.T) { ProxyAddress: "localhost", }) require.NoError(t, err) - _, err = a.UpsertTrustedCluster(ctx, trustedCluster) + _, err = a.UpsertTrustedClusterV2(ctx, trustedCluster) require.ErrorContains(t, err, "someNewRole") }) t.Run("Change role map of existing enabled trusted cluster", func(t *testing.T) { @@ -505,7 +511,7 @@ func TestUpsertTrustedCluster(t *testing.T) { ProxyAddress: "localhost", }) require.NoError(t, err) - _, err = a.UpsertTrustedCluster(ctx, trustedCluster) + _, err = a.UpsertTrustedClusterV2(ctx, trustedCluster) require.NoError(t, err) }) t.Run("Disable existing trusted cluster", func(t *testing.T) { @@ -521,7 +527,7 @@ func TestUpsertTrustedCluster(t *testing.T) { ProxyAddress: "localhost", }) require.NoError(t, err) - _, err = a.UpsertTrustedCluster(ctx, trustedCluster) + _, err = a.UpsertTrustedClusterV2(ctx, trustedCluster) require.NoError(t, err) }) t.Run("Change role map of existing disabled trusted cluster", func(t *testing.T) { @@ -537,7 +543,7 @@ func TestUpsertTrustedCluster(t *testing.T) { ProxyAddress: "localhost", }) require.NoError(t, err) - _, err = a.UpsertTrustedCluster(ctx, trustedCluster) + _, err = a.UpsertTrustedClusterV2(ctx, trustedCluster) require.NoError(t, err) }) t.Run("Enable existing trusted cluster", func(t *testing.T) { @@ -553,23 +559,177 @@ func TestUpsertTrustedCluster(t *testing.T) { ProxyAddress: "localhost", }) require.NoError(t, err) - _, err = a.UpsertTrustedCluster(ctx, trustedCluster) + _, err = a.UpsertTrustedClusterV2(ctx, trustedCluster) require.NoError(t, err) }) - t.Run("Cloud prohibits being a leaf cluster", func(t *testing.T) { - modules.SetTestModules(t, &modules.TestModules{ - TestFeatures: modules.Features{Cloud: true}, - }) + t.Run("Upsert unmodified trusted cluster", func(t *testing.T) { + trustedCluster, err := types.NewTrustedCluster("trustedcluster", trustedClusterSpec) + require.NoError(t, err) + _, err = a.UpsertTrustedClusterV2(ctx, trustedCluster) + require.NoError(t, err) + }) +} + +func TestUpdateTrustedCluster(t *testing.T) { + ctx := context.Background() + testAuth, err := NewTestAuthServer(TestAuthServerConfig{ + ClusterName: "localcluster", + Dir: t.TempDir(), + }) + require.NoError(t, err) + a := testAuth.AuthServer + + const validToken = "validtoken" + tks, err := types.NewStaticTokens(types.StaticTokensSpecV2{ + StaticTokens: []types.ProvisionTokenV1{{ + Roles: []types.SystemRole{types.RoleTrustedCluster}, + Token: validToken, + }}, + }) + require.NoError(t, err) + + err = a.SetStaticTokens(tks) + require.NoError(t, err) - tc, err := types.NewTrustedCluster("test", types.TrustedClusterSpecV2{ - RoleMap: []types.RoleMapping{ - {Remote: teleport.PresetAccessRoleName, Local: []string{teleport.PresetAccessRoleName}}, + role, err := types.NewRole("test-role", types.RoleSpecV6{}) + require.NoError(t, err) + _, err = a.UpsertRole(ctx, role) + require.NoError(t, err) + + trustedClusterSpec := types.TrustedClusterSpecV2{ + Enabled: true, + RoleMap: []types.RoleMapping{ + { + Local: []string{"test-role"}, + Remote: "someRole", }, - }) - require.NoError(t, err, "creating trusted cluster resource") + }, + ProxyAddress: "localhost", + } - server := ServerWithRoles{authServer: a} - _, err = server.UpsertTrustedCluster(ctx, tc) - require.True(t, trace.IsNotImplemented(err), "UpsertTrustedCluster returned an unexpected error, got = %v (%T), want trace.NotImplementedError", err, err) + testClusterName := "trustedcluster" + trustedCluster, err := types.NewTrustedCluster(testClusterName, trustedClusterSpec) + require.NoError(t, err) + + ca := suite.NewTestCA(types.UserCA, testClusterName) + + configureCAsForTrustedCluster(trustedCluster, []types.CertAuthority{ca}) + + _, err = a.Services.CreateTrustedCluster(ctx, trustedCluster, []types.CertAuthority{ca}) + require.NoError(t, err) + + err = a.createReverseTunnel(ctx, trustedCluster) + require.NoError(t, err) + + t.Run("Invalid role change", func(t *testing.T) { + existing, err := a.GetTrustedCluster(ctx, testClusterName) + require.NoError(t, err) + trustedCluster, err := types.NewTrustedCluster(testClusterName, + types.TrustedClusterSpecV2{ + Enabled: true, + RoleMap: []types.RoleMapping{ + { + Local: []string{"someNewRole"}, + Remote: "someRole", + }, + }, + ProxyAddress: "localhost", + }) + require.NoError(t, err) + trustedCluster.SetRevision(existing.GetRevision()) + _, err = a.UpdateTrustedCluster(ctx, trustedCluster) + require.ErrorContains(t, err, "someNewRole") + }) + t.Run("Change role map of existing enabled trusted cluster", func(t *testing.T) { + existing, err := a.GetTrustedCluster(ctx, testClusterName) + require.NoError(t, err) + trustedCluster, err := types.NewTrustedCluster(testClusterName, + types.TrustedClusterSpecV2{ + Enabled: true, + RoleMap: []types.RoleMapping{ + { + Local: []string{constants.DefaultImplicitRole}, + Remote: "someRole", + }, + }, + ProxyAddress: "localhost", + }) + require.NoError(t, err) + trustedCluster.SetRevision(existing.GetRevision()) + _, err = a.UpdateTrustedCluster(ctx, trustedCluster) + require.NoError(t, err) + }) + t.Run("Disable existing trusted cluster", func(t *testing.T) { + existing, err := a.GetTrustedCluster(ctx, testClusterName) + require.NoError(t, err) + trustedCluster, err := types.NewTrustedCluster(testClusterName, + types.TrustedClusterSpecV2{ + Enabled: false, + RoleMap: []types.RoleMapping{ + { + Local: []string{constants.DefaultImplicitRole}, + Remote: "someRole", + }, + }, + ProxyAddress: "localhost", + }) + require.NoError(t, err) + trustedCluster.SetRevision(existing.GetRevision()) + _, err = a.UpdateTrustedCluster(ctx, trustedCluster) + require.NoError(t, err) + }) + t.Run("Change role map of existing disabled trusted cluster", func(t *testing.T) { + existing, err := a.GetTrustedCluster(ctx, testClusterName) + require.NoError(t, err) + trustedCluster, err := types.NewTrustedCluster(testClusterName, + types.TrustedClusterSpecV2{ + Enabled: false, + RoleMap: []types.RoleMapping{ + { + Local: []string{constants.DefaultImplicitRole}, + Remote: "someOtherRole", + }, + }, + ProxyAddress: "localhost", + }) + require.NoError(t, err) + trustedCluster.SetRevision(existing.GetRevision()) + _, err = a.UpdateTrustedCluster(ctx, trustedCluster) + require.NoError(t, err) + }) + t.Run("Enable existing trusted cluster", func(t *testing.T) { + existing, err := a.GetTrustedCluster(ctx, testClusterName) + require.NoError(t, err) + trustedCluster, err := types.NewTrustedCluster(testClusterName, + types.TrustedClusterSpecV2{ + Enabled: true, + RoleMap: []types.RoleMapping{ + { + Local: []string{constants.DefaultImplicitRole}, + Remote: "someOtherRole", + }, + }, + ProxyAddress: "localhost", + }) + require.NoError(t, err) + trustedCluster.SetRevision(existing.GetRevision()) + _, err = a.UpdateTrustedCluster(ctx, trustedCluster) + require.NoError(t, err) + }) + t.Run("Update unmodified trusted cluster", func(t *testing.T) { + existing, err := a.GetTrustedCluster(ctx, testClusterName) + require.NoError(t, err) + trustedCluster, err := types.NewTrustedCluster(testClusterName, trustedClusterSpec) + require.NoError(t, err) + trustedCluster.SetRevision(existing.GetRevision()) + _, err = a.UpdateTrustedCluster(ctx, trustedCluster) + require.NoError(t, err) + }) + + t.Run("Invalid revision", func(t *testing.T) { + trustedCluster, err := types.NewTrustedCluster(testClusterName, trustedClusterSpec) + require.NoError(t, err) + _, err = a.UpdateTrustedCluster(ctx, trustedCluster) + require.Error(t, err) }) } diff --git a/tool/tctl/common/resource_command.go b/tool/tctl/common/resource_command.go index dd9d5ea13af20..cdb8115e9b9a6 100644 --- a/tool/tctl/common/resource_command.go +++ b/tool/tctl/common/resource_command.go @@ -409,6 +409,9 @@ func (rc *ResourceCommand) createTrustedCluster(ctx context.Context, client *aut return trace.AlreadyExists("trusted cluster %q already exists", name) } + //nolint:staticcheck // SA1019. UpsertTrustedCluster is deprecated but will + // continue being supported for tctl clients. + // TODO(bernardjkim) consider using UpsertTrustedClusterV2 in VX.0.0 out, err := client.UpsertTrustedCluster(ctx, tc) if err != nil { // If force is used and UpsertTrustedCluster returns trace.AlreadyExists, diff --git a/tool/teleport/testenv/test_server.go b/tool/teleport/testenv/test_server.go index 5d4607223c292..3e034d9fdf0d6 100644 --- a/tool/teleport/testenv/test_server.go +++ b/tool/teleport/testenv/test_server.go @@ -417,7 +417,7 @@ func SetupTrustedCluster(ctx context.Context, t *testing.T, rootServer, leafServ rootProxyTunnelAddr, err := rootServer.ProxyTunnelAddr() require.NoError(t, err) - tc, err := types.NewTrustedCluster("root-cluster", types.TrustedClusterSpecV2{ + tc, err := types.NewTrustedCluster(rootServer.Config.Auth.ClusterName.GetClusterName(), types.TrustedClusterSpecV2{ Enabled: true, Token: StaticToken, ProxyAddress: rootProxyAddr.String(), @@ -431,7 +431,7 @@ func SetupTrustedCluster(ctx context.Context, t *testing.T, rootServer, leafServ }) require.NoError(t, err) - _, err = leafServer.GetAuthServer().UpsertTrustedCluster(ctx, tc) + _, err = leafServer.GetAuthServer().UpsertTrustedClusterV2(ctx, tc) require.NoError(t, err) require.EventuallyWithT(t, func(t *assert.CollectT) { diff --git a/tool/tsh/common/tsh_helper_test.go b/tool/tsh/common/tsh_helper_test.go index 380b012805d3c..85ec86097b3bd 100644 --- a/tool/tsh/common/tsh_helper_test.go +++ b/tool/tsh/common/tsh_helper_test.go @@ -230,7 +230,7 @@ func (s *suite) setupLeafCluster(t *testing.T, options testSuiteOptions) { tunnelAddr = s.root.Config.Proxy.ReverseTunnelListenAddr.String() } - tc, err := types.NewTrustedCluster("root-cluster", types.TrustedClusterSpecV2{ + tc, err := types.NewTrustedCluster(s.root.Config.Auth.ClusterName.GetClusterName(), types.TrustedClusterSpecV2{ Enabled: true, Token: staticToken, ProxyAddress: s.root.Config.Proxy.WebAddr.String(), @@ -249,7 +249,7 @@ func (s *suite) setupLeafCluster(t *testing.T, options testSuiteOptions) { } s.leaf = runTeleport(t, cfg) - _, err = s.leaf.GetAuthServer().UpsertTrustedCluster(s.leaf.ExitContext(), tc) + _, err = s.leaf.GetAuthServer().UpsertTrustedClusterV2(s.leaf.ExitContext(), tc) require.NoError(t, err) } diff --git a/tool/tsh/common/tsh_test.go b/tool/tsh/common/tsh_test.go index 792c507b5c55d..9302a62ce29ae 100644 --- a/tool/tsh/common/tsh_test.go +++ b/tool/tsh/common/tsh_test.go @@ -2543,7 +2543,7 @@ func tryCreateTrustedCluster(t *testing.T, authServer *auth.Server, trustedClust ctx := context.TODO() for i := 0; i < 10; i++ { log.Debugf("Will create trusted cluster %v, attempt %v.", trustedCluster, i) - _, err := authServer.UpsertTrustedCluster(ctx, trustedCluster) + _, err := authServer.UpsertTrustedClusterV2(ctx, trustedCluster) if err == nil { return }