diff --git a/.github/ISSUE_TEMPLATE/testplan.md b/.github/ISSUE_TEMPLATE/testplan.md index 870e9592e8b31..7110906b6a0da 100644 --- a/.github/ISSUE_TEMPLATE/testplan.md +++ b/.github/ISSUE_TEMPLATE/testplan.md @@ -979,10 +979,14 @@ manualy testing. - [ ] Self-hosted MariaDB. - [ ] Self-hosted MongoDB. - [ ] Self-hosted CockroachDB. - - [ ] Self-hosted Redis. + - [ ] Self-hosted Redis/Valkey. - [ ] Self-hosted Redis Cluster. - [ ] Self-hosted MSSQL. - [ ] Self-hosted MSSQL with PKINIT authentication. + - [ ] Self-hosted Elasticsearch. + - [ ] Self-hosted Cassandra/ScyllaDB. + - [ ] Self-hosted Oracle. + - [ ] Self-hosted ClickHouse. - [ ] AWS Aurora Postgres. - [ ] AWS Aurora MySQL. - [ ] MySQL server version reported by Teleport is correct. @@ -992,32 +996,36 @@ manualy testing. - [ ] Verify connection to external AWS account works with `assume_role_arn: ""` and `external_id: ""` - [ ] AWS ElastiCache. - [ ] AWS MemoryDB. + - [ ] AWS OpenSearch. + - [ ] AWS Dynamodb. + - [ ] Verify connection to external AWS account works with `assume_role_arn: ""` and `external_id: ""` + - [ ] AWS DocumentDB + - [ ] AWS Keyspaces + - [ ] Verify connection to external AWS account works with `assume_role_arn: ""` and `external_id: ""` - [ ] GCP Cloud SQL Postgres. - [ ] GCP Cloud SQL MySQL. - [ ] GCP Cloud Spanner. - - [ ] Snowflake. - [ ] Azure Cache for Redis. - [x] Azure single-server MySQL and Postgres (EOL Sep 2024 and Mar 2025, skip) - - [ ] Azure flexible-server MySQL and Postgres - - [ ] Elasticsearch. - - [ ] OpenSearch. - - [ ] Cassandra/ScyllaDB. - - [ ] Verify connection to external AWS account works with `assume_role_arn: ""` and `external_id: ""` - - [ ] Dynamodb. - - [ ] Verify connection to external AWS account works with `assume_role_arn: ""` and `external_id: ""` + - [ ] Azure flexible-server MySQL + - [ ] Azure flexible-server Postgres - [ ] Azure SQL Server. - - [ ] Oracle. - - [ ] ClickHouse. + - [ ] Snowflake. + - [ ] MongoDB Atlas. - [ ] Connect to a database within a remote cluster via a trusted cluster. - [ ] Self-hosted Postgres. - [ ] Self-hosted MySQL. - [ ] Self-hosted MariaDB. - [ ] Self-hosted MongoDB. - [ ] Self-hosted CockroachDB. - - [ ] Self-hosted Redis. + - [ ] Self-hosted Redis/Valkey. - [ ] Self-hosted Redis Cluster. - [ ] Self-hosted MSSQL. - [ ] Self-hosted MSSQL with PKINIT authentication. + - [ ] Self-hosted Elasticsearch. + - [ ] Self-hosted Cassandra/ScyllaDB. + - [ ] Self-hosted Oracle. + - [ ] Self-hosted ClickHouse. - [ ] AWS Aurora Postgres. - [ ] AWS Aurora MySQL. - [ ] AWS RDS Proxy (MySQL, Postgres, MariaDB, or SQL Server) @@ -1025,20 +1033,20 @@ manualy testing. - [ ] AWS Redshift Serverless. - [ ] AWS ElastiCache. - [ ] AWS MemoryDB. + - [ ] AWS OpenSearch. + - [ ] AWS Dynamodb. + - [ ] AWS DocumentDB + - [ ] AWS Keyspaces - [ ] GCP Cloud SQL Postgres. - [ ] GCP Cloud SQL MySQL. - [ ] GCP Cloud Spanner. - - [ ] Snowflake. - [ ] Azure Cache for Redis. - [x] Azure single-server MySQL and Postgres (EOL Sep 2024 and Mar 2025, skip) - - [ ] Azure flexible-server MySQL and Postgres - - [ ] Elasticsearch. - - [ ] OpenSearch. - - [ ] Cassandra/ScyllaDB. - - [ ] Dynamodb. + - [ ] Azure flexible-server MySQL + - [ ] Azure flexible-server Postgres - [ ] Azure SQL Server. - - [ ] Oracle. - - [ ] ClickHouse. + - [ ] Snowflake. + - [ ] MongoDB Atlas. - [ ] Verify auto user provisioning. Verify all supported modes: `keep`, `best_effort_drop` - [ ] Self-hosted Postgres. @@ -1084,6 +1092,7 @@ manualy testing. - [ ] Can detect and register ElastiCache Redis clusters. - [ ] Can detect and register MemoryDB clusters. - [ ] Can detect and register OpenSearch domains. + - [ ] Can detect and register DocumentDB clusters. - [ ] Azure - [ ] Can detect and register MySQL and Postgres single-server instances. - [ ] Can detect and register MySQL and Postgres flexible-server instances. @@ -1098,6 +1107,11 @@ manualy testing. - [ ] Verify searching for all columns in the search bar works - [ ] Verify you can sort by all columns except `labels` - [ ] `tsh bench` load tests (instructions on Notion -> Database Access -> Load test) +- [ ] Verify database session player + - [ ] Web UI + - [ ] Postgres + - [ ] `tsh play` + - [ ] Postgres ## TLS Routing diff --git a/.github/workflows/doc-tests.yaml b/.github/workflows/doc-tests.yaml index 5030bebe367b1..272c2de479c5c 100644 --- a/.github/workflows/doc-tests.yaml +++ b/.github/workflows/doc-tests.yaml @@ -48,6 +48,8 @@ jobs: path: "docs" - name: Prepare docs site configuration + # Prevent occasional `yarn install` executions that run indefinitely + timeout-minutes: 10 # The environment we use for linting the docs differs from the one we # use for the live docs site in that we only test a single version of # the content. diff --git a/api/client/client.go b/api/client/client.go index 86cf448bcbe77..ee1ea80087791 100644 --- a/api/client/client.go +++ b/api/client/client.go @@ -1782,11 +1782,6 @@ func (c *Client) GetRoles(ctx context.Context) ([]types.Role, error) { for { rsp, err := c.ListRoles(ctx, &req) if err != nil { - if trace.IsNotImplemented(err) { - // fallback to calling the old non-paginated role API. - roles, err = c.getRoles(ctx) - return roles, trace.Wrap(err) - } return nil, trace.Wrap(err) } @@ -1802,21 +1797,6 @@ func (c *Client) GetRoles(ctx context.Context) ([]types.Role, error) { return roles, nil } -// getRoles calls the old non-paginated GetRoles method. -// -// DELETE IN 17.0 -func (c *Client) getRoles(ctx context.Context) ([]types.Role, error) { - resp, err := c.grpc.GetRoles(ctx, &emptypb.Empty{}) - if err != nil { - return nil, trace.Wrap(err) - } - roles := make([]types.Role, 0, len(resp.GetRoles())) - for _, role := range resp.GetRoles() { - roles = append(roles, role) - } - return roles, nil -} - // ListRoles is a paginated role getter. func (c *Client) ListRoles(ctx context.Context, req *proto.ListRolesRequest) (*proto.ListRolesResponse, error) { var header gmetadata.MD diff --git a/api/client/events.go b/api/client/events.go index 89c7260e38ac6..89e5b5ecc3157 100644 --- a/api/client/events.go +++ b/api/client/events.go @@ -23,6 +23,7 @@ import ( clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" crownjewelv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/crownjewel/v1" dbobjectv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobject/v1" + identitycenterv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/identitycenter/v1" kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" machineidv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1" notificationsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/notifications/v1" @@ -122,7 +123,18 @@ func EventToGRPC(in types.Event) (*proto.Event, error) { out.Resource = &proto.Event_AutoUpdateAgentRollout{ AutoUpdateAgentRollout: r, } - + case *identitycenterv1.Account: + out.Resource = &proto.Event_IdentityCenterAccount{ + IdentityCenterAccount: r, + } + case *identitycenterv1.PrincipalAssignment: + out.Resource = &proto.Event_IdentityCenterPrincipalAssignment{ + IdentityCenterPrincipalAssignment: r, + } + case *identitycenterv1.AccountAssignment: + out.Resource = &proto.Event_IdentityCenterAccountAssignment{ + IdentityCenterAccountAssignment: r, + } default: return nil, trace.BadParameter("resource type %T is not supported", r) } @@ -588,6 +600,15 @@ func EventFromGRPC(in *proto.Event) (*types.Event, error) { } else if r := in.GetProvisioningPrincipalState(); r != nil { out.Resource = types.Resource153ToLegacy(r) return &out, nil + } else if r := in.GetIdentityCenterAccount(); r != nil { + out.Resource = types.Resource153ToLegacy(r) + return &out, nil + } else if r := in.GetIdentityCenterPrincipalAssignment(); r != nil { + out.Resource = types.Resource153ToLegacy(r) + return &out, nil + } else if r := in.GetIdentityCenterAccountAssignment(); r != nil { + out.Resource = types.Resource153ToLegacy(r) + return &out, nil } else { return nil, trace.BadParameter("received unsupported resource %T", in.Resource) } diff --git a/api/client/proto/authservice.pb.go b/api/client/proto/authservice.pb.go index 3f66847c54fd5..bfd512d622ed5 100644 --- a/api/client/proto/authservice.pb.go +++ b/api/client/proto/authservice.pb.go @@ -15786,949 +15786,947 @@ func init() { } var fileDescriptor_0ffcffcda38ae159 = []byte{ - // 15058 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0xbd, 0x59, 0x6c, 0x5c, 0xcb, - 0x76, 0x18, 0xca, 0xe6, 0xcc, 0xc5, 0x41, 0xad, 0x22, 0x29, 0xb6, 0xa8, 0xa1, 0xa5, 0xad, 0x33, - 0xe8, 0xe8, 0x9e, 0xab, 0x81, 0x67, 0xb8, 0x67, 0xba, 0xe7, 0x9c, 0xe6, 0x20, 0x91, 0x12, 0xa7, - 0xb3, 0x9b, 0xa4, 0xce, 0xe4, 0xdb, 0x77, 0xab, 0xbb, 0x44, 0x6e, 0xab, 0xb9, 0x77, 0xdf, 0xbd, - 0x77, 0x4b, 0x47, 0xd7, 0xcf, 0x7e, 0xb0, 0xfd, 0x06, 0xff, 0xbc, 0xf7, 0x6c, 0xe0, 0x3d, 0xc3, - 0x0f, 0xfe, 0xf0, 0x7b, 0x40, 0x02, 0x04, 0x01, 0x12, 0xe4, 0x27, 0xf0, 0x4f, 0xfc, 0x11, 0xe4, - 0x23, 0x37, 0x06, 0x82, 0x24, 0xb0, 0xfd, 0x13, 0x20, 0x74, 0x72, 0x01, 0xff, 0x10, 0xc9, 0x87, - 0x11, 0x24, 0x40, 0x2e, 0x60, 0x20, 0xa8, 0x55, 0xc3, 0xae, 0xda, 0x53, 0x93, 0x3a, 0x3a, 0xd7, - 0xf9, 0x91, 0xd8, 0xab, 0xd6, 0x5a, 0x55, 0xb5, 0xaa, 0x76, 0xd5, 0xaa, 0x55, 0xab, 0xd6, 0x82, - 0x9b, 0x11, 0x6d, 0xd3, 0x8e, 0x1f, 0x44, 0xb7, 0xda, 0x74, 0xdf, 0x69, 0x3e, 0xbf, 0xd5, 0x6c, - 0xbb, 0xd4, 0x8b, 0x6e, 0x75, 0x02, 0x3f, 0xf2, 0x6f, 0x39, 0xdd, 0xe8, 0x20, 0xa4, 0xc1, 0x53, - 0xb7, 0x49, 0x6f, 0x22, 0x84, 0x0c, 0xe1, 0x7f, 0xf3, 0x33, 0xfb, 0xfe, 0xbe, 0xcf, 0x71, 0xd8, - 0x5f, 0xbc, 0x70, 0xfe, 0xc2, 0xbe, 0xef, 0xef, 0xb7, 0x29, 0x27, 0x7e, 0xd4, 0x7d, 0x7c, 0x8b, - 0x1e, 0x76, 0xa2, 0xe7, 0xa2, 0xb0, 0x9a, 0x2c, 0x8c, 0xdc, 0x43, 0x1a, 0x46, 0xce, 0x61, 0x47, - 0x20, 0xbc, 0xa1, 0x9a, 0xe2, 0x44, 0x11, 0x2b, 0x89, 0x5c, 0xdf, 0xbb, 0xf5, 0xf4, 0x8e, 0xfe, - 0x53, 0xa0, 0x5e, 0x2f, 0x6c, 0x75, 0x93, 0x06, 0x51, 0x78, 0x22, 0x4c, 0xfa, 0x94, 0x7a, 0x51, - 0xaa, 0x7a, 0x81, 0x19, 0x3d, 0xef, 0xd0, 0x90, 0xa3, 0xc8, 0xff, 0x04, 0xea, 0xd5, 0x6c, 0x54, - 0xfc, 0x57, 0xa0, 0x7c, 0x3f, 0x1b, 0xe5, 0x19, 0x7d, 0xc4, 0x64, 0xea, 0xa9, 0x3f, 0x7a, 0xa0, - 0x07, 0x4e, 0xa7, 0x43, 0x83, 0xf8, 0x0f, 0x81, 0x7e, 0x5e, 0xa1, 0x1f, 0x3e, 0x76, 0x98, 0x88, - 0x0e, 0x1f, 0x3b, 0xa9, 0x6e, 0x74, 0x43, 0x67, 0x9f, 0x8a, 0xe6, 0x3f, 0xbd, 0xa3, 0xff, 0xe4, - 0xa8, 0xd6, 0x1f, 0x95, 0x60, 0xe8, 0xa1, 0x13, 0x35, 0x0f, 0xc8, 0x27, 0x30, 0xf4, 0xc0, 0xf5, - 0x5a, 0x61, 0xa5, 0x74, 0x65, 0xe0, 0xfa, 0xf8, 0x42, 0xf9, 0x26, 0xef, 0x0a, 0x16, 0xb2, 0x82, - 0xc5, 0xb9, 0x9f, 0x1d, 0x55, 0xfb, 0x8e, 0x8f, 0xaa, 0x67, 0x9e, 0x30, 0xb4, 0x37, 0xfd, 0x43, - 0x37, 0xc2, 0xb1, 0xb5, 0x39, 0x1d, 0xd9, 0x85, 0xe9, 0x5a, 0xbb, 0xed, 0x3f, 0xdb, 0x76, 0x82, - 0xc8, 0x75, 0xda, 0xf5, 0x6e, 0xb3, 0x49, 0xc3, 0xb0, 0xd2, 0x7f, 0xa5, 0x74, 0x7d, 0x74, 0xf1, - 0xda, 0xf1, 0x51, 0xb5, 0xea, 0xb0, 0xe2, 0x46, 0x87, 0x97, 0x37, 0x42, 0x8e, 0xa0, 0x31, 0xca, - 0xa2, 0xb7, 0xfe, 0x74, 0x18, 0xca, 0xab, 0x7e, 0x18, 0x2d, 0xb1, 0x11, 0xb5, 0xe9, 0x4f, 0xba, - 0x34, 0x8c, 0xc8, 0x35, 0x18, 0x66, 0xb0, 0xb5, 0xe5, 0x4a, 0xe9, 0x4a, 0xe9, 0xfa, 0xd8, 0xe2, - 0xf8, 0xf1, 0x51, 0x75, 0xe4, 0xc0, 0x0f, 0xa3, 0x86, 0xdb, 0xb2, 0x45, 0x11, 0x79, 0x03, 0x46, - 0x37, 0xfd, 0x16, 0xdd, 0x74, 0x0e, 0x29, 0xb6, 0x62, 0x6c, 0x71, 0xf2, 0xf8, 0xa8, 0x3a, 0xe6, - 0xf9, 0x2d, 0xda, 0xf0, 0x9c, 0x43, 0x6a, 0xab, 0x62, 0xb2, 0x07, 0x83, 0xb6, 0xdf, 0xa6, 0x95, - 0x01, 0x44, 0x5b, 0x3c, 0x3e, 0xaa, 0x0e, 0x06, 0x7e, 0x9b, 0xfe, 0xe2, 0xa8, 0xfa, 0xee, 0xbe, - 0x1b, 0x1d, 0x74, 0x1f, 0xdd, 0x6c, 0xfa, 0x87, 0xb7, 0xf6, 0x03, 0xe7, 0xa9, 0xcb, 0x27, 0xa1, - 0xd3, 0xbe, 0x15, 0x4f, 0xd5, 0x8e, 0x2b, 0xc6, 0xbd, 0xfe, 0x3c, 0x8c, 0xe8, 0x21, 0xe3, 0x64, - 0x23, 0x3f, 0xf2, 0x10, 0x66, 0x6a, 0xad, 0x96, 0xcb, 0x29, 0xb6, 0x03, 0xd7, 0x6b, 0xba, 0x1d, - 0xa7, 0x1d, 0x56, 0x06, 0xaf, 0x0c, 0x5c, 0x1f, 0x13, 0x42, 0x51, 0xe5, 0x8d, 0x8e, 0x42, 0xd0, - 0x84, 0x92, 0xc9, 0x80, 0xbc, 0x05, 0xa3, 0xcb, 0x9b, 0x75, 0xd6, 0xf6, 0xb0, 0x32, 0x84, 0xcc, - 0xe6, 0x8e, 0x8f, 0xaa, 0xd3, 0x2d, 0x2f, 0xc4, 0xae, 0xe9, 0x0c, 0x14, 0x22, 0x79, 0x17, 0x26, - 0xb6, 0xbb, 0x8f, 0xda, 0x6e, 0x73, 0x67, 0xbd, 0xfe, 0x80, 0x3e, 0xaf, 0x0c, 0x5f, 0x29, 0x5d, - 0x9f, 0x58, 0x24, 0xc7, 0x47, 0xd5, 0xa9, 0x0e, 0xc2, 0x1b, 0x51, 0x3b, 0x6c, 0x3c, 0xa1, 0xcf, - 0x6d, 0x03, 0x2f, 0xa6, 0xab, 0xd7, 0x57, 0x19, 0xdd, 0x48, 0x8a, 0x2e, 0x0c, 0x0f, 0x74, 0x3a, - 0x8e, 0x47, 0x6e, 0x01, 0xd8, 0xf4, 0xd0, 0x8f, 0x68, 0xad, 0xd5, 0x0a, 0x2a, 0xa3, 0x28, 0xdb, - 0x33, 0xc7, 0x47, 0xd5, 0xf1, 0x00, 0xa1, 0x0d, 0xa7, 0xd5, 0x0a, 0x6c, 0x0d, 0x85, 0x2c, 0xc1, - 0xa8, 0xed, 0x73, 0x01, 0x57, 0xc6, 0xae, 0x94, 0xae, 0x8f, 0x2f, 0x9c, 0x11, 0xd3, 0x50, 0x82, - 0x17, 0xcf, 0x1d, 0x1f, 0x55, 0x49, 0x20, 0x7e, 0xe9, 0xbd, 0x94, 0x18, 0xa4, 0x0a, 0x23, 0x9b, - 0xfe, 0x92, 0xd3, 0x3c, 0xa0, 0x15, 0xc0, 0xb9, 0x37, 0x74, 0x7c, 0x54, 0x2d, 0x7d, 0xdf, 0x96, - 0x50, 0xf2, 0x14, 0xc6, 0xe3, 0x81, 0x0a, 0x2b, 0xe3, 0x28, 0xbe, 0x9d, 0xe3, 0xa3, 0xea, 0xb9, - 0x10, 0xc1, 0x0d, 0x36, 0xf4, 0x9a, 0x04, 0xbf, 0xc5, 0x2c, 0xd0, 0x2b, 0x22, 0x5f, 0xc3, 0x6c, - 0xfc, 0xb3, 0x16, 0x86, 0x34, 0x60, 0x3c, 0xd6, 0x96, 0x2b, 0x93, 0x28, 0x99, 0xd7, 0x8e, 0x8f, - 0xaa, 0x96, 0xd6, 0x82, 0x86, 0x23, 0x51, 0x1a, 0x6e, 0x4b, 0xeb, 0x69, 0x36, 0x93, 0xfb, 0x83, - 0xa3, 0x13, 0xe5, 0x49, 0xfb, 0xd2, 0xae, 0x17, 0x46, 0xce, 0xa3, 0x36, 0xcd, 0x44, 0xb2, 0xfe, - 0xa6, 0x04, 0x64, 0xab, 0x43, 0xbd, 0x7a, 0x7d, 0x95, 0x7d, 0x4f, 0xf2, 0x73, 0x7a, 0x13, 0xc6, - 0xf8, 0xc0, 0xb1, 0xd1, 0xed, 0xc7, 0xd1, 0x9d, 0x3a, 0x3e, 0xaa, 0x82, 0x18, 0x5d, 0x36, 0xb2, - 0x31, 0x02, 0x79, 0x15, 0x06, 0x76, 0x76, 0xd6, 0xf1, 0x5b, 0x19, 0x58, 0x9c, 0x3e, 0x3e, 0xaa, - 0x0e, 0x44, 0x51, 0xfb, 0x17, 0x47, 0xd5, 0xd1, 0xe5, 0x6e, 0x80, 0x62, 0xb1, 0x59, 0x39, 0x79, - 0x15, 0x46, 0x96, 0xda, 0xdd, 0x30, 0xa2, 0x41, 0x65, 0x30, 0xfe, 0x48, 0x9b, 0x1c, 0x64, 0xcb, - 0x32, 0xf2, 0x3d, 0x18, 0xdc, 0x0d, 0x69, 0x50, 0x19, 0xc2, 0xf1, 0x9e, 0x14, 0xe3, 0xcd, 0x40, - 0x7b, 0x0b, 0x8b, 0xa3, 0xec, 0x4b, 0xec, 0x86, 0x34, 0xb0, 0x11, 0x89, 0xdc, 0x84, 0x21, 0x3e, - 0x68, 0xc3, 0xb8, 0x48, 0x4d, 0xaa, 0xd9, 0xd1, 0xa6, 0x7b, 0xef, 0x2e, 0x8e, 0x1d, 0x1f, 0x55, - 0x87, 0x70, 0xf0, 0x6c, 0x8e, 0x76, 0x7f, 0x70, 0xb4, 0x54, 0xee, 0xb7, 0x47, 0x19, 0x2d, 0xfb, - 0x2c, 0xac, 0xef, 0xc1, 0xb8, 0xd6, 0x7d, 0x72, 0x11, 0x06, 0xd9, 0xff, 0xb8, 0x88, 0x4c, 0xf0, - 0xca, 0xd8, 0xc6, 0x61, 0x23, 0xd4, 0xfa, 0xff, 0xa6, 0xa1, 0xcc, 0x28, 0x8d, 0x95, 0xe7, 0xa6, - 0x2e, 0x2a, 0x4e, 0x57, 0x36, 0x45, 0x55, 0x29, 0xe9, 0xc2, 0xba, 0x0e, 0xaa, 0x76, 0xb1, 0x08, - 0x4d, 0x1c, 0x1f, 0x55, 0x47, 0xbb, 0x02, 0x16, 0xb7, 0x8d, 0xd4, 0x61, 0x64, 0xe5, 0x9b, 0x8e, - 0x1b, 0xd0, 0x10, 0x45, 0x3b, 0xbe, 0x30, 0x7f, 0x93, 0x6f, 0x97, 0x37, 0xe5, 0x76, 0x79, 0x73, - 0x47, 0x6e, 0x97, 0x8b, 0x97, 0xc4, 0x62, 0x7c, 0x96, 0x72, 0x92, 0x78, 0x7e, 0xfc, 0xee, 0x5f, - 0x56, 0x4b, 0xb6, 0xe4, 0x44, 0xde, 0x84, 0xe1, 0xbb, 0x7e, 0x70, 0xe8, 0x44, 0x62, 0x0c, 0x66, - 0x8e, 0x8f, 0xaa, 0xe5, 0xc7, 0x08, 0xd1, 0xa6, 0x94, 0xc0, 0x21, 0x77, 0x61, 0xca, 0xf6, 0xbb, - 0x11, 0xdd, 0xf1, 0xe5, 0xc8, 0x0d, 0x21, 0xd5, 0xe5, 0xe3, 0xa3, 0xea, 0x7c, 0xc0, 0x4a, 0x1a, - 0x91, 0xdf, 0x10, 0x43, 0xa8, 0xd1, 0x27, 0xa8, 0xc8, 0x0a, 0x4c, 0xd5, 0x70, 0xf5, 0x16, 0x52, - 0xe3, 0xe3, 0x35, 0xb6, 0x78, 0xe9, 0xf8, 0xa8, 0x7a, 0xde, 0xc1, 0x92, 0x46, 0x20, 0x8a, 0x74, - 0x36, 0x26, 0x11, 0xd9, 0x84, 0xb3, 0x0f, 0xba, 0x8f, 0x68, 0xe0, 0xd1, 0x88, 0x86, 0xb2, 0x45, - 0x23, 0xd8, 0xa2, 0x2b, 0xc7, 0x47, 0xd5, 0x8b, 0x4f, 0x54, 0x61, 0x46, 0x9b, 0xd2, 0xa4, 0x84, - 0xc2, 0x19, 0xd1, 0xd0, 0x65, 0x27, 0x72, 0x1e, 0x39, 0x21, 0xc5, 0x45, 0x69, 0x7c, 0xe1, 0x1c, - 0x17, 0xf1, 0xcd, 0x44, 0xe9, 0xe2, 0x35, 0x21, 0xe5, 0x0b, 0xaa, 0xef, 0x2d, 0x51, 0xa4, 0x55, - 0x94, 0xe4, 0xc9, 0xd6, 0x66, 0xb5, 0xef, 0x8c, 0x61, 0x6b, 0x71, 0x6d, 0x56, 0xfb, 0x8e, 0xbe, - 0x6a, 0xa9, 0x1d, 0x68, 0x1d, 0x86, 0x76, 0xd9, 0xee, 0x8c, 0x6b, 0xd6, 0xd4, 0xc2, 0x55, 0xd1, - 0xa2, 0xe4, 0xfc, 0xbb, 0xc9, 0x7e, 0x20, 0x22, 0x7e, 0x79, 0x67, 0x70, 0x47, 0xd7, 0xf7, 0x62, - 0x2c, 0x23, 0x9f, 0x01, 0x88, 0x56, 0xd5, 0x3a, 0x9d, 0xca, 0x38, 0x76, 0xf2, 0xac, 0xd9, 0xc9, - 0x5a, 0xa7, 0xb3, 0x78, 0x59, 0xf4, 0xef, 0x9c, 0xea, 0x9f, 0xd3, 0xe9, 0x68, 0xdc, 0x34, 0x26, - 0xe4, 0x13, 0x98, 0xc0, 0x25, 0x4d, 0x8e, 0xe8, 0x04, 0x8e, 0xe8, 0x85, 0xe3, 0xa3, 0xea, 0x1c, - 0xae, 0x56, 0x19, 0xe3, 0x69, 0x10, 0x90, 0xdf, 0x80, 0x59, 0xc1, 0xee, 0xa1, 0xeb, 0xb5, 0xfc, - 0x67, 0xe1, 0x32, 0x0d, 0x9f, 0x44, 0x7e, 0x07, 0x97, 0xbf, 0xf1, 0x85, 0x8b, 0x66, 0xf3, 0x4c, - 0x9c, 0xc5, 0x1b, 0xa2, 0xa5, 0x96, 0x6a, 0xe9, 0x33, 0x8e, 0xd0, 0x68, 0x71, 0x0c, 0x7d, 0x81, - 0xcc, 0x64, 0x41, 0xd6, 0xe0, 0xcc, 0x6e, 0x48, 0x8d, 0x3e, 0x4c, 0xe1, 0xfe, 0x50, 0x65, 0x23, - 0xdc, 0x0d, 0x69, 0x23, 0xaf, 0x1f, 0x49, 0x3a, 0x62, 0x03, 0x59, 0x0e, 0xfc, 0x4e, 0x62, 0x8e, - 0x9f, 0x41, 0x89, 0x58, 0xc7, 0x47, 0xd5, 0xcb, 0xad, 0xc0, 0xef, 0x34, 0xf2, 0x27, 0x7a, 0x06, - 0x35, 0xf9, 0x11, 0x9c, 0x5b, 0xf2, 0x3d, 0x8f, 0x36, 0xd9, 0x0a, 0xba, 0xec, 0x3a, 0xfb, 0x9e, - 0x1f, 0x46, 0x6e, 0x73, 0x6d, 0xb9, 0x52, 0x8e, 0xb7, 0x87, 0xa6, 0xc2, 0x68, 0xb4, 0x14, 0x8a, - 0xb9, 0x3d, 0xe4, 0x70, 0x21, 0x5f, 0xc1, 0xa4, 0xa8, 0x8b, 0x06, 0x38, 0x35, 0xcf, 0x16, 0x4f, - 0x34, 0x85, 0xcc, 0x37, 0xfa, 0x40, 0xfe, 0xe4, 0xaa, 0x93, 0xc9, 0x8b, 0x7c, 0x0d, 0xe3, 0x1b, - 0x77, 0x6b, 0x36, 0x0d, 0x3b, 0xbe, 0x17, 0xd2, 0x0a, 0xc1, 0x11, 0xbd, 0x2c, 0x58, 0x6f, 0xdc, - 0xad, 0xd5, 0xba, 0xd1, 0x01, 0xf5, 0x22, 0xb7, 0xe9, 0x44, 0x54, 0x62, 0x2d, 0xce, 0xb3, 0x99, - 0x77, 0xf8, 0xd8, 0x69, 0x04, 0x02, 0xa2, 0xf5, 0x42, 0x67, 0x47, 0xe6, 0x61, 0xb4, 0x5e, 0x5f, - 0x5d, 0xf7, 0xf7, 0x5d, 0xaf, 0x32, 0xcd, 0x84, 0x61, 0xab, 0xdf, 0xe4, 0x31, 0xcc, 0x6a, 0x67, - 0x83, 0x06, 0xfb, 0x9f, 0x1e, 0x52, 0x2f, 0xaa, 0xcc, 0x60, 0x1b, 0xbe, 0xaf, 0x0e, 0x37, 0x37, - 0xf5, 0x23, 0xc4, 0xd3, 0x3b, 0x37, 0x6b, 0xf1, 0xcf, 0xba, 0x24, 0x5a, 0xec, 0xaf, 0x94, 0xec, - 0x19, 0x27, 0xa3, 0x84, 0xec, 0xc0, 0xc8, 0x76, 0x37, 0xe8, 0xf8, 0x21, 0xad, 0xcc, 0xa2, 0xe0, - 0xae, 0x15, 0x7d, 0xa1, 0x02, 0x75, 0x71, 0x96, 0x2d, 0xd1, 0x1d, 0xfe, 0x43, 0xeb, 0x9d, 0x64, - 0x45, 0x3e, 0x85, 0x89, 0x7a, 0x7d, 0x35, 0xde, 0x50, 0xce, 0xe1, 0x86, 0x72, 0xf1, 0xf8, 0xa8, - 0x5a, 0x61, 0x2a, 0x55, 0xbc, 0xa9, 0xe8, 0x5f, 0x95, 0x4e, 0xc1, 0x38, 0xec, 0xac, 0xd7, 0x63, - 0x0e, 0x73, 0x31, 0x07, 0xa6, 0xcc, 0x65, 0x73, 0xd0, 0x29, 0xc8, 0x3f, 0x28, 0xc1, 0x15, 0x9d, - 0x65, 0x96, 0x60, 0x2a, 0xe7, 0x5f, 0x44, 0x9a, 0x0b, 0xc7, 0x47, 0xd5, 0x9b, 0x66, 0x3f, 0x1a, - 0x99, 0x83, 0xa5, 0xb5, 0xad, 0x67, 0x53, 0xb0, 0xbd, 0x7a, 0x07, 0x32, 0xdb, 0x3b, 0xff, 0xc2, - 0xed, 0x35, 0xa5, 0xd6, 0xbb, 0xbd, 0xbd, 0x9a, 0x62, 0x7d, 0x0e, 0x63, 0x6a, 0xd1, 0x26, 0x23, - 0x30, 0x50, 0x6b, 0xb7, 0xcb, 0x7d, 0xec, 0x8f, 0x7a, 0x7d, 0xb5, 0x5c, 0x22, 0x53, 0x00, 0xf1, - 0x4e, 0x55, 0xee, 0x27, 0x13, 0x30, 0x2a, 0x77, 0x92, 0xf2, 0x00, 0xe2, 0x77, 0x3a, 0xe5, 0x41, - 0x42, 0x60, 0xca, 0x5c, 0xcf, 0xca, 0x43, 0xd6, 0xef, 0x95, 0x60, 0x4c, 0x7d, 0x87, 0xe4, 0x0c, - 0x8c, 0xef, 0x6e, 0xd6, 0xb7, 0x57, 0x96, 0xd6, 0xee, 0xae, 0xad, 0x2c, 0x97, 0xfb, 0xc8, 0x25, - 0x38, 0xbf, 0x53, 0x5f, 0x6d, 0x2c, 0x2f, 0x36, 0xd6, 0xb7, 0x96, 0x6a, 0xeb, 0x8d, 0x6d, 0x7b, - 0xeb, 0xf3, 0x2f, 0x1a, 0x3b, 0xbb, 0x9b, 0x9b, 0x2b, 0xeb, 0xe5, 0x12, 0xa9, 0xc0, 0x0c, 0x2b, - 0x7e, 0xb0, 0xbb, 0xb8, 0xa2, 0x23, 0x94, 0xfb, 0xc9, 0x55, 0xb8, 0x94, 0x55, 0xd2, 0x58, 0x5d, - 0xa9, 0x2d, 0xaf, 0xaf, 0xd4, 0xeb, 0xe5, 0x01, 0x32, 0x07, 0xd3, 0x0c, 0xa5, 0xb6, 0xbd, 0x6d, - 0xd0, 0x0e, 0x5a, 0x6d, 0x18, 0xd7, 0x3e, 0x00, 0x72, 0x11, 0x2a, 0x4b, 0x2b, 0xf6, 0x4e, 0x63, - 0x7b, 0xd7, 0xde, 0xde, 0xaa, 0xaf, 0x34, 0xcc, 0x16, 0x26, 0x4b, 0xd7, 0xb7, 0xee, 0xad, 0x6d, - 0x36, 0x18, 0xa8, 0x5e, 0x2e, 0xb1, 0x66, 0x18, 0xa5, 0xf5, 0xb5, 0xcd, 0x7b, 0xeb, 0x2b, 0x8d, - 0xdd, 0xfa, 0x8a, 0x40, 0xe9, 0xb7, 0x7e, 0xab, 0x3f, 0xb5, 0xa5, 0x93, 0x05, 0x18, 0xaf, 0x73, - 0x7b, 0x05, 0x2e, 0x73, 0xfc, 0x80, 0xc8, 0x74, 0xb4, 0x09, 0x61, 0xc6, 0xe0, 0x2b, 0x98, 0x8e, - 0xc4, 0xb4, 0xb4, 0x6d, 0xf6, 0x35, 0x37, 0xfd, 0xb6, 0xae, 0xa5, 0x75, 0x04, 0xcc, 0x56, 0xa5, - 0x64, 0x41, 0xd3, 0xe7, 0xf8, 0x69, 0x11, 0x4f, 0x24, 0x52, 0x9f, 0xd3, 0xf7, 0x76, 0xa5, 0xd9, - 0x2d, 0xc4, 0x43, 0x2a, 0xd4, 0x30, 0xa4, 0xc9, 0xd0, 0x25, 0x14, 0x1e, 0x79, 0x43, 0x6a, 0xba, - 0xfc, 0x74, 0x87, 0x9b, 0x7d, 0xe2, 0x5c, 0x22, 0x94, 0x5c, 0xab, 0x9b, 0xb3, 0xb1, 0x92, 0x0f, - 0x93, 0x73, 0x46, 0x08, 0x03, 0x99, 0x25, 0xf6, 0x4f, 0x3b, 0x81, 0x4a, 0xaa, 0x30, 0xc4, 0x57, - 0x5c, 0x2e, 0x0f, 0xd4, 0xad, 0xdb, 0x0c, 0x60, 0x73, 0xb8, 0xf5, 0xfb, 0x03, 0xba, 0x92, 0xc1, - 0x74, 0x69, 0x4d, 0xde, 0xa8, 0x4b, 0xa3, 0x9c, 0x11, 0xca, 0x8e, 0x82, 0xfc, 0x2b, 0xc1, 0xa3, - 0xe0, 0x40, 0x7c, 0x14, 0x14, 0x9f, 0x1a, 0x3f, 0x0a, 0xc6, 0x28, 0x6c, 0x14, 0x85, 0xda, 0x86, - 0x5c, 0x07, 0xe3, 0x51, 0x14, 0xaa, 0x9e, 0x18, 0x45, 0x0d, 0x89, 0x7c, 0x00, 0x50, 0x7b, 0x58, - 0xc7, 0x33, 0x8f, 0xbd, 0x29, 0x54, 0x57, 0xdc, 0x64, 0x9c, 0x67, 0xa1, 0x38, 0x52, 0x05, 0xfa, - 0x99, 0x51, 0xc3, 0x26, 0x8b, 0x30, 0x59, 0xfb, 0x69, 0x37, 0xa0, 0x6b, 0x2d, 0xb6, 0x4f, 0x45, - 0xfc, 0x70, 0x3c, 0xc6, 0x17, 0x52, 0x87, 0x15, 0x34, 0x5c, 0x51, 0xa2, 0x31, 0x30, 0x49, 0xc8, - 0x16, 0x9c, 0xbd, 0xb7, 0xb4, 0x2d, 0xe6, 0x55, 0xad, 0xd9, 0xf4, 0xbb, 0x5e, 0x24, 0xf4, 0xd5, - 0xab, 0xc7, 0x47, 0xd5, 0x4b, 0xfb, 0xcd, 0x4e, 0x43, 0xce, 0x41, 0x87, 0x17, 0xeb, 0x0a, 0x6b, - 0x8a, 0x96, 0x5c, 0x83, 0x81, 0x5d, 0x7b, 0x4d, 0x9c, 0x9c, 0xcf, 0x1e, 0x1f, 0x55, 0x27, 0xbb, - 0x81, 0xab, 0x91, 0xb0, 0xd2, 0xfb, 0x83, 0xa3, 0xfd, 0xe5, 0x01, 0x7b, 0xac, 0x4e, 0xc3, 0x90, - 0x1f, 0xf2, 0xda, 0x30, 0x75, 0x8f, 0x46, 0x6c, 0xf6, 0xc9, 0x43, 0x4b, 0xf1, 0xd8, 0x7c, 0x04, - 0xe3, 0x0f, 0xdd, 0xe8, 0xa0, 0x4e, 0x9b, 0x01, 0x8d, 0xa4, 0xc1, 0x06, 0xe5, 0xf6, 0xcc, 0x8d, - 0x0e, 0x1a, 0x21, 0x87, 0xeb, 0x9b, 0xb3, 0x86, 0x6e, 0xad, 0xc0, 0x19, 0x51, 0x9b, 0x3a, 0x23, - 0x2d, 0x98, 0x0c, 0x4b, 0xc8, 0x10, 0xc7, 0x4e, 0x67, 0x68, 0xb2, 0xf9, 0xc7, 0xfd, 0x30, 0xbb, - 0x74, 0xe0, 0x78, 0xfb, 0x74, 0xdb, 0x09, 0xc3, 0x67, 0x7e, 0xd0, 0xd2, 0x1a, 0x8f, 0x07, 0xc4, - 0x54, 0xe3, 0xf1, 0x44, 0xb8, 0x00, 0xe3, 0x5b, 0xed, 0x96, 0xa4, 0x11, 0x87, 0x57, 0xac, 0xcb, - 0x6f, 0xb7, 0x1a, 0x1d, 0xc9, 0x4b, 0x47, 0x62, 0x34, 0x9b, 0xf4, 0x99, 0xa2, 0x19, 0x88, 0x69, - 0x3c, 0xfa, 0x4c, 0xa3, 0xd1, 0x90, 0xc8, 0x0a, 0x9c, 0xad, 0xd3, 0xa6, 0xef, 0xb5, 0xee, 0x3a, - 0xcd, 0xc8, 0x0f, 0x76, 0xfc, 0x27, 0xd4, 0x13, 0xb3, 0x12, 0xb5, 0xfb, 0x10, 0x0b, 0x1b, 0x8f, - 0xb1, 0xb4, 0x11, 0xb1, 0x62, 0x3b, 0x4d, 0x41, 0xb6, 0x60, 0xf4, 0xa1, 0x30, 0xfb, 0x89, 0x13, - 0xef, 0xab, 0x37, 0x95, 0x1d, 0x70, 0x29, 0xa0, 0x38, 0x95, 0x9c, 0xb6, 0x3a, 0xb3, 0x2b, 0x65, - 0x09, 0xd7, 0x23, 0x89, 0x69, 0x2b, 0x26, 0xd6, 0x2e, 0x4c, 0x6e, 0xb7, 0xbb, 0xfb, 0xae, 0xc7, - 0x56, 0x8e, 0x3a, 0xfd, 0x09, 0x59, 0x06, 0x88, 0x01, 0xc2, 0x98, 0x37, 0x2d, 0xce, 0xc9, 0x71, - 0xc1, 0xde, 0x5b, 0xe2, 0xf3, 0x43, 0x08, 0x1e, 0x6b, 0x6c, 0x8d, 0xce, 0xfa, 0x6f, 0x03, 0x40, - 0xc4, 0x00, 0xe0, 0x4e, 0x56, 0xa7, 0x11, 0xdb, 0x63, 0xce, 0x41, 0xbf, 0xb2, 0xb9, 0x0d, 0x1f, - 0x1f, 0x55, 0xfb, 0xdd, 0x96, 0xdd, 0xbf, 0xb6, 0x4c, 0xde, 0x86, 0x21, 0x44, 0x43, 0xf9, 0x4f, - 0xa9, 0xfa, 0x74, 0x0e, 0x7c, 0x05, 0xc1, 0x2d, 0xd4, 0xe6, 0xc8, 0xe4, 0x1d, 0x18, 0x5b, 0xa6, - 0x6d, 0xba, 0xef, 0x44, 0xbe, 0x5c, 0x13, 0xb8, 0x15, 0x4b, 0x02, 0xb5, 0x39, 0x17, 0x63, 0xb2, - 0x33, 0xad, 0x4d, 0x9d, 0xd0, 0xf7, 0xf4, 0x33, 0x6d, 0x80, 0x10, 0xfd, 0x4c, 0xcb, 0x71, 0xc8, - 0xff, 0x53, 0x82, 0xf1, 0x9a, 0xe7, 0x09, 0xeb, 0x50, 0x28, 0xa4, 0x3e, 0x7b, 0x53, 0x99, 0x53, - 0xd7, 0x9d, 0x47, 0xb4, 0xbd, 0xe7, 0xb4, 0xbb, 0x34, 0x5c, 0xfc, 0x9a, 0x1d, 0x33, 0xfe, 0xed, - 0x51, 0xf5, 0xc3, 0x53, 0xd8, 0x7b, 0x62, 0xc3, 0xec, 0x4e, 0xe0, 0xb8, 0x51, 0x78, 0x7c, 0x54, - 0x9d, 0x75, 0xe2, 0x0a, 0xf5, 0xef, 0x46, 0x6b, 0x47, 0xbc, 0xc0, 0x0f, 0xf7, 0x5a, 0xe0, 0xc9, - 0x21, 0x9c, 0xa9, 0x85, 0x61, 0xf7, 0x90, 0xd6, 0x23, 0x27, 0x88, 0x76, 0xdc, 0x43, 0x8a, 0xab, - 0x4a, 0xb1, 0x85, 0xe0, 0xf5, 0x9f, 0x1d, 0x55, 0x4b, 0xec, 0x64, 0xe3, 0x20, 0x29, 0x53, 0x5e, - 0x82, 0xa8, 0x11, 0xb9, 0xfa, 0x1e, 0x85, 0xb6, 0x82, 0x24, 0x6f, 0xeb, 0x9a, 0xd2, 0x2a, 0xd6, - 0x96, 0xf3, 0x46, 0xdc, 0x5a, 0x82, 0x8b, 0xf7, 0x68, 0x64, 0xd3, 0x90, 0x46, 0xf2, 0x1b, 0xc1, - 0x19, 0x1e, 0x5b, 0x68, 0x47, 0xf0, 0xb7, 0x22, 0xc6, 0xe1, 0xe7, 0xdf, 0x85, 0x2c, 0xb1, 0xfe, - 0x97, 0x12, 0x54, 0x97, 0x02, 0xca, 0x0f, 0x05, 0x39, 0x8c, 0x8a, 0xd7, 0xae, 0x8b, 0x30, 0xb8, - 0xf3, 0xbc, 0x23, 0x4d, 0x2b, 0x58, 0xca, 0x06, 0xc5, 0x46, 0xe8, 0x09, 0x2d, 0x55, 0xd6, 0x63, - 0x98, 0xb5, 0xa9, 0x47, 0x9f, 0x39, 0x8f, 0xda, 0xd4, 0x30, 0xf6, 0x54, 0x61, 0x88, 0x7f, 0xe8, - 0xa9, 0x2e, 0x70, 0xf8, 0xe9, 0x0c, 0x67, 0xd6, 0x24, 0x8c, 0x6f, 0xbb, 0xde, 0xbe, 0xe0, 0x6e, - 0xfd, 0xd5, 0x20, 0x4c, 0xf0, 0xdf, 0xe2, 0x9c, 0x93, 0xd8, 0xf3, 0x4a, 0x27, 0xd9, 0xf3, 0xde, - 0x83, 0x49, 0xb6, 0x69, 0xd0, 0x60, 0x8f, 0x06, 0x6c, 0xfd, 0x17, 0x92, 0xc0, 0x33, 0x5b, 0x88, - 0x05, 0x8d, 0xa7, 0xbc, 0xc4, 0x36, 0x11, 0xc9, 0x3a, 0x4c, 0x71, 0xc0, 0x5d, 0xea, 0x44, 0xdd, - 0xd8, 0xec, 0x74, 0x46, 0x1c, 0x6c, 0x24, 0x98, 0x4f, 0x4d, 0xc1, 0xeb, 0xb1, 0x00, 0xda, 0x09, - 0x5a, 0xf2, 0x09, 0x9c, 0xd9, 0x0e, 0xfc, 0x6f, 0x9e, 0x6b, 0xbb, 0x3c, 0xff, 0x3a, 0xf9, 0x11, - 0x88, 0x15, 0x35, 0xf4, 0xbd, 0x3e, 0x89, 0x4d, 0xde, 0x80, 0xd1, 0xb5, 0x70, 0xd1, 0x0f, 0x5c, - 0x6f, 0x1f, 0xbf, 0xd1, 0x51, 0x6e, 0xad, 0x77, 0xc3, 0xc6, 0x23, 0x04, 0xda, 0xaa, 0x38, 0x61, - 0x57, 0x1e, 0xe9, 0x6d, 0x57, 0xbe, 0x0d, 0xb0, 0xee, 0x3b, 0xad, 0x5a, 0xbb, 0xbd, 0x54, 0x0b, - 0x71, 0x3b, 0x15, 0xfb, 0x51, 0xdb, 0x77, 0x5a, 0x0d, 0xa7, 0xdd, 0x6e, 0x34, 0x9d, 0xd0, 0xd6, - 0x70, 0xc8, 0x97, 0x70, 0x3e, 0x74, 0xf7, 0x3d, 0xec, 0x5c, 0xc3, 0x69, 0xef, 0xfb, 0x81, 0x1b, - 0x1d, 0x1c, 0x36, 0xc2, 0xae, 0x1b, 0x71, 0xa3, 0xce, 0xd4, 0xc2, 0x65, 0xb1, 0xc8, 0xd5, 0x25, - 0x5e, 0x4d, 0xa2, 0xd5, 0x19, 0x96, 0x3d, 0x17, 0x66, 0x17, 0x90, 0x87, 0x30, 0xb9, 0xee, 0x36, - 0xa9, 0x17, 0x52, 0xb4, 0xd2, 0x3d, 0x47, 0x93, 0x4f, 0xf1, 0xc7, 0xcc, 0x84, 0x38, 0xd9, 0xd6, - 0x89, 0xf0, 0xd3, 0x35, 0xf9, 0xdc, 0x1f, 0x1c, 0x1d, 0x2e, 0x8f, 0xd8, 0x67, 0x04, 0xf0, 0xa1, - 0x13, 0x78, 0xae, 0xb7, 0x1f, 0x5a, 0xff, 0xf0, 0x2c, 0x8c, 0xaa, 0x71, 0xba, 0xa9, 0x1f, 0x37, - 0xc4, 0xd6, 0x8c, 0x53, 0x36, 0x36, 0xa6, 0xd9, 0x1a, 0x06, 0x39, 0x8f, 0x07, 0x10, 0xa1, 0x14, - 0x8c, 0xb0, 0x4f, 0xc8, 0xe9, 0x74, 0x6c, 0x06, 0x63, 0x4b, 0xc3, 0xf2, 0x22, 0x4e, 0x9a, 0x51, - 0xbe, 0x34, 0xb4, 0x1e, 0xd9, 0xfd, 0xcb, 0x8b, 0xec, 0x9b, 0xdc, 0x5a, 0x5b, 0x5e, 0xc2, 0xf1, - 0x1f, 0xe5, 0xdf, 0xa4, 0xef, 0xb6, 0x9a, 0x36, 0x42, 0x59, 0x69, 0xbd, 0xb6, 0xb1, 0x2e, 0xc6, - 0x18, 0x4b, 0x43, 0xe7, 0xb0, 0x6d, 0x23, 0x94, 0xa9, 0xac, 0xdc, 0x2e, 0xb2, 0xe4, 0x7b, 0x51, - 0xe0, 0xb7, 0x43, 0xd4, 0xc3, 0x46, 0xf9, 0x1c, 0x14, 0x06, 0x95, 0xa6, 0x28, 0xb2, 0x13, 0xa8, - 0xe4, 0x21, 0xcc, 0xd5, 0x5a, 0x4f, 0x1d, 0xaf, 0x49, 0x5b, 0xbc, 0xe4, 0xa1, 0x1f, 0x3c, 0x79, - 0xdc, 0xf6, 0x9f, 0x85, 0x38, 0x49, 0x46, 0x85, 0xfd, 0x51, 0xa0, 0x48, 0xfb, 0xcc, 0x33, 0x89, - 0x64, 0xe7, 0x51, 0xb3, 0x75, 0x60, 0xa9, 0xed, 0x77, 0x5b, 0x62, 0xea, 0xe0, 0x3a, 0xd0, 0x64, - 0x00, 0x9b, 0xc3, 0x99, 0x94, 0x56, 0xeb, 0x1b, 0x38, 0x31, 0x84, 0x94, 0x0e, 0xc2, 0x43, 0x9b, - 0xc1, 0xc8, 0xab, 0x30, 0x22, 0xb5, 0x6f, 0x7e, 0x1d, 0x81, 0x66, 0x70, 0xa9, 0x75, 0xcb, 0x32, - 0xf6, 0x1d, 0xdb, 0xb4, 0xe9, 0x3f, 0xa5, 0xc1, 0xf3, 0x25, 0xbf, 0x45, 0xa5, 0x6d, 0x4a, 0xd8, - 0x5e, 0x78, 0x41, 0xa3, 0xc9, 0x4a, 0x6c, 0x13, 0x91, 0x55, 0xc0, 0x37, 0xee, 0xb0, 0x72, 0x26, - 0xae, 0x80, 0x6f, 0xec, 0xa1, 0x2d, 0xcb, 0xc8, 0x32, 0x9c, 0xad, 0x75, 0x23, 0xff, 0xd0, 0x89, - 0xdc, 0xe6, 0x6e, 0x67, 0x3f, 0x70, 0x58, 0x25, 0x65, 0x24, 0xc0, 0xd3, 0x88, 0x23, 0x0b, 0x1b, - 0x5d, 0x51, 0x6a, 0xa7, 0x09, 0xc8, 0xbb, 0x30, 0xb1, 0x16, 0x72, 0xfb, 0xa3, 0x13, 0xd2, 0x16, - 0x1a, 0x91, 0x44, 0x2b, 0xdd, 0xb0, 0x81, 0xd6, 0xc8, 0x06, 0x3b, 0xbf, 0xb4, 0x6c, 0x03, 0x8f, - 0x58, 0x30, 0x5c, 0x0b, 0x43, 0x37, 0x8c, 0xd0, 0x36, 0x34, 0xba, 0x08, 0xc7, 0x47, 0xd5, 0x61, - 0x07, 0x21, 0xb6, 0x28, 0x21, 0x0f, 0x61, 0x7c, 0x99, 0x32, 0xf5, 0x77, 0x27, 0xe8, 0x86, 0x11, - 0x5a, 0x7a, 0xc6, 0x17, 0xce, 0x8b, 0xd5, 0x48, 0x2b, 0x11, 0x73, 0x99, 0xab, 0xa8, 0x2d, 0x84, - 0x37, 0x22, 0x56, 0xa0, 0x6f, 0xb5, 0x1a, 0x3e, 0xd3, 0xed, 0x05, 0xcd, 0xaa, 0xdb, 0x62, 0xeb, - 0xcb, 0x0c, 0xb6, 0x01, 0x75, 0x7b, 0xb1, 0xa0, 0x35, 0x0e, 0xb0, 0x44, 0xd7, 0xed, 0x0d, 0x12, - 0xd2, 0x4c, 0x99, 0xb4, 0x67, 0x0d, 0xb3, 0xa5, 0x59, 0x28, 0x9b, 0x78, 0x4a, 0x83, 0xf7, 0x47, - 0x30, 0xbe, 0xd4, 0x0d, 0x23, 0xff, 0x70, 0xe7, 0x80, 0x1e, 0x52, 0xb4, 0x06, 0x89, 0x13, 0x4c, - 0x13, 0xc1, 0x8d, 0x88, 0xc1, 0xf5, 0x6e, 0x6a, 0xe8, 0xe4, 0x33, 0x20, 0xf2, 0x28, 0x72, 0x8f, - 0xcd, 0x0f, 0x8f, 0xcd, 0x65, 0x34, 0x08, 0x8d, 0xf2, 0xf3, 0x87, 0x3c, 0xc1, 0x34, 0xf6, 0x55, - 0xb1, 0x6e, 0x94, 0x4c, 0x13, 0xb3, 0x06, 0xf1, 0x26, 0xde, 0x0b, 0x9c, 0xce, 0x41, 0xa5, 0x12, - 0x1f, 0x0d, 0x44, 0xa7, 0xf6, 0x19, 0xdc, 0x50, 0x71, 0x62, 0x74, 0x52, 0x07, 0xe0, 0x3f, 0xd7, - 0xd9, 0xc0, 0x73, 0x13, 0x52, 0xc5, 0x90, 0x17, 0x2b, 0x90, 0xb2, 0x3a, 0x8f, 0x8a, 0x13, 0x67, - 0xdb, 0x76, 0x8d, 0xd1, 0xd4, 0xd8, 0x90, 0x27, 0x50, 0xe6, 0xbf, 0x36, 0x7c, 0xcf, 0x8d, 0xf8, - 0x7e, 0x31, 0x6f, 0xd8, 0x1b, 0x93, 0xc5, 0xb2, 0x02, 0xb4, 0xf3, 0x8a, 0x0a, 0x0e, 0x55, 0xa9, - 0x56, 0x4d, 0x8a, 0x31, 0xd9, 0x86, 0xf1, 0xed, 0xc0, 0x6f, 0x75, 0x9b, 0x11, 0x6a, 0x19, 0x17, - 0x70, 0xe1, 0x27, 0xa2, 0x1e, 0xad, 0x84, 0xcb, 0xa4, 0xc3, 0x01, 0x0d, 0xb6, 0x2f, 0xe8, 0x32, - 0xd1, 0x10, 0xc9, 0x22, 0x0c, 0x6f, 0xfb, 0x6d, 0xb7, 0xf9, 0xbc, 0x72, 0x11, 0x1b, 0x3d, 0x23, - 0x99, 0x21, 0x50, 0x36, 0x15, 0x55, 0xda, 0x0e, 0x82, 0x74, 0x95, 0x96, 0x23, 0x91, 0x1a, 0x4c, - 0x7e, 0xc6, 0x26, 0x8c, 0xeb, 0x7b, 0x9e, 0xe3, 0x06, 0xb4, 0x72, 0x09, 0xc7, 0x05, 0x6d, 0xf1, - 0x3f, 0xd1, 0x0b, 0xf4, 0xe9, 0x6c, 0x50, 0x90, 0x35, 0x38, 0xb3, 0x16, 0xd6, 0xa3, 0xc0, 0xed, - 0xd0, 0x0d, 0xc7, 0x73, 0xf6, 0x69, 0xab, 0x72, 0x39, 0x36, 0x86, 0xbb, 0x61, 0x23, 0xc4, 0xb2, - 0xc6, 0x21, 0x2f, 0xd4, 0x8d, 0xe1, 0x09, 0x3a, 0xf2, 0x39, 0xcc, 0xac, 0x7c, 0x13, 0xb1, 0x19, - 0xd3, 0xae, 0x75, 0x5b, 0x6e, 0x54, 0x8f, 0xfc, 0xc0, 0xd9, 0xa7, 0x95, 0x2a, 0xf2, 0x7b, 0xe5, - 0xf8, 0xa8, 0x7a, 0x85, 0x8a, 0xf2, 0x86, 0xc3, 0x10, 0x1a, 0x21, 0xc7, 0xd0, 0x2f, 0xb9, 0xb3, - 0x38, 0x30, 0xe9, 0xd7, 0xbb, 0x1d, 0xa6, 0x6d, 0xa3, 0xf4, 0xaf, 0x18, 0xd2, 0xd7, 0x4a, 0xb8, - 0xf4, 0x43, 0x0e, 0x48, 0x49, 0x5f, 0x43, 0x24, 0x36, 0x90, 0xfb, 0xbe, 0xeb, 0xd5, 0x9a, 0x91, - 0xfb, 0x94, 0x8a, 0x13, 0x73, 0x58, 0xb9, 0x8a, 0x2d, 0x45, 0xc3, 0xfd, 0xaf, 0xfa, 0xae, 0xd7, - 0x70, 0xb0, 0xb8, 0x11, 0x8a, 0x72, 0xfd, 0x1b, 0x49, 0x53, 0x93, 0x1f, 0xc1, 0xb9, 0x0d, 0xff, - 0x91, 0xdb, 0xa6, 0x7c, 0xc9, 0xe1, 0x62, 0x41, 0x23, 0xa4, 0x85, 0x7c, 0xd1, 0x70, 0x7f, 0x88, - 0x18, 0x0d, 0xb1, 0x5a, 0x1d, 0x2a, 0x1c, 0xdd, 0x70, 0x9f, 0xcd, 0x85, 0xac, 0xc0, 0x04, 0x7e, - 0x97, 0x6d, 0xfc, 0x19, 0x56, 0xae, 0xe1, 0x91, 0xee, 0x6a, 0x42, 0x4b, 0xbb, 0xb9, 0xa2, 0xe1, - 0xac, 0x78, 0x51, 0xf0, 0xdc, 0x36, 0xc8, 0xc8, 0xc7, 0x30, 0x9f, 0x9c, 0xde, 0x4b, 0xbe, 0xf7, - 0xd8, 0xdd, 0xef, 0x06, 0xb4, 0x55, 0x79, 0x85, 0x35, 0xd5, 0x2e, 0xc0, 0x98, 0x7f, 0x08, 0x67, - 0x53, 0x55, 0x90, 0x32, 0x0c, 0x3c, 0x11, 0xf7, 0xa0, 0x63, 0x36, 0xfb, 0x93, 0xbc, 0x09, 0x43, - 0x4f, 0xd9, 0x59, 0x0a, 0x35, 0x86, 0xf8, 0x66, 0x4d, 0x23, 0x5d, 0xf3, 0x1e, 0xfb, 0x36, 0x47, - 0xfa, 0xa0, 0xff, 0xbd, 0xd2, 0xfd, 0xc1, 0xd1, 0xf1, 0xf2, 0x04, 0xbf, 0xbe, 0xbe, 0x3f, 0x38, - 0x3a, 0x59, 0x9e, 0xb2, 0x6a, 0x70, 0x26, 0x81, 0x4f, 0x2a, 0x30, 0x42, 0x3d, 0xa6, 0x9f, 0xb7, - 0xb8, 0xce, 0x62, 0xcb, 0x9f, 0x64, 0x06, 0x86, 0xda, 0xee, 0xa1, 0x1b, 0x61, 0x85, 0x43, 0x36, - 0xff, 0x61, 0xfd, 0x41, 0x09, 0x48, 0x7a, 0xcb, 0x20, 0xb7, 0x12, 0x6c, 0xb8, 0x76, 0x2a, 0x40, - 0xba, 0x81, 0x5e, 0x72, 0xff, 0x0c, 0xa6, 0xf9, 0x98, 0xc9, 0xcd, 0x4d, 0xab, 0x8b, 0x2f, 0xaa, - 0x19, 0xc5, 0xba, 0x51, 0x47, 0x14, 0xe3, 0x56, 0xb8, 0x8e, 0x4d, 0xeb, 0xc2, 0x6c, 0xe6, 0x66, - 0x41, 0x36, 0x60, 0xf6, 0xd0, 0xf7, 0xa2, 0x83, 0xf6, 0x73, 0xb9, 0x57, 0x88, 0xda, 0x4a, 0x58, - 0x1b, 0xae, 0x8f, 0x99, 0x08, 0xf6, 0xb4, 0x00, 0x0b, 0x8e, 0x58, 0x8f, 0xb0, 0x0b, 0xc9, 0x9e, - 0x58, 0x36, 0x9c, 0x4d, 0xad, 0xb9, 0xe4, 0x87, 0x30, 0xd1, 0xc4, 0xf3, 0x97, 0x51, 0x13, 0xdf, - 0x71, 0x34, 0xb8, 0xfe, 0x39, 0x71, 0x38, 0xef, 0xca, 0xdf, 0x2d, 0xc1, 0x5c, 0xce, 0x6a, 0x7b, - 0x7a, 0x51, 0x7f, 0x01, 0xe7, 0x0e, 0x9d, 0x6f, 0x1a, 0x01, 0x1e, 0xaf, 0x1b, 0x81, 0xe3, 0x25, - 0xa4, 0x8d, 0x2b, 0x49, 0x36, 0x86, 0xee, 0x43, 0x74, 0xe8, 0x7c, 0x63, 0x23, 0x82, 0xcd, 0xca, - 0x79, 0x3b, 0x3f, 0x85, 0x49, 0x63, 0x7d, 0x3d, 0x75, 0xe3, 0xac, 0x3b, 0x70, 0x76, 0x99, 0xb6, - 0x69, 0x44, 0x4f, 0x6c, 0x56, 0xb3, 0xb6, 0x01, 0xea, 0xf4, 0xd0, 0xe9, 0x1c, 0xf8, 0x4c, 0xef, - 0x5e, 0xd4, 0x7f, 0x09, 0xb3, 0x0c, 0x91, 0x27, 0x08, 0x59, 0xb0, 0xf7, 0x16, 0xd7, 0xc5, 0x43, - 0x85, 0x69, 0x6b, 0x54, 0xd6, 0xbf, 0xec, 0x07, 0x22, 0x16, 0xc8, 0x80, 0x3a, 0x87, 0xb2, 0x19, - 0xef, 0xc3, 0x04, 0x3f, 0x44, 0x73, 0x30, 0x36, 0x67, 0x7c, 0x61, 0x5a, 0x7c, 0x79, 0x7a, 0xd1, - 0x6a, 0x9f, 0x6d, 0xa0, 0x32, 0x52, 0x9b, 0xf2, 0xd3, 0x3f, 0x92, 0xf6, 0x1b, 0xa4, 0x7a, 0x11, - 0x23, 0xd5, 0x7f, 0x93, 0x4f, 0x60, 0x6a, 0xc9, 0x3f, 0xec, 0x30, 0x99, 0x08, 0xe2, 0x01, 0x61, - 0x59, 0x11, 0xf5, 0x1a, 0x85, 0xab, 0x7d, 0x76, 0x02, 0x9d, 0x6c, 0xc2, 0xf4, 0xdd, 0x76, 0x37, - 0x3c, 0xa8, 0x79, 0xad, 0xa5, 0xb6, 0x1f, 0x4a, 0x2e, 0x83, 0xe2, 0x30, 0x24, 0x96, 0xb7, 0x34, - 0xc6, 0x6a, 0x9f, 0x9d, 0x45, 0x48, 0x5e, 0x85, 0xa1, 0x95, 0xa7, 0x6c, 0xd9, 0x95, 0x9e, 0x24, - 0xc2, 0xd1, 0x6d, 0xcb, 0xa3, 0x5b, 0x8f, 0x57, 0xfb, 0x6c, 0x5e, 0xba, 0x38, 0x06, 0x23, 0xf2, - 0x00, 0x7e, 0x8b, 0xa9, 0xc4, 0x4a, 0x9c, 0xf5, 0xc8, 0x89, 0xba, 0x21, 0x99, 0x87, 0xd1, 0xdd, - 0x0e, 0x3b, 0x17, 0x4a, 0xcb, 0x85, 0xad, 0x7e, 0x5b, 0x6f, 0x9a, 0x92, 0x26, 0x17, 0x21, 0x36, - 0xbb, 0x0a, 0x64, 0xcd, 0x0e, 0xbb, 0x6a, 0x0a, 0xb7, 0x18, 0xdb, 0xa8, 0xb7, 0x3f, 0x51, 0x6f, - 0x39, 0x29, 0x6b, 0x6b, 0x36, 0x53, 0x78, 0xd6, 0xe7, 0x70, 0x79, 0xb7, 0x13, 0xd2, 0x20, 0xaa, - 0x75, 0x3a, 0x6d, 0xb7, 0xc9, 0x6f, 0xa2, 0xf0, 0xa0, 0x2e, 0x27, 0xcb, 0xbb, 0x30, 0xcc, 0x01, - 0x62, 0x9a, 0xc8, 0x39, 0x58, 0xeb, 0x74, 0x84, 0x79, 0xe0, 0x2d, 0xae, 0x9c, 0xf3, 0x03, 0xbf, - 0x2d, 0xb0, 0xad, 0xdf, 0x2d, 0xc1, 0x65, 0xfe, 0x05, 0xe4, 0xb2, 0xfe, 0x1e, 0x8c, 0xa1, 0x9f, - 0x59, 0xc7, 0x69, 0xca, 0x6f, 0x82, 0x3b, 0xdc, 0x49, 0xa0, 0x1d, 0x97, 0x6b, 0x1e, 0x7c, 0xfd, - 0xf9, 0x1e, 0x7c, 0xf2, 0x03, 0x1b, 0xc8, 0xfc, 0xc0, 0x3e, 0x03, 0x4b, 0xb4, 0xa8, 0xdd, 0x4e, - 0x35, 0x2a, 0x7c, 0x91, 0x56, 0x59, 0xff, 0xa9, 0x1f, 0xe6, 0xee, 0x51, 0x8f, 0x06, 0x0e, 0xf6, - 0xd3, 0x30, 0x44, 0xe9, 0x9e, 0x3c, 0xa5, 0x42, 0x4f, 0x9e, 0xaa, 0x34, 0xed, 0xf5, 0xa3, 0x69, - 0x2f, 0xe5, 0x96, 0xc4, 0x8e, 0x8b, 0xbb, 0xf6, 0x9a, 0xe8, 0x16, 0x1e, 0x17, 0xbb, 0x81, 0x8b, - 0xd6, 0x7c, 0xb2, 0x16, 0x7b, 0x01, 0x0d, 0xf6, 0x34, 0x0b, 0x4c, 0x0b, 0xaf, 0x88, 0x11, 0xe1, - 0x05, 0x64, 0xfa, 0xfe, 0x6c, 0xc2, 0x30, 0xb7, 0x48, 0xe2, 0x1d, 0xd2, 0xf8, 0xc2, 0x0d, 0xf1, - 0x4d, 0xe5, 0x74, 0x50, 0x98, 0x2f, 0x71, 0x63, 0xe7, 0x53, 0x20, 0x42, 0x80, 0x2d, 0xb8, 0xcc, - 0x7f, 0x06, 0xe3, 0x1a, 0xca, 0x49, 0xf6, 0x7e, 0x65, 0x19, 0x65, 0x1a, 0xa3, 0xb7, 0xcf, 0x8d, - 0xac, 0xda, 0xde, 0x6f, 0x7d, 0x08, 0x95, 0x74, 0x6b, 0x84, 0x35, 0xac, 0x97, 0xf1, 0xcd, 0x5a, - 0x86, 0x99, 0x7b, 0x34, 0xc2, 0x89, 0x8b, 0x1f, 0x91, 0xe6, 0xcd, 0x96, 0xf8, 0xce, 0xe4, 0xaa, - 0x8a, 0x40, 0x36, 0xc1, 0xb4, 0xaf, 0xb4, 0x0e, 0xb3, 0x09, 0x2e, 0xa2, 0xfe, 0x0f, 0x60, 0x44, - 0x80, 0xd4, 0x8a, 0x2a, 0x5c, 0x62, 0xe9, 0x23, 0x51, 0xb0, 0xb7, 0xc0, 0xe7, 0xad, 0xe0, 0x6c, - 0x4b, 0x02, 0xeb, 0x00, 0xce, 0xb1, 0x6d, 0x36, 0xe6, 0xaa, 0xa6, 0xe3, 0x05, 0x18, 0xeb, 0x30, - 0x45, 0x21, 0x74, 0x7f, 0xca, 0xa7, 0xd1, 0x90, 0x3d, 0xca, 0x00, 0x75, 0xf7, 0xa7, 0x94, 0x5c, - 0x02, 0xc0, 0x42, 0xec, 0xa6, 0x58, 0x05, 0x10, 0x9d, 0x5b, 0x1b, 0x09, 0xa0, 0x2f, 0x1c, 0x9f, - 0x37, 0x36, 0xfe, 0x6d, 0x05, 0x30, 0x97, 0xaa, 0x49, 0x74, 0xe0, 0x16, 0x8c, 0x4a, 0x15, 0x36, - 0x71, 0x0f, 0xa0, 0xf7, 0xc0, 0x56, 0x48, 0xe4, 0x35, 0x38, 0xe3, 0xd1, 0x6f, 0xa2, 0x46, 0xaa, - 0x0d, 0x93, 0x0c, 0xbc, 0x2d, 0xdb, 0x61, 0xfd, 0x0a, 0xda, 0x7e, 0xeb, 0x9e, 0xff, 0xec, 0x71, - 0xdb, 0x79, 0x42, 0x53, 0x15, 0xff, 0x10, 0x46, 0xeb, 0xbd, 0x2b, 0xe6, 0x9f, 0x8f, 0xac, 0xdc, - 0x56, 0x24, 0x56, 0x1b, 0xe6, 0x59, 0x97, 0xea, 0xb5, 0x8d, 0xf5, 0xb5, 0xd6, 0xf6, 0x77, 0x2d, - 0xc0, 0xa7, 0x70, 0x21, 0xb3, 0xb6, 0xef, 0x5a, 0x88, 0x7f, 0x32, 0x08, 0x73, 0x7c, 0x33, 0x49, - 0xcf, 0xe0, 0x93, 0x2f, 0x35, 0xbf, 0x94, 0x7b, 0xd5, 0xdb, 0x19, 0xf7, 0xaa, 0x48, 0xa2, 0xdf, - 0xab, 0x1a, 0xb7, 0xa9, 0xef, 0x65, 0xdf, 0xa6, 0xa2, 0x9d, 0xc8, 0xbc, 0x4d, 0x4d, 0xde, 0xa1, - 0xae, 0xe4, 0xdf, 0xa1, 0xe2, 0xdd, 0x50, 0xc6, 0x1d, 0x6a, 0xd6, 0xcd, 0x69, 0xc2, 0x21, 0x69, - 0xf4, 0xe5, 0x3a, 0x24, 0xbd, 0x06, 0x23, 0xb5, 0x4e, 0x47, 0x73, 0xf0, 0xc3, 0xe1, 0x71, 0x3a, - 0x1d, 0x2e, 0x3c, 0x59, 0x28, 0xd7, 0x79, 0xc8, 0x58, 0xe7, 0xdf, 0x07, 0x58, 0xc2, 0x67, 0x08, - 0x38, 0x70, 0xe3, 0x88, 0x81, 0x1a, 0x3e, 0x7f, 0x9c, 0x80, 0x03, 0xa7, 0x5b, 0x40, 0x62, 0x64, - 0xae, 0xd8, 0x5b, 0x7b, 0x50, 0x49, 0x4f, 0x9f, 0x97, 0xb0, 0x74, 0xfd, 0x71, 0x09, 0x2e, 0x09, - 0x25, 0x27, 0xf1, 0x81, 0x9f, 0x7e, 0x76, 0xbe, 0x03, 0x13, 0x82, 0x76, 0x27, 0xfe, 0x10, 0xf8, - 0x45, 0xb6, 0x5c, 0x8c, 0xf9, 0x8a, 0x6e, 0xa0, 0x91, 0x77, 0x60, 0x14, 0xff, 0x88, 0xef, 0x6e, - 0x98, 0x64, 0xc6, 0x10, 0xb5, 0x91, 0xbc, 0xc1, 0x51, 0xa8, 0xd6, 0xd7, 0x70, 0x39, 0xaf, 0xe1, - 0x2f, 0x41, 0x2e, 0xff, 0xb4, 0x04, 0x17, 0x04, 0x7b, 0x63, 0xa9, 0x78, 0xa1, 0x5d, 0xe7, 0x14, - 0x6e, 0xc1, 0xf7, 0x61, 0x9c, 0x55, 0x28, 0xdb, 0x3d, 0x20, 0xb6, 0x56, 0x71, 0x72, 0x88, 0x4b, - 0x96, 0x9d, 0xc8, 0x11, 0x6e, 0x2e, 0xce, 0x61, 0x5b, 0x1a, 0x2f, 0x6c, 0x9d, 0xd8, 0xfa, 0x12, - 0x2e, 0x66, 0x77, 0xe1, 0x25, 0xc8, 0xe7, 0x3e, 0xcc, 0x67, 0x6c, 0x0a, 0x2f, 0xb6, 0x27, 0x7f, - 0x01, 0x17, 0x32, 0x79, 0xbd, 0x84, 0x66, 0xae, 0x32, 0x8d, 0x23, 0x7a, 0x09, 0x43, 0x68, 0x3d, - 0x84, 0xf3, 0x19, 0x9c, 0x5e, 0x42, 0x13, 0xef, 0xc1, 0x9c, 0xd2, 0xb4, 0xbf, 0x55, 0x0b, 0x37, - 0xe0, 0x12, 0x67, 0xf4, 0x72, 0x46, 0xe5, 0x01, 0x5c, 0x10, 0xec, 0x5e, 0x82, 0xf4, 0x56, 0xe1, - 0x62, 0x7c, 0xa0, 0xce, 0xd0, 0x93, 0x4e, 0xbc, 0xc8, 0x58, 0xeb, 0x70, 0x25, 0xe6, 0x94, 0xa3, - 0x34, 0x9c, 0x9c, 0x1b, 0x57, 0x07, 0xe3, 0x51, 0x7a, 0x29, 0x23, 0xfa, 0x10, 0xce, 0x19, 0x4c, - 0x5f, 0x9a, 0xaa, 0xb4, 0x06, 0xd3, 0x9c, 0xb1, 0xa9, 0x3a, 0x2f, 0xe8, 0xaa, 0xf3, 0xf8, 0xc2, - 0xd9, 0x98, 0x25, 0x82, 0xf7, 0xde, 0xca, 0xd0, 0xa6, 0x37, 0x50, 0x9b, 0x96, 0x28, 0x71, 0x0b, - 0xdf, 0x81, 0x61, 0x0e, 0x11, 0xed, 0xcb, 0x60, 0xc6, 0x0f, 0x0b, 0x9c, 0x4c, 0x20, 0x5b, 0x3f, - 0x82, 0x4b, 0xfc, 0x24, 0x1a, 0xdf, 0x25, 0x9a, 0xa7, 0xc5, 0x1f, 0x26, 0x0e, 0xa2, 0xe7, 0x05, - 0xdf, 0x24, 0x7e, 0xce, 0x79, 0xf4, 0x91, 0x9c, 0xdb, 0x79, 0xfc, 0x4f, 0xf4, 0x44, 0x4c, 0x1e, - 0x30, 0xfb, 0x33, 0x0f, 0x98, 0xd7, 0xe0, 0xaa, 0x3a, 0x60, 0x26, 0xab, 0x91, 0x53, 0xcb, 0xfa, - 0x12, 0x2e, 0xf0, 0x8e, 0x4a, 0xd7, 0x3d, 0xb3, 0x19, 0x1f, 0x26, 0xba, 0x39, 0x27, 0xba, 0x69, - 0x62, 0xe7, 0x74, 0xf2, 0xff, 0x28, 0xc9, 0x4f, 0x2e, 0x9b, 0xf9, 0x2f, 0xfb, 0xc4, 0xbd, 0x09, - 0x55, 0x25, 0x10, 0xb3, 0x45, 0x2f, 0x76, 0xdc, 0xde, 0x80, 0x59, 0x9d, 0x8d, 0xdb, 0xa4, 0x7b, - 0x77, 0xf0, 0x92, 0xe7, 0x6d, 0xf6, 0x59, 0x20, 0x40, 0x4e, 0xbb, 0x4a, 0x86, 0xdc, 0x10, 0xdf, - 0x56, 0x98, 0x56, 0x03, 0x2e, 0xa6, 0x87, 0xc2, 0x6d, 0x4a, 0xbf, 0x7d, 0xf2, 0x09, 0xfb, 0x84, - 0x11, 0x22, 0x06, 0x23, 0x97, 0xa9, 0xfc, 0x8e, 0x39, 0xb9, 0xa4, 0xb2, 0x2c, 0xb9, 0xd4, 0x24, - 0xfa, 0xcf, 0x6a, 0x97, 0xf3, 0xe1, 0xd7, 0x81, 0xc8, 0xa2, 0xa5, 0xba, 0x2d, 0xab, 0x3e, 0x0f, - 0x03, 0x4b, 0x75, 0x5b, 0x3c, 0x18, 0x42, 0x4d, 0xb0, 0x19, 0x06, 0x36, 0x83, 0x25, 0x35, 0xf2, - 0xfe, 0x13, 0x68, 0xe4, 0xf7, 0x07, 0x47, 0x07, 0xca, 0x83, 0x36, 0xa9, 0xbb, 0xfb, 0xde, 0x43, - 0x37, 0x3a, 0x50, 0x15, 0xd6, 0xac, 0xaf, 0x60, 0xda, 0xa8, 0x5e, 0x7c, 0xc5, 0x85, 0x2f, 0x9d, - 0x98, 0x3e, 0xbb, 0x54, 0x43, 0xcf, 0x17, 0x34, 0x59, 0x4c, 0xf0, 0xf5, 0xa6, 0xe9, 0x34, 0xf0, - 0x19, 0xad, 0x2d, 0x0b, 0xad, 0xbf, 0x33, 0xa8, 0x71, 0xd7, 0xde, 0x8f, 0x15, 0xf4, 0xee, 0x0e, - 0x00, 0x9f, 0x21, 0x5a, 0xe7, 0x98, 0x02, 0x38, 0x2e, 0x1c, 0x4a, 0xf8, 0x92, 0x6c, 0x6b, 0x48, - 0x27, 0x7d, 0x5f, 0x26, 0xfc, 0x7c, 0x39, 0x91, 0x7c, 0x52, 0xa9, 0xfc, 0x7c, 0x05, 0xeb, 0xd0, - 0xd6, 0x91, 0xc8, 0x8f, 0x92, 0x8f, 0x20, 0x86, 0xf0, 0x4e, 0xe9, 0x15, 0x79, 0xc9, 0x9c, 0xee, - 0xdb, 0xe9, 0xde, 0x41, 0x3c, 0x83, 0x59, 0x46, 0xeb, 0x3e, 0xc6, 0x83, 0xc5, 0xca, 0x37, 0x11, - 0xf5, 0xf8, 0xda, 0x3e, 0x8c, 0xf5, 0xbc, 0x5a, 0x50, 0x4f, 0x8c, 0x2c, 0xec, 0xef, 0x31, 0x9f, - 0x06, 0x55, 0x65, 0x76, 0x36, 0x7f, 0x9c, 0x44, 0xf6, 0xfa, 0x8a, 0xd7, 0xea, 0xf8, 0xae, 0x3a, - 0x30, 0xf1, 0x49, 0x14, 0xb4, 0x1b, 0x54, 0xc0, 0x6d, 0x1d, 0xc9, 0x7a, 0xad, 0xd0, 0x7b, 0x7c, - 0x14, 0x06, 0x77, 0x96, 0x76, 0xd6, 0xcb, 0x25, 0xeb, 0x16, 0x80, 0x56, 0x13, 0xc0, 0xf0, 0xe6, - 0x96, 0xbd, 0x51, 0x5b, 0x2f, 0xf7, 0x91, 0x59, 0x38, 0xfb, 0x70, 0x6d, 0x73, 0x79, 0xeb, 0x61, - 0xbd, 0x51, 0xdf, 0xa8, 0xd9, 0x3b, 0x4b, 0x35, 0x7b, 0xb9, 0x5c, 0xb2, 0xbe, 0x86, 0x19, 0xb3, - 0x87, 0x2f, 0x75, 0x12, 0x46, 0x30, 0xad, 0xf4, 0x99, 0xfb, 0x0f, 0x77, 0x34, 0xa7, 0x53, 0x71, - 0xf8, 0x4b, 0x3a, 0x4f, 0x89, 0x63, 0xa2, 0xf8, 0x8c, 0x34, 0x24, 0xf2, 0x06, 0x57, 0x0b, 0x92, - 0x2f, 0x84, 0x99, 0x5a, 0xd0, 0x88, 0xf5, 0x02, 0x5c, 0xfa, 0x7e, 0x00, 0x33, 0x66, 0xad, 0x27, - 0xb5, 0x52, 0xbd, 0x82, 0xde, 0xb8, 0xda, 0xf3, 0x21, 0x42, 0xf4, 0x6b, 0x03, 0xb1, 0xb2, 0xfe, - 0x00, 0xca, 0x02, 0x2b, 0xde, 0x79, 0xaf, 0x49, 0x33, 0x62, 0x29, 0xe3, 0xb1, 0xa3, 0x74, 0xfe, - 0xf6, 0xa1, 0xcc, 0x56, 0x4c, 0x41, 0xc9, 0x2b, 0x98, 0x81, 0xa1, 0xf5, 0xf8, 0x3a, 0xc7, 0xe6, - 0x3f, 0xf0, 0x15, 0x4d, 0xe4, 0x04, 0x91, 0x74, 0x55, 0x1b, 0xb3, 0xd5, 0x6f, 0xf2, 0x06, 0x0c, - 0xdf, 0x75, 0xdb, 0x91, 0x30, 0x8d, 0xc4, 0x9b, 0x3c, 0x63, 0xcb, 0x0b, 0x6c, 0x81, 0x60, 0xd9, - 0x70, 0x56, 0xab, 0xf0, 0x14, 0x4d, 0x25, 0x15, 0x18, 0xd9, 0xa4, 0xdf, 0x68, 0xf5, 0xcb, 0x9f, - 0xd6, 0xbb, 0x70, 0x56, 0xb8, 0x01, 0x6a, 0x62, 0xba, 0x2a, 0xde, 0x64, 0x97, 0x8c, 0x87, 0xa1, - 0x82, 0x25, 0x16, 0x31, 0xba, 0xdd, 0x4e, 0xeb, 0x05, 0xe9, 0xd8, 0x46, 0x71, 0x4a, 0xba, 0xd7, - 0xe5, 0x2d, 0x50, 0xaf, 0xe1, 0xfc, 0xdf, 0xfa, 0xa1, 0x92, 0xb0, 0x32, 0x2c, 0x1d, 0x38, 0xed, - 0x36, 0xf5, 0xf6, 0x29, 0xb9, 0x0e, 0x83, 0x3b, 0x5b, 0x3b, 0xdb, 0xc2, 0x4a, 0x2a, 0x1d, 0x00, - 0x18, 0x48, 0xe1, 0xd8, 0x88, 0x41, 0x1e, 0xc0, 0x59, 0xe9, 0xe8, 0xab, 0x8a, 0xc4, 0x08, 0x5d, - 0x2a, 0x76, 0x1b, 0x4e, 0xd3, 0x91, 0xb7, 0x85, 0x49, 0xe4, 0x27, 0x5d, 0x37, 0xa0, 0x2d, 0xb4, - 0xfc, 0xc4, 0xb7, 0xe9, 0x5a, 0x89, 0xad, 0xa3, 0x91, 0x1f, 0xc0, 0x44, 0xbd, 0xbe, 0x15, 0xd7, - 0x3e, 0x64, 0xdc, 0x10, 0xe9, 0x45, 0xb6, 0x81, 0xc8, 0x9f, 0xde, 0x5a, 0x7f, 0x52, 0x82, 0xb9, - 0x1c, 0x73, 0x0b, 0x79, 0xc3, 0x90, 0xc3, 0xb4, 0x26, 0x07, 0x89, 0xb2, 0xda, 0x27, 0x04, 0xb1, - 0xa4, 0xb9, 0x4d, 0x0f, 0x9c, 0xc2, 0x6d, 0x7a, 0xb5, 0x2f, 0x76, 0x95, 0x26, 0xaf, 0xc1, 0x40, - 0xbd, 0xbe, 0x25, 0xcc, 0xea, 0x24, 0xee, 0x81, 0x86, 0xcc, 0x10, 0x16, 0x01, 0x46, 0x25, 0xc8, - 0x3a, 0x03, 0x93, 0xc6, 0xc0, 0x58, 0x16, 0x4c, 0xe8, 0x2d, 0x64, 0xa3, 0xbf, 0xe4, 0xb7, 0xd4, - 0xe8, 0xb3, 0xbf, 0xad, 0x6d, 0x53, 0x66, 0xe4, 0x12, 0x80, 0xbc, 0xaf, 0x75, 0x5b, 0xf2, 0xe6, - 0x47, 0x40, 0xd6, 0x5a, 0xe4, 0x2a, 0x4c, 0x04, 0xb4, 0xe5, 0x06, 0xb4, 0x19, 0x35, 0xba, 0x81, - 0x78, 0x80, 0x62, 0x8f, 0x4b, 0xd8, 0x6e, 0xd0, 0xb6, 0x16, 0x61, 0x5c, 0x6b, 0x68, 0x2f, 0x86, - 0x33, 0x30, 0xa4, 0x1b, 0x1e, 0xf9, 0x0f, 0xeb, 0xf7, 0x4a, 0x30, 0x83, 0x23, 0xbb, 0xef, 0xb2, - 0x15, 0x3f, 0x6e, 0xde, 0x82, 0x31, 0x0e, 0x17, 0x8d, 0x71, 0x48, 0xe0, 0xaa, 0x01, 0xf9, 0x20, - 0x35, 0x20, 0x17, 0xb3, 0x06, 0x04, 0xbf, 0x6a, 0xd7, 0xf7, 0xf4, 0x71, 0xd0, 0x6f, 0xe0, 0xfe, - 0xa0, 0x04, 0xd3, 0x5a, 0x9b, 0x54, 0x07, 0xef, 0x18, 0x4d, 0xba, 0x90, 0xd1, 0xa4, 0xd4, 0x14, - 0x59, 0x4c, 0xb5, 0xe8, 0x95, 0xa2, 0x16, 0x65, 0xcd, 0x10, 0x63, 0xe4, 0xff, 0xaa, 0x04, 0xb3, - 0x99, 0x32, 0x20, 0xe7, 0x98, 0x4a, 0xdf, 0x0c, 0x68, 0x24, 0x24, 0x2f, 0x7e, 0x31, 0xf8, 0x5a, - 0x18, 0x76, 0x69, 0x20, 0xe4, 0x2e, 0x7e, 0x91, 0x57, 0x60, 0x72, 0x9b, 0x06, 0xae, 0xdf, 0xe2, - 0xcf, 0x01, 0xb8, 0x9f, 0xed, 0xa4, 0x6d, 0x02, 0xc9, 0x45, 0x18, 0x53, 0x7e, 0xa2, 0xdc, 0x2c, - 0x6b, 0xc7, 0x00, 0xc6, 0x7b, 0xd9, 0xdd, 0xe7, 0x77, 0x39, 0x8c, 0x58, 0xfc, 0x62, 0x6b, 0xaa, - 0x34, 0x92, 0x0e, 0xf3, 0x35, 0x55, 0x5a, 0x40, 0xcf, 0xc1, 0xf0, 0x67, 0x36, 0x4e, 0x4d, 0x0c, - 0xd7, 0x60, 0x8b, 0x5f, 0x64, 0x0a, 0x1d, 0xba, 0xf1, 0x49, 0x09, 0x3a, 0x72, 0x7f, 0x00, 0x33, - 0x59, 0x72, 0xcd, 0x9a, 0xd8, 0x82, 0xb6, 0x5f, 0xd1, 0x7e, 0x09, 0xd3, 0xb5, 0x56, 0x6b, 0xe3, - 0x6e, 0x8d, 0xbb, 0x5a, 0x88, 0x51, 0xe5, 0x9f, 0x3e, 0x37, 0x53, 0x0a, 0x4d, 0x75, 0x70, 0xcd, - 0x73, 0x23, 0x7b, 0x7a, 0xe5, 0x1b, 0x37, 0x8c, 0x5c, 0x6f, 0x5f, 0xb3, 0xa5, 0xda, 0xe7, 0x36, - 0xe9, 0xb3, 0x8c, 0x29, 0xc0, 0x94, 0x08, 0x93, 0x37, 0x87, 0x67, 0x30, 0x9f, 0xd1, 0xd8, 0xc6, - 0xab, 0xd1, 0x9c, 0xc9, 0x37, 0x2e, 0x18, 0xa8, 0x35, 0x9f, 0x58, 0x3f, 0x80, 0x73, 0x7c, 0x25, - 0x2f, 0x6a, 0xbc, 0x68, 0xb6, 0x6e, 0xfa, 0xb5, 0xde, 0x93, 0xc6, 0x99, 0xc2, 0x96, 0xd9, 0x13, - 0x46, 0x5b, 0xb0, 0xca, 0xff, 0x58, 0x82, 0xf9, 0x04, 0x69, 0xfd, 0xb9, 0xd7, 0x94, 0xdb, 0xc8, - 0x6b, 0x49, 0x87, 0x79, 0x54, 0x7f, 0xb8, 0xcd, 0xd3, 0x6d, 0x29, 0x9f, 0x79, 0x72, 0x0b, 0x80, - 0x13, 0x6b, 0x5a, 0x0b, 0x5a, 0xfc, 0x85, 0x6f, 0x11, 0xea, 0x2d, 0x1a, 0x0a, 0xe9, 0x42, 0x96, - 0xdc, 0xc5, 0x37, 0xd2, 0xcb, 0x24, 0x8e, 0x21, 0x4a, 0xa8, 0x20, 0x6f, 0xe4, 0xd8, 0xc6, 0xb3, - 0xf8, 0x5b, 0xff, 0xe7, 0x00, 0xcc, 0xe9, 0x03, 0xf8, 0x22, 0x7d, 0xdd, 0x86, 0xf1, 0x25, 0xdf, - 0x8b, 0xe8, 0x37, 0x91, 0x16, 0x22, 0x82, 0x28, 0x07, 0x03, 0x55, 0x22, 0x34, 0x66, 0x0e, 0x68, - 0x30, 0xf5, 0xcd, 0xf0, 0x91, 0x8c, 0x11, 0xc9, 0x12, 0x4c, 0x6e, 0xd2, 0x67, 0x29, 0x01, 0xa2, - 0x9f, 0xa6, 0x47, 0x9f, 0x35, 0x34, 0x21, 0xea, 0xce, 0x73, 0x06, 0x0d, 0x79, 0x04, 0x53, 0x72, - 0x72, 0x19, 0xc2, 0x9c, 0xd7, 0x37, 0x53, 0x73, 0x3a, 0xf3, 0x10, 0x0a, 0xac, 0x86, 0x1c, 0x19, - 0x26, 0x38, 0xb2, 0xae, 0xf3, 0x1a, 0x79, 0x54, 0x00, 0x73, 0xb7, 0xd6, 0x4a, 0x0c, 0x2f, 0xd8, - 0x64, 0x34, 0x00, 0x9d, 0x85, 0xb5, 0x0d, 0x95, 0xf4, 0x78, 0x88, 0xda, 0xde, 0x86, 0x61, 0x0e, - 0x15, 0xda, 0x8f, 0x8c, 0xfe, 0xa3, 0xb0, 0xb9, 0x79, 0x82, 0x57, 0x63, 0x0b, 0x5c, 0x6b, 0x15, - 0x4d, 0x46, 0x0a, 0x47, 0xe9, 0x9f, 0xb7, 0x93, 0xc3, 0x8b, 0x0e, 0xc6, 0x72, 0x78, 0x75, 0xf7, - 0x1a, 0xf9, 0x10, 0x64, 0x09, 0xad, 0x6e, 0x3a, 0x27, 0xd1, 0xb0, 0x1b, 0x30, 0x22, 0x40, 0x89, - 0xb8, 0x44, 0xf1, 0xe7, 0x27, 0x11, 0xac, 0x0f, 0xe0, 0x3c, 0x9a, 0x00, 0x5d, 0x6f, 0xbf, 0x4d, - 0x77, 0x43, 0xe3, 0x29, 0x47, 0xaf, 0xcf, 0xfa, 0x23, 0x98, 0xcf, 0xa2, 0xed, 0xf9, 0x65, 0xf3, - 0x48, 0x21, 0x7f, 0xd1, 0x0f, 0x33, 0x6b, 0xa1, 0xae, 0x43, 0xa9, 0x68, 0x21, 0x19, 0x11, 0x2c, - 0x50, 0x26, 0xab, 0x7d, 0x59, 0x11, 0x2a, 0xde, 0xd6, 0x5e, 0x8a, 0xf6, 0x17, 0x85, 0xa6, 0x60, - 0xdb, 0x96, 0x7a, 0x2b, 0xfa, 0x1a, 0x0c, 0x6e, 0xb2, 0xa5, 0x7a, 0x40, 0x8c, 0x1d, 0xa7, 0x60, - 0x20, 0x7c, 0xa9, 0xc9, 0xb6, 0x48, 0xf6, 0x83, 0xdc, 0x4d, 0xbd, 0x07, 0x1d, 0xec, 0x1d, 0x7a, - 0x61, 0xb5, 0x2f, 0xf5, 0x34, 0xf4, 0x5d, 0x18, 0xaf, 0xb5, 0x0e, 0xb9, 0x23, 0xa4, 0xef, 0x25, - 0x3e, 0x4b, 0xad, 0x64, 0xb5, 0xcf, 0xd6, 0x11, 0xd9, 0xc1, 0xbe, 0xd6, 0xe9, 0xe0, 0x46, 0x95, - 0x15, 0x8e, 0x82, 0xe9, 0x5f, 0xb5, 0x4e, 0x67, 0x71, 0x14, 0x86, 0x77, 0x9c, 0x60, 0x9f, 0x46, - 0xd6, 0x97, 0x30, 0x2f, 0x7c, 0x73, 0xb8, 0xc1, 0x13, 0x3d, 0x78, 0xc2, 0xd8, 0xfd, 0xaa, 0xc8, - 0x9f, 0xe6, 0x32, 0x00, 0x1e, 0x6f, 0xd6, 0xbc, 0x16, 0xfd, 0x46, 0x38, 0x07, 0x6a, 0x10, 0xeb, - 0x1d, 0x18, 0x53, 0x12, 0x42, 0x1d, 0x5e, 0xdb, 0xec, 0x50, 0x5a, 0x33, 0xc6, 0x03, 0x58, 0xf9, - 0xea, 0xf5, 0xbc, 0xd1, 0x77, 0x11, 0x60, 0x86, 0x2b, 0xfd, 0x2e, 0xcc, 0x26, 0x26, 0x41, 0x1c, - 0xbf, 0x40, 0xa9, 0xdd, 0xdc, 0x7b, 0x51, 0xfd, 0x4e, 0x6a, 0xe5, 0xfd, 0x27, 0xd2, 0xca, 0xad, - 0xbf, 0xdf, 0x8f, 0xe7, 0xc5, 0x94, 0x3c, 0x12, 0xa6, 0x37, 0xdd, 0xfc, 0xb7, 0x08, 0x63, 0xd8, - 0xfb, 0x65, 0xf9, 0x4c, 0xaf, 0xd8, 0xb5, 0x64, 0xf4, 0x67, 0x47, 0xd5, 0x3e, 0xf4, 0x27, 0x89, - 0xc9, 0xc8, 0xc7, 0x30, 0xb2, 0xe2, 0xb5, 0x90, 0xc3, 0xc0, 0x29, 0x38, 0x48, 0x22, 0x36, 0x26, - 0xd8, 0xe4, 0x1d, 0xf6, 0x09, 0x73, 0x8b, 0x8d, 0xad, 0x41, 0xe2, 0x83, 0xeb, 0x50, 0xde, 0xc1, - 0x75, 0x38, 0x71, 0x70, 0xb5, 0x60, 0x68, 0x2b, 0x68, 0x89, 0xb0, 0x30, 0x53, 0x0b, 0x13, 0x42, - 0x70, 0x08, 0xb3, 0x79, 0x91, 0xf5, 0x9f, 0x4b, 0x30, 0x77, 0x8f, 0x46, 0x99, 0x73, 0xc8, 0x90, - 0x4a, 0xe9, 0x5b, 0x4b, 0xa5, 0xff, 0x45, 0xa4, 0xa2, 0x7a, 0x3d, 0x90, 0xd7, 0xeb, 0xc1, 0xbc, - 0x5e, 0x0f, 0xe5, 0xf7, 0xfa, 0x1e, 0x0c, 0xf3, 0xae, 0xb2, 0xc3, 0xf9, 0x5a, 0x44, 0x0f, 0xe3, - 0xc3, 0xb9, 0xee, 0x18, 0x67, 0xf3, 0x32, 0xa6, 0x48, 0xae, 0x3b, 0xa1, 0x7e, 0x38, 0x17, 0x3f, - 0xad, 0x1f, 0xe3, 0x03, 0xdf, 0x75, 0xbf, 0xf9, 0x44, 0x33, 0xf2, 0x8e, 0xf0, 0x2f, 0x34, 0x79, - 0x29, 0xc0, 0xb0, 0x78, 0x89, 0x2d, 0x31, 0xc8, 0x15, 0x18, 0x5f, 0xf3, 0xee, 0xfa, 0x41, 0x93, - 0x6e, 0x79, 0x6d, 0xce, 0x7d, 0xd4, 0xd6, 0x41, 0xc2, 0xf8, 0x21, 0x6a, 0x88, 0x2d, 0x0a, 0x08, - 0x48, 0x58, 0x14, 0x18, 0x6c, 0x6f, 0xc1, 0xe6, 0x65, 0xc2, 0xb6, 0xc2, 0xfe, 0x2e, 0x3a, 0x8c, - 0xab, 0x53, 0x7b, 0x2f, 0xc4, 0x47, 0x70, 0xde, 0xa6, 0x9d, 0xb6, 0xc3, 0x74, 0xba, 0x43, 0x9f, - 0xe3, 0xab, 0x3e, 0x5f, 0xc9, 0x78, 0x9c, 0x67, 0xba, 0x49, 0xa8, 0x26, 0xf7, 0x17, 0x34, 0xf9, - 0x10, 0xae, 0xde, 0xa3, 0x91, 0xb9, 0xa0, 0xc6, 0x26, 0x64, 0xd1, 0xf9, 0x55, 0x18, 0x0d, 0x4d, - 0xf3, 0xb7, 0x7c, 0x6c, 0x96, 0x49, 0xb8, 0xf7, 0x96, 0xbc, 0x20, 0x12, 0x7c, 0xd4, 0x5f, 0xd6, - 0x27, 0x50, 0xcd, 0xab, 0xee, 0x64, 0x5e, 0xac, 0x2e, 0x5c, 0xc9, 0x67, 0x20, 0x9a, 0xbb, 0x02, - 0xd2, 0x54, 0x2e, 0x3e, 0xa1, 0x5e, 0xad, 0x35, 0xad, 0xeb, 0xe2, 0x0f, 0x6b, 0x51, 0xfa, 0xf3, - 0x7d, 0x8b, 0xe6, 0x36, 0xf0, 0x16, 0xda, 0x64, 0x10, 0xcb, 0xb5, 0x06, 0xa3, 0x12, 0x26, 0xe4, - 0x3a, 0x97, 0xd9, 0x52, 0x29, 0xd0, 0x96, 0x64, 0xa0, 0xc8, 0xac, 0x1f, 0xcb, 0x1b, 0x19, 0x93, - 0xe2, 0x64, 0xaf, 0x55, 0x4f, 0x72, 0x05, 0x63, 0xf9, 0x70, 0xde, 0xe4, 0xad, 0x5b, 0xda, 0xcb, - 0x9a, 0xa5, 0x9d, 0x1b, 0xd8, 0xaf, 0x98, 0x96, 0x5f, 0x61, 0x3c, 0xd0, 0x40, 0xe4, 0xb2, 0x6e, - 0x4f, 0x9f, 0x48, 0x3f, 0x7f, 0xbd, 0x0d, 0xf3, 0x59, 0x15, 0x6a, 0xe7, 0x40, 0x65, 0xb4, 0x15, - 0xfa, 0xce, 0x32, 0x5c, 0x96, 0x81, 0x99, 0x7c, 0x3f, 0x0a, 0xa3, 0xc0, 0xe9, 0xd4, 0x9b, 0x81, - 0xdb, 0x89, 0xa9, 0x2c, 0x18, 0xe6, 0x10, 0x21, 0x09, 0x7e, 0xbb, 0xc5, 0x71, 0x44, 0x89, 0xf5, - 0x9b, 0x25, 0xb0, 0x0c, 0xd7, 0x2b, 0x1c, 0xe7, 0xed, 0xc0, 0x7f, 0xea, 0xb6, 0xb4, 0x1b, 0xa5, - 0x37, 0x0c, 0x6b, 0x26, 0x7f, 0x09, 0x98, 0xf4, 0xfa, 0x16, 0x6b, 0xe6, 0xed, 0x84, 0x85, 0x91, - 0x2b, 0x9e, 0xe8, 0x8e, 0x65, 0x46, 0xc0, 0x51, 0x96, 0xc7, 0xff, 0x5a, 0x82, 0x6b, 0x85, 0x6d, - 0x10, 0xfd, 0x79, 0x04, 0xe5, 0x64, 0x99, 0x98, 0x41, 0x55, 0xcd, 0x15, 0x23, 0xcd, 0x61, 0xef, - 0x0e, 0x77, 0x2d, 0x97, 0x2e, 0x4b, 0x1d, 0xc5, 0x39, 0xc5, 0xef, 0xf4, 0xad, 0x27, 0xef, 0x03, - 0xec, 0xf8, 0x91, 0xd3, 0x5e, 0x42, 0x03, 0xc0, 0x40, 0xfc, 0x4c, 0x20, 0x62, 0xd0, 0x46, 0x32, - 0xc2, 0x84, 0x86, 0x6c, 0x7d, 0x8a, 0xdf, 0x75, 0x76, 0xa3, 0x4f, 0xf6, 0xa9, 0x2d, 0xc1, 0xb5, - 0x84, 0x3b, 0xc0, 0x0b, 0x30, 0x89, 0x60, 0x96, 0x89, 0x9f, 0xe9, 0xde, 0xf7, 0x02, 0xbf, 0xdb, - 0xf9, 0xe5, 0x8c, 0xfa, 0x9f, 0x96, 0xb8, 0x7f, 0xa6, 0x5e, 0xad, 0x18, 0xe8, 0x25, 0x80, 0x18, - 0x9a, 0xf0, 0xd3, 0x57, 0x05, 0x7b, 0x77, 0xf8, 0x91, 0x1b, 0x2f, 0x0a, 0xf6, 0x39, 0x03, 0x8d, - 0xec, 0x97, 0x3b, 0x92, 0x6f, 0xa1, 0x0f, 0x80, 0xaa, 0xfd, 0x64, 0x72, 0x7f, 0x57, 0xda, 0x3f, - 0x4e, 0x49, 0x77, 0x00, 0x33, 0x6c, 0x05, 0xa8, 0x75, 0xa3, 0x03, 0x3f, 0x70, 0x23, 0xf9, 0xe2, - 0x84, 0x6c, 0x8b, 0x77, 0xf8, 0x9c, 0xea, 0xa3, 0x5f, 0x1c, 0x55, 0xdf, 0x3b, 0x4d, 0xc8, 0x4c, - 0xc9, 0x73, 0x47, 0xbd, 0xdd, 0xb7, 0xe6, 0x60, 0x60, 0xc9, 0x5e, 0xc7, 0x05, 0xcf, 0x5e, 0x57, - 0x0b, 0x9e, 0xbd, 0x6e, 0xfd, 0x75, 0x3f, 0x54, 0x79, 0xa4, 0x10, 0x74, 0x1d, 0x89, 0xad, 0x16, - 0x9a, 0x2f, 0xca, 0x49, 0x0d, 0x0c, 0x89, 0x48, 0x20, 0xfd, 0x27, 0x89, 0x04, 0xf2, 0x6b, 0x90, - 0x63, 0xb2, 0x3a, 0x81, 0x15, 0xe0, 0xf5, 0xe3, 0xa3, 0xea, 0xb5, 0xd8, 0x0a, 0xc0, 0x4b, 0xb3, - 0xcc, 0x01, 0x39, 0x55, 0xa4, 0xed, 0x17, 0x83, 0x2f, 0x60, 0xbf, 0xb8, 0x0d, 0x23, 0x78, 0x98, - 0x59, 0xdb, 0x16, 0xce, 0x9c, 0x38, 0x3d, 0x31, 0xb8, 0x4f, 0xc3, 0xd5, 0x23, 0xe9, 0x49, 0x34, - 0xeb, 0xf7, 0xfb, 0xe1, 0x4a, 0xbe, 0xcc, 0x45, 0xdb, 0x96, 0x01, 0x62, 0xa7, 0x95, 0x22, 0x27, - 0x19, 0xfc, 0x76, 0x9e, 0xd1, 0x47, 0xca, 0x49, 0x4d, 0xa3, 0x63, 0xba, 0x8f, 0x7c, 0xdf, 0x9c, - 0xb8, 0x21, 0x31, 0x9e, 0x3d, 0x8b, 0x40, 0xb0, 0x02, 0x64, 0x04, 0x82, 0x15, 0x30, 0xf2, 0x08, - 0xe6, 0xb6, 0x03, 0xf7, 0xa9, 0x13, 0xd1, 0x07, 0xf4, 0x39, 0x7f, 0xff, 0xb3, 0x22, 0x1e, 0xfd, - 0xf0, 0x47, 0xeb, 0xd7, 0x8f, 0x8f, 0xaa, 0xaf, 0x74, 0x38, 0x0a, 0x06, 0xfb, 0xe2, 0x2f, 0x2e, - 0x1b, 0xe9, 0x77, 0x40, 0x79, 0x8c, 0xac, 0x7f, 0x51, 0x82, 0x0b, 0xa8, 0x96, 0x0b, 0xb3, 0xab, - 0xac, 0xfc, 0x85, 0x7c, 0x25, 0xf5, 0x0e, 0x8a, 0xb9, 0x88, 0xbe, 0x92, 0xc6, 0xfb, 0x6f, 0xdb, - 0x40, 0x23, 0x6b, 0x30, 0x2e, 0x7e, 0xe3, 0xf7, 0x37, 0x80, 0x07, 0x82, 0x59, 0x6d, 0xc1, 0xc2, - 0xa9, 0xce, 0x4d, 0x45, 0x38, 0xb1, 0x05, 0x33, 0x7c, 0x26, 0x69, 0xeb, 0xb4, 0xd6, 0xcf, 0xfb, - 0xe1, 0xe2, 0x1e, 0x0d, 0xdc, 0xc7, 0xcf, 0x73, 0x3a, 0xb3, 0x05, 0x33, 0x12, 0xc4, 0xa3, 0x85, - 0x18, 0x9f, 0x18, 0x0f, 0x05, 0x29, 0x9b, 0x2a, 0xc2, 0x8d, 0xc8, 0x2f, 0x2e, 0x93, 0xf0, 0x14, - 0x5e, 0x90, 0x6f, 0xc3, 0x68, 0x22, 0x5e, 0x0f, 0x8e, 0xbf, 0xfc, 0x42, 0xe3, 0xa1, 0x5a, 0xed, - 0xb3, 0x15, 0x26, 0xf9, 0xed, 0xfc, 0xdb, 0x27, 0x61, 0xfa, 0xe8, 0x65, 0xff, 0xc4, 0x0f, 0x96, - 0x7d, 0xac, 0x8e, 0x56, 0x9a, 0xf1, 0xc1, 0xae, 0xf6, 0xd9, 0x79, 0x35, 0x2d, 0x8e, 0xc3, 0x58, - 0x0d, 0xaf, 0xe2, 0xd8, 0xc9, 0xfd, 0xbf, 0xf4, 0xc3, 0x65, 0xf9, 0x96, 0x27, 0x47, 0xcc, 0x9f, - 0xc3, 0x9c, 0x04, 0xd5, 0x3a, 0x4c, 0x61, 0xa0, 0x2d, 0x53, 0xd2, 0x3c, 0x1c, 0xab, 0x94, 0xb4, - 0x23, 0x70, 0x62, 0x61, 0xe7, 0x91, 0xbf, 0x1c, 0xeb, 0xe7, 0xc7, 0x59, 0xd1, 0x93, 0xd0, 0x0a, - 0xa9, 0xaf, 0x99, 0x86, 0x68, 0x8c, 0xf5, 0xb3, 0x95, 0xb2, 0x9e, 0x0e, 0x7e, 0x5b, 0xeb, 0xe9, - 0x6a, 0x5f, 0xd2, 0x7e, 0xba, 0x38, 0x05, 0x13, 0x9b, 0xf4, 0x59, 0x2c, 0xf7, 0xff, 0xb5, 0x94, - 0x08, 0xb0, 0xc0, 0x34, 0x0c, 0x1e, 0x69, 0xa1, 0x14, 0x07, 0xe0, 0xc1, 0x00, 0x0b, 0xba, 0x86, - 0xc1, 0x51, 0xd7, 0x60, 0x84, 0xdf, 0x4f, 0xb7, 0x4e, 0x70, 0xc2, 0x57, 0x8f, 0x72, 0xf8, 0x4b, - 0xc9, 0x16, 0x3f, 0xec, 0x0b, 0x7a, 0xeb, 0x01, 0x5c, 0x15, 0x6e, 0xdb, 0xe6, 0xe0, 0x63, 0x45, - 0xa7, 0xdc, 0xbe, 0x2c, 0x07, 0x2e, 0xdf, 0xa3, 0xc9, 0xa5, 0xc7, 0x78, 0xb4, 0xf4, 0x09, 0x9c, - 0x31, 0xe0, 0x8a, 0x23, 0x6a, 0xa5, 0x6a, 0x0e, 0x29, 0xd6, 0x49, 0x6c, 0xeb, 0x4a, 0x56, 0x15, - 0x7a, 0x63, 0x2d, 0x8a, 0x71, 0x55, 0x83, 0xf8, 0x8a, 0x2d, 0x3c, 0xc5, 0xaa, 0x77, 0x5d, 0xfb, - 0xae, 0xf9, 0x8a, 0xc7, 0x03, 0xef, 0xc9, 0x9d, 0x57, 0x95, 0x5a, 0x93, 0xc6, 0x5d, 0x80, 0x35, - 0x05, 0x13, 0xb2, 0xa8, 0x4d, 0xc3, 0xd0, 0xfa, 0x77, 0x43, 0x60, 0x09, 0xc1, 0x66, 0x5d, 0xba, - 0x4b, 0x79, 0x3c, 0x4a, 0x35, 0x56, 0x6c, 0x54, 0xe7, 0xf4, 0x70, 0x9e, 0x71, 0x29, 0x9f, 0x79, - 0xa8, 0xe7, 0x35, 0x63, 0xa8, 0x31, 0xf3, 0x52, 0xbd, 0xff, 0x2a, 0x67, 0x99, 0xe4, 0x1f, 0xdb, - 0xab, 0xc7, 0x47, 0xd5, 0xab, 0x39, 0xcb, 0xa4, 0xc1, 0x37, 0x7b, 0xc9, 0xb4, 0xcd, 0x2b, 0x91, - 0x81, 0x17, 0xb9, 0x12, 0x61, 0x5f, 0xa4, 0x7e, 0x29, 0xb2, 0x6b, 0xca, 0x52, 0x7c, 0x8f, 0xf2, - 0x42, 0x5e, 0x2f, 0x12, 0x71, 0x0e, 0x34, 0x88, 0xc1, 0xd5, 0x60, 0x43, 0x5c, 0x28, 0x6b, 0x36, - 0xcb, 0xa5, 0x03, 0xda, 0x7c, 0x22, 0x6c, 0xc5, 0xf2, 0x42, 0x37, 0xcb, 0x66, 0xce, 0x43, 0x3b, - 0xf3, 0xef, 0x9c, 0x17, 0x34, 0x9a, 0x8c, 0x54, 0x8f, 0xd3, 0x90, 0x64, 0x4b, 0x7e, 0x0a, 0xd3, - 0x6a, 0xa8, 0x13, 0x5e, 0x57, 0xe3, 0x0b, 0xaf, 0xc4, 0x51, 0x40, 0x0f, 0x1f, 0x3b, 0x37, 0x9f, - 0xde, 0xb9, 0x99, 0x81, 0xcb, 0x9f, 0xff, 0x37, 0x65, 0x81, 0xe6, 0x72, 0xa5, 0x5f, 0x74, 0x65, - 0x10, 0x92, 0x2f, 0x60, 0xa6, 0x5e, 0xdf, 0xe2, 0xef, 0x33, 0x6c, 0x79, 0x67, 0x6f, 0xaf, 0x0b, - 0x1f, 0x2c, 0x1c, 0xee, 0x30, 0xf4, 0x1b, 0xe2, 0x5d, 0x87, 0x7e, 0xd3, 0xaf, 0x07, 0x40, 0xc8, - 0x62, 0xa1, 0xdf, 0x94, 0xff, 0xdf, 0xea, 0xf9, 0x01, 0x53, 0x45, 0xdc, 0x36, 0x15, 0xef, 0x88, - 0xe4, 0xc4, 0xce, 0xb9, 0xe5, 0x2b, 0x7d, 0xc7, 0xb7, 0x7c, 0xff, 0xa8, 0x5f, 0x3e, 0xba, 0x48, - 0x5f, 0xb4, 0x9e, 0xfa, 0xb2, 0x2f, 0xb3, 0x07, 0x27, 0xda, 0xa7, 0x33, 0x1b, 0x47, 0x16, 0xe5, - 0x55, 0xa9, 0x0a, 0x11, 0x36, 0xa5, 0xae, 0x1d, 0xe2, 0x02, 0xe3, 0xf6, 0x14, 0xb5, 0x22, 0x8d, - 0x2a, 0x79, 0x0f, 0x37, 0xf0, 0xed, 0xef, 0xe1, 0xfe, 0xc9, 0x18, 0x9c, 0xdd, 0x76, 0xf6, 0x5d, - 0x8f, 0xed, 0x07, 0x36, 0x0d, 0xfd, 0x6e, 0xd0, 0xa4, 0xa4, 0x06, 0x53, 0xa6, 0x47, 0x6d, 0x0f, - 0x7f, 0x61, 0xb6, 0xe5, 0x99, 0x30, 0xb2, 0x00, 0x63, 0xea, 0x15, 0xaf, 0xd8, 0xa7, 0x32, 0x5e, - 0xf7, 0xae, 0xf6, 0xd9, 0x31, 0x1a, 0x79, 0xdf, 0xb8, 0x3a, 0x3a, 0xa3, 0x1e, 0xa4, 0x23, 0xee, - 0x02, 0x77, 0x79, 0xf4, 0xfc, 0x96, 0xb9, 0xd7, 0xf2, 0xfb, 0x91, 0x1f, 0xa7, 0x6e, 0x93, 0x86, - 0x8c, 0x16, 0xa7, 0x4c, 0x6a, 0xa8, 0x66, 0xe4, 0x86, 0xed, 0xce, 0xb8, 0x67, 0xfa, 0x12, 0xc6, - 0x1f, 0x74, 0x1f, 0x51, 0x79, 0x6f, 0x36, 0x2c, 0xb6, 0xde, 0xa4, 0x9f, 0xb8, 0x28, 0xdf, 0x7b, - 0x8b, 0x8f, 0xc1, 0x93, 0xee, 0x23, 0x9a, 0x8e, 0x07, 0xcf, 0xd6, 0x3c, 0x8d, 0x19, 0x39, 0x80, - 0x72, 0xd2, 0xa5, 0x5b, 0x04, 0xd5, 0x2b, 0x70, 0x44, 0xc7, 0xe0, 0x28, 0x5a, 0xd4, 0x79, 0xee, - 0x68, 0x6a, 0x54, 0x92, 0xe2, 0x4a, 0x7e, 0x1d, 0x66, 0x33, 0x0d, 0x9a, 0xea, 0x51, 0x5a, 0xb1, - 0xad, 0x14, 0x17, 0x90, 0x84, 0xd4, 0xe4, 0x0b, 0x38, 0xa3, 0xe6, 0xec, 0x5a, 0x48, 0x0b, 0xce, - 0x24, 0x5c, 0x95, 0x45, 0x6a, 0x8d, 0x7c, 0xe7, 0x67, 0xdc, 0xf3, 0x64, 0x74, 0xda, 0xcc, 0xba, - 0x92, 0x2c, 0xc9, 0x3a, 0x8c, 0x29, 0x4b, 0x82, 0x88, 0x67, 0x96, 0x65, 0x35, 0xa9, 0x1c, 0x1f, - 0x55, 0x67, 0x62, 0xab, 0x89, 0xc1, 0x33, 0x66, 0x40, 0x7e, 0x03, 0xae, 0xaa, 0x29, 0xba, 0x15, - 0x64, 0xdb, 0x97, 0x44, 0x54, 0xfb, 0x1b, 0xc9, 0x19, 0x9e, 0x87, 0xbf, 0x77, 0x67, 0xb1, 0xbf, - 0x52, 0x5a, 0xed, 0xb3, 0x7b, 0xb3, 0x26, 0xbf, 0x55, 0x82, 0x73, 0x39, 0xb5, 0x4e, 0x60, 0xad, - 0x3d, 0x8d, 0x7e, 0x78, 0x6e, 0xc0, 0x87, 0x58, 0x6e, 0x2b, 0x7e, 0xb0, 0x28, 0xad, 0x7f, 0x46, - 0xbf, 0x73, 0x6a, 0x22, 0x6f, 0xc2, 0x30, 0x1e, 0xbf, 0xc3, 0xca, 0x24, 0x2a, 0xa8, 0x18, 0x13, - 0x08, 0x0f, 0xe9, 0xfa, 0x96, 0x24, 0x70, 0xc8, 0x2a, 0x53, 0xf4, 0x70, 0x4b, 0x94, 0x8a, 0x99, - 0x88, 0x20, 0x26, 0x0e, 0x0b, 0xbc, 0x48, 0xc6, 0x0d, 0x31, 0xd2, 0x17, 0x98, 0x64, 0x8b, 0x00, - 0xa3, 0x81, 0x58, 0x95, 0xee, 0x0f, 0x8e, 0x0e, 0x96, 0x87, 0xf8, 0x87, 0x23, 0x7d, 0xe0, 0x7f, - 0x67, 0x94, 0x3f, 0x98, 0xdd, 0xf5, 0xdc, 0xc7, 0x6e, 0xbc, 0x80, 0xe9, 0x86, 0xbb, 0x38, 0x8f, - 0x90, 0x50, 0xab, 0x73, 0x32, 0x06, 0x29, 0x1b, 0x5f, 0x7f, 0x4f, 0x1b, 0xdf, 0x5b, 0xda, 0x6d, - 0x98, 0x16, 0x29, 0x94, 0xab, 0x4f, 0xa6, 0x4d, 0x2d, 0xbe, 0x26, 0xfb, 0x1a, 0x86, 0x31, 0xb8, - 0x27, 0xbf, 0x6a, 0x1c, 0x5f, 0xb8, 0x29, 0x96, 0xed, 0x82, 0xe6, 0xf3, 0x68, 0xa0, 0xe2, 0x11, - 0x3c, 0x97, 0x38, 0x02, 0x0c, 0x89, 0x23, 0x84, 0xec, 0xc0, 0xf4, 0x36, 0xdb, 0xcd, 0xb9, 0x27, - 0x76, 0x27, 0x10, 0x76, 0x0f, 0x6e, 0x51, 0x41, 0x6d, 0xa2, 0x23, 0x8b, 0x1b, 0x54, 0x95, 0xeb, - 0x1b, 0x6a, 0x06, 0x39, 0x59, 0x81, 0xa9, 0x3a, 0x75, 0x82, 0xe6, 0xc1, 0x03, 0xfa, 0x9c, 0x69, - 0x52, 0x46, 0xea, 0x8c, 0x10, 0x4b, 0x58, 0x7f, 0xb1, 0x48, 0x77, 0x1f, 0x31, 0x89, 0xc8, 0xa7, - 0x30, 0x5c, 0xf7, 0x83, 0x68, 0xf1, 0xb9, 0x58, 0xd4, 0xe4, 0x65, 0x14, 0x07, 0x2e, 0x9e, 0x97, - 0xe9, 0x43, 0x42, 0x3f, 0x88, 0x1a, 0x8f, 0x8c, 0x20, 0x53, 0x1c, 0x85, 0x3c, 0x87, 0x19, 0x73, - 0x41, 0x11, 0x0e, 0xc2, 0xa3, 0x42, 0x83, 0xcb, 0x5a, 0xb5, 0x38, 0xca, 0xe2, 0x75, 0xc1, 0xfd, - 0x4a, 0x72, 0xd9, 0x7a, 0x8c, 0xe5, 0xba, 0xda, 0x93, 0x45, 0x4f, 0x36, 0x30, 0xef, 0x0a, 0xef, - 0x51, 0x2d, 0xe4, 0x8e, 0xc5, 0x63, 0x71, 0x18, 0xb3, 0x2e, 0x2e, 0x4a, 0x28, 0x09, 0x27, 0x4c, - 0x26, 0xeb, 0xb1, 0x53, 0xa4, 0x64, 0x1b, 0xce, 0xee, 0x86, 0x74, 0x3b, 0xa0, 0x4f, 0x5d, 0xfa, - 0x4c, 0xf2, 0x83, 0x38, 0xe6, 0x13, 0xe3, 0xd7, 0xe1, 0xa5, 0x59, 0x0c, 0xd3, 0xc4, 0xe4, 0x7d, - 0x80, 0x6d, 0xd7, 0xf3, 0x68, 0x0b, 0x6f, 0x34, 0xc7, 0x91, 0x15, 0x5a, 0x6b, 0x3b, 0x08, 0x6d, - 0xf8, 0x5e, 0x5b, 0x17, 0xa9, 0x86, 0x4c, 0x16, 0x61, 0x72, 0xcd, 0x6b, 0xb6, 0xbb, 0xc2, 0xf3, - 0x20, 0xc4, 0x05, 0x45, 0xc4, 0xa2, 0x73, 0x79, 0x41, 0x23, 0xf5, 0x91, 0x9b, 0x24, 0xe4, 0x01, - 0x10, 0x01, 0x10, 0xb3, 0xd6, 0x79, 0xd4, 0xa6, 0xe2, 0x73, 0x47, 0x2b, 0x8c, 0x64, 0x84, 0xd3, - 0xdd, 0x08, 0xf1, 0x96, 0x22, 0x9b, 0x7f, 0x1f, 0xc6, 0xb5, 0x39, 0x9f, 0x11, 0xd5, 0x61, 0x46, - 0x8f, 0xea, 0x30, 0xa6, 0x47, 0x6f, 0xf8, 0xff, 0x4b, 0x70, 0x31, 0xfb, 0x5b, 0x12, 0x0a, 0xd8, - 0x16, 0x8c, 0x29, 0xa0, 0x7a, 0xc7, 0x23, 0x4f, 0x15, 0x09, 0x0d, 0x88, 0x7f, 0xd0, 0x72, 0xe5, - 0xd1, 0x7b, 0x1f, 0xf3, 0x78, 0x01, 0x53, 0xff, 0xff, 0x3e, 0x0a, 0x33, 0xe8, 0xaf, 0x9e, 0x5c, - 0xa7, 0x3e, 0xc1, 0xe8, 0x2c, 0x08, 0xd3, 0x2c, 0xd7, 0xc2, 0x88, 0xc5, 0xe1, 0xc9, 0x50, 0x62, - 0x06, 0x01, 0x79, 0x47, 0x77, 0xb7, 0xe8, 0xd7, 0xf2, 0xbc, 0x48, 0xa0, 0xde, 0x85, 0xd8, 0x0f, - 0xe3, 0x0d, 0xe3, 0xb6, 0xff, 0xc4, 0x8b, 0xde, 0xe0, 0x49, 0x17, 0xbd, 0x5d, 0xb5, 0xe8, 0xf1, - 0xa8, 0x1f, 0xaf, 0x6b, 0x8b, 0xde, 0xcb, 0x5f, 0xed, 0x86, 0x5f, 0xf6, 0x6a, 0x37, 0xf2, 0xed, - 0x56, 0xbb, 0xd1, 0x17, 0x5c, 0xed, 0xee, 0xc2, 0xd4, 0x26, 0xa5, 0x2d, 0xed, 0x0e, 0x66, 0x2c, - 0xde, 0x3d, 0x3d, 0x8a, 0xd6, 0xb5, 0xac, 0x8b, 0x98, 0x04, 0x55, 0xee, 0xaa, 0x09, 0x7f, 0x3b, - 0xab, 0xe6, 0xf8, 0x4b, 0x5e, 0x35, 0x27, 0xbe, 0xcd, 0xaa, 0x99, 0x5a, 0xfa, 0x26, 0x4f, 0xbd, - 0xf4, 0x7d, 0x9b, 0xd5, 0xea, 0x63, 0xf4, 0x56, 0xac, 0xd7, 0x57, 0x85, 0x63, 0x8a, 0xe6, 0x09, - 0xb2, 0xea, 0x87, 0xd2, 0x99, 0x1b, 0xff, 0x66, 0xb0, 0x6d, 0x3f, 0x90, 0xb7, 0xe9, 0xf8, 0xb7, - 0xb5, 0x88, 0x3e, 0x8a, 0x3a, 0xbd, 0x7a, 0xc7, 0x30, 0x22, 0x1e, 0x41, 0x8a, 0x35, 0x2e, 0x79, - 0x8c, 0xb2, 0x65, 0xb9, 0xf5, 0x17, 0x25, 0x7e, 0xdf, 0xf9, 0x3f, 0xe2, 0x52, 0xf9, 0x6d, 0xee, - 0x20, 0x7f, 0x3b, 0x0e, 0x8e, 0x20, 0x02, 0x39, 0x04, 0x4e, 0xf3, 0x49, 0x7c, 0x09, 0xfc, 0x23, - 0xf6, 0x9d, 0xeb, 0x05, 0x18, 0xaa, 0x36, 0x3e, 0x2b, 0x9a, 0x85, 0x7b, 0x77, 0xe4, 0x02, 0x20, - 0x62, 0x44, 0x70, 0xb0, 0xb9, 0x00, 0xe8, 0x04, 0xe8, 0x86, 0x77, 0xc6, 0xb2, 0xf9, 0xdb, 0xfe, - 0xcc, 0x16, 0xbc, 0x9b, 0x7e, 0x9d, 0x8e, 0x87, 0x91, 0xf8, 0x75, 0xba, 0x2e, 0xc6, 0xf8, 0x9d, - 0xfa, 0x2e, 0x5c, 0xb0, 0xe9, 0xa1, 0xff, 0x94, 0xbe, 0x5c, 0xb6, 0x5f, 0xc1, 0x79, 0x93, 0x21, - 0x7f, 0xc7, 0xc4, 0xe3, 0xe2, 0x7f, 0x9c, 0x1d, 0x4d, 0x5f, 0x10, 0xf0, 0x68, 0xfa, 0x3c, 0x28, - 0x37, 0xfb, 0x53, 0xdf, 0x37, 0xb0, 0xcc, 0xf2, 0xe1, 0xa2, 0xc9, 0xbc, 0xd6, 0x6a, 0x61, 0x56, - 0xcd, 0xa6, 0xdb, 0x71, 0xbc, 0x88, 0x6c, 0xc1, 0xb8, 0xf6, 0x33, 0x61, 0x2a, 0xd0, 0x4a, 0x84, - 0x4e, 0x13, 0x03, 0x8c, 0xa0, 0xa6, 0x31, 0xd8, 0xa2, 0x50, 0x4d, 0x8a, 0x87, 0x89, 0x4c, 0xaf, - 0x73, 0x11, 0x26, 0xb5, 0x9f, 0xca, 0x1a, 0x8a, 0x1f, 0xbf, 0x56, 0x83, 0x29, 0x30, 0x93, 0xc4, - 0x6a, 0xc2, 0x7c, 0x96, 0xd0, 0x78, 0xf4, 0x6b, 0xb2, 0x12, 0x47, 0xce, 0xea, 0xed, 0xc8, 0x77, - 0x26, 0x2f, 0x6a, 0x96, 0xf5, 0x7f, 0x0d, 0xc2, 0x05, 0x31, 0x18, 0x2f, 0x73, 0xc4, 0xc9, 0x8f, - 0x61, 0x5c, 0x1b, 0x63, 0x21, 0xf4, 0x2b, 0xf2, 0x15, 0x52, 0xde, 0x5c, 0xe0, 0x26, 0x8d, 0x2e, - 0x02, 0x1a, 0x89, 0xe1, 0x5e, 0xed, 0xb3, 0x75, 0x96, 0xa4, 0x0d, 0x53, 0xe6, 0x40, 0x0b, 0xab, - 0xce, 0xb5, 0xcc, 0x4a, 0x4c, 0x54, 0x19, 0x1a, 0xbb, 0xd5, 0xc8, 0x1c, 0xee, 0xd5, 0x3e, 0x3b, - 0xc1, 0x9b, 0x7c, 0x03, 0x67, 0x53, 0xa3, 0x2c, 0x8c, 0x75, 0xaf, 0x65, 0x56, 0x98, 0xc2, 0xe6, - 0x96, 0xde, 0x00, 0xc1, 0xb9, 0xd5, 0xa6, 0x2b, 0x21, 0x2d, 0x98, 0xd0, 0x07, 0x5e, 0x98, 0x9d, - 0xae, 0x16, 0x88, 0x92, 0x23, 0x72, 0xe5, 0x4e, 0xc8, 0x12, 0xc7, 0xfe, 0xb9, 0x69, 0xbd, 0x36, - 0x90, 0x47, 0x61, 0x98, 0xff, 0x66, 0x4b, 0xc0, 0x76, 0x40, 0x43, 0xea, 0x35, 0xa9, 0xe1, 0xfb, - 0xfd, 0x2d, 0x97, 0x80, 0x7f, 0x5e, 0x82, 0x4a, 0x16, 0xdf, 0x3a, 0xf5, 0x5a, 0x64, 0x1b, 0xca, - 0xc9, 0x8a, 0xc4, 0xac, 0xb6, 0x54, 0xf4, 0xe1, 0xdc, 0x26, 0xad, 0xf6, 0xd9, 0x29, 0x6a, 0xb2, - 0x09, 0x67, 0x35, 0x98, 0x30, 0xae, 0xf6, 0x9f, 0xc4, 0xb8, 0xca, 0x46, 0x21, 0x45, 0xaa, 0xdb, - 0xa6, 0x57, 0x71, 0x67, 0x5c, 0xf6, 0x0f, 0x1d, 0xd7, 0x63, 0x8a, 0xae, 0x16, 0x3c, 0x0b, 0x62, - 0xa8, 0x90, 0x0d, 0xb7, 0xb6, 0x22, 0x54, 0xbe, 0x55, 0x51, 0x28, 0xd6, 0x47, 0xb8, 0x82, 0x0b, - 0x1b, 0x1d, 0x7f, 0xf0, 0xab, 0x98, 0x5d, 0x81, 0xa1, 0x9d, 0xf5, 0xfa, 0x52, 0x4d, 0x3c, 0x1f, - 0xe6, 0x41, 0x27, 0xda, 0x61, 0xa3, 0xe9, 0xd8, 0xbc, 0xc0, 0xfa, 0x10, 0xc8, 0x3d, 0x1a, 0x89, - 0xf0, 0xf7, 0x8a, 0xee, 0x55, 0x18, 0x11, 0x20, 0x41, 0x89, 0x5e, 0x77, 0x22, 0x98, 0xbe, 0x2d, - 0xcb, 0xac, 0x6d, 0x79, 0x4e, 0x68, 0x53, 0x27, 0xd4, 0x36, 0xe6, 0xf7, 0x60, 0x34, 0x10, 0x30, - 0xb1, 0x2f, 0x4f, 0xa9, 0xec, 0x26, 0x08, 0xe6, 0xf6, 0x6c, 0x89, 0x63, 0xab, 0xbf, 0xac, 0x75, - 0x0c, 0x10, 0xb3, 0xb5, 0xb6, 0xbc, 0xc4, 0xa4, 0x2a, 0x84, 0x25, 0x87, 0xe3, 0x16, 0xba, 0xa7, - 0x47, 0x54, 0x7f, 0x3c, 0x8c, 0xa2, 0xc1, 0x8f, 0x5c, 0x84, 0x45, 0xd2, 0x50, 0xac, 0xb7, 0x54, - 0xb8, 0x99, 0x0c, 0x6e, 0x79, 0x59, 0x3a, 0x36, 0x31, 0x90, 0xce, 0x3d, 0xf4, 0xc4, 0x79, 0x19, - 0x8d, 0x70, 0x60, 0x9e, 0x6f, 0xf3, 0xac, 0x57, 0x22, 0xd1, 0xa0, 0xaf, 0x96, 0xc6, 0x25, 0x18, - 0x53, 0x30, 0x75, 0xad, 0xc6, 0x65, 0x65, 0xe0, 0xef, 0xbd, 0xc5, 0xdf, 0x59, 0x37, 0x15, 0x83, - 0x98, 0x8e, 0x55, 0xc1, 0xbf, 0xbb, 0xef, 0xb8, 0x8a, 0x90, 0x06, 0xd1, 0x77, 0x5a, 0x45, 0x1c, - 0x69, 0xe9, 0x34, 0x55, 0x18, 0xf8, 0x7b, 0x0b, 0x27, 0x11, 0xd4, 0x77, 0x5c, 0x05, 0x13, 0xd4, - 0x77, 0x57, 0x05, 0x95, 0x21, 0xa9, 0xf8, 0x24, 0x4d, 0x55, 0xb2, 0x92, 0xae, 0x44, 0x1a, 0xae, - 0x13, 0x14, 0x85, 0xe3, 0x41, 0xe1, 0x22, 0x17, 0xd6, 0x2f, 0xa1, 0x1a, 0x26, 0xb0, 0xef, 0xb6, - 0x9a, 0xff, 0xb7, 0xc4, 0x03, 0x64, 0xd5, 0xb7, 0xb4, 0x14, 0x9f, 0xde, 0x63, 0x5f, 0xbb, 0xf5, - 0xd7, 0xbe, 0xf6, 0x07, 0xae, 0xd7, 0xd2, 0x6f, 0xfd, 0x9d, 0x6e, 0x74, 0xa0, 0x02, 0x48, 0x3f, - 0x71, 0xbd, 0x96, 0x9d, 0xc4, 0x26, 0xef, 0xc3, 0xa4, 0x06, 0x52, 0xda, 0x1a, 0xcf, 0xc2, 0xa1, - 0x93, 0xbb, 0x2d, 0xdb, 0xc4, 0xb4, 0xfe, 0xa6, 0x04, 0xd3, 0x19, 0xc9, 0xa7, 0xd1, 0x98, 0x81, - 0xa7, 0x20, 0xb5, 0x50, 0x89, 0xbc, 0x59, 0x18, 0xab, 0xc3, 0xd8, 0x24, 0x15, 0x22, 0xe6, 0x1f, - 0xd0, 0x12, 0x65, 0xf7, 0x6b, 0x29, 0xdd, 0xb2, 0x93, 0x63, 0xeb, 0xe8, 0x24, 0x04, 0x88, 0x5b, - 0x22, 0xcc, 0xc6, 0x75, 0xa6, 0xd2, 0x6a, 0x59, 0xb6, 0x5f, 0x4a, 0x9a, 0x6f, 0xad, 0x1a, 0xeb, - 0xb7, 0xfb, 0xe1, 0x5c, 0x46, 0xff, 0xeb, 0x34, 0xfa, 0xdb, 0x10, 0x41, 0x22, 0xd7, 0xf9, 0xc0, - 0x2f, 0x29, 0xd7, 0xb9, 0xf5, 0x6f, 0xfa, 0xe1, 0xdc, 0x6e, 0x27, 0xc4, 0xc7, 0x5b, 0x6b, 0xde, - 0x53, 0xea, 0x45, 0x7e, 0xf0, 0x1c, 0x1f, 0x9c, 0x90, 0x77, 0x60, 0x68, 0x95, 0xb6, 0xdb, 0xbe, - 0x98, 0xff, 0x97, 0xa4, 0xe3, 0x45, 0x12, 0x1b, 0x91, 0x56, 0xfb, 0x6c, 0x8e, 0x4d, 0xde, 0x87, - 0xb1, 0x55, 0xea, 0x04, 0xd1, 0x23, 0xea, 0xc8, 0x23, 0x8b, 0xcc, 0x0d, 0xa2, 0x91, 0x08, 0x84, - 0xd5, 0x3e, 0x3b, 0xc6, 0x26, 0x0b, 0xec, 0x34, 0xef, 0xed, 0xab, 0x87, 0xea, 0x39, 0x15, 0x32, - 0x9c, 0xd5, 0x3e, 0x1b, 0x71, 0xc9, 0x06, 0x4c, 0xd6, 0xf6, 0xa9, 0x17, 0x6d, 0xd0, 0xc8, 0x69, - 0x39, 0x91, 0x23, 0x54, 0xdb, 0x57, 0xf3, 0x88, 0x0d, 0xe4, 0xd5, 0x3e, 0xdb, 0xa4, 0x26, 0x1f, - 0xc2, 0xc8, 0x3d, 0xdf, 0x6f, 0x3d, 0x7a, 0x2e, 0x23, 0x28, 0x54, 0xf3, 0x18, 0x09, 0xb4, 0xd5, - 0x3e, 0x5b, 0x52, 0x2c, 0x0e, 0xc1, 0xc0, 0x46, 0xb8, 0x6f, 0x1d, 0x95, 0xa0, 0xb2, 0xec, 0x3f, - 0xf3, 0x32, 0xa5, 0xfa, 0x03, 0x53, 0xaa, 0x92, 0x7d, 0x06, 0x7e, 0x42, 0xae, 0x6f, 0xc3, 0xe0, - 0xb6, 0xeb, 0xed, 0x27, 0x54, 0xc1, 0x0c, 0x3a, 0x86, 0x85, 0xe2, 0x71, 0xbd, 0x7d, 0xb2, 0x2e, - 0x75, 0x70, 0x61, 0x6b, 0x1c, 0x30, 0x14, 0xff, 0x0c, 0x6a, 0x1d, 0x3b, 0xd6, 0xb5, 0xf9, 0x6f, - 0xd9, 0xc1, 0x37, 0x60, 0x2e, 0xa7, 0x5e, 0xf1, 0xf2, 0x9c, 0xf5, 0x6d, 0x10, 0x15, 0x9b, 0xd7, - 0x61, 0x36, 0x73, 0xfc, 0x52, 0x88, 0x7f, 0x2f, 0x6b, 0x22, 0xf2, 0x9e, 0x57, 0x60, 0x44, 0x26, - 0xcd, 0xe2, 0xb6, 0x1f, 0xf9, 0x13, 0xdf, 0x5e, 0xc9, 0x0f, 0x55, 0x86, 0x4a, 0x91, 0xdf, 0xe3, - 0x9e, 0x16, 0x9a, 0x8a, 0x7f, 0x4e, 0x1f, 0x7c, 0x8b, 0x8f, 0x46, 0xf1, 0x62, 0x75, 0xae, 0xfa, - 0x61, 0xe4, 0x29, 0xa7, 0x5e, 0x5b, 0xfd, 0x26, 0x37, 0xa0, 0x2c, 0x13, 0x64, 0x88, 0x4c, 0x3c, - 0x22, 0x33, 0xbb, 0x9d, 0x82, 0x93, 0xf7, 0x60, 0x2e, 0x09, 0x93, 0xbd, 0xe4, 0x8f, 0xe7, 0xf2, - 0x8a, 0xad, 0x3f, 0xef, 0xc7, 0xe8, 0xe1, 0x05, 0xf3, 0x9a, 0x49, 0x77, 0xab, 0x2e, 0xa4, 0xd5, - 0xbf, 0x55, 0x27, 0x17, 0x61, 0x6c, 0xab, 0x6e, 0x64, 0x1e, 0xb3, 0x63, 0x00, 0x6b, 0x36, 0xeb, - 0x42, 0x2d, 0x68, 0x1e, 0xb8, 0x11, 0x6d, 0x46, 0xdd, 0x40, 0xac, 0xc2, 0x76, 0x0a, 0x4e, 0x2c, - 0x98, 0xb8, 0xd7, 0x76, 0x1f, 0x35, 0x25, 0x33, 0x2e, 0x02, 0x03, 0x46, 0x5e, 0x83, 0xa9, 0x35, - 0x2f, 0x8c, 0x9c, 0x76, 0x7b, 0x83, 0x46, 0x07, 0x7e, 0x4b, 0x24, 0x47, 0xb5, 0x13, 0x50, 0x56, - 0xef, 0x92, 0xef, 0x45, 0x8e, 0xeb, 0xd1, 0xc0, 0xee, 0x7a, 0x91, 0x7b, 0x48, 0x45, 0xdf, 0x53, - 0x70, 0xf2, 0x36, 0xcc, 0x2a, 0xd8, 0x56, 0xd0, 0x3c, 0xa0, 0x61, 0x14, 0x60, 0x3e, 0x42, 0x74, - 0xdf, 0xb1, 0xb3, 0x0b, 0xb1, 0x86, 0xb6, 0xdf, 0x6d, 0xad, 0x78, 0x4f, 0xdd, 0xc0, 0xf7, 0x30, - 0xdb, 0xc7, 0xa8, 0xa8, 0x21, 0x01, 0xb7, 0xfe, 0x68, 0x34, 0xf3, 0xb3, 0xfd, 0x36, 0x73, 0xf0, - 0x0b, 0x98, 0x58, 0x72, 0x3a, 0xce, 0x23, 0xb7, 0xed, 0x46, 0xae, 0x4a, 0xdc, 0xf6, 0x4e, 0x8f, - 0x6f, 0x5e, 0xa6, 0x4c, 0xa1, 0x2d, 0x9d, 0xd8, 0x36, 0x58, 0xcd, 0xff, 0xf5, 0x30, 0xcc, 0x66, - 0xe2, 0x91, 0xeb, 0x22, 0xc3, 0x9b, 0x5a, 0x57, 0x45, 0xfa, 0x30, 0x3b, 0x09, 0x66, 0x63, 0x89, - 0xa0, 0xa5, 0x36, 0x75, 0xbc, 0xae, 0x48, 0x1e, 0x66, 0x1b, 0x30, 0x36, 0x96, 0x4c, 0x6f, 0xd0, - 0x98, 0xa1, 0x4f, 0xb6, 0x9d, 0x80, 0x92, 0x2b, 0x30, 0xce, 0x20, 0x92, 0xd5, 0x20, 0x7f, 0x3d, - 0xa8, 0x81, 0x18, 0xa7, 0x4d, 0xbf, 0x45, 0x35, 0x4e, 0x43, 0x9c, 0x93, 0x09, 0x65, 0x9c, 0x18, - 0x44, 0x72, 0x1a, 0xe6, 0x9c, 0x34, 0x10, 0x79, 0x05, 0x26, 0x6b, 0x9d, 0x8e, 0xc6, 0x08, 0xb3, - 0x86, 0xd9, 0x26, 0x90, 0x5c, 0x06, 0xa8, 0x75, 0x3a, 0x92, 0x0d, 0x66, 0x04, 0xb3, 0x35, 0x08, - 0xb9, 0x19, 0x07, 0x80, 0xd3, 0x58, 0xe1, 0x75, 0x82, 0x9d, 0x51, 0xc2, 0xe4, 0xaa, 0xa2, 0x65, - 0x09, 0xa6, 0xc0, 0xe5, 0x9a, 0x00, 0x93, 0x8f, 0xe0, 0x7c, 0xc2, 0xef, 0x42, 0xab, 0x00, 0x4d, - 0xfd, 0x76, 0x3e, 0x02, 0x79, 0x17, 0xce, 0x25, 0x0a, 0x65, 0x75, 0x68, 0xd5, 0xb7, 0x73, 0x4a, - 0xc9, 0x07, 0x50, 0x49, 0xbc, 0x08, 0x8f, 0x2b, 0x45, 0x0b, 0xbe, 0x9d, 0x5b, 0xce, 0xbe, 0xae, - 0xc4, 0xd3, 0x32, 0x51, 0x25, 0x5e, 0x56, 0xda, 0xd9, 0x85, 0x64, 0x15, 0xaa, 0x99, 0xbe, 0x2c, - 0x5a, 0xc5, 0x98, 0xe9, 0xcc, 0xee, 0x85, 0x46, 0x16, 0xe1, 0x62, 0x26, 0x8a, 0x6c, 0x06, 0xe6, - 0x3f, 0xb3, 0x0b, 0x71, 0xc8, 0x02, 0xcc, 0xc4, 0x3e, 0x3d, 0x5a, 0x13, 0x30, 0xf5, 0x99, 0x9d, - 0x59, 0x46, 0xde, 0x34, 0xdf, 0xfd, 0xf3, 0xca, 0x30, 0xf3, 0x99, 0x9d, 0x2e, 0xb0, 0x8e, 0x4b, - 0x70, 0x31, 0x73, 0xa3, 0x94, 0xfa, 0xfc, 0x7c, 0x52, 0x71, 0xd4, 0xd6, 0x82, 0x1b, 0x30, 0x88, - 0x0a, 0x3e, 0xb7, 0x15, 0x4b, 0x37, 0x56, 0xa4, 0xe7, 0xac, 0x58, 0xa9, 0x8d, 0x38, 0xe4, 0x9e, - 0xba, 0x1b, 0x1c, 0x40, 0x4b, 0xc6, 0xad, 0xa4, 0x02, 0x95, 0x51, 0xb9, 0x7e, 0x47, 0x28, 0x6f, - 0x03, 0xbf, 0xcd, 0x35, 0xcc, 0x9f, 0x97, 0xa0, 0xda, 0x43, 0x3f, 0x50, 0x7d, 0x2a, 0x9d, 0xa0, - 0x4f, 0xf7, 0x55, 0x9f, 0xf8, 0xb3, 0xdb, 0x85, 0x93, 0xe9, 0x20, 0x2f, 0xbb, 0x5b, 0x7f, 0x53, - 0x02, 0x92, 0xd6, 0x43, 0xc9, 0xf7, 0x61, 0xac, 0x5e, 0x5f, 0x35, 0x3c, 0xfa, 0x52, 0xb7, 0x43, - 0x31, 0x06, 0xb9, 0x7d, 0x22, 0x17, 0x3e, 0xdd, 0x81, 0xef, 0x93, 0x94, 0xdf, 0xe0, 0x40, 0xa1, - 0xdf, 0x60, 0xca, 0x6b, 0x70, 0x25, 0xc3, 0x11, 0x6e, 0xb0, 0x87, 0x23, 0x5c, 0xda, 0xcb, 0xcd, - 0x5a, 0x86, 0x4a, 0x9e, 0x2a, 0x8b, 0x2b, 0x1c, 0x0f, 0x9b, 0xa6, 0xdd, 0x70, 0xf1, 0x15, 0xce, - 0x04, 0x5b, 0xef, 0xc2, 0x39, 0x45, 0xcd, 0xf3, 0xb1, 0x68, 0xc1, 0x0d, 0xc4, 0xf9, 0x57, 0x05, - 0x51, 0x88, 0x01, 0xd6, 0x9f, 0x0d, 0xa6, 0x08, 0xeb, 0xdd, 0xc3, 0x43, 0x27, 0x78, 0x4e, 0x6a, - 0x26, 0xe1, 0x40, 0xcf, 0x23, 0xc7, 0xe2, 0xe0, 0xcf, 0x8e, 0xaa, 0x7d, 0x1a, 0x77, 0xb6, 0x2f, - 0xa0, 0x86, 0xe1, 0x35, 0x29, 0xbf, 0x1b, 0xeb, 0xe7, 0x01, 0x9c, 0x0c, 0x20, 0xd9, 0x83, 0x49, - 0xb1, 0x77, 0xe3, 0x6f, 0xf9, 0x8d, 0xdd, 0x4e, 0x7e, 0x63, 0x46, 0xf3, 0x6e, 0x1a, 0x24, 0x7c, - 0x36, 0x9a, 0x6c, 0xc8, 0x17, 0x30, 0x25, 0x35, 0x35, 0xc1, 0x98, 0x7b, 0x33, 0xdd, 0x29, 0x66, - 0x6c, 0xd2, 0x70, 0xce, 0x09, 0x46, 0xac, 0xc9, 0x72, 0xb1, 0xe3, 0x9c, 0x87, 0x4e, 0xd2, 0x64, - 0x83, 0x44, 0x34, 0xd9, 0x80, 0xcd, 0x7f, 0x0a, 0x24, 0xdd, 0xaf, 0x5e, 0x9f, 0xd3, 0xa4, 0xf6, - 0x39, 0xcd, 0xd7, 0x60, 0x3a, 0xa3, 0x03, 0xa7, 0x62, 0xf1, 0x29, 0x90, 0x74, 0x4b, 0x4f, 0xc3, - 0xc1, 0xba, 0x0e, 0xaf, 0x29, 0x11, 0xa8, 0xd9, 0x60, 0xf0, 0x94, 0x16, 0xf0, 0xdf, 0xec, 0x87, - 0x6a, 0x0f, 0x54, 0xf2, 0x87, 0xa5, 0xa4, 0xb4, 0xf9, 0x6c, 0x7c, 0x3f, 0x29, 0xed, 0x6c, 0xfa, - 0x0c, 0xb1, 0x2f, 0x7e, 0xf0, 0x5b, 0x7f, 0xf9, 0xc2, 0x27, 0x8f, 0xf4, 0x90, 0x9d, 0x5e, 0x5a, - 0x83, 0xba, 0xb4, 0x6c, 0x98, 0x31, 0xce, 0x6c, 0x27, 0xd9, 0xbc, 0x2e, 0x03, 0x88, 0xec, 0xad, - 0xeb, 0xfe, 0xbe, 0xd0, 0x13, 0x35, 0x88, 0x75, 0x17, 0x66, 0x13, 0x3c, 0x85, 0x55, 0xfe, 0xfb, - 0xa0, 0x1e, 0xb1, 0x23, 0xd3, 0x81, 0xc5, 0xb3, 0xbf, 0x38, 0xaa, 0x4e, 0x32, 0x95, 0xfe, 0x66, - 0x9c, 0x1a, 0x40, 0xfe, 0x65, 0x6d, 0xe8, 0xf7, 0x0a, 0xb5, 0xb6, 0x1e, 0xdc, 0x87, 0xdc, 0x81, - 0x61, 0x0e, 0x49, 0x04, 0xe0, 0xd6, 0xb1, 0xc5, 0x9a, 0x20, 0x10, 0xad, 0x59, 0x7c, 0x72, 0x8b, - 0x3f, 0x6a, 0x71, 0x88, 0x08, 0x6b, 0x97, 0x27, 0xa4, 0x89, 0xc1, 0x2a, 0xc8, 0xf7, 0x60, 0x2d, - 0x0e, 0x65, 0x21, 0x9d, 0x40, 0x24, 0x9e, 0xe7, 0x3f, 0x6b, 0xd3, 0x16, 0x4f, 0xf6, 0xb7, 0x38, - 0x21, 0x9c, 0x40, 0x06, 0x1d, 0xc6, 0x00, 0xc9, 0xac, 0x4f, 0x60, 0x96, 0x69, 0x0a, 0x41, 0xb2, - 0x3e, 0x4c, 0x43, 0xc1, 0x60, 0xa6, 0x67, 0xbd, 0xc3, 0x40, 0xe8, 0x59, 0x2f, 0x0a, 0xad, 0x75, - 0x38, 0xcf, 0xad, 0x92, 0x7a, 0x97, 0xe2, 0x3b, 0x80, 0x21, 0xfc, 0x9d, 0x78, 0xb0, 0x99, 0xd1, - 0x7b, 0x8e, 0x67, 0x7d, 0x8c, 0x2f, 0x82, 0xc4, 0x24, 0x75, 0x7d, 0x2f, 0x36, 0x41, 0x9e, 0xec, - 0x09, 0xf1, 0xff, 0x0c, 0x17, 0x6b, 0x9d, 0x0e, 0xf5, 0x5a, 0x31, 0xe1, 0x4e, 0xe0, 0x9c, 0x30, - 0xc0, 0x03, 0xa9, 0xc1, 0x10, 0x62, 0xab, 0x0b, 0x54, 0xd1, 0xdc, 0x8c, 0xe6, 0x20, 0x9e, 0x88, - 0xc8, 0x8a, 0x15, 0x70, 0x4a, 0xab, 0x05, 0x73, 0xf5, 0xee, 0xa3, 0x43, 0x37, 0x42, 0x7f, 0x7c, - 0x0c, 0x92, 0x22, 0xeb, 0x5e, 0x93, 0x39, 0xc4, 0xb8, 0x30, 0xae, 0xc7, 0x2f, 0x47, 0xd0, 0xa5, - 0x5f, 0x04, 0x4e, 0x79, 0x7a, 0xe7, 0x66, 0x4c, 0x8a, 0xe6, 0x17, 0x5e, 0x0b, 0x16, 0x8b, 0x3c, - 0x63, 0xd6, 0x34, 0x9c, 0xd5, 0x2f, 0xa3, 0xf8, 0x0c, 0x99, 0x85, 0x69, 0xf3, 0x92, 0x89, 0x83, - 0xbf, 0x86, 0x19, 0x6e, 0x04, 0xe7, 0x11, 0xd5, 0x17, 0xe2, 0xe0, 0xe1, 0xfd, 0x7b, 0x0b, 0x89, - 0x87, 0x00, 0xe8, 0x1f, 0xac, 0x72, 0x65, 0xec, 0x2d, 0xf0, 0x57, 0x9d, 0x4f, 0x17, 0x8c, 0xab, - 0xcc, 0xfe, 0xbd, 0x85, 0xc5, 0x11, 0x11, 0x99, 0x96, 0x71, 0xe7, 0xc3, 0xff, 0x9d, 0x70, 0x5f, - 0xc0, 0x40, 0x02, 0xab, 0xd4, 0xc1, 0x47, 0x3f, 0xd9, 0xcf, 0xb1, 0xa7, 0xa0, 0x5f, 0xc5, 0xa9, - 0xec, 0x77, 0x5b, 0xd6, 0x1f, 0x97, 0xe0, 0x3a, 0x57, 0xc6, 0xb2, 0xe9, 0xf0, 0xc6, 0x29, 0x87, - 0x98, 0xbc, 0x07, 0x43, 0xa1, 0xe6, 0x1d, 0x61, 0x89, 0x96, 0x17, 0x71, 0xe2, 0x04, 0xa4, 0x06, - 0x13, 0xfa, 0xdb, 0x96, 0x93, 0x85, 0xc0, 0xb3, 0xc7, 0x0f, 0x1f, 0x3b, 0xea, 0xbd, 0xcb, 0x13, - 0xb8, 0xb0, 0xf2, 0x0d, 0x9b, 0x10, 0x62, 0x77, 0x12, 0x27, 0x87, 0xf8, 0xb9, 0xef, 0x99, 0x1d, - 0x31, 0x63, 0xcc, 0x63, 0x7d, 0x12, 0xcc, 0xce, 0xc8, 0x72, 0x83, 0x53, 0xea, 0xfb, 0x98, 0x6d, - 0xc0, 0xac, 0x3f, 0x2b, 0xc1, 0xc5, 0xec, 0xda, 0xc4, 0xc2, 0xb2, 0x06, 0x67, 0x97, 0x1c, 0xcf, - 0xf7, 0xdc, 0xa6, 0xd3, 0xae, 0x37, 0x0f, 0x68, 0xab, 0xab, 0xe2, 0xd7, 0xaa, 0x55, 0x66, 0x9f, - 0x7a, 0x92, 0x5c, 0xa2, 0xd8, 0x69, 0x2a, 0x76, 0x3a, 0xc4, 0xe7, 0x11, 0x7c, 0xed, 0x6d, 0xd3, - 0x40, 0xf1, 0xe3, 0x2d, 0xcb, 0x29, 0x25, 0xb7, 0xa5, 0xb5, 0xbf, 0xb5, 0xeb, 0xb9, 0x91, 0x22, - 0xe2, 0x66, 0x9e, 0xac, 0x22, 0xeb, 0x5f, 0x95, 0xe0, 0x3c, 0xa6, 0xac, 0x32, 0x92, 0x60, 0xc6, - 0x61, 0x9c, 0x65, 0x24, 0xe2, 0x92, 0xf1, 0xdc, 0xc3, 0xc0, 0x36, 0x43, 0x12, 0x93, 0x37, 0x61, - 0xb0, 0x2e, 0xbd, 0xb5, 0xa6, 0x12, 0x19, 0x86, 0x05, 0x05, 0x2b, 0xb7, 0x11, 0x8b, 0xed, 0x39, - 0xcb, 0x34, 0x6c, 0x52, 0x0f, 0x53, 0x41, 0x73, 0xab, 0x83, 0x06, 0x89, 0xc3, 0x31, 0x0d, 0xe6, - 0x85, 0x63, 0x1a, 0x32, 0xc3, 0x31, 0x59, 0x4f, 0x79, 0xc2, 0xaa, 0x64, 0x87, 0xc4, 0x20, 0x7d, - 0x9c, 0xca, 0x1c, 0xcd, 0xf7, 0x81, 0x73, 0x59, 0x3d, 0x63, 0x0a, 0x7a, 0x22, 0x29, 0x74, 0x7e, - 0xd8, 0xe4, 0x6d, 0x78, 0xc5, 0xc0, 0xad, 0xb5, 0xdb, 0xfe, 0x33, 0xda, 0xda, 0x0e, 0xfc, 0x43, - 0x3f, 0x32, 0x12, 0xf6, 0x88, 0xd4, 0xe9, 0xf1, 0x7d, 0x8e, 0x98, 0x95, 0x09, 0xb0, 0xf5, 0x3f, - 0xc1, 0xab, 0x3d, 0x38, 0x8a, 0x4e, 0xd5, 0xe1, 0xac, 0x93, 0x28, 0x93, 0x6e, 0x37, 0xaf, 0x66, - 0xf5, 0x2b, 0xc9, 0x28, 0xb4, 0xd3, 0xf4, 0x37, 0x76, 0x8c, 0x6c, 0xcb, 0xa4, 0x02, 0x33, 0xdb, - 0xf6, 0xd6, 0xf2, 0xee, 0xd2, 0x4e, 0x63, 0xe7, 0x8b, 0xed, 0x95, 0xc6, 0xee, 0xe6, 0x83, 0xcd, - 0xad, 0x87, 0x9b, 0x3c, 0xee, 0xb8, 0x51, 0xb2, 0xb3, 0x52, 0xdb, 0x28, 0x97, 0xc8, 0x0c, 0x94, - 0x0d, 0xf0, 0xca, 0xee, 0x62, 0xb9, 0xff, 0xc6, 0xd7, 0x46, 0x16, 0x61, 0x72, 0x11, 0x2a, 0xf5, - 0xdd, 0xed, 0xed, 0x2d, 0x5b, 0x71, 0xd5, 0xa3, 0x9e, 0xcf, 0xc2, 0x59, 0xa3, 0xf4, 0xae, 0xbd, - 0xb2, 0x52, 0x2e, 0xb1, 0xa6, 0x18, 0xe0, 0x6d, 0x7b, 0x65, 0x63, 0x6d, 0x77, 0xa3, 0xdc, 0x7f, - 0xa3, 0xa1, 0xbf, 0x31, 0x23, 0x17, 0x60, 0x6e, 0x79, 0x65, 0x6f, 0x6d, 0x69, 0x25, 0x8b, 0xf7, - 0x0c, 0x94, 0xf5, 0xc2, 0x9d, 0xad, 0x9d, 0x6d, 0xce, 0x5a, 0x87, 0x3e, 0x5c, 0x59, 0xac, 0xed, - 0xee, 0xac, 0x6e, 0x96, 0x07, 0xac, 0xc1, 0xd1, 0xfe, 0x72, 0xff, 0x8d, 0x1f, 0x1b, 0x0f, 0xd0, - 0x58, 0xf3, 0x05, 0xfa, 0x6e, 0xbd, 0x76, 0x2f, 0xbf, 0x0a, 0x5e, 0xba, 0x71, 0xb7, 0x56, 0x2e, - 0x91, 0x4b, 0x70, 0xde, 0x80, 0x6e, 0xd7, 0xea, 0xf5, 0x87, 0x5b, 0xf6, 0xf2, 0xfa, 0x4a, 0xbd, - 0x5e, 0xee, 0xbf, 0xb1, 0x67, 0x84, 0xa0, 0x63, 0x35, 0x6c, 0xdc, 0xad, 0x35, 0xec, 0x95, 0xcf, - 0x76, 0xd7, 0xec, 0x95, 0xe5, 0x74, 0x0d, 0x46, 0xe9, 0x17, 0x2b, 0xf5, 0x72, 0x89, 0x4c, 0xc3, - 0x19, 0x03, 0xba, 0xb9, 0x55, 0xee, 0xbf, 0xf1, 0x9a, 0x88, 0x52, 0x46, 0xa6, 0x00, 0x96, 0x57, - 0xea, 0x4b, 0x2b, 0x9b, 0xcb, 0x6b, 0x9b, 0xf7, 0xca, 0x7d, 0x64, 0x12, 0xc6, 0x6a, 0xea, 0x67, - 0xe9, 0xc6, 0x07, 0x70, 0x26, 0x71, 0xb4, 0x67, 0x18, 0xea, 0x50, 0x5c, 0xee, 0x43, 0xf1, 0xcb, - 0x9f, 0x68, 0x5f, 0xe5, 0xa7, 0xf4, 0x72, 0xe9, 0xc6, 0xa2, 0xcc, 0x6a, 0xab, 0x7d, 0xe7, 0x64, - 0x1c, 0x46, 0x96, 0x57, 0xee, 0xd6, 0x76, 0xd7, 0x77, 0xca, 0x7d, 0xec, 0xc7, 0x92, 0xbd, 0x52, - 0xdb, 0x59, 0x59, 0x2e, 0x97, 0xc8, 0x18, 0x0c, 0xd5, 0x77, 0x6a, 0x3b, 0x2b, 0xe5, 0x7e, 0x32, - 0x0a, 0x83, 0xbb, 0xf5, 0x15, 0xbb, 0x3c, 0xb0, 0xf0, 0xcf, 0xfe, 0xb0, 0xc4, 0x8d, 0x8c, 0xf2, - 0x31, 0xd3, 0xd7, 0xda, 0x61, 0x52, 0x2c, 0x79, 0x22, 0x85, 0x67, 0xee, 0xc9, 0x11, 0xb5, 0x80, - 0xf9, 0x82, 0x5b, 0x17, 0x44, 0xb8, 0x5e, 0xba, 0x5d, 0x22, 0x36, 0x7a, 0xa9, 0x24, 0xce, 0x56, - 0x8a, 0x73, 0xf6, 0xf1, 0x77, 0xfe, 0x52, 0xe1, 0x91, 0x8c, 0xfc, 0x1a, 0x58, 0x3a, 0xcf, 0x9c, - 0x13, 0xc8, 0xf7, 0x4f, 0x76, 0xd2, 0x90, 0x75, 0xbe, 0x76, 0x32, 0x74, 0x72, 0x1f, 0x26, 0x99, - 0x6e, 0xae, 0xd0, 0xc8, 0x85, 0x24, 0xa1, 0x76, 0x1c, 0x98, 0xbf, 0x98, 0x5d, 0xa8, 0xb2, 0xec, - 0x4c, 0x60, 0x47, 0xf8, 0xc1, 0x3a, 0x24, 0x32, 0x92, 0x85, 0x84, 0xf0, 0x15, 0x7f, 0xfe, 0x6c, - 0x02, 0xbc, 0x77, 0xe7, 0x76, 0x89, 0xd4, 0x31, 0x8c, 0x9c, 0xa1, 0xe4, 0x13, 0xf9, 0xba, 0x2e, - 0xad, 0xfd, 0xf3, 0xd6, 0x54, 0x55, 0x4e, 0xcc, 0x9c, 0xd3, 0xc1, 0x26, 0x90, 0xb4, 0xee, 0x4c, - 0xae, 0xc4, 0xf3, 0x20, 0x5b, 0xad, 0x9e, 0x3f, 0x97, 0x72, 0x3e, 0x5c, 0x61, 0xda, 0x13, 0x59, - 0x81, 0x29, 0xf1, 0x4c, 0x5d, 0x68, 0xf3, 0xa4, 0xe8, 0x3c, 0x90, 0xcb, 0xe6, 0x1e, 0xca, 0x49, - 0x9d, 0x08, 0xc8, 0x7c, 0xdc, 0x8f, 0xe4, 0x31, 0x61, 0xfe, 0x42, 0x66, 0x99, 0xe8, 0xdf, 0x5d, - 0x98, 0x32, 0x0f, 0x17, 0x44, 0x0e, 0x50, 0xe6, 0x99, 0x23, 0xb7, 0x41, 0x0d, 0x98, 0xdb, 0x70, - 0x5c, 0xbc, 0x2b, 0x11, 0x2e, 0x6e, 0xd2, 0x41, 0x8d, 0x54, 0x0b, 0x3c, 0xd6, 0xea, 0xd4, 0x6b, - 0xa9, 0x41, 0xc8, 0x8b, 0x98, 0x8f, 0x9f, 0x4d, 0x5d, 0xea, 0xc8, 0xa6, 0x83, 0x1f, 0xb1, 0xcc, - 0x3c, 0xc7, 0x59, 0x3e, 0x9b, 0xf3, 0x79, 0x6e, 0xc6, 0x64, 0x03, 0x95, 0xf4, 0x04, 0x47, 0x6d, - 0x4e, 0x9c, 0x9a, 0x5d, 0x05, 0x83, 0x25, 0x68, 0xf9, 0xe1, 0x45, 0x61, 0x48, 0x72, 0x04, 0x97, - 0xcb, 0xec, 0x76, 0x89, 0x7c, 0x8d, 0x5f, 0x75, 0x26, 0xbb, 0x87, 0x6e, 0x74, 0x20, 0xb4, 0x9f, - 0x0b, 0x99, 0x0c, 0xc4, 0x87, 0x52, 0xc0, 0xdd, 0x86, 0x99, 0x2c, 0xcf, 0x66, 0x25, 0xd0, 0x02, - 0xb7, 0xe7, 0xdc, 0x59, 0x60, 0xb3, 0xa3, 0x46, 0x2b, 0x7f, 0x90, 0x0a, 0x1c, 0x6b, 0x73, 0x79, - 0x7e, 0x04, 0x53, 0x6c, 0x96, 0x3c, 0xa0, 0xb4, 0x53, 0x6b, 0xbb, 0x4f, 0x69, 0x48, 0x64, 0x0c, - 0x60, 0x05, 0xca, 0xa3, 0xbd, 0x5e, 0x22, 0xdf, 0x83, 0xf1, 0x87, 0x4e, 0xd4, 0x3c, 0x10, 0xb1, - 0x30, 0x65, 0xa8, 0x4c, 0x84, 0xcd, 0xcb, 0x5f, 0x58, 0x78, 0xbb, 0x44, 0x7e, 0x08, 0x23, 0xf7, - 0x68, 0x84, 0xaf, 0x9b, 0xaf, 0x2a, 0x27, 0x3f, 0x6e, 0x9b, 0x5c, 0xf3, 0xd4, 0x13, 0x1e, 0xd9, - 0xe0, 0xa4, 0x21, 0x97, 0xdc, 0x02, 0xe0, 0x0b, 0x02, 0x72, 0x48, 0x16, 0xcf, 0xa7, 0x9a, 0x4d, - 0xee, 0x31, 0xe5, 0xa1, 0x4d, 0x23, 0x7a, 0xd2, 0x2a, 0xf3, 0x64, 0xb4, 0x0e, 0x53, 0x2a, 0x31, - 0xd1, 0x26, 0x86, 0x2c, 0xb1, 0x12, 0xcc, 0xc2, 0x53, 0x70, 0xfb, 0x80, 0x7d, 0x15, 0x3c, 0x2b, - 0x2f, 0xc6, 0xb6, 0xc0, 0x95, 0x74, 0x4e, 0x0f, 0x90, 0xa1, 0x2f, 0xa1, 0x52, 0x88, 0x1c, 0x4d, - 0xa3, 0x5d, 0xf5, 0xc3, 0xc8, 0xa4, 0x55, 0x90, 0x6c, 0xda, 0x5f, 0x85, 0x79, 0xbd, 0x5e, 0x33, - 0x18, 0x73, 0xbc, 0xe6, 0xe6, 0xc5, 0x78, 0x9e, 0xbf, 0x5a, 0x80, 0x21, 0xce, 0x6f, 0x03, 0xbf, - 0xd3, 0x5f, 0xc2, 0xe5, 0x64, 0x19, 0xa6, 0x65, 0x5d, 0x5b, 0x1d, 0xea, 0xd5, 0xeb, 0xab, 0x98, - 0x84, 0x46, 0xba, 0x94, 0x68, 0x30, 0xc9, 0x9d, 0xa4, 0x8b, 0xd8, 0xd6, 0x67, 0xc4, 0xb0, 0x20, - 0x45, 0x91, 0x2d, 0xe2, 0xad, 0x2f, 0x33, 0x4a, 0xf0, 0x03, 0x6e, 0x54, 0x32, 0x94, 0xff, 0xbd, - 0x05, 0x52, 0x70, 0x00, 0x9a, 0xcf, 0x39, 0x42, 0xdc, 0x2e, 0x91, 0x2f, 0x80, 0xa4, 0x8f, 0x24, - 0x4a, 0x84, 0xb9, 0xc7, 0x2f, 0x25, 0xc2, 0x82, 0xf3, 0xcc, 0x0a, 0x4c, 0xab, 0x08, 0x36, 0x71, - 0x39, 0xc9, 0x69, 0x4b, 0xc1, 0x0e, 0x36, 0x9b, 0xc1, 0x66, 0x6f, 0xa1, 0x80, 0x51, 0x26, 0x9c, - 0x7c, 0x02, 0xd3, 0x62, 0xee, 0x1b, 0xed, 0x29, 0xab, 0x65, 0x4c, 0x1c, 0x6e, 0x72, 0x5b, 0x72, - 0x1f, 0x66, 0xeb, 0x09, 0xc1, 0x73, 0x87, 0xfa, 0xf3, 0x26, 0x0b, 0x04, 0xd6, 0x69, 0xc4, 0x25, - 0x9f, 0xcd, 0xeb, 0x01, 0x10, 0x6e, 0x5b, 0x92, 0xec, 0x9e, 0xba, 0xf4, 0x19, 0xb9, 0x94, 0x68, - 0x3a, 0x03, 0x22, 0x1a, 0xae, 0x83, 0xb9, 0x3d, 0xdb, 0xe1, 0xa9, 0xa9, 0x11, 0x6a, 0x5c, 0xc5, - 0x5f, 0x31, 0x08, 0x8c, 0xdb, 0x7c, 0x31, 0x8e, 0xe7, 0x73, 0x31, 0xc8, 0x6f, 0x60, 0x04, 0xda, - 0xe2, 0xd3, 0x19, 0xf9, 0x5e, 0xd6, 0x21, 0x3a, 0xe7, 0x7c, 0x39, 0xff, 0xe6, 0xc9, 0x90, 0xd5, - 0x79, 0x78, 0xf2, 0x1e, 0x8d, 0xb6, 0xdb, 0xdd, 0x7d, 0x17, 0x93, 0x96, 0x12, 0x65, 0x7b, 0x52, - 0x20, 0x31, 0xbd, 0x65, 0xe0, 0xb7, 0xb8, 0xa0, 0x4e, 0x7f, 0x42, 0xd6, 0xa0, 0xcc, 0xb7, 0x11, - 0x8d, 0xc5, 0xa5, 0x14, 0x0b, 0x81, 0xe2, 0x04, 0xce, 0x61, 0x98, 0x3b, 0x5a, 0xb7, 0xb8, 0xef, - 0x13, 0x91, 0x9f, 0xb6, 0xae, 0xa7, 0x4e, 0x1b, 0x30, 0x15, 0x95, 0x9f, 0x8d, 0x88, 0x4d, 0x43, - 0x1a, 0xc9, 0x50, 0x37, 0x3c, 0x65, 0xed, 0xb5, 0x58, 0x67, 0x48, 0x97, 0xc6, 0x2b, 0x48, 0x22, - 0x2c, 0xdb, 0xde, 0x5b, 0x44, 0xa5, 0xf1, 0xcd, 0x60, 0xfa, 0x9a, 0xa1, 0xda, 0x9c, 0x8e, 0xef, - 0xdb, 0xb8, 0x95, 0x61, 0x78, 0x9f, 0xd9, 0xb8, 0x6d, 0xec, 0xb7, 0xa4, 0x9a, 0xd4, 0xa8, 0xf6, - 0x16, 0x70, 0x65, 0x64, 0x7b, 0x2d, 0xd3, 0x84, 0xbb, 0x41, 0x40, 0x3d, 0x4e, 0x9c, 0xa7, 0xb6, - 0x64, 0x51, 0x7f, 0x8c, 0x2b, 0x98, 0x46, 0xcd, 0xdf, 0xfd, 0xf5, 0x62, 0xc1, 0x53, 0x2c, 0xdd, - 0x2e, 0x91, 0xf7, 0x60, 0x54, 0xb4, 0x91, 0x11, 0x19, 0x8d, 0x0e, 0x0b, 0x5a, 0x8d, 0x94, 0xc0, - 0x85, 0x84, 0x6d, 0x36, 0x71, 0xf2, 0x46, 0x9f, 0xb7, 0xf9, 0x3d, 0xb6, 0x67, 0xb7, 0x5e, 0x84, - 0x72, 0x49, 0x6e, 0xde, 0x48, 0x59, 0x51, 0x21, 0x61, 0x24, 0xa8, 0xc7, 0x2e, 0xcb, 0x99, 0x30, - 0xf5, 0x1b, 0xe3, 0x2a, 0xaa, 0xf0, 0x68, 0x4a, 0xfd, 0x36, 0xc0, 0xbd, 0xb6, 0xec, 0x35, 0x28, - 0xd7, 0x9a, 0xb8, 0xa1, 0xd4, 0xe9, 0xa1, 0xd3, 0x39, 0xf0, 0x03, 0xaa, 0xce, 0x3e, 0xc9, 0x02, - 0xc9, 0x6b, 0x56, 0x29, 0x28, 0xa2, 0x60, 0x9d, 0x3a, 0x18, 0x7c, 0x7a, 0x4e, 0x69, 0x28, 0x89, - 0xa2, 0x6c, 0x8a, 0x82, 0xb3, 0xce, 0xcc, 0x12, 0x3b, 0x9d, 0xb5, 0xbf, 0x1d, 0x9b, 0x0f, 0x70, - 0xc1, 0x50, 0xc8, 0xa1, 0xda, 0x21, 0x14, 0x48, 0x9d, 0x0a, 0xe5, 0x13, 0x20, 0x85, 0x5a, 0x93, - 0x57, 0xcf, 0xb1, 0x58, 0xf2, 0xa8, 0xf3, 0xaa, 0xff, 0x01, 0x4c, 0xad, 0xb0, 0x05, 0xbd, 0xdb, - 0x72, 0x79, 0xc0, 0x7d, 0x62, 0x46, 0x50, 0xcf, 0x25, 0x5c, 0x95, 0x59, 0xcd, 0x90, 0x54, 0x58, - 0x10, 0xe4, 0x9e, 0xa2, 0xc1, 0xe4, 0x78, 0xcc, 0x48, 0xb6, 0x22, 0xe7, 0x01, 0x9e, 0xf0, 0x85, - 0xc9, 0x60, 0x8e, 0x2b, 0x96, 0xb5, 0x4e, 0xa7, 0x2d, 0x2d, 0xdb, 0xfc, 0xfa, 0xfe, 0x55, 0xe3, - 0x24, 0x9a, 0x2a, 0x97, 0xbc, 0xd3, 0xba, 0xe7, 0xe7, 0x5a, 0x96, 0xe1, 0x1c, 0x9e, 0x39, 0xe5, - 0xbd, 0xe6, 0xa2, 0x0a, 0x91, 0x5d, 0x6b, 0xb7, 0x53, 0xc4, 0x21, 0x79, 0xc3, 0xe4, 0x9e, 0x85, - 0xd3, 0xab, 0x06, 0x3c, 0xe9, 0x73, 0xe5, 0xad, 0xd6, 0xe9, 0xf0, 0xc5, 0xf2, 0xb2, 0x5a, 0x30, - 0xcc, 0x82, 0xf4, 0x49, 0x3f, 0x59, 0x2e, 0xd6, 0xf6, 0xfb, 0x38, 0xcd, 0xe2, 0x54, 0xc4, 0x44, - 0x3f, 0x37, 0x27, 0x33, 0x31, 0x2b, 0x5d, 0x2e, 0x51, 0xa8, 0xf6, 0x89, 0x33, 0xa8, 0x41, 0xc5, - 0x79, 0x8d, 0x95, 0x81, 0x27, 0x01, 0x97, 0xfc, 0x2e, 0xe7, 0x15, 0x2b, 0x83, 0x6b, 0x39, 0x99, - 0xee, 0x5d, 0x75, 0x39, 0x9d, 0x07, 0xde, 0xec, 0x72, 0x6e, 0x9e, 0xf8, 0xfb, 0x50, 0x4e, 0x66, - 0x9a, 0x56, 0x4c, 0x73, 0x52, 0x50, 0xe7, 0x8e, 0xc9, 0x5d, 0x98, 0xd1, 0x47, 0x54, 0xf5, 0x3b, - 0x6f, 0xf5, 0xcf, 0xe3, 0xb3, 0x03, 0xb3, 0x99, 0x89, 0xa1, 0xd5, 0x16, 0x5b, 0x94, 0x36, 0x3a, - 0x97, 0x2b, 0x85, 0x73, 0xd9, 0xb9, 0xe1, 0xc9, 0x2b, 0xa6, 0xfd, 0x20, 0x3b, 0x53, 0xf6, 0xfc, - 0xab, 0x3d, 0xb0, 0x84, 0x40, 0xbf, 0xc6, 0x1d, 0x30, 0x55, 0xc7, 0x55, 0xcd, 0xa2, 0x90, 0x53, - 0x81, 0x55, 0x84, 0xa2, 0xe6, 0xc0, 0x4c, 0x46, 0x71, 0xbe, 0x88, 0xaf, 0xe5, 0xf3, 0x8c, 0x27, - 0xd6, 0x9e, 0x8c, 0x04, 0x9d, 0x2b, 0x99, 0xc2, 0x1c, 0xe2, 0x05, 0x47, 0xd2, 0x79, 0x35, 0x1f, - 0x4e, 0xde, 0xe4, 0x3c, 0x6e, 0x2d, 0x65, 0xfd, 0x31, 0x12, 0x7c, 0x27, 0xad, 0x3f, 0x59, 0x89, - 0xc9, 0x95, 0x18, 0x8a, 0x52, 0xdf, 0xf3, 0xdd, 0xf8, 0x2b, 0x6e, 0x0e, 0x32, 0xab, 0xd0, 0xcd, - 0x41, 0x99, 0xfc, 0xaf, 0xe4, 0x23, 0xe8, 0xcc, 0x1d, 0x7e, 0xf7, 0x9b, 0xc8, 0x50, 0x4e, 0xf4, - 0x13, 0x57, 0x76, 0xf6, 0x72, 0x35, 0x37, 0x32, 0x51, 0xf4, 0x2a, 0x1e, 0xca, 0x6f, 0x30, 0x47, - 0x4a, 0x05, 0xe9, 0xdb, 0x8b, 0xd5, 0x94, 0x2d, 0xa8, 0xc4, 0x83, 0x99, 0xe8, 0xc0, 0x29, 0x87, - 0x52, 0x0a, 0xe3, 0x7c, 0x6e, 0xd2, 0x76, 0xf2, 0x7a, 0xea, 0x4b, 0xcf, 0x11, 0x4c, 0x61, 0x15, - 0x7c, 0x3d, 0xd7, 0x22, 0x4b, 0x5f, 0x88, 0x6d, 0xc1, 0x7a, 0x7e, 0xf7, 0xd4, 0x7a, 0x9e, 0x91, - 0xfc, 0xfd, 0x1e, 0xea, 0xc5, 0x5a, 0x02, 0xf7, 0xdc, 0x5e, 0x5f, 0xca, 0xe2, 0x13, 0xa6, 0x57, - 0x5c, 0xad, 0x5d, 0x52, 0x4f, 0x4b, 0x16, 0x9c, 0x66, 0xc5, 0x3d, 0x49, 0xd3, 0xf2, 0xf8, 0x2c, - 0xc3, 0xb8, 0x96, 0xf9, 0x9d, 0x9c, 0x37, 0xc4, 0x64, 0xec, 0xa1, 0xf3, 0x46, 0xe7, 0xcc, 0xed, - 0x73, 0x09, 0x2d, 0xd2, 0x2a, 0x7f, 0x7c, 0x6e, 0x2b, 0x2e, 0xa4, 0x79, 0x18, 0xd6, 0x68, 0x25, - 0x05, 0xde, 0x9a, 0x8b, 0x49, 0xe1, 0x18, 0x0d, 0xca, 0xef, 0x12, 0xd1, 0x45, 0xd3, 0xa3, 0x49, - 0xf9, 0xfa, 0xeb, 0xb4, 0x48, 0x2f, 0x8b, 0xe9, 0x60, 0x64, 0xe8, 0xc0, 0x73, 0xca, 0xb4, 0xa6, - 0x41, 0x0b, 0x2c, 0x1d, 0xdb, 0xf8, 0x02, 0x25, 0x23, 0x15, 0xbe, 0x5a, 0x61, 0x0b, 0x33, 0xe5, - 0x67, 0xe8, 0x6e, 0x6a, 0xcd, 0xce, 0xe5, 0x58, 0x98, 0x1b, 0x3f, 0xb7, 0xa5, 0x3f, 0xd2, 0xd6, - 0xec, 0x54, 0xc2, 0x7b, 0x72, 0x3d, 0xa9, 0xb8, 0xe5, 0xe5, 0xc4, 0x2f, 0xd8, 0x13, 0x66, 0xb2, - 0x72, 0xe5, 0x6b, 0xe6, 0xe1, 0xdc, 0x44, 0xfa, 0x19, 0x52, 0xb0, 0xe5, 0xfc, 0xcf, 0xe1, 0x56, - 0x90, 0x39, 0x3f, 0xb7, 0x85, 0x5f, 0x6a, 0x0b, 0x5d, 0x22, 0xc3, 0xbd, 0x3a, 0x8e, 0xf7, 0x48, - 0x81, 0x9f, 0xcb, 0x7b, 0x13, 0xdf, 0x2c, 0xa5, 0xd3, 0xd3, 0x2b, 0xcd, 0xa6, 0x28, 0x79, 0x7d, - 0xa6, 0xf5, 0x78, 0x36, 0xdd, 0x45, 0xc6, 0xef, 0x5c, 0xc2, 0xf6, 0xdb, 0xab, 0x61, 0x5f, 0xcb, - 0xc5, 0x38, 0x23, 0xad, 0x7d, 0x62, 0x31, 0xce, 0x4f, 0x7c, 0x5f, 0x70, 0x0c, 0x3a, 0x53, 0x77, - 0xf7, 0x3d, 0x2d, 0x2b, 0xbd, 0x3a, 0x04, 0xa5, 0x13, 0xe5, 0xab, 0x25, 0x26, 0x2b, 0x89, 0xfd, - 0x16, 0xd3, 0x7f, 0xb8, 0xf6, 0xae, 0xe7, 0x17, 0x27, 0xf3, 0xf9, 0x69, 0xd5, 0xd5, 0x72, 0x93, - 0x99, 0x90, 0x5c, 0x63, 0xa8, 0x27, 0xf7, 0x56, 0x0c, 0x33, 0xf2, 0x8c, 0x2b, 0x86, 0x99, 0xd9, - 0xc0, 0x6f, 0xa1, 0xd5, 0xc5, 0xf6, 0xdb, 0x54, 0xb7, 0xba, 0x68, 0xd9, 0xa2, 0x13, 0x46, 0x0f, - 0xf2, 0x21, 0x9a, 0x3c, 0x8a, 0xed, 0x24, 0x73, 0x26, 0x27, 0xdd, 0xb3, 0x64, 0x4c, 0xa5, 0xe2, - 0x56, 0x36, 0xf6, 0x64, 0x36, 0xf0, 0xf9, 0x4a, 0xba, 0x40, 0xd0, 0xbf, 0x23, 0xad, 0x26, 0xd8, - 0xe0, 0x8a, 0x69, 0x6d, 0xca, 0x6f, 0xf3, 0x3b, 0xd2, 0x64, 0x62, 0x90, 0xa5, 0x12, 0x71, 0x27, - 0xc9, 0x7e, 0x00, 0x13, 0x71, 0xd2, 0xed, 0xbd, 0x05, 0x8d, 0x30, 0x91, 0x89, 0x3b, 0x49, 0xf8, - 0x9e, 0xbc, 0x56, 0xc1, 0xfa, 0xcc, 0xc2, 0x62, 0x15, 0xe0, 0x63, 0x69, 0xa2, 0x31, 0x5a, 0x9a, - 0x4a, 0xe1, 0x5d, 0xb0, 0x72, 0x4f, 0xe8, 0x29, 0x33, 0xd5, 0xbc, 0xc8, 0x48, 0x7a, 0xab, 0xe6, - 0x45, 0x56, 0xd2, 0xda, 0xf8, 0xda, 0xe1, 0x0b, 0x69, 0x8f, 0x88, 0x99, 0x5e, 0x32, 0x9a, 0x95, - 0xe2, 0x7b, 0x39, 0xaf, 0x38, 0xc9, 0xba, 0x0e, 0xe5, 0x64, 0x7e, 0x4f, 0x75, 0x98, 0xcb, 0x49, - 0xc4, 0xaa, 0x4e, 0x88, 0xb9, 0x89, 0x41, 0xb7, 0xa5, 0x71, 0xdd, 0xe4, 0x7b, 0x35, 0xbb, 0x51, - 0x3a, 0xeb, 0x7c, 0x6b, 0xfb, 0xa4, 0x91, 0xea, 0x53, 0x3f, 0x66, 0xa7, 0x52, 0x89, 0xea, 0x6a, - 0x59, 0x46, 0x76, 0x50, 0x57, 0x46, 0x9d, 0xca, 0x4e, 0xb4, 0xfe, 0x86, 0x79, 0xfe, 0x2d, 0x88, - 0x0b, 0xdf, 0xf3, 0x0a, 0x9a, 0xfc, 0x0a, 0xcc, 0xe5, 0xc4, 0xb9, 0x26, 0xaf, 0x26, 0xcc, 0xb4, - 0xd9, 0x71, 0xb0, 0xd5, 0x04, 0xc9, 0xcc, 0xc1, 0xbd, 0x81, 0xbe, 0x0b, 0x46, 0x7c, 0x89, 0xd4, - 0x7d, 0xe0, 0x43, 0x37, 0x3a, 0xe0, 0xa9, 0xa6, 0xb5, 0x35, 0x37, 0x33, 0x30, 0x05, 0xa9, 0xe3, - 0x41, 0xc6, 0x80, 0x66, 0x5c, 0x09, 0x66, 0x30, 0x9c, 0xcf, 0x66, 0xc8, 0xd6, 0x0e, 0x36, 0x17, - 0x32, 0x82, 0x7f, 0xa8, 0xb9, 0x90, 0x1f, 0x18, 0x24, 0xb7, 0x99, 0xdb, 0x52, 0xc1, 0xca, 0xe6, - 0x98, 0x1f, 0x07, 0x24, 0x97, 0xe3, 0x7d, 0xc6, 0x31, 0x15, 0xda, 0x83, 0xe4, 0xa0, 0x17, 0xaf, - 0x1e, 0xb6, 0xdc, 0xaf, 0x4d, 0xaa, 0x05, 0xad, 0x7d, 0x79, 0x41, 0x44, 0x72, 0xdb, 0xb7, 0x22, - 0xbf, 0xa7, 0xec, 0xf6, 0x9d, 0x74, 0xc7, 0x56, 0x97, 0x67, 0x89, 0xe8, 0x32, 0x46, 0x47, 0x35, - 0xf8, 0x7c, 0x0e, 0x9c, 0x6c, 0xa2, 0x33, 0x52, 0x12, 0xaa, 0x9d, 0x68, 0xb3, 0xc3, 0xd7, 0xe4, - 0xf2, 0xe3, 0xf3, 0xd8, 0x08, 0xff, 0x71, 0x9a, 0x79, 0x9c, 0x88, 0x1b, 0x22, 0xe6, 0xb1, 0x01, - 0x3d, 0xdd, 0x3c, 0x4e, 0x30, 0x34, 0xe7, 0x71, 0xb2, 0x99, 0x49, 0x33, 0x41, 0xee, 0xa8, 0x26, - 0x9b, 0xa9, 0xe6, 0x71, 0x36, 0xc7, 0xfc, 0x30, 0x2d, 0xb9, 0x1c, 0xd5, 0x3c, 0x36, 0x39, 0xe6, - 0xa0, 0x9f, 0x70, 0x1e, 0x27, 0x2b, 0x31, 0xe7, 0xf1, 0xa9, 0xda, 0xa7, 0xe6, 0x71, 0x76, 0xfb, - 0x4e, 0x3d, 0x8f, 0x13, 0x71, 0x8d, 0x8c, 0x8e, 0x66, 0xcd, 0xe3, 0x24, 0x3e, 0x9f, 0xc7, 0x49, - 0x68, 0xc2, 0x32, 0x53, 0x30, 0x8f, 0x93, 0x94, 0x9f, 0x21, 0xbf, 0x44, 0x4c, 0x96, 0x93, 0xcc, - 0xe4, 0xdc, 0x70, 0x2e, 0xe4, 0x21, 0xda, 0x06, 0x13, 0xf0, 0x93, 0xcd, 0xe6, 0x8b, 0x79, 0x4c, - 0x71, 0x3e, 0xef, 0x49, 0x21, 0x26, 0x9b, 0x6b, 0x1a, 0xbe, 0xb2, 0x43, 0xd2, 0x14, 0x34, 0x78, - 0x8f, 0xcd, 0x9b, 0x56, 0x01, 0xdf, 0xa2, 0x88, 0x3a, 0x05, 0x7c, 0xd5, 0x39, 0x28, 0xc9, 0x37, - 0x97, 0xa4, 0x78, 0x7e, 0x7f, 0x2e, 0x6f, 0x47, 0x92, 0x74, 0x0b, 0x89, 0x93, 0xd5, 0xa9, 0x5b, - 0xaa, 0x4e, 0x58, 0xc9, 0x96, 0x9e, 0x76, 0x9e, 0x6f, 0x48, 0xed, 0x21, 0x15, 0x8a, 0x2b, 0xd1, - 0x69, 0x7d, 0xae, 0xe7, 0x96, 0x90, 0x1d, 0x34, 0x04, 0xa7, 0xe1, 0x9a, 0x11, 0x39, 0x2f, 0xe6, - 0x57, 0x4f, 0xae, 0xa9, 0xa0, 0x42, 0x3a, 0xd7, 0xbc, 0x88, 0x43, 0x8a, 0x6b, 0x9a, 0xfa, 0x13, - 0x34, 0x9d, 0x89, 0x17, 0x5f, 0xde, 0x63, 0x3f, 0xff, 0x9c, 0x33, 0x6d, 0x38, 0x4c, 0x31, 0x5c, - 0xf4, 0x53, 0xfb, 0x48, 0x5c, 0xff, 0x49, 0x60, 0xae, 0xf0, 0xb3, 0xe8, 0xc9, 0x27, 0x50, 0x16, - 0xcb, 0x5b, 0xcc, 0x20, 0x0b, 0x31, 0x77, 0xe8, 0x16, 0xa5, 0xc5, 0xee, 0x04, 0x2d, 0x38, 0x89, - 0xa5, 0xee, 0x24, 0x92, 0xc8, 0x37, 0x6b, 0xb1, 0xed, 0x70, 0x27, 0xe8, 0x86, 0x11, 0x6d, 0xa5, - 0xcd, 0x51, 0x66, 0x63, 0xa4, 0x5b, 0x85, 0x89, 0xbe, 0xb7, 0x40, 0xd6, 0x70, 0x6d, 0x33, 0xc1, - 0x45, 0xf6, 0xba, 0x6c, 0x36, 0xb8, 0xf4, 0xac, 0xaa, 0xa7, 0x45, 0x66, 0x9b, 0xf2, 0xea, 0xce, - 0x6f, 0x94, 0x12, 0xd1, 0x09, 0x7b, 0x97, 0x27, 0x22, 0x7e, 0xa0, 0xe6, 0xb6, 0xc3, 0x5e, 0x92, - 0x49, 0x3e, 0x76, 0x22, 0x9f, 0xc2, 0x98, 0x24, 0xee, 0x2d, 0x90, 0x24, 0x35, 0x0a, 0x64, 0x19, - 0x26, 0x8d, 0x97, 0x5c, 0xea, 0x74, 0x93, 0xf5, 0xbe, 0xab, 0x60, 0x9c, 0x27, 0x8d, 0x17, 0x5b, - 0x8a, 0x4b, 0xd6, 0x3b, 0xae, 0x5c, 0x2e, 0x3f, 0x84, 0x71, 0x21, 0xd2, 0x42, 0x69, 0xe4, 0x1b, - 0xeb, 0x66, 0x35, 0xaf, 0xe8, 0x6e, 0xcb, 0x8d, 0x96, 0x7c, 0xef, 0xb1, 0xbb, 0xdf, 0x53, 0x30, - 0x69, 0x92, 0xbd, 0x05, 0xf2, 0x15, 0x26, 0x66, 0x96, 0xe9, 0xb2, 0x69, 0xf4, 0xcc, 0x0f, 0x9e, - 0xb8, 0xde, 0x7e, 0x0f, 0x96, 0x57, 0x4c, 0x96, 0x49, 0x3a, 0xe9, 0x78, 0xf2, 0x15, 0xcc, 0xd7, - 0xf3, 0x99, 0xf7, 0x64, 0x52, 0xbc, 0xbd, 0xd4, 0xe1, 0x22, 0xba, 0xde, 0x9c, 0xb6, 0xed, 0x85, - 0x4c, 0xbf, 0xe0, 0xd1, 0x1c, 0xa5, 0xa1, 0xbf, 0xe9, 0x07, 0xad, 0xde, 0x1c, 0xab, 0xa6, 0x33, - 0x6f, 0x82, 0x4c, 0x0a, 0xe3, 0x0b, 0x38, 0x5f, 0xcf, 0x65, 0xdd, 0x8b, 0x45, 0x2f, 0x4d, 0xf2, - 0x02, 0x8a, 0xe2, 0x94, 0xed, 0x2e, 0xe4, 0xb9, 0x86, 0x6b, 0x1a, 0xdb, 0x87, 0xb6, 0x03, 0xfa, - 0x98, 0x06, 0xe8, 0x32, 0xde, 0xcb, 0x59, 0xda, 0x44, 0x97, 0x3d, 0x5f, 0x83, 0xb3, 0xf5, 0x14, - 0xab, 0x3c, 0x92, 0x5e, 0x97, 0x47, 0xd3, 0xd8, 0xd3, 0x13, 0xb6, 0xab, 0x87, 0x8b, 0xd1, 0xf8, - 0x3d, 0x1a, 0xed, 0xae, 0xf5, 0x90, 0x92, 0x7c, 0xd3, 0x20, 0x11, 0xf7, 0xee, 0x30, 0xca, 0xba, - 0x46, 0x99, 0xc6, 0xc8, 0xfd, 0x78, 0x3f, 0x95, 0x17, 0x29, 0x3d, 0xab, 0xcd, 0xe3, 0xf0, 0x16, - 0xae, 0x85, 0xc2, 0x6d, 0x5a, 0x33, 0x41, 0x72, 0x48, 0x6c, 0xaa, 0xd3, 0x3c, 0xa8, 0x43, 0x52, - 0xe3, 0xc7, 0x3f, 0x3e, 0x3d, 0x04, 0xec, 0x72, 0xca, 0x9d, 0xbe, 0x90, 0x05, 0x37, 0xa1, 0xae, - 0xfb, 0xcd, 0x27, 0xba, 0x09, 0x55, 0x4b, 0xdd, 0x3f, 0x6f, 0x26, 0xd6, 0x17, 0x2b, 0x3e, 0x66, - 0xd7, 0xd7, 0xbd, 0xc6, 0xf4, 0xe4, 0xfd, 0xba, 0x09, 0x55, 0xc0, 0x85, 0x05, 0xe9, 0x2d, 0x69, - 0x5b, 0xc4, 0x0a, 0x4d, 0xce, 0xb9, 0xa2, 0x51, 0x66, 0x45, 0x24, 0x32, 0xcd, 0x8a, 0x7a, 0x43, - 0xf3, 0x2f, 0x02, 0x88, 0x4d, 0x3b, 0x6d, 0xf4, 0xc4, 0x3e, 0xf4, 0x39, 0x4d, 0xec, 0x9c, 0x9b, - 0x2e, 0xea, 0xed, 0xfc, 0x35, 0x2d, 0x5c, 0x86, 0x0c, 0xc1, 0xab, 0x88, 0xc8, 0xe9, 0xb2, 0x58, - 0x94, 0xba, 0x27, 0xd3, 0xed, 0x12, 0xd9, 0x84, 0x73, 0xf7, 0x68, 0x24, 0xd6, 0x38, 0x9b, 0x86, - 0x51, 0xe0, 0x36, 0xa3, 0xc2, 0x5b, 0x45, 0x79, 0x36, 0xc9, 0xa0, 0xd9, 0x7b, 0x9b, 0xf1, 0xab, - 0x67, 0xf3, 0x2b, 0xa4, 0x2b, 0xf0, 0xaf, 0x15, 0x57, 0x15, 0xa7, 0x69, 0x62, 0xfe, 0x14, 0x1f, - 0xe1, 0xee, 0x3b, 0xf9, 0xa4, 0xe5, 0x38, 0xfa, 0x8a, 0x38, 0x6d, 0xdd, 0x84, 0x61, 0x4e, 0x94, - 0xbb, 0xa1, 0x4e, 0xe8, 0x34, 0xe4, 0x0e, 0x8c, 0x29, 0xff, 0x1b, 0x62, 0x14, 0xe5, 0xb6, 0xeb, - 0x0e, 0x8c, 0xf1, 0xa3, 0xd5, 0xc9, 0x49, 0x3e, 0x84, 0x31, 0xe5, 0xb0, 0x73, 0xea, 0x9d, 0xfe, - 0x13, 0x98, 0xd4, 0x5d, 0x77, 0x4e, 0x2f, 0xc8, 0x1f, 0xe2, 0xdd, 0xaf, 0xbc, 0x62, 0xc9, 0xa7, - 0x9f, 0x4d, 0x04, 0xa5, 0x11, 0x22, 0xe5, 0x0b, 0xa4, 0x04, 0xe6, 0x36, 0xff, 0x6c, 0x8a, 0x9a, - 0x7c, 0x28, 0x5f, 0x53, 0x29, 0xe2, 0x34, 0x52, 0x81, 0xcc, 0xa6, 0xb8, 0x98, 0x5f, 0x84, 0x58, - 0x2d, 0xb0, 0x3d, 0x9b, 0x7d, 0x92, 0x3b, 0xea, 0xde, 0xa2, 0xcb, 0xe3, 0xb2, 0x85, 0x5a, 0x5a, - 0x2a, 0x19, 0x5e, 0x3e, 0xa3, 0xcb, 0xf9, 0xf9, 0xf3, 0x70, 0x30, 0xee, 0xe3, 0x29, 0x30, 0x55, - 0x9a, 0xdb, 0xbd, 0x82, 0x7c, 0x7c, 0xf1, 0xb1, 0x37, 0xcd, 0xae, 0x80, 0xac, 0xe8, 0x14, 0x2d, - 0xde, 0x88, 0xbe, 0x14, 0x76, 0x6b, 0xd2, 0x03, 0xf2, 0xe4, 0x9d, 0xcd, 0x6f, 0xd9, 0x85, 0x8c, - 0x5b, 0xf1, 0x9e, 0x63, 0x91, 0xc7, 0xee, 0x57, 0x50, 0x3b, 0xcc, 0x8c, 0x4a, 0x96, 0xcf, 0xec, - 0xba, 0xe6, 0x58, 0x91, 0x49, 0xa9, 0x36, 0xbd, 0x27, 0xf8, 0x4c, 0x2d, 0x3b, 0x5d, 0xe0, 0x6b, - 0x3d, 0xb8, 0x48, 0x49, 0xbc, 0xde, 0x13, 0x4f, 0xdd, 0xb1, 0x5e, 0xe0, 0x3b, 0x6c, 0x76, 0x7d, - 0x3d, 0xd2, 0x1f, 0x66, 0x5c, 0x7b, 0x2b, 0xf7, 0xd2, 0x6c, 0x86, 0xa6, 0x7b, 0x69, 0x61, 0x1f, - 0xf2, 0xc4, 0xff, 0x19, 0x54, 0x63, 0xef, 0x91, 0xd3, 0x0d, 0x42, 0xbe, 0x57, 0x23, 0x49, 0x49, - 0x2a, 0x24, 0x45, 0xf9, 0x80, 0xe6, 0xaf, 0xe6, 0x49, 0x38, 0xd4, 0xdc, 0x92, 0x84, 0x57, 0x5c, - 0x22, 0x71, 0x66, 0x5e, 0x0a, 0xce, 0x02, 0x3b, 0xac, 0x78, 0xb7, 0xf7, 0x52, 0x18, 0xa5, 0x47, - 0xfb, 0xf4, 0x8c, 0x94, 0x73, 0x47, 0x82, 0x91, 0x55, 0x30, 0xbc, 0xbd, 0xaf, 0x1e, 0x2b, 0x39, - 0xe3, 0x7a, 0xfa, 0x01, 0x75, 0xe2, 0xb7, 0x6a, 0x89, 0x20, 0x86, 0xfa, 0xfb, 0xe0, 0x74, 0x51, - 0xf2, 0xa1, 0x55, 0x16, 0x86, 0xf2, 0xa8, 0xaa, 0xc8, 0x2a, 0x18, 0x9c, 0x1d, 0x45, 0xfc, 0xc0, - 0x8d, 0x9e, 0x2f, 0xd9, 0xeb, 0xb1, 0x59, 0x41, 0x2f, 0x90, 0xbc, 0x41, 0x16, 0xda, 0xeb, 0xe4, - 0x4b, 0x5c, 0x4a, 0x04, 0xfb, 0x45, 0xdf, 0x8f, 0xc2, 0x28, 0x70, 0x3a, 0xf5, 0x66, 0xe0, 0x76, - 0xa2, 0xdc, 0x4e, 0xc7, 0x0e, 0xe0, 0x59, 0x64, 0x9a, 0x3f, 0xaa, 0x08, 0x72, 0x9f, 0x15, 0x7d, - 0x47, 0xbd, 0xc9, 0xc9, 0x2a, 0x2c, 0x38, 0xb9, 0xd4, 0x65, 0x58, 0xfb, 0x97, 0xc9, 0xb4, 0x01, - 0x73, 0x39, 0x31, 0x8b, 0xd4, 0xed, 0x6d, 0x71, 0x4c, 0xa3, 0xf9, 0xe2, 0x8a, 0xc9, 0x57, 0x30, - 0x9b, 0x19, 0xd4, 0x48, 0x59, 0xa0, 0x8b, 0x42, 0x1e, 0xf5, 0x62, 0xfe, 0x04, 0x2a, 0xfc, 0x35, - 0x08, 0x3a, 0x3d, 0x1b, 0xf1, 0x6d, 0xe2, 0x37, 0x42, 0x39, 0x08, 0xc9, 0xf5, 0x3a, 0x1f, 0x4f, - 0x3d, 0x78, 0x9f, 0xc1, 0xc0, 0x26, 0x89, 0x94, 0xef, 0xea, 0xc3, 0xcb, 0x2a, 0x2c, 0x7a, 0x88, - 0xb4, 0x0d, 0xb3, 0x7b, 0x34, 0x70, 0x1f, 0x3f, 0x4f, 0x32, 0x94, 0x92, 0xc9, 0x2c, 0x2d, 0xe2, - 0xf8, 0x39, 0xcc, 0x2d, 0xf9, 0x87, 0x1d, 0xf1, 0xe4, 0xcf, 0xe0, 0xa9, 0xae, 0xe2, 0xb3, 0xcb, - 0x7b, 0x3b, 0x42, 0xcd, 0xe7, 0x27, 0xe7, 0x57, 0xfe, 0x6f, 0x3d, 0xf3, 0xf7, 0xab, 0x87, 0x6b, - 0x26, 0xfd, 0x0e, 0x4e, 0xc2, 0xac, 0x6c, 0xfd, 0xfa, 0x24, 0x2c, 0xc8, 0xe6, 0x9f, 0xf3, 0x80, - 0x6c, 0x2e, 0x27, 0x41, 0x7f, 0x01, 0xd7, 0x13, 0xb4, 0x76, 0x53, 0xee, 0x2d, 0x66, 0xbe, 0xf1, - 0x84, 0xc7, 0x75, 0x66, 0x32, 0xf2, 0xcc, 0x76, 0x6a, 0x91, 0x1d, 0xda, 0xed, 0x02, 0x15, 0x8b, - 0xe8, 0xa1, 0x1d, 0x18, 0x26, 0x1a, 0xf1, 0x27, 0x75, 0xda, 0xa2, 0xd5, 0x3a, 0x45, 0x8c, 0x4a, - 0xed, 0x07, 0x30, 0x51, 0xd7, 0x2b, 0xcf, 0xa8, 0x24, 0x77, 0x52, 0xa8, 0x27, 0x44, 0xbd, 0xdb, - 0x5e, 0xe0, 0x48, 0xaa, 0x36, 0x9e, 0x13, 0xf5, 0x22, 0xd7, 0x75, 0xc6, 0x48, 0x1e, 0xa7, 0x76, - 0x81, 0xac, 0xdc, 0x8e, 0xca, 0x75, 0x26, 0x3b, 0xdf, 0x5c, 0x83, 0xa7, 0xbb, 0x49, 0xa6, 0xee, - 0x24, 0x56, 0xef, 0x1c, 0xb9, 0xca, 0xa1, 0xbe, 0x30, 0xf7, 0x27, 0xf7, 0xf3, 0x89, 0xd3, 0xe5, - 0xe9, 0x7e, 0x3e, 0xa9, 0x24, 0x7c, 0xba, 0x9f, 0x4f, 0x46, 0x86, 0xbd, 0x15, 0xe4, 0x15, 0xe7, - 0x09, 0x2a, 0x30, 0x46, 0x28, 0x36, 0x19, 0xe9, 0x88, 0x1e, 0xe8, 0x01, 0x42, 0x78, 0x76, 0xa1, - 0x02, 0x5b, 0x6b, 0x32, 0x30, 0x48, 0x22, 0x1d, 0xd1, 0x5d, 0x28, 0xf3, 0x44, 0x0b, 0x71, 0x4c, - 0xc5, 0xd8, 0x6f, 0x30, 0x9d, 0xff, 0xa1, 0x60, 0x50, 0xcb, 0xc9, 0x68, 0x74, 0xca, 0x64, 0x96, - 0x13, 0xa6, 0xae, 0x60, 0xaa, 0x42, 0x1c, 0x73, 0x4e, 0x19, 0xa6, 0x52, 0x61, 0xe8, 0xe6, 0xcf, - 0x67, 0x94, 0x28, 0x95, 0x72, 0x42, 0x8f, 0x50, 0xa7, 0xba, 0x94, 0x11, 0xb6, 0x6e, 0xfe, 0x42, - 0x66, 0x99, 0x60, 0x14, 0xf1, 0x34, 0xd1, 0xd9, 0xc9, 0xad, 0xe3, 0x57, 0x60, 0x05, 0x38, 0xb2, - 0x9a, 0x1b, 0x27, 0x41, 0x15, 0xb5, 0x52, 0x95, 0x25, 0x29, 0x23, 0xa3, 0xf6, 0xeb, 0x19, 0x0f, - 0x35, 0x0c, 0x8c, 0xd8, 0x1b, 0xac, 0x38, 0xbd, 0x37, 0x79, 0x28, 0xb3, 0xd6, 0xe4, 0xd4, 0xd4, - 0x8b, 0x41, 0xee, 0x08, 0x3e, 0x94, 0x79, 0x6a, 0x5e, 0x36, 0xe3, 0x47, 0x70, 0x31, 0xf1, 0xfa, - 0xc3, 0x64, 0x7c, 0x23, 0xfb, 0x89, 0x48, 0xa6, 0x78, 0xf2, 0x75, 0xf6, 0x2b, 0xe9, 0x57, 0x22, - 0x89, 0x71, 0x3f, 0xed, 0x9a, 0xb7, 0x01, 0x53, 0xb8, 0xcc, 0xc8, 0xdc, 0xf0, 0x71, 0x7c, 0x1a, - 0x13, 0x9c, 0x0c, 0x94, 0x94, 0x2c, 0x55, 0x2e, 0xb3, 0x13, 0xe2, 0x45, 0x31, 0xcf, 0x34, 0x3f, - 0x6f, 0x3e, 0x33, 0x46, 0x60, 0xd6, 0x2e, 0x26, 0x12, 0xd8, 0x93, 0x1f, 0xc2, 0x99, 0xf8, 0xa1, - 0x31, 0x67, 0x91, 0x81, 0x56, 0x60, 0x28, 0x3b, 0x13, 0xbf, 0x36, 0x3e, 0x3d, 0xf9, 0xaa, 0xdc, - 0x8a, 0x62, 0xf2, 0x4b, 0xa9, 0xb7, 0x32, 0x46, 0x1f, 0x4e, 0xb2, 0x23, 0x69, 0xb2, 0x3d, 0xed, - 0xe8, 0x34, 0xf1, 0x73, 0xcb, 0x0e, 0xbd, 0xa8, 0x7f, 0x6e, 0x85, 0xe1, 0x21, 0x95, 0xfa, 0x9b, - 0xc3, 0x67, 0x03, 0xae, 0x61, 0xb8, 0x96, 0x6d, 0x1e, 0xa0, 0x2f, 0x1b, 0x2b, 0xbf, 0xed, 0xc9, - 0x20, 0x2f, 0x6d, 0xb8, 0xda, 0x33, 0xf6, 0x24, 0xb9, 0x65, 0xb8, 0xb8, 0xf4, 0x8e, 0x52, 0x59, - 0x70, 0xf2, 0x98, 0xc9, 0x0a, 0xe1, 0xa8, 0xf6, 0xd9, 0x82, 0x68, 0x92, 0x6a, 0x9f, 0x2d, 0x8c, - 0x01, 0xf9, 0x39, 0xa6, 0x82, 0x12, 0x7b, 0x14, 0x86, 0x60, 0xa2, 0x1e, 0x0f, 0x4a, 0x5d, 0x78, - 0xed, 0x73, 0xd5, 0xbc, 0x14, 0x4d, 0x11, 0xe2, 0x99, 0xe6, 0xb2, 0x38, 0x89, 0xe5, 0x31, 0xef, - 0xcd, 0xa4, 0xc0, 0xb5, 0xfa, 0x32, 0x9f, 0x80, 0xa7, 0x6e, 0x79, 0x0e, 0x7c, 0x71, 0xf9, 0x67, - 0xff, 0xe1, 0x72, 0xe9, 0x67, 0x3f, 0xbf, 0x5c, 0xfa, 0xd7, 0x3f, 0xbf, 0x5c, 0xfa, 0xf7, 0x3f, - 0xbf, 0x5c, 0xfa, 0x72, 0xe1, 0x64, 0xa1, 0x91, 0x9b, 0x6d, 0x97, 0x7a, 0xd1, 0x2d, 0xce, 0x6e, - 0x18, 0xff, 0x7b, 0xeb, 0xbf, 0x07, 0x00, 0x00, 0xff, 0xff, 0xdc, 0x66, 0x4b, 0x5c, 0x15, 0xeb, - 0x00, 0x00, + // 15036 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0xbd, 0x59, 0x6c, 0x64, 0x49, + 0x76, 0x18, 0xca, 0x4c, 0xee, 0x87, 0x4b, 0x65, 0x05, 0xc9, 0x62, 0x16, 0x6b, 0xc9, 0xaa, 0x5b, + 0xbd, 0x54, 0xd7, 0xf4, 0xd4, 0xc2, 0x5e, 0xa6, 0xb7, 0xe9, 0xee, 0xe4, 0x52, 0x24, 0xab, 0xb8, + 0xf5, 0x4d, 0x92, 0xd5, 0x9b, 0x26, 0xe7, 0x32, 0x33, 0x8a, 0xbc, 0xaa, 0xe4, 0xbd, 0x39, 0xf7, + 0xde, 0xac, 0xea, 0x1a, 0x3d, 0xe9, 0x41, 0xd2, 0x5b, 0xf4, 0xf3, 0xde, 0x93, 0x80, 0xf7, 0x04, + 0xbd, 0xf7, 0x3e, 0x64, 0x03, 0x36, 0x60, 0x18, 0xb0, 0xe1, 0x1f, 0x43, 0x3f, 0x16, 0x0c, 0x7f, + 0x79, 0x2c, 0xc0, 0xb0, 0x0d, 0x49, 0x3f, 0x06, 0x4c, 0xd9, 0x03, 0xe8, 0x87, 0xb0, 0x3f, 0x04, + 0xc3, 0x06, 0x3c, 0x80, 0x00, 0x23, 0x4e, 0x2c, 0x37, 0xe2, 0x2e, 0x99, 0x64, 0x75, 0xf5, 0xc8, + 0x3f, 0x55, 0xcc, 0x13, 0xe7, 0x9c, 0x88, 0x7b, 0x62, 0x3b, 0x71, 0xe2, 0xc4, 0x39, 0x70, 0x3b, + 0xa2, 0x2d, 0xda, 0xf6, 0x83, 0xe8, 0x4e, 0x8b, 0x1e, 0x38, 0x8d, 0xe7, 0x77, 0x1a, 0x2d, 0x97, + 0x7a, 0xd1, 0x9d, 0x76, 0xe0, 0x47, 0xfe, 0x1d, 0xa7, 0x13, 0x1d, 0x86, 0x34, 0x78, 0xea, 0x36, + 0xe8, 0x6d, 0x84, 0x90, 0x41, 0xfc, 0x6f, 0x6e, 0xfa, 0xc0, 0x3f, 0xf0, 0x39, 0x0e, 0xfb, 0x8b, + 0x17, 0xce, 0x5d, 0x3a, 0xf0, 0xfd, 0x83, 0x16, 0xe5, 0xc4, 0xfb, 0x9d, 0xc7, 0x77, 0xe8, 0x51, + 0x3b, 0x7a, 0x2e, 0x0a, 0x2b, 0xc9, 0xc2, 0xc8, 0x3d, 0xa2, 0x61, 0xe4, 0x1c, 0xb5, 0x05, 0xc2, + 0x1b, 0xaa, 0x29, 0x4e, 0x14, 0xb1, 0x92, 0xc8, 0xf5, 0xbd, 0x3b, 0x4f, 0xef, 0xe9, 0x3f, 0x05, + 0xea, 0xcd, 0xae, 0xad, 0x6e, 0xd0, 0x20, 0x0a, 0x4f, 0x85, 0x49, 0x9f, 0x52, 0x2f, 0x4a, 0x55, + 0x2f, 0x30, 0xa3, 0xe7, 0x6d, 0x1a, 0x72, 0x14, 0xf9, 0x9f, 0x40, 0xbd, 0x9e, 0x8d, 0x8a, 0xff, + 0x0a, 0x94, 0xef, 0x67, 0xa3, 0x3c, 0xa3, 0xfb, 0x4c, 0xa6, 0x9e, 0xfa, 0xa3, 0x07, 0x7a, 0xe0, + 0xb4, 0xdb, 0x34, 0x88, 0xff, 0x10, 0xe8, 0x17, 0x15, 0xfa, 0xd1, 0x63, 0x87, 0x89, 0xe8, 0xe8, + 0xb1, 0x93, 0xfa, 0x8c, 0x4e, 0xe8, 0x1c, 0x50, 0xd1, 0xfc, 0xa7, 0xf7, 0xf4, 0x9f, 0x1c, 0xd5, + 0xfa, 0xc3, 0x02, 0x0c, 0x3e, 0x72, 0xa2, 0xc6, 0x21, 0xf9, 0x04, 0x06, 0x1f, 0xba, 0x5e, 0x33, + 0x2c, 0x17, 0xae, 0xf5, 0xdf, 0x1c, 0x9b, 0x2f, 0xdd, 0xe6, 0x9f, 0x82, 0x85, 0xac, 0x60, 0x61, + 0xf6, 0x67, 0xc7, 0x95, 0xbe, 0x93, 0xe3, 0xca, 0xb9, 0x27, 0x0c, 0xed, 0x4d, 0xff, 0xc8, 0x8d, + 0xb0, 0x6f, 0x6d, 0x4e, 0x47, 0x76, 0x61, 0xaa, 0xda, 0x6a, 0xf9, 0xcf, 0xb6, 0x9d, 0x20, 0x72, + 0x9d, 0x56, 0xad, 0xd3, 0x68, 0xd0, 0x30, 0x2c, 0x17, 0xaf, 0x15, 0x6e, 0x8e, 0x2c, 0xdc, 0x38, + 0x39, 0xae, 0x54, 0x1c, 0x56, 0x5c, 0x6f, 0xf3, 0xf2, 0x7a, 0xc8, 0x11, 0x34, 0x46, 0x59, 0xf4, + 0xd6, 0x9f, 0x0c, 0x41, 0x69, 0xd5, 0x0f, 0xa3, 0x45, 0xd6, 0xa3, 0x36, 0xfd, 0x49, 0x87, 0x86, + 0x11, 0xb9, 0x01, 0x43, 0x0c, 0xb6, 0xb6, 0x54, 0x2e, 0x5c, 0x2b, 0xdc, 0x1c, 0x5d, 0x18, 0x3b, + 0x39, 0xae, 0x0c, 0x1f, 0xfa, 0x61, 0x54, 0x77, 0x9b, 0xb6, 0x28, 0x22, 0x6f, 0xc0, 0xc8, 0xa6, + 0xdf, 0xa4, 0x9b, 0xce, 0x11, 0xc5, 0x56, 0x8c, 0x2e, 0x4c, 0x9c, 0x1c, 0x57, 0x46, 0x3d, 0xbf, + 0x49, 0xeb, 0x9e, 0x73, 0x44, 0x6d, 0x55, 0x4c, 0xf6, 0x60, 0xc0, 0xf6, 0x5b, 0xb4, 0xdc, 0x8f, + 0x68, 0x0b, 0x27, 0xc7, 0x95, 0x81, 0xc0, 0x6f, 0xd1, 0x5f, 0x1c, 0x57, 0xde, 0x3d, 0x70, 0xa3, + 0xc3, 0xce, 0xfe, 0xed, 0x86, 0x7f, 0x74, 0xe7, 0x20, 0x70, 0x9e, 0xba, 0x7c, 0x10, 0x3a, 0xad, + 0x3b, 0xf1, 0x50, 0x6d, 0xbb, 0xa2, 0xdf, 0x6b, 0xcf, 0xc3, 0x88, 0x1e, 0x31, 0x4e, 0x36, 0xf2, + 0x23, 0x8f, 0x60, 0xba, 0xda, 0x6c, 0xba, 0x9c, 0x62, 0x3b, 0x70, 0xbd, 0x86, 0xdb, 0x76, 0x5a, + 0x61, 0x79, 0xe0, 0x5a, 0xff, 0xcd, 0x51, 0x21, 0x14, 0x55, 0x5e, 0x6f, 0x2b, 0x04, 0x4d, 0x28, + 0x99, 0x0c, 0xc8, 0x5b, 0x30, 0xb2, 0xb4, 0x59, 0x63, 0x6d, 0x0f, 0xcb, 0x83, 0xc8, 0x6c, 0xf6, + 0xe4, 0xb8, 0x32, 0xd5, 0xf4, 0x42, 0xfc, 0x34, 0x9d, 0x81, 0x42, 0x24, 0xef, 0xc2, 0xf8, 0x76, + 0x67, 0xbf, 0xe5, 0x36, 0x76, 0xd6, 0x6b, 0x0f, 0xe9, 0xf3, 0xf2, 0xd0, 0xb5, 0xc2, 0xcd, 0xf1, + 0x05, 0x72, 0x72, 0x5c, 0x99, 0x6c, 0x23, 0xbc, 0x1e, 0xb5, 0xc2, 0xfa, 0x13, 0xfa, 0xdc, 0x36, + 0xf0, 0x62, 0xba, 0x5a, 0x6d, 0x95, 0xd1, 0x0d, 0xa7, 0xe8, 0xc2, 0xf0, 0x50, 0xa7, 0xe3, 0x78, + 0xe4, 0x0e, 0x80, 0x4d, 0x8f, 0xfc, 0x88, 0x56, 0x9b, 0xcd, 0xa0, 0x3c, 0x82, 0xb2, 0x3d, 0x77, + 0x72, 0x5c, 0x19, 0x0b, 0x10, 0x5a, 0x77, 0x9a, 0xcd, 0xc0, 0xd6, 0x50, 0xc8, 0x22, 0x8c, 0xd8, + 0x3e, 0x17, 0x70, 0x79, 0xf4, 0x5a, 0xe1, 0xe6, 0xd8, 0xfc, 0x39, 0x31, 0x0c, 0x25, 0x78, 0xe1, + 0xc2, 0xc9, 0x71, 0x85, 0x04, 0xe2, 0x97, 0xfe, 0x95, 0x12, 0x83, 0x54, 0x60, 0x78, 0xd3, 0x5f, + 0x74, 0x1a, 0x87, 0xb4, 0x0c, 0x38, 0xf6, 0x06, 0x4f, 0x8e, 0x2b, 0x85, 0xef, 0xdb, 0x12, 0x4a, + 0x9e, 0xc2, 0x58, 0xdc, 0x51, 0x61, 0x79, 0x0c, 0xc5, 0xb7, 0x73, 0x72, 0x5c, 0xb9, 0x10, 0x22, + 0xb8, 0xce, 0xba, 0x5e, 0x93, 0xe0, 0xb7, 0x18, 0x05, 0x7a, 0x45, 0xe4, 0x6b, 0x98, 0x89, 0x7f, + 0x56, 0xc3, 0x90, 0x06, 0x8c, 0xc7, 0xda, 0x52, 0x79, 0x02, 0x25, 0xf3, 0xda, 0xc9, 0x71, 0xc5, + 0xd2, 0x5a, 0x50, 0x77, 0x24, 0x4a, 0xdd, 0x6d, 0x6a, 0x5f, 0x9a, 0xcd, 0xe4, 0xc1, 0xc0, 0xc8, + 0x78, 0x69, 0xc2, 0xbe, 0xb2, 0xeb, 0x85, 0x91, 0xb3, 0xdf, 0xa2, 0x99, 0x48, 0xd6, 0x5f, 0x17, + 0x80, 0x6c, 0xb5, 0xa9, 0x57, 0xab, 0xad, 0xb2, 0xf9, 0x24, 0xa7, 0xd3, 0x9b, 0x30, 0xca, 0x3b, + 0x8e, 0xf5, 0x6e, 0x11, 0x7b, 0x77, 0xf2, 0xe4, 0xb8, 0x02, 0xa2, 0x77, 0x59, 0xcf, 0xc6, 0x08, + 0xe4, 0x55, 0xe8, 0xdf, 0xd9, 0x59, 0xc7, 0xb9, 0xd2, 0xbf, 0x30, 0x75, 0x72, 0x5c, 0xe9, 0x8f, + 0xa2, 0xd6, 0x2f, 0x8e, 0x2b, 0x23, 0x4b, 0x9d, 0x00, 0xc5, 0x62, 0xb3, 0x72, 0xf2, 0x2a, 0x0c, + 0x2f, 0xb6, 0x3a, 0x61, 0x44, 0x83, 0xf2, 0x40, 0x3c, 0x49, 0x1b, 0x1c, 0x64, 0xcb, 0x32, 0xf2, + 0x3d, 0x18, 0xd8, 0x0d, 0x69, 0x50, 0x1e, 0xc4, 0xfe, 0x9e, 0x10, 0xfd, 0xcd, 0x40, 0x7b, 0xf3, + 0x0b, 0x23, 0x6c, 0x26, 0x76, 0x42, 0x1a, 0xd8, 0x88, 0x44, 0x6e, 0xc3, 0x20, 0xef, 0xb4, 0x21, + 0x5c, 0xa4, 0x26, 0xd4, 0xe8, 0x68, 0xd1, 0xbd, 0x77, 0x17, 0x46, 0x4f, 0x8e, 0x2b, 0x83, 0xd8, + 0x79, 0x36, 0x47, 0x7b, 0x30, 0x30, 0x52, 0x28, 0x15, 0xed, 0x11, 0x46, 0xcb, 0xa6, 0x85, 0xf5, + 0x3d, 0x18, 0xd3, 0x3e, 0x9f, 0x5c, 0x86, 0x01, 0xf6, 0x3f, 0x2e, 0x22, 0xe3, 0xbc, 0x32, 0xb6, + 0x71, 0xd8, 0x08, 0xb5, 0xfe, 0xd6, 0x14, 0x94, 0x18, 0xa5, 0xb1, 0xf2, 0xdc, 0xd6, 0x45, 0xc5, + 0xe9, 0x4a, 0xa6, 0xa8, 0xca, 0x05, 0x5d, 0x58, 0x37, 0x41, 0xd5, 0x2e, 0x16, 0xa1, 0xf1, 0x93, + 0xe3, 0xca, 0x48, 0x47, 0xc0, 0xe2, 0xb6, 0x91, 0x1a, 0x0c, 0x2f, 0x7f, 0xd3, 0x76, 0x03, 0x1a, + 0xa2, 0x68, 0xc7, 0xe6, 0xe7, 0x6e, 0xf3, 0xed, 0xf2, 0xb6, 0xdc, 0x2e, 0x6f, 0xef, 0xc8, 0xed, + 0x72, 0xe1, 0x8a, 0x58, 0x8c, 0xcf, 0x53, 0x4e, 0x12, 0x8f, 0x8f, 0xdf, 0xfd, 0x8b, 0x4a, 0xc1, + 0x96, 0x9c, 0xc8, 0x9b, 0x30, 0x74, 0xdf, 0x0f, 0x8e, 0x9c, 0x48, 0xf4, 0xc1, 0xf4, 0xc9, 0x71, + 0xa5, 0xf4, 0x18, 0x21, 0xda, 0x90, 0x12, 0x38, 0xe4, 0x3e, 0x4c, 0xda, 0x7e, 0x27, 0xa2, 0x3b, + 0xbe, 0xec, 0xb9, 0x41, 0xa4, 0xba, 0x7a, 0x72, 0x5c, 0x99, 0x0b, 0x58, 0x49, 0x3d, 0xf2, 0xeb, + 0xa2, 0x0b, 0x35, 0xfa, 0x04, 0x15, 0x59, 0x86, 0xc9, 0x2a, 0xae, 0xde, 0x42, 0x6a, 0xbc, 0xbf, + 0x46, 0x17, 0xae, 0x9c, 0x1c, 0x57, 0x2e, 0x3a, 0x58, 0x52, 0x0f, 0x44, 0x91, 0xce, 0xc6, 0x24, + 0x22, 0x9b, 0x70, 0xfe, 0x61, 0x67, 0x9f, 0x06, 0x1e, 0x8d, 0x68, 0x28, 0x5b, 0x34, 0x8c, 0x2d, + 0xba, 0x76, 0x72, 0x5c, 0xb9, 0xfc, 0x44, 0x15, 0x66, 0xb4, 0x29, 0x4d, 0x4a, 0x28, 0x9c, 0x13, + 0x0d, 0x5d, 0x72, 0x22, 0x67, 0xdf, 0x09, 0x29, 0x2e, 0x4a, 0x63, 0xf3, 0x17, 0xb8, 0x88, 0x6f, + 0x27, 0x4a, 0x17, 0x6e, 0x08, 0x29, 0x5f, 0x52, 0xdf, 0xde, 0x14, 0x45, 0x5a, 0x45, 0x49, 0x9e, + 0x6c, 0x6d, 0x56, 0xfb, 0xce, 0x28, 0xb6, 0x16, 0xd7, 0x66, 0xb5, 0xef, 0xe8, 0xab, 0x96, 0xda, + 0x81, 0xd6, 0x61, 0x70, 0x97, 0xed, 0xce, 0xb8, 0x66, 0x4d, 0xce, 0x5f, 0x17, 0x2d, 0x4a, 0x8e, + 0xbf, 0xdb, 0xec, 0x07, 0x22, 0xe2, 0xcc, 0x3b, 0x87, 0x3b, 0xba, 0xbe, 0x17, 0x63, 0x19, 0xf9, + 0x0c, 0x40, 0xb4, 0xaa, 0xda, 0x6e, 0x97, 0xc7, 0xf0, 0x23, 0xcf, 0x9b, 0x1f, 0x59, 0x6d, 0xb7, + 0x17, 0xae, 0x8a, 0xef, 0xbb, 0xa0, 0xbe, 0xcf, 0x69, 0xb7, 0x35, 0x6e, 0x1a, 0x13, 0xf2, 0x09, + 0x8c, 0xe3, 0x92, 0x26, 0x7b, 0x74, 0x1c, 0x7b, 0xf4, 0xd2, 0xc9, 0x71, 0x65, 0x16, 0x57, 0xab, + 0x8c, 0xfe, 0x34, 0x08, 0xc8, 0x6f, 0xc0, 0x8c, 0x60, 0xf7, 0xc8, 0xf5, 0x9a, 0xfe, 0xb3, 0x70, + 0x89, 0x86, 0x4f, 0x22, 0xbf, 0x8d, 0xcb, 0xdf, 0xd8, 0xfc, 0x65, 0xb3, 0x79, 0x26, 0xce, 0xc2, + 0x2d, 0xd1, 0x52, 0x4b, 0xb5, 0xf4, 0x19, 0x47, 0xa8, 0x37, 0x39, 0x86, 0xbe, 0x40, 0x66, 0xb2, + 0x20, 0x6b, 0x70, 0x6e, 0x37, 0xa4, 0xc6, 0x37, 0x4c, 0xe2, 0xfe, 0x50, 0x61, 0x3d, 0xdc, 0x09, + 0x69, 0x3d, 0xef, 0x3b, 0x92, 0x74, 0xc4, 0x06, 0xb2, 0x14, 0xf8, 0xed, 0xc4, 0x18, 0x3f, 0x87, + 0x12, 0xb1, 0x4e, 0x8e, 0x2b, 0x57, 0x9b, 0x81, 0xdf, 0xae, 0xe7, 0x0f, 0xf4, 0x0c, 0x6a, 0xf2, + 0x23, 0xb8, 0xb0, 0xe8, 0x7b, 0x1e, 0x6d, 0xb0, 0x15, 0x74, 0xc9, 0x75, 0x0e, 0x3c, 0x3f, 0x8c, + 0xdc, 0xc6, 0xda, 0x52, 0xb9, 0x14, 0x6f, 0x0f, 0x0d, 0x85, 0x51, 0x6f, 0x2a, 0x14, 0x73, 0x7b, + 0xc8, 0xe1, 0x42, 0xbe, 0x82, 0x09, 0x51, 0x17, 0x0d, 0x70, 0x68, 0x9e, 0xef, 0x3e, 0xd0, 0x14, + 0x32, 0xdf, 0xe8, 0x03, 0xf9, 0x93, 0xab, 0x4e, 0x26, 0x2f, 0xf2, 0x35, 0x8c, 0x6d, 0xdc, 0xaf, + 0xda, 0x34, 0x6c, 0xfb, 0x5e, 0x48, 0xcb, 0x04, 0x7b, 0xf4, 0xaa, 0x60, 0xbd, 0x71, 0xbf, 0x5a, + 0xed, 0x44, 0x87, 0xd4, 0x8b, 0xdc, 0x86, 0x13, 0x51, 0x89, 0xb5, 0x30, 0xc7, 0x46, 0xde, 0xd1, + 0x63, 0xa7, 0x1e, 0x08, 0x88, 0xf6, 0x15, 0x3a, 0x3b, 0x32, 0x07, 0x23, 0xb5, 0xda, 0xea, 0xba, + 0x7f, 0xe0, 0x7a, 0xe5, 0x29, 0x26, 0x0c, 0x5b, 0xfd, 0x26, 0x8f, 0x61, 0x46, 0x3b, 0x1b, 0xd4, + 0xd9, 0xff, 0xf4, 0x88, 0x7a, 0x51, 0x79, 0x1a, 0xdb, 0xf0, 0x7d, 0x75, 0xb8, 0xb9, 0xad, 0x1f, + 0x21, 0x9e, 0xde, 0xbb, 0x5d, 0x8d, 0x7f, 0xd6, 0x24, 0xd1, 0x42, 0xb1, 0x5c, 0xb0, 0xa7, 0x9d, + 0x8c, 0x12, 0xb2, 0x03, 0xc3, 0xdb, 0x9d, 0xa0, 0xed, 0x87, 0xb4, 0x3c, 0x83, 0x82, 0xbb, 0xd1, + 0x6d, 0x86, 0x0a, 0xd4, 0x85, 0x19, 0xb6, 0x44, 0xb7, 0xf9, 0x0f, 0xed, 0xeb, 0x24, 0x2b, 0xf2, + 0x29, 0x8c, 0xd7, 0x6a, 0xab, 0xf1, 0x86, 0x72, 0x01, 0x37, 0x94, 0xcb, 0x27, 0xc7, 0x95, 0x32, + 0x53, 0xa9, 0xe2, 0x4d, 0x45, 0x9f, 0x55, 0x3a, 0x05, 0xe3, 0xb0, 0xb3, 0x5e, 0x8b, 0x39, 0xcc, + 0xc6, 0x1c, 0x98, 0x32, 0x97, 0xcd, 0x41, 0xa7, 0x20, 0xff, 0xa0, 0x00, 0xd7, 0x74, 0x96, 0x59, + 0x82, 0x29, 0x5f, 0x7c, 0x11, 0x69, 0xce, 0x9f, 0x1c, 0x57, 0x6e, 0x9b, 0xdf, 0x51, 0xcf, 0xec, + 0x2c, 0xad, 0x6d, 0x3d, 0x9b, 0x82, 0xed, 0xd5, 0x3f, 0x20, 0xb3, 0xbd, 0x73, 0x2f, 0xdc, 0x5e, + 0x53, 0x6a, 0xbd, 0xdb, 0xdb, 0xab, 0x29, 0xd6, 0xe7, 0x30, 0xaa, 0x16, 0x6d, 0x32, 0x0c, 0xfd, + 0xd5, 0x56, 0xab, 0xd4, 0xc7, 0xfe, 0xa8, 0xd5, 0x56, 0x4b, 0x05, 0x32, 0x09, 0x10, 0xef, 0x54, + 0xa5, 0x22, 0x19, 0x87, 0x11, 0xb9, 0x93, 0x94, 0xfa, 0x11, 0xbf, 0xdd, 0x2e, 0x0d, 0x10, 0x02, + 0x93, 0xe6, 0x7a, 0x56, 0x1a, 0xb4, 0x7e, 0xaf, 0x00, 0xa3, 0x6a, 0x1e, 0x92, 0x73, 0x30, 0xb6, + 0xbb, 0x59, 0xdb, 0x5e, 0x5e, 0x5c, 0xbb, 0xbf, 0xb6, 0xbc, 0x54, 0xea, 0x23, 0x57, 0xe0, 0xe2, + 0x4e, 0x6d, 0xb5, 0xbe, 0xb4, 0x50, 0x5f, 0xdf, 0x5a, 0xac, 0xae, 0xd7, 0xb7, 0xed, 0xad, 0xcf, + 0xbf, 0xa8, 0xef, 0xec, 0x6e, 0x6e, 0x2e, 0xaf, 0x97, 0x0a, 0xa4, 0x0c, 0xd3, 0xac, 0xf8, 0xe1, + 0xee, 0xc2, 0xb2, 0x8e, 0x50, 0x2a, 0x92, 0xeb, 0x70, 0x25, 0xab, 0xa4, 0xbe, 0xba, 0x5c, 0x5d, + 0x5a, 0x5f, 0xae, 0xd5, 0x4a, 0xfd, 0x64, 0x16, 0xa6, 0x18, 0x4a, 0x75, 0x7b, 0xdb, 0xa0, 0x1d, + 0xb0, 0x5a, 0x30, 0xa6, 0x4d, 0x00, 0x72, 0x19, 0xca, 0x8b, 0xcb, 0xf6, 0x4e, 0x7d, 0x7b, 0xd7, + 0xde, 0xde, 0xaa, 0x2d, 0xd7, 0xcd, 0x16, 0x26, 0x4b, 0xd7, 0xb7, 0x56, 0xd6, 0x36, 0xeb, 0x0c, + 0x54, 0x2b, 0x15, 0x58, 0x33, 0x8c, 0xd2, 0xda, 0xda, 0xe6, 0xca, 0xfa, 0x72, 0x7d, 0xb7, 0xb6, + 0x2c, 0x50, 0x8a, 0xd6, 0x6f, 0x15, 0x53, 0x5b, 0x3a, 0x99, 0x87, 0xb1, 0x1a, 0xb7, 0x57, 0xe0, + 0x32, 0xc7, 0x0f, 0x88, 0x4c, 0x47, 0x1b, 0x17, 0x66, 0x0c, 0xbe, 0x82, 0xe9, 0x48, 0x4c, 0x4b, + 0xdb, 0x66, 0xb3, 0xb9, 0xe1, 0xb7, 0x74, 0x2d, 0xad, 0x2d, 0x60, 0xb6, 0x2a, 0x25, 0xf3, 0x9a, + 0x3e, 0xc7, 0x4f, 0x8b, 0x78, 0x22, 0x91, 0xfa, 0x9c, 0xbe, 0xb7, 0x2b, 0xcd, 0x6e, 0x3e, 0xee, + 0x52, 0xa1, 0x86, 0x21, 0x4d, 0x86, 0x2e, 0xa1, 0xf0, 0xc8, 0x1b, 0x52, 0xd3, 0xe5, 0xa7, 0x3b, + 0xdc, 0xec, 0x13, 0xe7, 0x12, 0xa1, 0xe4, 0x5a, 0x9d, 0x9c, 0x8d, 0x95, 0x7c, 0x98, 0x1c, 0x33, + 0x42, 0x18, 0xc8, 0x2c, 0xb1, 0x7f, 0xda, 0x09, 0x54, 0x52, 0x81, 0x41, 0xbe, 0xe2, 0x72, 0x79, + 0xa0, 0x6e, 0xdd, 0x62, 0x00, 0x9b, 0xc3, 0xad, 0xdf, 0xef, 0xd7, 0x95, 0x0c, 0xa6, 0x4b, 0x6b, + 0xf2, 0x46, 0x5d, 0x1a, 0xe5, 0x8c, 0x50, 0x76, 0x14, 0xe4, 0xb3, 0x04, 0x8f, 0x82, 0xfd, 0xf1, + 0x51, 0x50, 0x4c, 0x35, 0x7e, 0x14, 0x8c, 0x51, 0x58, 0x2f, 0x0a, 0xb5, 0x0d, 0xb9, 0x0e, 0xc4, + 0xbd, 0x28, 0x54, 0x3d, 0xd1, 0x8b, 0x1a, 0x12, 0xf9, 0x00, 0xa0, 0xfa, 0xa8, 0x86, 0x67, 0x1e, + 0x7b, 0x53, 0xa8, 0xae, 0xb8, 0xc9, 0x38, 0xcf, 0x42, 0x71, 0xa4, 0x0a, 0xf4, 0x33, 0xa3, 0x86, + 0x4d, 0x16, 0x60, 0xa2, 0xfa, 0xd3, 0x4e, 0x40, 0xd7, 0x9a, 0x6c, 0x9f, 0x8a, 0xf8, 0xe1, 0x78, + 0x94, 0x2f, 0xa4, 0x0e, 0x2b, 0xa8, 0xbb, 0xa2, 0x44, 0x63, 0x60, 0x92, 0x90, 0x2d, 0x38, 0xbf, + 0xb2, 0xb8, 0x2d, 0xc6, 0x55, 0xb5, 0xd1, 0xf0, 0x3b, 0x5e, 0x24, 0xf4, 0xd5, 0xeb, 0x27, 0xc7, + 0x95, 0x2b, 0x07, 0x8d, 0x76, 0x5d, 0x8e, 0x41, 0x87, 0x17, 0xeb, 0x0a, 0x6b, 0x8a, 0x96, 0xdc, + 0x80, 0xfe, 0x5d, 0x7b, 0x4d, 0x9c, 0x9c, 0xcf, 0x9f, 0x1c, 0x57, 0x26, 0x3a, 0x81, 0xab, 0x91, + 0xb0, 0xd2, 0x07, 0x03, 0x23, 0xc5, 0x52, 0xbf, 0x3d, 0x5a, 0xa3, 0x61, 0xc8, 0x0f, 0x79, 0x2d, + 0x98, 0x5c, 0xa1, 0x11, 0x1b, 0x7d, 0xf2, 0xd0, 0xd2, 0xbd, 0x6f, 0x3e, 0x82, 0xb1, 0x47, 0x6e, + 0x74, 0x58, 0xa3, 0x8d, 0x80, 0x46, 0xd2, 0x60, 0x83, 0x72, 0x7b, 0xe6, 0x46, 0x87, 0xf5, 0x90, + 0xc3, 0xf5, 0xcd, 0x59, 0x43, 0xb7, 0x96, 0xe1, 0x9c, 0xa8, 0x4d, 0x9d, 0x91, 0xe6, 0x4d, 0x86, + 0x05, 0x64, 0x88, 0x7d, 0xa7, 0x33, 0x34, 0xd9, 0xfc, 0xe3, 0x22, 0xcc, 0x2c, 0x1e, 0x3a, 0xde, + 0x01, 0xdd, 0x76, 0xc2, 0xf0, 0x99, 0x1f, 0x34, 0xb5, 0xc6, 0xe3, 0x01, 0x31, 0xd5, 0x78, 0x3c, + 0x11, 0xce, 0xc3, 0xd8, 0x56, 0xab, 0x29, 0x69, 0xc4, 0xe1, 0x15, 0xeb, 0xf2, 0x5b, 0xcd, 0x7a, + 0x5b, 0xf2, 0xd2, 0x91, 0x18, 0xcd, 0x26, 0x7d, 0xa6, 0x68, 0xfa, 0x63, 0x1a, 0x8f, 0x3e, 0xd3, + 0x68, 0x34, 0x24, 0xb2, 0x0c, 0xe7, 0x6b, 0xb4, 0xe1, 0x7b, 0xcd, 0xfb, 0x4e, 0x23, 0xf2, 0x83, + 0x1d, 0xff, 0x09, 0xf5, 0xc4, 0xa8, 0x44, 0xed, 0x3e, 0xc4, 0xc2, 0xfa, 0x63, 0x2c, 0xad, 0x47, + 0xac, 0xd8, 0x4e, 0x53, 0x90, 0x2d, 0x18, 0x79, 0x24, 0xcc, 0x7e, 0xe2, 0xc4, 0xfb, 0xea, 0x6d, + 0x65, 0x07, 0x5c, 0x0c, 0x28, 0x0e, 0x25, 0xa7, 0xa5, 0xce, 0xec, 0x4a, 0x59, 0xc2, 0xf5, 0x48, + 0x62, 0xda, 0x8a, 0x89, 0xb5, 0x0b, 0x13, 0xdb, 0xad, 0xce, 0x81, 0xeb, 0xb1, 0x95, 0xa3, 0x46, + 0x7f, 0x42, 0x96, 0x00, 0x62, 0x80, 0x30, 0xe6, 0x4d, 0x89, 0x73, 0x72, 0x5c, 0xb0, 0xf7, 0x96, + 0x98, 0x7e, 0x08, 0xc1, 0x63, 0x8d, 0xad, 0xd1, 0x59, 0xff, 0xad, 0x1f, 0x88, 0xe8, 0x00, 0xdc, + 0xc9, 0x6a, 0x34, 0x62, 0x7b, 0xcc, 0x05, 0x28, 0x2a, 0x9b, 0xdb, 0xd0, 0xc9, 0x71, 0xa5, 0xe8, + 0x36, 0xed, 0xe2, 0xda, 0x12, 0x79, 0x1b, 0x06, 0x11, 0x0d, 0xe5, 0x3f, 0xa9, 0xea, 0xd3, 0x39, + 0xf0, 0x15, 0x04, 0xb7, 0x50, 0x9b, 0x23, 0x93, 0x77, 0x60, 0x74, 0x89, 0xb6, 0xe8, 0x81, 0x13, + 0xf9, 0x72, 0x4d, 0xe0, 0x56, 0x2c, 0x09, 0xd4, 0xc6, 0x5c, 0x8c, 0xc9, 0xce, 0xb4, 0x36, 0x75, + 0x42, 0xdf, 0xd3, 0xcf, 0xb4, 0x01, 0x42, 0xf4, 0x33, 0x2d, 0xc7, 0x21, 0xff, 0x4f, 0x01, 0xc6, + 0xaa, 0x9e, 0x27, 0xac, 0x43, 0xa1, 0x90, 0xfa, 0xcc, 0x6d, 0x65, 0x4e, 0x5d, 0x77, 0xf6, 0x69, + 0x6b, 0xcf, 0x69, 0x75, 0x68, 0xb8, 0xf0, 0x35, 0x3b, 0x66, 0xfc, 0xdb, 0xe3, 0xca, 0x87, 0x67, + 0xb0, 0xf7, 0xc4, 0x86, 0xd9, 0x9d, 0xc0, 0x71, 0xa3, 0xf0, 0xe4, 0xb8, 0x32, 0xe3, 0xc4, 0x15, + 0xea, 0xf3, 0x46, 0x6b, 0x47, 0xbc, 0xc0, 0x0f, 0xf5, 0x5a, 0xe0, 0xc9, 0x11, 0x9c, 0xab, 0x86, + 0x61, 0xe7, 0x88, 0xd6, 0x22, 0x27, 0x88, 0x76, 0xdc, 0x23, 0x8a, 0xab, 0x4a, 0x77, 0x0b, 0xc1, + 0xeb, 0x3f, 0x3b, 0xae, 0x14, 0xd8, 0xc9, 0xc6, 0x41, 0x52, 0xa6, 0xbc, 0x04, 0x51, 0x3d, 0x72, + 0xf5, 0x3d, 0x0a, 0x6d, 0x05, 0x49, 0xde, 0xd6, 0x0d, 0xa5, 0x55, 0xac, 0x2d, 0xe5, 0xf5, 0xb8, + 0xb5, 0x08, 0x97, 0x57, 0x68, 0x64, 0xd3, 0x90, 0x46, 0x72, 0x8e, 0xe0, 0x08, 0x8f, 0x2d, 0xb4, + 0xc3, 0xf8, 0x5b, 0x11, 0x63, 0xf7, 0xf3, 0x79, 0x21, 0x4b, 0xac, 0xff, 0xa5, 0x00, 0x95, 0xc5, + 0x80, 0xf2, 0x43, 0x41, 0x0e, 0xa3, 0xee, 0x6b, 0xd7, 0x65, 0x18, 0xd8, 0x79, 0xde, 0x96, 0xa6, + 0x15, 0x2c, 0x65, 0x9d, 0x62, 0x23, 0xf4, 0x94, 0x96, 0x2a, 0xeb, 0x31, 0xcc, 0xd8, 0xd4, 0xa3, + 0xcf, 0x9c, 0xfd, 0x16, 0x35, 0x8c, 0x3d, 0x15, 0x18, 0xe4, 0x13, 0x3d, 0xf5, 0x09, 0x1c, 0x7e, + 0x36, 0xc3, 0x99, 0x35, 0x01, 0x63, 0xdb, 0xae, 0x77, 0x20, 0xb8, 0x5b, 0x7f, 0x39, 0x00, 0xe3, + 0xfc, 0xb7, 0x38, 0xe7, 0x24, 0xf6, 0xbc, 0xc2, 0x69, 0xf6, 0xbc, 0xf7, 0x60, 0x82, 0x6d, 0x1a, + 0x34, 0xd8, 0xa3, 0x01, 0x5b, 0xff, 0x85, 0x24, 0xf0, 0xcc, 0x16, 0x62, 0x41, 0xfd, 0x29, 0x2f, + 0xb1, 0x4d, 0x44, 0xb2, 0x0e, 0x93, 0x1c, 0x70, 0x9f, 0x3a, 0x51, 0x27, 0x36, 0x3b, 0x9d, 0x13, + 0x07, 0x1b, 0x09, 0xe6, 0x43, 0x53, 0xf0, 0x7a, 0x2c, 0x80, 0x76, 0x82, 0x96, 0x7c, 0x02, 0xe7, + 0xb6, 0x03, 0xff, 0x9b, 0xe7, 0xda, 0x2e, 0xcf, 0x67, 0x27, 0x3f, 0x02, 0xb1, 0xa2, 0xba, 0xbe, + 0xd7, 0x27, 0xb1, 0xc9, 0x1b, 0x30, 0xb2, 0x16, 0x2e, 0xf8, 0x81, 0xeb, 0x1d, 0xe0, 0x1c, 0x1d, + 0xe1, 0xd6, 0x7a, 0x37, 0xac, 0xef, 0x23, 0xd0, 0x56, 0xc5, 0x09, 0xbb, 0xf2, 0x70, 0x6f, 0xbb, + 0xf2, 0x5d, 0x80, 0x75, 0xdf, 0x69, 0x56, 0x5b, 0xad, 0xc5, 0x6a, 0x88, 0xdb, 0xa9, 0xd8, 0x8f, + 0x5a, 0xbe, 0xd3, 0xac, 0x3b, 0xad, 0x56, 0xbd, 0xe1, 0x84, 0xb6, 0x86, 0x43, 0xbe, 0x84, 0x8b, + 0xa1, 0x7b, 0xe0, 0xe1, 0xc7, 0xd5, 0x9d, 0xd6, 0x81, 0x1f, 0xb8, 0xd1, 0xe1, 0x51, 0x3d, 0xec, + 0xb8, 0x11, 0x37, 0xea, 0x4c, 0xce, 0x5f, 0x15, 0x8b, 0x5c, 0x4d, 0xe2, 0x55, 0x25, 0x5a, 0x8d, + 0x61, 0xd9, 0xb3, 0x61, 0x76, 0x01, 0x79, 0x04, 0x13, 0xeb, 0x6e, 0x83, 0x7a, 0x21, 0x45, 0x2b, + 0xdd, 0x73, 0x34, 0xf9, 0x74, 0x9f, 0xcc, 0x4c, 0x88, 0x13, 0x2d, 0x9d, 0x08, 0xa7, 0xae, 0xc9, + 0xe7, 0xc1, 0xc0, 0xc8, 0x50, 0x69, 0xd8, 0x3e, 0x27, 0x80, 0x8f, 0x9c, 0xc0, 0x73, 0xbd, 0x83, + 0xd0, 0xfa, 0x87, 0xe7, 0x61, 0x44, 0xf5, 0xd3, 0x6d, 0xfd, 0xb8, 0x21, 0xb6, 0x66, 0x1c, 0xb2, + 0xb1, 0x31, 0xcd, 0xd6, 0x30, 0xc8, 0x45, 0x3c, 0x80, 0x08, 0xa5, 0x60, 0x98, 0x4d, 0x21, 0xa7, + 0xdd, 0xb6, 0x19, 0x8c, 0x2d, 0x0d, 0x4b, 0x0b, 0x38, 0x68, 0x46, 0xf8, 0xd2, 0xd0, 0xdc, 0xb7, + 0x8b, 0x4b, 0x0b, 0x6c, 0x4e, 0x6e, 0xad, 0x2d, 0x2d, 0x62, 0xff, 0x8f, 0xf0, 0x39, 0xe9, 0xbb, + 0xcd, 0x86, 0x8d, 0x50, 0x56, 0x5a, 0xab, 0x6e, 0xac, 0x8b, 0x3e, 0xc6, 0xd2, 0xd0, 0x39, 0x6a, + 0xd9, 0x08, 0x65, 0x2a, 0x2b, 0xb7, 0x8b, 0x2c, 0xfa, 0x5e, 0x14, 0xf8, 0xad, 0x10, 0xf5, 0xb0, + 0x11, 0x3e, 0x06, 0x85, 0x41, 0xa5, 0x21, 0x8a, 0xec, 0x04, 0x2a, 0x79, 0x04, 0xb3, 0xd5, 0xe6, + 0x53, 0xc7, 0x6b, 0xd0, 0x26, 0x2f, 0x79, 0xe4, 0x07, 0x4f, 0x1e, 0xb7, 0xfc, 0x67, 0x21, 0x0e, + 0x92, 0x11, 0x61, 0x7f, 0x14, 0x28, 0xd2, 0x3e, 0xf3, 0x4c, 0x22, 0xd9, 0x79, 0xd4, 0x6c, 0x1d, + 0x58, 0x6c, 0xf9, 0x9d, 0xa6, 0x18, 0x3a, 0xb8, 0x0e, 0x34, 0x18, 0xc0, 0xe6, 0x70, 0x26, 0xa5, + 0xd5, 0xda, 0x06, 0x0e, 0x0c, 0x21, 0xa5, 0xc3, 0xf0, 0xc8, 0x66, 0x30, 0xf2, 0x2a, 0x0c, 0x4b, + 0xed, 0x9b, 0x5f, 0x47, 0xa0, 0x19, 0x5c, 0x6a, 0xdd, 0xb2, 0x8c, 0xcd, 0x63, 0x9b, 0x36, 0xfc, + 0xa7, 0x34, 0x78, 0xbe, 0xe8, 0x37, 0xa9, 0xb4, 0x4d, 0x09, 0xdb, 0x0b, 0x2f, 0xa8, 0x37, 0x58, + 0x89, 0x6d, 0x22, 0xb2, 0x0a, 0xf8, 0xc6, 0x1d, 0x96, 0xcf, 0xc5, 0x15, 0xf0, 0x8d, 0x3d, 0xb4, + 0x65, 0x19, 0x59, 0x82, 0xf3, 0xd5, 0x4e, 0xe4, 0x1f, 0x39, 0x91, 0xdb, 0xd8, 0x6d, 0x1f, 0x04, + 0x0e, 0xab, 0xa4, 0x84, 0x04, 0x78, 0x1a, 0x71, 0x64, 0x61, 0xbd, 0x23, 0x4a, 0xed, 0x34, 0x01, + 0x79, 0x17, 0xc6, 0xd7, 0x42, 0x6e, 0x7f, 0x74, 0x42, 0xda, 0x44, 0x23, 0x92, 0x68, 0xa5, 0x1b, + 0xd6, 0xd1, 0x1a, 0x59, 0x67, 0xe7, 0x97, 0xa6, 0x6d, 0xe0, 0x11, 0x0b, 0x86, 0xaa, 0x61, 0xe8, + 0x86, 0x11, 0xda, 0x86, 0x46, 0x16, 0xe0, 0xe4, 0xb8, 0x32, 0xe4, 0x20, 0xc4, 0x16, 0x25, 0xe4, + 0x11, 0x8c, 0x2d, 0x51, 0xa6, 0xfe, 0xee, 0x04, 0x9d, 0x30, 0x42, 0x4b, 0xcf, 0xd8, 0xfc, 0x45, + 0xb1, 0x1a, 0x69, 0x25, 0x62, 0x2c, 0x73, 0x15, 0xb5, 0x89, 0xf0, 0x7a, 0xc4, 0x0a, 0xf4, 0xad, + 0x56, 0xc3, 0x67, 0xba, 0xbd, 0xa0, 0x59, 0x75, 0x9b, 0x6c, 0x7d, 0x99, 0xc6, 0x36, 0xa0, 0x6e, + 0x2f, 0x16, 0xb4, 0xfa, 0x21, 0x96, 0xe8, 0xba, 0xbd, 0x41, 0x42, 0x1a, 0x29, 0x93, 0xf6, 0x8c, + 0x61, 0xb6, 0x34, 0x0b, 0x65, 0x13, 0xcf, 0x68, 0xf0, 0xfe, 0x08, 0xc6, 0x16, 0x3b, 0x61, 0xe4, + 0x1f, 0xed, 0x1c, 0xd2, 0x23, 0x8a, 0xd6, 0x20, 0x71, 0x82, 0x69, 0x20, 0xb8, 0x1e, 0x31, 0xb8, + 0xfe, 0x99, 0x1a, 0x3a, 0xf9, 0x0c, 0x88, 0x3c, 0x8a, 0xac, 0xb0, 0xf1, 0xe1, 0xb1, 0xb1, 0x8c, + 0x06, 0xa1, 0x11, 0x7e, 0xfe, 0x90, 0x27, 0x98, 0xfa, 0x81, 0x2a, 0xd6, 0x8d, 0x92, 0x69, 0x62, + 0xd6, 0x20, 0xde, 0xc4, 0x95, 0xc0, 0x69, 0x1f, 0x96, 0xcb, 0xf1, 0xd1, 0x40, 0x7c, 0xd4, 0x01, + 0x83, 0x1b, 0x2a, 0x4e, 0x8c, 0x4e, 0x6a, 0x00, 0xfc, 0xe7, 0x3a, 0xeb, 0x78, 0x6e, 0x42, 0x2a, + 0x1b, 0xf2, 0x62, 0x05, 0x52, 0x56, 0x17, 0x51, 0x71, 0xe2, 0x6c, 0x5b, 0xae, 0xd1, 0x9b, 0x1a, + 0x1b, 0xf2, 0x04, 0x4a, 0xfc, 0xd7, 0x86, 0xef, 0xb9, 0x11, 0xdf, 0x2f, 0xe6, 0x0c, 0x7b, 0x63, + 0xb2, 0x58, 0x56, 0x80, 0x76, 0x5e, 0x51, 0xc1, 0x91, 0x2a, 0xd5, 0xaa, 0x49, 0x31, 0x26, 0xdb, + 0x30, 0xb6, 0x1d, 0xf8, 0xcd, 0x4e, 0x23, 0x42, 0x2d, 0xe3, 0x12, 0x2e, 0xfc, 0x44, 0xd4, 0xa3, + 0x95, 0x70, 0x99, 0xb4, 0x39, 0xa0, 0xce, 0xf6, 0x05, 0x5d, 0x26, 0x1a, 0x22, 0x59, 0x80, 0xa1, + 0x6d, 0xbf, 0xe5, 0x36, 0x9e, 0x97, 0x2f, 0x63, 0xa3, 0xa7, 0x25, 0x33, 0x04, 0xca, 0xa6, 0xa2, + 0x4a, 0xdb, 0x46, 0x90, 0xae, 0xd2, 0x72, 0x24, 0x52, 0x85, 0x89, 0xcf, 0xd8, 0x80, 0x71, 0x7d, + 0xcf, 0x73, 0xdc, 0x80, 0x96, 0xaf, 0x60, 0xbf, 0xa0, 0x2d, 0xfe, 0x27, 0x7a, 0x81, 0x3e, 0x9c, + 0x0d, 0x0a, 0xb2, 0x06, 0xe7, 0xd6, 0xc2, 0x5a, 0x14, 0xb8, 0x6d, 0xba, 0xe1, 0x78, 0xce, 0x01, + 0x6d, 0x96, 0xaf, 0xc6, 0xc6, 0x70, 0x37, 0xac, 0x87, 0x58, 0x56, 0x3f, 0xe2, 0x85, 0xba, 0x31, + 0x3c, 0x41, 0x47, 0x3e, 0x87, 0xe9, 0xe5, 0x6f, 0x22, 0x36, 0x62, 0x5a, 0xd5, 0x4e, 0xd3, 0x8d, + 0x6a, 0x91, 0x1f, 0x38, 0x07, 0xb4, 0x5c, 0x41, 0x7e, 0xaf, 0x9c, 0x1c, 0x57, 0xae, 0x51, 0x51, + 0x5e, 0x77, 0x18, 0x42, 0x3d, 0xe4, 0x18, 0xfa, 0x25, 0x77, 0x16, 0x07, 0x26, 0xfd, 0x5a, 0xa7, + 0xcd, 0xb4, 0x6d, 0x94, 0xfe, 0x35, 0x43, 0xfa, 0x5a, 0x09, 0x97, 0x7e, 0xc8, 0x01, 0x29, 0xe9, + 0x6b, 0x88, 0xc4, 0x06, 0xf2, 0xc0, 0x77, 0xbd, 0x6a, 0x23, 0x72, 0x9f, 0x52, 0x71, 0x62, 0x0e, + 0xcb, 0xd7, 0xb1, 0xa5, 0x68, 0xb8, 0xff, 0x55, 0xdf, 0xf5, 0xea, 0x0e, 0x16, 0xd7, 0x43, 0x51, + 0xae, 0xcf, 0x91, 0x34, 0x35, 0xf9, 0x11, 0x5c, 0xd8, 0xf0, 0xf7, 0xdd, 0x16, 0xe5, 0x4b, 0x0e, + 0x17, 0x0b, 0x1a, 0x21, 0x2d, 0xe4, 0x8b, 0x86, 0xfb, 0x23, 0xc4, 0xa8, 0x8b, 0xd5, 0xea, 0x48, + 0xe1, 0xe8, 0x86, 0xfb, 0x6c, 0x2e, 0x64, 0x19, 0xc6, 0x71, 0x5e, 0xb6, 0xf0, 0x67, 0x58, 0xbe, + 0x81, 0x47, 0xba, 0xeb, 0x09, 0x2d, 0xed, 0xf6, 0xb2, 0x86, 0xb3, 0xec, 0x45, 0xc1, 0x73, 0xdb, + 0x20, 0x23, 0x1f, 0xc3, 0x5c, 0x72, 0x78, 0x2f, 0xfa, 0xde, 0x63, 0xf7, 0xa0, 0x13, 0xd0, 0x66, + 0xf9, 0x15, 0xd6, 0x54, 0xbb, 0x0b, 0xc6, 0xdc, 0x23, 0x38, 0x9f, 0xaa, 0x82, 0x94, 0xa0, 0xff, + 0x89, 0xb8, 0x07, 0x1d, 0xb5, 0xd9, 0x9f, 0xe4, 0x4d, 0x18, 0x7c, 0xca, 0xce, 0x52, 0xa8, 0x31, + 0xc4, 0x37, 0x6b, 0x1a, 0xe9, 0x9a, 0xf7, 0xd8, 0xb7, 0x39, 0xd2, 0x07, 0xc5, 0xf7, 0x0a, 0x0f, + 0x06, 0x46, 0xc6, 0x4a, 0xe3, 0xfc, 0xfa, 0xfa, 0xc1, 0xc0, 0xc8, 0x44, 0x69, 0xd2, 0xaa, 0xc2, + 0xb9, 0x04, 0x3e, 0x29, 0xc3, 0x30, 0xf5, 0x98, 0x7e, 0xde, 0xe4, 0x3a, 0x8b, 0x2d, 0x7f, 0x92, + 0x69, 0x18, 0x6c, 0xb9, 0x47, 0x6e, 0x84, 0x15, 0x0e, 0xda, 0xfc, 0x87, 0xf5, 0x07, 0x05, 0x20, + 0xe9, 0x2d, 0x83, 0xdc, 0x49, 0xb0, 0xe1, 0xda, 0xa9, 0x00, 0xe9, 0x06, 0x7a, 0xc9, 0xfd, 0x33, + 0x98, 0xe2, 0x7d, 0x26, 0x37, 0x37, 0xad, 0x2e, 0xbe, 0xa8, 0x66, 0x14, 0xeb, 0x46, 0x1d, 0x51, + 0x8c, 0x5b, 0xe1, 0x3a, 0x36, 0xad, 0x03, 0x33, 0x99, 0x9b, 0x05, 0xd9, 0x80, 0x99, 0x23, 0xdf, + 0x8b, 0x0e, 0x5b, 0xcf, 0xe5, 0x5e, 0x21, 0x6a, 0x2b, 0x60, 0x6d, 0xb8, 0x3e, 0x66, 0x22, 0xd8, + 0x53, 0x02, 0x2c, 0x38, 0x62, 0x3d, 0xc2, 0x2e, 0x24, 0xbf, 0xc4, 0xb2, 0xe1, 0x7c, 0x6a, 0xcd, + 0x25, 0x3f, 0x84, 0xf1, 0x06, 0x9e, 0xbf, 0x8c, 0x9a, 0xf8, 0x8e, 0xa3, 0xc1, 0xf5, 0xe9, 0xc4, + 0xe1, 0xfc, 0x53, 0xfe, 0x6e, 0x01, 0x66, 0x73, 0x56, 0xdb, 0xb3, 0x8b, 0xfa, 0x0b, 0xb8, 0x70, + 0xe4, 0x7c, 0x53, 0x0f, 0xf0, 0x78, 0x5d, 0x0f, 0x1c, 0x2f, 0x21, 0x6d, 0x5c, 0x49, 0xb2, 0x31, + 0x74, 0x1f, 0xa2, 0x23, 0xe7, 0x1b, 0x1b, 0x11, 0x6c, 0x56, 0xce, 0xdb, 0xf9, 0x29, 0x4c, 0x18, + 0xeb, 0xeb, 0x99, 0x1b, 0x67, 0xdd, 0x83, 0xf3, 0x4b, 0xb4, 0x45, 0x23, 0x7a, 0x6a, 0xb3, 0x9a, + 0xb5, 0x0d, 0x50, 0xa3, 0x47, 0x4e, 0xfb, 0xd0, 0x67, 0x7a, 0xf7, 0x82, 0xfe, 0x4b, 0x98, 0x65, + 0x88, 0x3c, 0x41, 0xc8, 0x82, 0xbd, 0xb7, 0xb8, 0x2e, 0x1e, 0x2a, 0x4c, 0x5b, 0xa3, 0xb2, 0xfe, + 0x65, 0x11, 0x88, 0x58, 0x20, 0x03, 0xea, 0x1c, 0xc9, 0x66, 0xbc, 0x0f, 0xe3, 0xfc, 0x10, 0xcd, + 0xc1, 0xd8, 0x9c, 0xb1, 0xf9, 0x29, 0x31, 0xf3, 0xf4, 0xa2, 0xd5, 0x3e, 0xdb, 0x40, 0x65, 0xa4, + 0x36, 0xe5, 0xa7, 0x7f, 0x24, 0x2d, 0x1a, 0xa4, 0x7a, 0x11, 0x23, 0xd5, 0x7f, 0x93, 0x4f, 0x60, + 0x72, 0xd1, 0x3f, 0x6a, 0x33, 0x99, 0x08, 0xe2, 0x7e, 0x61, 0x59, 0x11, 0xf5, 0x1a, 0x85, 0xab, + 0x7d, 0x76, 0x02, 0x9d, 0x6c, 0xc2, 0xd4, 0xfd, 0x56, 0x27, 0x3c, 0xac, 0x7a, 0xcd, 0xc5, 0x96, + 0x1f, 0x4a, 0x2e, 0x03, 0xe2, 0x30, 0x24, 0x96, 0xb7, 0x34, 0xc6, 0x6a, 0x9f, 0x9d, 0x45, 0x48, + 0x5e, 0x85, 0xc1, 0xe5, 0xa7, 0x6c, 0xd9, 0x95, 0x9e, 0x24, 0xc2, 0xd1, 0x6d, 0xcb, 0xa3, 0x5b, + 0x8f, 0x57, 0xfb, 0x6c, 0x5e, 0xba, 0x30, 0x0a, 0xc3, 0xf2, 0x00, 0x7e, 0x87, 0xa9, 0xc4, 0x4a, + 0x9c, 0xb5, 0xc8, 0x89, 0x3a, 0x21, 0x99, 0x83, 0x91, 0xdd, 0x36, 0x3b, 0x17, 0x4a, 0xcb, 0x85, + 0xad, 0x7e, 0x5b, 0x6f, 0x9a, 0x92, 0x26, 0x97, 0x21, 0x36, 0xbb, 0x0a, 0x64, 0xcd, 0x0e, 0xbb, + 0x6a, 0x0a, 0xb7, 0x3b, 0xb6, 0x51, 0x6f, 0x31, 0x51, 0x6f, 0x29, 0x29, 0x6b, 0x6b, 0x26, 0x53, + 0x78, 0xd6, 0xe7, 0x70, 0x75, 0xb7, 0x1d, 0xd2, 0x20, 0xaa, 0xb6, 0xdb, 0x2d, 0xb7, 0xc1, 0x6f, + 0xa2, 0xf0, 0xa0, 0x2e, 0x07, 0xcb, 0xbb, 0x30, 0xc4, 0x01, 0x62, 0x98, 0xc8, 0x31, 0x58, 0x6d, + 0xb7, 0x85, 0x79, 0xe0, 0x2d, 0xae, 0x9c, 0xf3, 0x03, 0xbf, 0x2d, 0xb0, 0xad, 0xdf, 0x2d, 0xc0, + 0x55, 0x3e, 0x03, 0x72, 0x59, 0x7f, 0x0f, 0x46, 0xd1, 0xcf, 0xac, 0xed, 0x34, 0xe4, 0x9c, 0xe0, + 0x0e, 0x77, 0x12, 0x68, 0xc7, 0xe5, 0x9a, 0x07, 0x5f, 0x31, 0xdf, 0x83, 0x4f, 0x4e, 0xb0, 0xfe, + 0xcc, 0x09, 0xf6, 0x19, 0x58, 0xa2, 0x45, 0xad, 0x56, 0xaa, 0x51, 0xe1, 0x8b, 0xb4, 0xca, 0xfa, + 0x4f, 0x45, 0x98, 0x5d, 0xa1, 0x1e, 0x0d, 0x1c, 0xfc, 0x4e, 0xc3, 0x10, 0xa5, 0x7b, 0xf2, 0x14, + 0xba, 0x7a, 0xf2, 0x54, 0xa4, 0x69, 0xaf, 0x88, 0xa6, 0xbd, 0x94, 0x5b, 0x12, 0x3b, 0x2e, 0xee, + 0xda, 0x6b, 0xe2, 0xb3, 0xf0, 0xb8, 0xd8, 0x09, 0x5c, 0xb4, 0xe6, 0x93, 0xb5, 0xd8, 0x0b, 0x68, + 0xa0, 0xa7, 0x59, 0x60, 0x4a, 0x78, 0x45, 0x0c, 0x0b, 0x2f, 0x20, 0xd3, 0xf7, 0x67, 0x13, 0x86, + 0xb8, 0x45, 0x12, 0xef, 0x90, 0xc6, 0xe6, 0x6f, 0x89, 0x39, 0x95, 0xf3, 0x81, 0xc2, 0x7c, 0x89, + 0x1b, 0x3b, 0x1f, 0x02, 0x11, 0x02, 0x6c, 0xc1, 0x65, 0xee, 0x33, 0x18, 0xd3, 0x50, 0x4e, 0xb3, + 0xf7, 0x2b, 0xcb, 0x28, 0xd3, 0x18, 0xbd, 0x03, 0x6e, 0x64, 0xd5, 0xf6, 0x7e, 0xeb, 0x43, 0x28, + 0xa7, 0x5b, 0x23, 0xac, 0x61, 0xbd, 0x8c, 0x6f, 0xd6, 0x12, 0x4c, 0xaf, 0xd0, 0x08, 0x07, 0x2e, + 0x4e, 0x22, 0xcd, 0x9b, 0x2d, 0x31, 0xcf, 0xe4, 0xaa, 0x8a, 0x40, 0x36, 0xc0, 0xb4, 0x59, 0x5a, + 0x83, 0x99, 0x04, 0x17, 0x51, 0xff, 0x07, 0x30, 0x2c, 0x40, 0x6a, 0x45, 0x15, 0x2e, 0xb1, 0x74, + 0x5f, 0x14, 0xec, 0xcd, 0xf3, 0x71, 0x2b, 0x38, 0xdb, 0x92, 0xc0, 0x3a, 0x84, 0x0b, 0x6c, 0x9b, + 0x8d, 0xb9, 0xaa, 0xe1, 0x78, 0x09, 0x46, 0xdb, 0x4c, 0x51, 0x08, 0xdd, 0x9f, 0xf2, 0x61, 0x34, + 0x68, 0x8f, 0x30, 0x40, 0xcd, 0xfd, 0x29, 0x25, 0x57, 0x00, 0xb0, 0x10, 0x3f, 0x53, 0xac, 0x02, + 0x88, 0xce, 0xad, 0x8d, 0x04, 0xd0, 0x17, 0x8e, 0x8f, 0x1b, 0x1b, 0xff, 0xb6, 0x02, 0x98, 0x4d, + 0xd5, 0x24, 0x3e, 0xe0, 0x0e, 0x8c, 0x48, 0x15, 0x36, 0x71, 0x0f, 0xa0, 0x7f, 0x81, 0xad, 0x90, + 0xc8, 0x6b, 0x70, 0xce, 0xa3, 0xdf, 0x44, 0xf5, 0x54, 0x1b, 0x26, 0x18, 0x78, 0x5b, 0xb6, 0xc3, + 0xfa, 0x15, 0xb4, 0xfd, 0xd6, 0x3c, 0xff, 0xd9, 0xe3, 0x96, 0xf3, 0x84, 0xa6, 0x2a, 0xfe, 0x21, + 0x8c, 0xd4, 0x7a, 0x57, 0xcc, 0xa7, 0x8f, 0xac, 0xdc, 0x56, 0x24, 0x56, 0x0b, 0xe6, 0xd8, 0x27, + 0xd5, 0xaa, 0x1b, 0xeb, 0x6b, 0xcd, 0xed, 0xef, 0x5a, 0x80, 0x4f, 0xe1, 0x52, 0x66, 0x6d, 0xdf, + 0xb5, 0x10, 0xff, 0x78, 0x00, 0x66, 0xf9, 0x66, 0x92, 0x1e, 0xc1, 0xa7, 0x5f, 0x6a, 0x7e, 0x29, + 0xf7, 0xaa, 0x77, 0x33, 0xee, 0x55, 0x91, 0x44, 0xbf, 0x57, 0x35, 0x6e, 0x53, 0xdf, 0xcb, 0xbe, + 0x4d, 0x45, 0x3b, 0x91, 0x79, 0x9b, 0x9a, 0xbc, 0x43, 0x5d, 0xce, 0xbf, 0x43, 0xc5, 0xbb, 0xa1, + 0x8c, 0x3b, 0xd4, 0xac, 0x9b, 0xd3, 0x84, 0x43, 0xd2, 0xc8, 0xcb, 0x75, 0x48, 0x7a, 0x0d, 0x86, + 0xab, 0xed, 0xb6, 0xe6, 0xe0, 0x87, 0xdd, 0xe3, 0xb4, 0xdb, 0x5c, 0x78, 0xb2, 0x50, 0xae, 0xf3, + 0x90, 0xb1, 0xce, 0xbf, 0x0f, 0xb0, 0x88, 0xcf, 0x10, 0xb0, 0xe3, 0xc6, 0x10, 0x03, 0x35, 0x7c, + 0xfe, 0x38, 0x01, 0x3b, 0x4e, 0xb7, 0x80, 0xc4, 0xc8, 0x5c, 0xb1, 0xb7, 0xf6, 0xa0, 0x9c, 0x1e, + 0x3e, 0x2f, 0x61, 0xe9, 0xfa, 0xa3, 0x02, 0x5c, 0x11, 0x4a, 0x4e, 0x62, 0x82, 0x9f, 0x7d, 0x74, + 0xbe, 0x03, 0xe3, 0x82, 0x76, 0x27, 0x9e, 0x08, 0xfc, 0x22, 0x5b, 0x2e, 0xc6, 0x7c, 0x45, 0x37, + 0xd0, 0xc8, 0x3b, 0x30, 0x82, 0x7f, 0xc4, 0x77, 0x37, 0x4c, 0x32, 0xa3, 0x88, 0x5a, 0x4f, 0xde, + 0xe0, 0x28, 0x54, 0xeb, 0x6b, 0xb8, 0x9a, 0xd7, 0xf0, 0x97, 0x20, 0x97, 0x7f, 0x56, 0x80, 0x4b, + 0x82, 0xbd, 0xb1, 0x54, 0xbc, 0xd0, 0xae, 0x73, 0x06, 0xb7, 0xe0, 0x07, 0x30, 0xc6, 0x2a, 0x94, + 0xed, 0xee, 0x17, 0x5b, 0xab, 0x38, 0x39, 0xc4, 0x25, 0x4b, 0x4e, 0xe4, 0x08, 0x37, 0x17, 0xe7, + 0xa8, 0x25, 0x8d, 0x17, 0xb6, 0x4e, 0x6c, 0x7d, 0x09, 0x97, 0xb3, 0x3f, 0xe1, 0x25, 0xc8, 0xe7, + 0x01, 0xcc, 0x65, 0x6c, 0x0a, 0x2f, 0xb6, 0x27, 0x7f, 0x01, 0x97, 0x32, 0x79, 0xbd, 0x84, 0x66, + 0xae, 0x32, 0x8d, 0x23, 0x7a, 0x09, 0x5d, 0x68, 0x3d, 0x82, 0x8b, 0x19, 0x9c, 0x5e, 0x42, 0x13, + 0x57, 0x60, 0x56, 0x69, 0xda, 0xdf, 0xaa, 0x85, 0x1b, 0x70, 0x85, 0x33, 0x7a, 0x39, 0xbd, 0xf2, + 0x10, 0x2e, 0x09, 0x76, 0x2f, 0x41, 0x7a, 0xab, 0x70, 0x39, 0x3e, 0x50, 0x67, 0xe8, 0x49, 0xa7, + 0x5e, 0x64, 0xac, 0x75, 0xb8, 0x16, 0x73, 0xca, 0x51, 0x1a, 0x4e, 0xcf, 0x8d, 0xab, 0x83, 0x71, + 0x2f, 0xbd, 0x94, 0x1e, 0x7d, 0x04, 0x17, 0x0c, 0xa6, 0x2f, 0x4d, 0x55, 0x5a, 0x83, 0x29, 0xce, + 0xd8, 0x54, 0x9d, 0xe7, 0x75, 0xd5, 0x79, 0x6c, 0xfe, 0x7c, 0xcc, 0x12, 0xc1, 0x7b, 0x6f, 0x65, + 0x68, 0xd3, 0x1b, 0xa8, 0x4d, 0x4b, 0x94, 0xb8, 0x85, 0xef, 0xc0, 0x10, 0x87, 0x88, 0xf6, 0x65, + 0x30, 0xe3, 0x87, 0x05, 0x4e, 0x26, 0x90, 0xad, 0x1f, 0xc1, 0x15, 0x7e, 0x12, 0x8d, 0xef, 0x12, + 0xcd, 0xd3, 0xe2, 0x0f, 0x13, 0x07, 0xd1, 0x8b, 0x82, 0x6f, 0x12, 0x3f, 0xe7, 0x3c, 0xba, 0x2f, + 0xc7, 0x76, 0x1e, 0xff, 0x53, 0x3d, 0x11, 0x93, 0x07, 0xcc, 0x62, 0xe6, 0x01, 0xf3, 0x06, 0x5c, + 0x57, 0x07, 0xcc, 0x64, 0x35, 0x72, 0x68, 0x59, 0x5f, 0xc2, 0x25, 0xfe, 0xa1, 0xd2, 0x75, 0xcf, + 0x6c, 0xc6, 0x87, 0x89, 0xcf, 0x9c, 0x15, 0x9f, 0x69, 0x62, 0xe7, 0x7c, 0xe4, 0xff, 0x51, 0x90, + 0x53, 0x2e, 0x9b, 0xf9, 0x2f, 0xfb, 0xc4, 0xbd, 0x09, 0x15, 0x25, 0x10, 0xb3, 0x45, 0x2f, 0x76, + 0xdc, 0xde, 0x80, 0x19, 0x9d, 0x8d, 0xdb, 0xa0, 0x7b, 0xf7, 0xf0, 0x92, 0xe7, 0x6d, 0x36, 0x2d, + 0x10, 0x20, 0x87, 0x5d, 0x39, 0x43, 0x6e, 0x88, 0x6f, 0x2b, 0x4c, 0xab, 0x0e, 0x97, 0xd3, 0x5d, + 0xe1, 0x36, 0xa4, 0xdf, 0x3e, 0xf9, 0x84, 0x4d, 0x61, 0x84, 0x88, 0xce, 0xc8, 0x65, 0x2a, 0xe7, + 0x31, 0x27, 0x97, 0x54, 0x96, 0x25, 0x97, 0x9a, 0xc4, 0xf7, 0xb3, 0xda, 0xe5, 0x78, 0xf8, 0x75, + 0x20, 0xb2, 0x68, 0xb1, 0x66, 0xcb, 0xaa, 0x2f, 0x42, 0xff, 0x62, 0xcd, 0x16, 0x0f, 0x86, 0x50, + 0x13, 0x6c, 0x84, 0x81, 0xcd, 0x60, 0x49, 0x8d, 0xbc, 0x78, 0x0a, 0x8d, 0xfc, 0xc1, 0xc0, 0x48, + 0x7f, 0x69, 0xc0, 0x26, 0x35, 0xf7, 0xc0, 0x7b, 0xe4, 0x46, 0x87, 0xaa, 0xc2, 0xaa, 0xf5, 0x15, + 0x4c, 0x19, 0xd5, 0x8b, 0x59, 0xdc, 0xf5, 0xa5, 0x13, 0xd3, 0x67, 0x17, 0xab, 0xe8, 0xf9, 0x82, + 0x26, 0x8b, 0x71, 0xbe, 0xde, 0x34, 0x9c, 0x3a, 0x3e, 0xa3, 0xb5, 0x65, 0xa1, 0xf5, 0x77, 0x06, + 0x34, 0xee, 0xda, 0xfb, 0xb1, 0x2e, 0x5f, 0x77, 0x0f, 0x80, 0x8f, 0x10, 0xed, 0xe3, 0x98, 0x02, + 0x38, 0x26, 0x1c, 0x4a, 0xf8, 0x92, 0x6c, 0x6b, 0x48, 0xa7, 0x7d, 0x5f, 0x26, 0xfc, 0x7c, 0x39, + 0x91, 0x7c, 0x52, 0xa9, 0xfc, 0x7c, 0x05, 0xeb, 0xd0, 0xd6, 0x91, 0xc8, 0x8f, 0x92, 0x8f, 0x20, + 0x06, 0xf1, 0x4e, 0xe9, 0x15, 0x79, 0xc9, 0x9c, 0xfe, 0xb6, 0xb3, 0xbd, 0x83, 0x78, 0x06, 0x33, + 0x8c, 0xd6, 0x7d, 0x8c, 0x07, 0x8b, 0xe5, 0x6f, 0x22, 0xea, 0xf1, 0xb5, 0x7d, 0x08, 0xeb, 0x79, + 0xb5, 0x4b, 0x3d, 0x31, 0xb2, 0xb0, 0xbf, 0xc7, 0x7c, 0xea, 0x54, 0x95, 0xd9, 0xd9, 0xfc, 0x71, + 0x10, 0xd9, 0xeb, 0xcb, 0x5e, 0xb3, 0xed, 0xbb, 0xea, 0xc0, 0xc4, 0x07, 0x51, 0xd0, 0xaa, 0x53, + 0x01, 0xb7, 0x75, 0x24, 0xeb, 0xb5, 0xae, 0xde, 0xe3, 0x23, 0x30, 0xb0, 0xb3, 0xb8, 0xb3, 0x5e, + 0x2a, 0x58, 0x77, 0x00, 0xb4, 0x9a, 0x00, 0x86, 0x36, 0xb7, 0xec, 0x8d, 0xea, 0x7a, 0xa9, 0x8f, + 0xcc, 0xc0, 0xf9, 0x47, 0x6b, 0x9b, 0x4b, 0x5b, 0x8f, 0x6a, 0xf5, 0xda, 0x46, 0xd5, 0xde, 0x59, + 0xac, 0xda, 0x4b, 0xa5, 0x82, 0xf5, 0x35, 0x4c, 0x9b, 0x5f, 0xf8, 0x52, 0x07, 0x61, 0x04, 0x53, + 0x4a, 0x9f, 0x79, 0xf0, 0x68, 0x47, 0x73, 0x3a, 0x15, 0x87, 0xbf, 0xa4, 0xf3, 0x94, 0x38, 0x26, + 0x8a, 0x69, 0xa4, 0x21, 0x91, 0x37, 0xb8, 0x5a, 0x90, 0x7c, 0x21, 0xcc, 0xd4, 0x82, 0x7a, 0xac, + 0x17, 0xe0, 0xd2, 0xf7, 0x03, 0x98, 0x36, 0x6b, 0x3d, 0xad, 0x95, 0xea, 0x15, 0xf4, 0xc6, 0xd5, + 0x9e, 0x0f, 0x11, 0xa2, 0x5f, 0x1b, 0x88, 0x95, 0xf5, 0x07, 0x50, 0x12, 0x58, 0xf1, 0xce, 0x7b, + 0x43, 0x9a, 0x11, 0x0b, 0x19, 0x8f, 0x1d, 0xa5, 0xf3, 0xb7, 0x0f, 0x25, 0xb6, 0x62, 0x0a, 0x4a, + 0x5e, 0xc1, 0x34, 0x0c, 0xae, 0xc7, 0xd7, 0x39, 0x36, 0xff, 0x81, 0xaf, 0x68, 0x22, 0x27, 0x88, + 0xa4, 0xab, 0xda, 0xa8, 0xad, 0x7e, 0x93, 0x37, 0x60, 0xe8, 0xbe, 0xdb, 0x8a, 0x84, 0x69, 0x24, + 0xde, 0xe4, 0x19, 0x5b, 0x5e, 0x60, 0x0b, 0x04, 0xcb, 0x86, 0xf3, 0x5a, 0x85, 0x67, 0x68, 0x2a, + 0x29, 0xc3, 0xf0, 0x26, 0xfd, 0x46, 0xab, 0x5f, 0xfe, 0xb4, 0xde, 0x85, 0xf3, 0xc2, 0x0d, 0x50, + 0x13, 0xd3, 0x75, 0xf1, 0x26, 0xbb, 0x60, 0x3c, 0x0c, 0x15, 0x2c, 0xb1, 0x88, 0xd1, 0xed, 0xb6, + 0x9b, 0x2f, 0x48, 0xc7, 0x36, 0x8a, 0x33, 0xd2, 0xbd, 0x2e, 0x6f, 0x81, 0x7a, 0x75, 0xe7, 0xff, + 0x56, 0x84, 0x72, 0xc2, 0xca, 0xb0, 0x78, 0xe8, 0xb4, 0x5a, 0xd4, 0x3b, 0xa0, 0xe4, 0x26, 0x0c, + 0xec, 0x6c, 0xed, 0x6c, 0x0b, 0x2b, 0xa9, 0x74, 0x00, 0x60, 0x20, 0x85, 0x63, 0x23, 0x06, 0x79, + 0x08, 0xe7, 0xa5, 0xa3, 0xaf, 0x2a, 0x12, 0x3d, 0x74, 0xa5, 0xbb, 0xdb, 0x70, 0x9a, 0x8e, 0xbc, + 0x2d, 0x4c, 0x22, 0x3f, 0xe9, 0xb8, 0x01, 0x6d, 0xa2, 0xe5, 0x27, 0xbe, 0x4d, 0xd7, 0x4a, 0x6c, + 0x1d, 0x8d, 0xfc, 0x00, 0xc6, 0x6b, 0xb5, 0xad, 0xb8, 0xf6, 0x41, 0xe3, 0x86, 0x48, 0x2f, 0xb2, + 0x0d, 0x44, 0xfe, 0xf4, 0xd6, 0xfa, 0xe3, 0x02, 0xcc, 0xe6, 0x98, 0x5b, 0xc8, 0x1b, 0x86, 0x1c, + 0xa6, 0x34, 0x39, 0x48, 0x94, 0xd5, 0x3e, 0x21, 0x88, 0x45, 0xcd, 0x6d, 0xba, 0xff, 0x0c, 0x6e, + 0xd3, 0xab, 0x7d, 0xb1, 0xab, 0x34, 0x79, 0x0d, 0xfa, 0x6b, 0xb5, 0x2d, 0x61, 0x56, 0x27, 0xf1, + 0x17, 0x68, 0xc8, 0x0c, 0x61, 0x01, 0x60, 0x44, 0x82, 0xac, 0x73, 0x30, 0x61, 0x74, 0x8c, 0x65, + 0xc1, 0xb8, 0xde, 0x42, 0xd6, 0xfb, 0x8b, 0x7e, 0x53, 0xf5, 0x3e, 0xfb, 0xdb, 0xda, 0x36, 0x65, + 0x46, 0xae, 0x00, 0xc8, 0xfb, 0x5a, 0xb7, 0x29, 0x6f, 0x7e, 0x04, 0x64, 0xad, 0x49, 0xae, 0xc3, + 0x78, 0x40, 0x9b, 0x6e, 0x40, 0x1b, 0x51, 0xbd, 0x13, 0x88, 0x07, 0x28, 0xf6, 0x98, 0x84, 0xed, + 0x06, 0x2d, 0x6b, 0x01, 0xc6, 0xb4, 0x86, 0xf6, 0x62, 0x38, 0x0d, 0x83, 0xba, 0xe1, 0x91, 0xff, + 0xb0, 0x7e, 0xaf, 0x00, 0xd3, 0xd8, 0xb3, 0x07, 0x2e, 0x5b, 0xf1, 0xe3, 0xe6, 0xcd, 0x1b, 0xfd, + 0x70, 0xd9, 0xe8, 0x87, 0x04, 0xae, 0xea, 0x90, 0x0f, 0x52, 0x1d, 0x72, 0x39, 0xab, 0x43, 0x70, + 0x56, 0xbb, 0xbe, 0xa7, 0xf7, 0x83, 0x7e, 0x03, 0xf7, 0x07, 0x05, 0x98, 0xd2, 0xda, 0xa4, 0x3e, + 0xf0, 0x9e, 0xd1, 0xa4, 0x4b, 0x19, 0x4d, 0x4a, 0x0d, 0x91, 0x85, 0x54, 0x8b, 0x5e, 0xe9, 0xd6, + 0xa2, 0xac, 0x11, 0x62, 0xf4, 0xfc, 0x5f, 0x16, 0x60, 0x26, 0x53, 0x06, 0xe4, 0x02, 0x53, 0xe9, + 0x1b, 0x01, 0x8d, 0x84, 0xe4, 0xc5, 0x2f, 0x06, 0x5f, 0x0b, 0xc3, 0x0e, 0x0d, 0x84, 0xdc, 0xc5, + 0x2f, 0xf2, 0x0a, 0x4c, 0x6c, 0xd3, 0xc0, 0xf5, 0x9b, 0xfc, 0x39, 0x00, 0xf7, 0xb3, 0x9d, 0xb0, + 0x4d, 0x20, 0xb9, 0x0c, 0xa3, 0xca, 0x4f, 0x94, 0x9b, 0x65, 0xed, 0x18, 0xc0, 0x78, 0x2f, 0xb9, + 0x07, 0xfc, 0x2e, 0x87, 0x11, 0x8b, 0x5f, 0x6c, 0x4d, 0x95, 0x46, 0xd2, 0x21, 0xbe, 0xa6, 0x4a, + 0x0b, 0xe8, 0x05, 0x18, 0xfa, 0xcc, 0xc6, 0xa1, 0x89, 0xe1, 0x1a, 0x6c, 0xf1, 0x8b, 0x4c, 0xa2, + 0x43, 0x37, 0x3e, 0x29, 0x41, 0x47, 0xee, 0x0f, 0x60, 0x3a, 0x4b, 0xae, 0x59, 0x03, 0x5b, 0xd0, + 0x16, 0x15, 0xed, 0x97, 0x30, 0x55, 0x6d, 0x36, 0x37, 0xee, 0x57, 0xb9, 0xab, 0x85, 0xe8, 0x55, + 0x3e, 0xf5, 0xb9, 0x99, 0x52, 0x68, 0xaa, 0x03, 0x6b, 0x9e, 0x1b, 0xd9, 0x53, 0xcb, 0xdf, 0xb8, + 0x61, 0xe4, 0x7a, 0x07, 0x9a, 0x2d, 0xd5, 0xbe, 0xb0, 0x49, 0x9f, 0x65, 0x0c, 0x01, 0xa6, 0x44, + 0x98, 0xbc, 0x39, 0x3c, 0x83, 0xf9, 0xb4, 0xc6, 0x36, 0x5e, 0x8d, 0x66, 0x4d, 0xbe, 0x71, 0x41, + 0x7f, 0xb5, 0xf1, 0xc4, 0xfa, 0x01, 0x5c, 0xe0, 0x2b, 0x79, 0xb7, 0xc6, 0x8b, 0x66, 0xeb, 0xa6, + 0x5f, 0xeb, 0x3d, 0x69, 0x9c, 0xe9, 0xda, 0x32, 0x7b, 0xdc, 0x68, 0x0b, 0x56, 0xf9, 0x1f, 0x0b, + 0x30, 0x97, 0x20, 0xad, 0x3d, 0xf7, 0x1a, 0x72, 0x1b, 0x79, 0x2d, 0xe9, 0x30, 0x8f, 0xea, 0x0f, + 0xb7, 0x79, 0xba, 0x4d, 0xe5, 0x33, 0x4f, 0xee, 0x00, 0x70, 0x62, 0x4d, 0x6b, 0x41, 0x8b, 0xbf, + 0xf0, 0x2d, 0x42, 0xbd, 0x45, 0x43, 0x21, 0x1d, 0xc8, 0x92, 0xbb, 0x98, 0x23, 0xbd, 0x4c, 0xe2, + 0x18, 0xa2, 0x84, 0x0a, 0xf2, 0x7a, 0x8e, 0x6d, 0x3c, 0x8b, 0xbf, 0xf5, 0x7f, 0xf6, 0xc3, 0xac, + 0xde, 0x81, 0x2f, 0xf2, 0xad, 0xdb, 0x30, 0xb6, 0xe8, 0x7b, 0x11, 0xfd, 0x26, 0xd2, 0x42, 0x44, + 0x10, 0xe5, 0x60, 0xa0, 0x4a, 0x84, 0xc6, 0xcc, 0x01, 0x75, 0xa6, 0xbe, 0x19, 0x3e, 0x92, 0x31, + 0x22, 0x59, 0x84, 0x89, 0x4d, 0xfa, 0x2c, 0x25, 0x40, 0xf4, 0xd3, 0xf4, 0xe8, 0xb3, 0xba, 0x26, + 0x44, 0xdd, 0x79, 0xce, 0xa0, 0x21, 0xfb, 0x30, 0x29, 0x07, 0x97, 0x21, 0xcc, 0x39, 0x7d, 0x33, + 0x35, 0x87, 0x33, 0x0f, 0xa1, 0xc0, 0x6a, 0xc8, 0x91, 0x61, 0x82, 0x23, 0xfb, 0x74, 0x5e, 0x23, + 0x8f, 0x0a, 0x60, 0xee, 0xd6, 0x5a, 0x89, 0xe1, 0x05, 0x9b, 0x8c, 0x06, 0xa0, 0xb3, 0xb0, 0xb6, + 0xa1, 0x9c, 0xee, 0x0f, 0x51, 0xdb, 0xdb, 0x30, 0xc4, 0xa1, 0x42, 0xfb, 0x91, 0xd1, 0x7f, 0x14, + 0x36, 0x37, 0x4f, 0xf0, 0x6a, 0x6c, 0x81, 0x6b, 0xad, 0xa2, 0xc9, 0x48, 0xe1, 0x28, 0xfd, 0xf3, + 0x6e, 0xb2, 0x7b, 0xd1, 0xc1, 0x58, 0x76, 0xaf, 0xee, 0x5e, 0x23, 0x1f, 0x82, 0x2c, 0xa2, 0xd5, + 0x4d, 0xe7, 0x24, 0x1a, 0x76, 0x0b, 0x86, 0x05, 0x28, 0x11, 0x97, 0x28, 0x9e, 0x7e, 0x12, 0xc1, + 0xfa, 0x00, 0x2e, 0xa2, 0x09, 0xd0, 0xf5, 0x0e, 0x5a, 0x74, 0x37, 0x34, 0x9e, 0x72, 0xf4, 0x9a, + 0xd6, 0x1f, 0xc1, 0x5c, 0x16, 0x6d, 0xcf, 0x99, 0xcd, 0x23, 0x85, 0xfc, 0x79, 0x11, 0xa6, 0xd7, + 0x42, 0x5d, 0x87, 0x52, 0xd1, 0x42, 0x32, 0x22, 0x58, 0xa0, 0x4c, 0x56, 0xfb, 0xb2, 0x22, 0x54, + 0xbc, 0xad, 0xbd, 0x14, 0x2d, 0x76, 0x0b, 0x4d, 0xc1, 0xb6, 0x2d, 0xf5, 0x56, 0xf4, 0x35, 0x18, + 0xd8, 0x64, 0x4b, 0x75, 0xbf, 0xe8, 0x3b, 0x4e, 0xc1, 0x40, 0xf8, 0x52, 0x93, 0x6d, 0x91, 0xec, + 0x07, 0xb9, 0x9f, 0x7a, 0x0f, 0x3a, 0xd0, 0x3b, 0xf4, 0xc2, 0x6a, 0x5f, 0xea, 0x69, 0xe8, 0xbb, + 0x30, 0x56, 0x6d, 0x1e, 0x71, 0x47, 0x48, 0xdf, 0x4b, 0x4c, 0x4b, 0xad, 0x64, 0xb5, 0xcf, 0xd6, + 0x11, 0xd9, 0xc1, 0xbe, 0xda, 0x6e, 0xe3, 0x46, 0x95, 0x15, 0x8e, 0x82, 0xe9, 0x5f, 0xd5, 0x76, + 0x7b, 0x61, 0x04, 0x86, 0x76, 0x9c, 0xe0, 0x80, 0x46, 0xd6, 0x97, 0x30, 0x27, 0x7c, 0x73, 0xb8, + 0xc1, 0x13, 0x3d, 0x78, 0xc2, 0xd8, 0xfd, 0xaa, 0x9b, 0x3f, 0xcd, 0x55, 0x00, 0x3c, 0xde, 0xac, + 0x79, 0x4d, 0xfa, 0x8d, 0x70, 0x0e, 0xd4, 0x20, 0xd6, 0x3b, 0x30, 0xaa, 0x24, 0x84, 0x3a, 0xbc, + 0xb6, 0xd9, 0xa1, 0xb4, 0xa6, 0x8d, 0x07, 0xb0, 0xf2, 0xd5, 0xeb, 0x45, 0xe3, 0xdb, 0x45, 0x80, + 0x19, 0xae, 0xf4, 0xbb, 0x30, 0x93, 0x18, 0x04, 0x71, 0xfc, 0x02, 0xa5, 0x76, 0x73, 0xef, 0x45, + 0xf5, 0x3b, 0xa9, 0x95, 0x17, 0x4f, 0xa5, 0x95, 0x5b, 0x7f, 0xbf, 0x88, 0xe7, 0xc5, 0x94, 0x3c, + 0x12, 0xa6, 0x37, 0xdd, 0xfc, 0xb7, 0x00, 0xa3, 0xf8, 0xf5, 0x4b, 0xf2, 0x99, 0x5e, 0x77, 0xd7, + 0x92, 0x91, 0x9f, 0x1d, 0x57, 0xfa, 0xd0, 0x9f, 0x24, 0x26, 0x23, 0x1f, 0xc3, 0xf0, 0xb2, 0xd7, + 0x44, 0x0e, 0xfd, 0x67, 0xe0, 0x20, 0x89, 0x58, 0x9f, 0x60, 0x93, 0x77, 0xd8, 0x14, 0xe6, 0x16, + 0x1b, 0x5b, 0x83, 0xc4, 0x07, 0xd7, 0xc1, 0xbc, 0x83, 0xeb, 0x50, 0xe2, 0xe0, 0x6a, 0xc1, 0xe0, + 0x56, 0xd0, 0x14, 0x61, 0x61, 0x26, 0xe7, 0xc7, 0x85, 0xe0, 0x10, 0x66, 0xf3, 0x22, 0xeb, 0x3f, + 0x17, 0x60, 0x76, 0x85, 0x46, 0x99, 0x63, 0xc8, 0x90, 0x4a, 0xe1, 0x5b, 0x4b, 0xa5, 0xf8, 0x22, + 0x52, 0x51, 0x5f, 0xdd, 0x9f, 0xf7, 0xd5, 0x03, 0x79, 0x5f, 0x3d, 0x98, 0xff, 0xd5, 0x2b, 0x30, + 0xc4, 0x3f, 0x95, 0x1d, 0xce, 0xd7, 0x22, 0x7a, 0x14, 0x1f, 0xce, 0x75, 0xc7, 0x38, 0x9b, 0x97, + 0x31, 0x45, 0x72, 0xdd, 0x09, 0xf5, 0xc3, 0xb9, 0xf8, 0x69, 0xfd, 0x18, 0x1f, 0xf8, 0xae, 0xfb, + 0x8d, 0x27, 0x9a, 0x91, 0x77, 0x98, 0xcf, 0xd0, 0xe4, 0xa5, 0x00, 0xc3, 0xe2, 0x25, 0xb6, 0xc4, + 0x20, 0xd7, 0x60, 0x6c, 0xcd, 0xbb, 0xef, 0x07, 0x0d, 0xba, 0xe5, 0xb5, 0x38, 0xf7, 0x11, 0x5b, + 0x07, 0x09, 0xe3, 0x87, 0xa8, 0x21, 0xb6, 0x28, 0x20, 0x20, 0x61, 0x51, 0x60, 0xb0, 0xbd, 0x79, + 0x9b, 0x97, 0x09, 0xdb, 0x0a, 0xfb, 0xbb, 0xdb, 0x61, 0x5c, 0x9d, 0xda, 0x7b, 0x21, 0xee, 0xc3, + 0x45, 0x9b, 0xb6, 0x5b, 0x0e, 0xd3, 0xe9, 0x8e, 0x7c, 0x8e, 0xaf, 0xbe, 0xf9, 0x5a, 0xc6, 0xe3, + 0x3c, 0xd3, 0x4d, 0x42, 0x35, 0xb9, 0xd8, 0xa5, 0xc9, 0x47, 0x70, 0x7d, 0x85, 0x46, 0xe6, 0x82, + 0x1a, 0x9b, 0x90, 0xc5, 0xc7, 0xaf, 0xc2, 0x48, 0x68, 0x9a, 0xbf, 0xe5, 0x63, 0xb3, 0x4c, 0xc2, + 0xbd, 0xb7, 0xe4, 0x05, 0x91, 0xe0, 0xa3, 0xfe, 0xb2, 0x3e, 0x81, 0x4a, 0x5e, 0x75, 0xa7, 0xf3, + 0x62, 0x75, 0xe1, 0x5a, 0x3e, 0x03, 0xd1, 0xdc, 0x65, 0x90, 0xa6, 0x72, 0x31, 0x85, 0x7a, 0xb5, + 0xd6, 0xb4, 0xae, 0x8b, 0x3f, 0xac, 0x05, 0xe9, 0xcf, 0xf7, 0x2d, 0x9a, 0x5b, 0xc7, 0x5b, 0x68, + 0x93, 0x41, 0x2c, 0xd7, 0x2a, 0x8c, 0x48, 0x98, 0x90, 0xeb, 0x6c, 0x66, 0x4b, 0xa5, 0x40, 0x9b, + 0x92, 0x81, 0x22, 0xb3, 0x7e, 0x2c, 0x6f, 0x64, 0x4c, 0x8a, 0xd3, 0xbd, 0x56, 0x3d, 0xcd, 0x15, + 0x8c, 0xe5, 0xc3, 0x45, 0x93, 0xb7, 0x6e, 0x69, 0x2f, 0x69, 0x96, 0x76, 0x6e, 0x60, 0xbf, 0x66, + 0x5a, 0x7e, 0x85, 0xf1, 0x40, 0x03, 0x91, 0xab, 0xba, 0x3d, 0x7d, 0x3c, 0xfd, 0xfc, 0xf5, 0x2e, + 0xcc, 0x65, 0x55, 0xa8, 0x9d, 0x03, 0x95, 0xd1, 0x56, 0xe8, 0x3b, 0x4b, 0x70, 0x55, 0x06, 0x66, + 0xf2, 0xfd, 0x28, 0x8c, 0x02, 0xa7, 0x5d, 0x6b, 0x04, 0x6e, 0x3b, 0xa6, 0xb2, 0x60, 0x88, 0x43, + 0x84, 0x24, 0xf8, 0xed, 0x16, 0xc7, 0x11, 0x25, 0xd6, 0x6f, 0x16, 0xc0, 0x32, 0x5c, 0xaf, 0xb0, + 0x9f, 0xb7, 0x03, 0xff, 0xa9, 0xdb, 0xd4, 0x6e, 0x94, 0xde, 0x30, 0xac, 0x99, 0xfc, 0x25, 0x60, + 0xd2, 0xeb, 0x5b, 0xac, 0x99, 0x77, 0x13, 0x16, 0x46, 0xae, 0x78, 0xa2, 0x3b, 0x96, 0x19, 0x01, + 0x47, 0x59, 0x1e, 0xff, 0x6b, 0x01, 0x6e, 0x74, 0x6d, 0x83, 0xf8, 0x9e, 0x7d, 0x28, 0x25, 0xcb, + 0xc4, 0x08, 0xaa, 0x68, 0xae, 0x18, 0x69, 0x0e, 0x7b, 0xf7, 0xb8, 0x6b, 0xb9, 0x74, 0x59, 0x6a, + 0x2b, 0xce, 0x29, 0x7e, 0x67, 0x6f, 0x3d, 0x79, 0x1f, 0x60, 0xc7, 0x8f, 0x9c, 0xd6, 0x22, 0x1a, + 0x00, 0xfa, 0xe3, 0x67, 0x02, 0x11, 0x83, 0xd6, 0x93, 0x11, 0x26, 0x34, 0x64, 0xeb, 0x53, 0x9c, + 0xd7, 0xd9, 0x8d, 0x3e, 0xdd, 0x54, 0x5b, 0x84, 0x1b, 0x09, 0x77, 0x80, 0x17, 0x60, 0x12, 0xc1, + 0x0c, 0x13, 0x3f, 0xd3, 0xbd, 0x57, 0x02, 0xbf, 0xd3, 0xfe, 0xe5, 0xf4, 0xfa, 0x9f, 0x14, 0xb8, + 0x7f, 0xa6, 0x5e, 0xad, 0xe8, 0xe8, 0x45, 0x80, 0x18, 0x9a, 0xf0, 0xd3, 0x57, 0x05, 0x7b, 0xf7, + 0xf8, 0x91, 0x1b, 0x2f, 0x0a, 0x0e, 0x38, 0x03, 0x8d, 0xec, 0x97, 0xdb, 0x93, 0x6f, 0xa1, 0x0f, + 0x80, 0xaa, 0xfd, 0x74, 0x72, 0x7f, 0x57, 0xda, 0x3f, 0xce, 0x48, 0x77, 0x08, 0xd3, 0x6c, 0x05, + 0xa8, 0x76, 0xa2, 0x43, 0x3f, 0x70, 0x23, 0xf9, 0xe2, 0x84, 0x6c, 0x8b, 0x77, 0xf8, 0x9c, 0xea, + 0xa3, 0x5f, 0x1c, 0x57, 0xde, 0x3b, 0x4b, 0xc8, 0x4c, 0xc9, 0x73, 0x47, 0xbd, 0xdd, 0xb7, 0x66, + 0xa1, 0x7f, 0xd1, 0x5e, 0xc7, 0x05, 0xcf, 0x5e, 0x57, 0x0b, 0x9e, 0xbd, 0x6e, 0xfd, 0x55, 0x11, + 0x2a, 0x3c, 0x52, 0x08, 0xba, 0x8e, 0xc4, 0x56, 0x0b, 0xcd, 0x17, 0xe5, 0xb4, 0x06, 0x86, 0x44, + 0x24, 0x90, 0xe2, 0x69, 0x22, 0x81, 0xfc, 0x1a, 0xe4, 0x98, 0xac, 0x4e, 0x61, 0x05, 0x78, 0xfd, + 0xe4, 0xb8, 0x72, 0x23, 0xb6, 0x02, 0xf0, 0xd2, 0x2c, 0x73, 0x40, 0x4e, 0x15, 0x69, 0xfb, 0xc5, + 0xc0, 0x0b, 0xd8, 0x2f, 0xee, 0xc2, 0x30, 0x1e, 0x66, 0xd6, 0xb6, 0x85, 0x33, 0x27, 0x0e, 0x4f, + 0x0c, 0xee, 0x53, 0x77, 0xf5, 0x48, 0x7a, 0x12, 0xcd, 0xfa, 0xfd, 0x22, 0x5c, 0xcb, 0x97, 0xb9, + 0x68, 0xdb, 0x12, 0x40, 0xec, 0xb4, 0xd2, 0xcd, 0x49, 0x06, 0xe7, 0xce, 0x33, 0xba, 0xaf, 0x9c, + 0xd4, 0x34, 0x3a, 0xa6, 0xfb, 0xc8, 0xf7, 0xcd, 0x89, 0x1b, 0x12, 0xe3, 0xd9, 0xb3, 0x08, 0x04, + 0x2b, 0x40, 0x46, 0x20, 0x58, 0x01, 0x23, 0xfb, 0x30, 0xbb, 0x1d, 0xb8, 0x4f, 0x9d, 0x88, 0x3e, + 0xa4, 0xcf, 0xf9, 0xfb, 0x9f, 0x65, 0xf1, 0xe8, 0x87, 0x3f, 0x5a, 0xbf, 0x79, 0x72, 0x5c, 0x79, + 0xa5, 0xcd, 0x51, 0x30, 0xd8, 0x17, 0x7f, 0x71, 0x59, 0x4f, 0xbf, 0x03, 0xca, 0x63, 0x64, 0xfd, + 0x8b, 0x02, 0x5c, 0x42, 0xb5, 0x5c, 0x98, 0x5d, 0x65, 0xe5, 0x2f, 0xe4, 0x2b, 0xa9, 0x7f, 0xa0, + 0x18, 0x8b, 0xe8, 0x2b, 0x69, 0xbc, 0xff, 0xb6, 0x0d, 0x34, 0xb2, 0x06, 0x63, 0xe2, 0x37, 0xce, + 0xbf, 0x7e, 0x3c, 0x10, 0xcc, 0x68, 0x0b, 0x16, 0x0e, 0x75, 0x6e, 0x2a, 0xc2, 0x81, 0x2d, 0x98, + 0xe1, 0x33, 0x49, 0x5b, 0xa7, 0xb5, 0x7e, 0x5e, 0x84, 0xcb, 0x7b, 0x34, 0x70, 0x1f, 0x3f, 0xcf, + 0xf9, 0x98, 0x2d, 0x98, 0x96, 0x20, 0x1e, 0x2d, 0xc4, 0x98, 0x62, 0x3c, 0x14, 0xa4, 0x6c, 0xaa, + 0x08, 0x37, 0x22, 0x67, 0x5c, 0x26, 0xe1, 0x19, 0xbc, 0x20, 0xdf, 0x86, 0x91, 0x44, 0xbc, 0x1e, + 0xec, 0x7f, 0x39, 0x43, 0xe3, 0xae, 0x5a, 0xed, 0xb3, 0x15, 0x26, 0xf9, 0xed, 0xfc, 0xdb, 0x27, + 0x61, 0xfa, 0xe8, 0x65, 0xff, 0xc4, 0x09, 0xcb, 0x26, 0xab, 0xa3, 0x95, 0x66, 0x4c, 0xd8, 0xd5, + 0x3e, 0x3b, 0xaf, 0xa6, 0x85, 0x31, 0x18, 0xad, 0xe2, 0x55, 0x1c, 0x3b, 0xb9, 0xff, 0x97, 0x22, + 0x5c, 0x95, 0x6f, 0x79, 0x72, 0xc4, 0xfc, 0x39, 0xcc, 0x4a, 0x50, 0xb5, 0xcd, 0x14, 0x06, 0xda, + 0x34, 0x25, 0xcd, 0xc3, 0xb1, 0x4a, 0x49, 0x3b, 0x02, 0x27, 0x16, 0x76, 0x1e, 0xf9, 0xcb, 0xb1, + 0x7e, 0x7e, 0x9c, 0x15, 0x3d, 0x09, 0xad, 0x90, 0xfa, 0x9a, 0x69, 0x88, 0xc6, 0x58, 0x3f, 0x9b, + 0x29, 0xeb, 0xe9, 0xc0, 0xb7, 0xb5, 0x9e, 0xae, 0xf6, 0x25, 0xed, 0xa7, 0x0b, 0x93, 0x30, 0xbe, + 0x49, 0x9f, 0xc5, 0x72, 0xff, 0x5f, 0x0b, 0x89, 0x00, 0x0b, 0x4c, 0xc3, 0xe0, 0x91, 0x16, 0x0a, + 0x71, 0x00, 0x1e, 0x0c, 0xb0, 0xa0, 0x6b, 0x18, 0x1c, 0x75, 0x0d, 0x86, 0xf9, 0xfd, 0x74, 0xf3, + 0x14, 0x27, 0x7c, 0xf5, 0x28, 0x87, 0xbf, 0x94, 0x6c, 0xf2, 0xc3, 0xbe, 0xa0, 0xb7, 0x1e, 0xc2, + 0x75, 0xe1, 0xb6, 0x6d, 0x76, 0x3e, 0x56, 0x74, 0xc6, 0xed, 0xcb, 0x72, 0xe0, 0xea, 0x0a, 0x4d, + 0x2e, 0x3d, 0xc6, 0xa3, 0xa5, 0x4f, 0xe0, 0x9c, 0x01, 0x57, 0x1c, 0x51, 0x2b, 0x55, 0x63, 0x48, + 0xb1, 0x4e, 0x62, 0x5b, 0xd7, 0xb2, 0xaa, 0xd0, 0x1b, 0x6b, 0x51, 0x8c, 0xab, 0x1a, 0xc4, 0x57, + 0x6c, 0xe1, 0x19, 0x56, 0xbd, 0x9b, 0xda, 0xbc, 0xe6, 0x2b, 0x1e, 0x0f, 0xbc, 0x27, 0x77, 0x5e, + 0x55, 0x6a, 0x4d, 0x18, 0x77, 0x01, 0xd6, 0x24, 0x8c, 0xcb, 0xa2, 0x16, 0x0d, 0x43, 0xeb, 0xdf, + 0x0d, 0x82, 0x25, 0x04, 0x9b, 0x75, 0xe9, 0x2e, 0xe5, 0xb1, 0x9f, 0x6a, 0xac, 0xd8, 0xa8, 0x2e, + 0xe8, 0xe1, 0x3c, 0xe3, 0x52, 0x3e, 0xf2, 0x50, 0xcf, 0x6b, 0xc4, 0x50, 0x63, 0xe4, 0xa5, 0xbe, + 0xfe, 0xab, 0x9c, 0x65, 0x92, 0x4f, 0xb6, 0x57, 0x4f, 0x8e, 0x2b, 0xd7, 0x73, 0x96, 0x49, 0x83, + 0x6f, 0xf6, 0x92, 0x69, 0x9b, 0x57, 0x22, 0xfd, 0x2f, 0x72, 0x25, 0xc2, 0x66, 0xa4, 0x7e, 0x29, + 0xb2, 0x6b, 0xca, 0x52, 0xcc, 0x47, 0x79, 0x21, 0xaf, 0x17, 0x89, 0x38, 0x07, 0x1a, 0xc4, 0xe0, + 0x6a, 0xb0, 0x21, 0x2e, 0x94, 0x34, 0x9b, 0xe5, 0xe2, 0x21, 0x6d, 0x3c, 0x11, 0xb6, 0x62, 0x79, + 0xa1, 0x9b, 0x65, 0x33, 0xe7, 0xa1, 0x9d, 0xf9, 0x3c, 0xe7, 0x05, 0xf5, 0x06, 0x23, 0xd5, 0xe3, + 0x34, 0x24, 0xd9, 0x92, 0x9f, 0xc2, 0x94, 0xea, 0xea, 0x84, 0xd7, 0xd5, 0xd8, 0xfc, 0x2b, 0x71, + 0x14, 0xd0, 0xa3, 0xc7, 0xce, 0xed, 0xa7, 0xf7, 0x6e, 0x67, 0xe0, 0xf2, 0xe7, 0xff, 0x0d, 0x59, + 0xa0, 0xb9, 0x5c, 0xe9, 0x17, 0x5d, 0x19, 0x84, 0xe4, 0x0b, 0x98, 0xae, 0xd5, 0xb6, 0xf8, 0xfb, + 0x0c, 0x5b, 0xde, 0xd9, 0xdb, 0xeb, 0xc2, 0x07, 0x0b, 0xbb, 0x3b, 0x0c, 0xfd, 0xba, 0x78, 0xd7, + 0xa1, 0xdf, 0xf4, 0xeb, 0x01, 0x10, 0xb2, 0x58, 0xe8, 0x37, 0xe5, 0xff, 0xb7, 0x7a, 0x7e, 0xc0, + 0x54, 0x11, 0xb7, 0x45, 0xc5, 0x3b, 0x22, 0x39, 0xb0, 0x73, 0x6e, 0xf9, 0x0a, 0xdf, 0xf1, 0x2d, + 0xdf, 0x3f, 0x2a, 0xca, 0x47, 0x17, 0xe9, 0x8b, 0xd6, 0x33, 0x5f, 0xf6, 0x65, 0x7e, 0xc1, 0xa9, + 0xf6, 0xe9, 0xcc, 0xc6, 0x91, 0x05, 0x79, 0x55, 0xaa, 0x42, 0x84, 0x4d, 0xaa, 0x6b, 0x87, 0xb8, + 0xc0, 0xb8, 0x3d, 0x45, 0xad, 0x48, 0xa3, 0x4a, 0xde, 0xc3, 0xf5, 0x7f, 0xfb, 0x7b, 0xb8, 0x7f, + 0x32, 0x0a, 0xe7, 0xb7, 0x9d, 0x03, 0xd7, 0x63, 0xfb, 0x81, 0x4d, 0x43, 0xbf, 0x13, 0x34, 0x28, + 0xa9, 0xc2, 0xa4, 0xe9, 0x51, 0xdb, 0xc3, 0x5f, 0x98, 0x6d, 0x79, 0x26, 0x8c, 0xcc, 0xc3, 0xa8, + 0x7a, 0xc5, 0x2b, 0xf6, 0xa9, 0x8c, 0xd7, 0xbd, 0xab, 0x7d, 0x76, 0x8c, 0x46, 0xde, 0x37, 0xae, + 0x8e, 0xce, 0xa9, 0x07, 0xe9, 0x88, 0x3b, 0xcf, 0x5d, 0x1e, 0x3d, 0xbf, 0x69, 0xee, 0xb5, 0xfc, + 0x7e, 0xe4, 0xc7, 0xa9, 0xdb, 0xa4, 0x41, 0xa3, 0xc5, 0x29, 0x93, 0x1a, 0xaa, 0x19, 0xb9, 0x61, + 0xbb, 0x33, 0xee, 0x99, 0xbe, 0x84, 0xb1, 0x87, 0x9d, 0x7d, 0x2a, 0xef, 0xcd, 0x86, 0xc4, 0xd6, + 0x9b, 0xf4, 0x13, 0x17, 0xe5, 0x7b, 0x6f, 0xf1, 0x3e, 0x78, 0xd2, 0xd9, 0xa7, 0xe9, 0x78, 0xf0, + 0x6c, 0xcd, 0xd3, 0x98, 0x91, 0x43, 0x28, 0x25, 0x5d, 0xba, 0x45, 0x50, 0xbd, 0x2e, 0x8e, 0xe8, + 0x18, 0x1c, 0x45, 0x8b, 0x3a, 0xcf, 0x1d, 0x4d, 0x8d, 0x4a, 0x52, 0x5c, 0xc9, 0xaf, 0xc3, 0x4c, + 0xa6, 0x41, 0x53, 0x3d, 0x4a, 0xeb, 0x6e, 0x2b, 0xc5, 0x05, 0x24, 0x21, 0x35, 0xf9, 0x02, 0xce, + 0xa8, 0x39, 0xbb, 0x16, 0xd2, 0x84, 0x73, 0x09, 0x57, 0x65, 0x91, 0x5a, 0x23, 0xdf, 0xf9, 0x19, + 0xf7, 0x3c, 0x19, 0x9d, 0x36, 0xb3, 0xae, 0x24, 0x4b, 0xb2, 0x0e, 0xa3, 0xca, 0x92, 0x20, 0xe2, + 0x99, 0x65, 0x59, 0x4d, 0xca, 0x27, 0xc7, 0x95, 0xe9, 0xd8, 0x6a, 0x62, 0xf0, 0x8c, 0x19, 0x90, + 0xdf, 0x80, 0xeb, 0x6a, 0x88, 0x6e, 0x05, 0xd9, 0xf6, 0x25, 0x11, 0xd5, 0xfe, 0x56, 0x72, 0x84, + 0xe7, 0xe1, 0xef, 0xdd, 0x5b, 0x28, 0x96, 0x0b, 0xab, 0x7d, 0x76, 0x6f, 0xd6, 0xe4, 0xb7, 0x0a, + 0x70, 0x21, 0xa7, 0xd6, 0x71, 0xac, 0xb5, 0xa7, 0xd1, 0x0f, 0xcf, 0x0d, 0xf8, 0x10, 0xcb, 0x6d, + 0xc6, 0x0f, 0x16, 0xa5, 0xf5, 0xcf, 0xf8, 0xee, 0x9c, 0x9a, 0xc8, 0x9b, 0x30, 0x84, 0xc7, 0xef, + 0xb0, 0x3c, 0x81, 0x0a, 0x2a, 0xc6, 0x04, 0xc2, 0x43, 0xba, 0xbe, 0x25, 0x09, 0x1c, 0xb2, 0xca, + 0x14, 0x3d, 0xdc, 0x12, 0xa5, 0x62, 0x26, 0x22, 0x88, 0x89, 0xc3, 0x02, 0x2f, 0x92, 0x71, 0x43, + 0x8c, 0xf4, 0x05, 0x26, 0xd9, 0x02, 0xc0, 0x48, 0x20, 0x56, 0xa5, 0x07, 0x03, 0x23, 0x03, 0xa5, + 0x41, 0x3e, 0x71, 0xa4, 0x0f, 0xfc, 0xef, 0x8c, 0xf0, 0x07, 0xb3, 0xbb, 0x9e, 0xfb, 0xd8, 0x8d, + 0x17, 0x30, 0xdd, 0x70, 0x17, 0xe7, 0x11, 0x12, 0x6a, 0x75, 0x4e, 0xc6, 0x20, 0x65, 0xe3, 0x2b, + 0xf6, 0xb4, 0xf1, 0xbd, 0xa5, 0xdd, 0x86, 0x69, 0x91, 0x42, 0xb9, 0xfa, 0x64, 0xda, 0xd4, 0xe2, + 0x6b, 0xb2, 0xaf, 0x61, 0x08, 0x83, 0x7b, 0xf2, 0xab, 0xc6, 0xb1, 0xf9, 0xdb, 0x62, 0xd9, 0xee, + 0xd2, 0x7c, 0x1e, 0x0d, 0x54, 0x3c, 0x82, 0xe7, 0x12, 0x47, 0x80, 0x21, 0x71, 0x84, 0x90, 0x1d, + 0x98, 0xda, 0x66, 0xbb, 0x39, 0xf7, 0xc4, 0x6e, 0x07, 0xc2, 0xee, 0xc1, 0x2d, 0x2a, 0xa8, 0x4d, + 0xb4, 0x65, 0x71, 0x9d, 0xaa, 0x72, 0x7d, 0x43, 0xcd, 0x20, 0x27, 0xcb, 0x30, 0x59, 0xa3, 0x4e, + 0xd0, 0x38, 0x7c, 0x48, 0x9f, 0x33, 0x4d, 0xca, 0x48, 0x9d, 0x11, 0x62, 0x09, 0xfb, 0x5e, 0x2c, + 0xd2, 0xdd, 0x47, 0x4c, 0x22, 0xf2, 0x29, 0x0c, 0xd5, 0xfc, 0x20, 0x5a, 0x78, 0x2e, 0x16, 0x35, + 0x79, 0x19, 0xc5, 0x81, 0x0b, 0x17, 0x65, 0xfa, 0x90, 0xd0, 0x0f, 0xa2, 0xfa, 0xbe, 0x11, 0x64, + 0x8a, 0xa3, 0x90, 0xe7, 0x30, 0x6d, 0x2e, 0x28, 0xc2, 0x41, 0x78, 0x44, 0x68, 0x70, 0x59, 0xab, + 0x16, 0x47, 0x59, 0xb8, 0x29, 0xb8, 0x5f, 0x4b, 0x2e, 0x5b, 0x8f, 0xb1, 0x5c, 0x57, 0x7b, 0xb2, + 0xe8, 0xc9, 0x06, 0xe6, 0x5d, 0xe1, 0x5f, 0x54, 0x0d, 0xb9, 0x63, 0xf1, 0x68, 0x1c, 0xc6, 0xac, + 0x83, 0x8b, 0x12, 0x4a, 0xc2, 0x09, 0x93, 0xc9, 0x7a, 0xec, 0x14, 0x29, 0xd9, 0x86, 0xf3, 0xbb, + 0x21, 0xdd, 0x0e, 0xe8, 0x53, 0x97, 0x3e, 0x93, 0xfc, 0x20, 0x8e, 0xf9, 0xc4, 0xf8, 0xb5, 0x79, + 0x69, 0x16, 0xc3, 0x34, 0x31, 0x79, 0x1f, 0x60, 0xdb, 0xf5, 0x3c, 0xda, 0xc4, 0x1b, 0xcd, 0x31, + 0x64, 0x85, 0xd6, 0xda, 0x36, 0x42, 0xeb, 0xbe, 0xd7, 0xd2, 0x45, 0xaa, 0x21, 0x93, 0x05, 0x98, + 0x58, 0xf3, 0x1a, 0xad, 0x8e, 0xf0, 0x3c, 0x08, 0x71, 0x41, 0x11, 0xb1, 0xe8, 0x5c, 0x5e, 0x50, + 0x4f, 0x4d, 0x72, 0x93, 0x84, 0x3c, 0x04, 0x22, 0x00, 0x62, 0xd4, 0x3a, 0xfb, 0x2d, 0x2a, 0xa6, + 0x3b, 0x5a, 0x61, 0x24, 0x23, 0x1c, 0xee, 0x46, 0x88, 0xb7, 0x14, 0xd9, 0xdc, 0xfb, 0x30, 0xa6, + 0x8d, 0xf9, 0x8c, 0xa8, 0x0e, 0xd3, 0x7a, 0x54, 0x87, 0x51, 0x3d, 0x7a, 0xc3, 0xdf, 0x2e, 0xc0, + 0xe5, 0xec, 0xb9, 0x24, 0x14, 0xb0, 0x2d, 0x18, 0x55, 0x40, 0xf5, 0x8e, 0x47, 0x9e, 0x2a, 0x12, + 0x1a, 0x10, 0x9f, 0xd0, 0x72, 0xe5, 0xd1, 0xbf, 0x3e, 0xe6, 0xf1, 0x02, 0xa6, 0xfe, 0xff, 0x7d, + 0x04, 0xa6, 0xd1, 0x5f, 0x3d, 0xb9, 0x4e, 0x7d, 0x82, 0xd1, 0x59, 0x10, 0xa6, 0x59, 0xae, 0x85, + 0x11, 0x8b, 0xc3, 0x93, 0xa1, 0xc4, 0x0c, 0x02, 0xf2, 0x8e, 0xee, 0x6e, 0x51, 0xd4, 0xf2, 0xbc, + 0x48, 0xa0, 0xfe, 0x09, 0xb1, 0x1f, 0xc6, 0x1b, 0xc6, 0x6d, 0xff, 0xa9, 0x17, 0xbd, 0x81, 0xd3, + 0x2e, 0x7a, 0xbb, 0x6a, 0xd1, 0xe3, 0x51, 0x3f, 0x5e, 0xd7, 0x16, 0xbd, 0x97, 0xbf, 0xda, 0x0d, + 0xbd, 0xec, 0xd5, 0x6e, 0xf8, 0xdb, 0xad, 0x76, 0x23, 0x2f, 0xb8, 0xda, 0xdd, 0x87, 0xc9, 0x4d, + 0x4a, 0x9b, 0xda, 0x1d, 0xcc, 0x68, 0xbc, 0x7b, 0x7a, 0x14, 0xad, 0x6b, 0x59, 0x17, 0x31, 0x09, + 0xaa, 0xdc, 0x55, 0x13, 0xfe, 0x66, 0x56, 0xcd, 0xb1, 0x97, 0xbc, 0x6a, 0x8e, 0x7f, 0x9b, 0x55, + 0x33, 0xb5, 0xf4, 0x4d, 0x9c, 0x79, 0xe9, 0xfb, 0x36, 0xab, 0xd5, 0xc7, 0xe8, 0xad, 0x58, 0xab, + 0xad, 0x0a, 0xc7, 0x14, 0xcd, 0x13, 0x64, 0xd5, 0x0f, 0xa5, 0x33, 0x37, 0xfe, 0xcd, 0x60, 0xdb, + 0x7e, 0x20, 0x6f, 0xd3, 0xf1, 0x6f, 0x6b, 0x01, 0x7d, 0x14, 0x75, 0x7a, 0xf5, 0x8e, 0x61, 0x58, + 0x3c, 0x82, 0x14, 0x6b, 0x5c, 0xf2, 0x18, 0x65, 0xcb, 0x72, 0xeb, 0xcf, 0x0b, 0xfc, 0xbe, 0xf3, + 0x7f, 0xc4, 0xa5, 0xf2, 0xdb, 0xdc, 0x41, 0xfe, 0x76, 0x1c, 0x1c, 0x41, 0x04, 0x72, 0x08, 0x9c, + 0xc6, 0x93, 0xf8, 0x12, 0xf8, 0x47, 0x6c, 0x9e, 0xeb, 0x05, 0x18, 0xaa, 0x36, 0x3e, 0x2b, 0x9a, + 0x85, 0x7b, 0xf7, 0xe4, 0x02, 0x20, 0x62, 0x44, 0x70, 0xb0, 0xb9, 0x00, 0xe8, 0x04, 0xe8, 0x86, + 0x77, 0xce, 0xb2, 0xf9, 0xdb, 0xfe, 0xcc, 0x16, 0xbc, 0x9b, 0x7e, 0x9d, 0x8e, 0x87, 0x91, 0xf8, + 0x75, 0xba, 0x2e, 0xc6, 0xf8, 0x9d, 0xfa, 0x2e, 0x5c, 0xb2, 0xe9, 0x91, 0xff, 0x94, 0xbe, 0x5c, + 0xb6, 0x5f, 0xc1, 0x45, 0x93, 0x21, 0x7f, 0xc7, 0xc4, 0xe3, 0xe2, 0x7f, 0x9c, 0x1d, 0x4d, 0x5f, + 0x10, 0xf0, 0x68, 0xfa, 0x3c, 0x28, 0x37, 0xfb, 0x53, 0xdf, 0x37, 0xb0, 0xcc, 0xf2, 0xe1, 0xb2, + 0xc9, 0xbc, 0xda, 0x6c, 0x62, 0x56, 0xcd, 0x86, 0xdb, 0x76, 0xbc, 0x88, 0x6c, 0xc1, 0x98, 0xf6, + 0x33, 0x61, 0x2a, 0xd0, 0x4a, 0x84, 0x4e, 0x13, 0x03, 0x8c, 0xa0, 0xa6, 0x31, 0xd8, 0xa2, 0x50, + 0x49, 0x8a, 0x87, 0x89, 0x4c, 0xaf, 0x73, 0x01, 0x26, 0xb4, 0x9f, 0xca, 0x1a, 0x8a, 0x93, 0x5f, + 0xab, 0xc1, 0x14, 0x98, 0x49, 0x62, 0x35, 0x60, 0x2e, 0x4b, 0x68, 0x3c, 0xfa, 0x35, 0x59, 0x8e, + 0x23, 0x67, 0xf5, 0x76, 0xe4, 0x3b, 0x97, 0x17, 0x35, 0xcb, 0xfa, 0xbf, 0x06, 0xe0, 0x92, 0xe8, + 0x8c, 0x97, 0xd9, 0xe3, 0xe4, 0xc7, 0x30, 0xa6, 0xf5, 0xb1, 0x10, 0xfa, 0x35, 0xf9, 0x0a, 0x29, + 0x6f, 0x2c, 0x70, 0x93, 0x46, 0x07, 0x01, 0xf5, 0x44, 0x77, 0xaf, 0xf6, 0xd9, 0x3a, 0x4b, 0xd2, + 0x82, 0x49, 0xb3, 0xa3, 0x85, 0x55, 0xe7, 0x46, 0x66, 0x25, 0x26, 0xaa, 0x0c, 0x8d, 0xdd, 0xac, + 0x67, 0x76, 0xf7, 0x6a, 0x9f, 0x9d, 0xe0, 0x4d, 0xbe, 0x81, 0xf3, 0xa9, 0x5e, 0x16, 0xc6, 0xba, + 0xd7, 0x32, 0x2b, 0x4c, 0x61, 0x73, 0x4b, 0x6f, 0x80, 0xe0, 0xdc, 0x6a, 0xd3, 0x95, 0x90, 0x26, + 0x8c, 0xeb, 0x1d, 0x2f, 0xcc, 0x4e, 0xd7, 0xbb, 0x88, 0x92, 0x23, 0x72, 0xe5, 0x4e, 0xc8, 0x12, + 0xfb, 0xfe, 0xb9, 0x69, 0xbd, 0x36, 0x90, 0x47, 0x60, 0x88, 0xff, 0x66, 0x4b, 0xc0, 0x76, 0x40, + 0x43, 0xea, 0x35, 0xa8, 0xe1, 0xfb, 0xfd, 0x2d, 0x97, 0x80, 0x7f, 0x5e, 0x80, 0x72, 0x16, 0xdf, + 0x1a, 0xf5, 0x9a, 0x64, 0x1b, 0x4a, 0xc9, 0x8a, 0xc4, 0xa8, 0xb6, 0x54, 0xf4, 0xe1, 0xdc, 0x26, + 0xad, 0xf6, 0xd9, 0x29, 0x6a, 0xb2, 0x09, 0xe7, 0x35, 0x98, 0x30, 0xae, 0x16, 0x4f, 0x63, 0x5c, + 0x65, 0xbd, 0x90, 0x22, 0xd5, 0x6d, 0xd3, 0xab, 0xb8, 0x33, 0x2e, 0xf9, 0x47, 0x8e, 0xeb, 0x31, + 0x45, 0x57, 0x0b, 0x9e, 0x05, 0x31, 0x54, 0xc8, 0x86, 0x5b, 0x5b, 0x11, 0x2a, 0xdf, 0xaa, 0x28, + 0x14, 0xeb, 0x23, 0x5c, 0xc1, 0x85, 0x8d, 0x8e, 0x3f, 0xf8, 0x55, 0xcc, 0xae, 0xc1, 0xe0, 0xce, + 0x7a, 0x6d, 0xb1, 0x2a, 0x9e, 0x0f, 0xf3, 0xa0, 0x13, 0xad, 0xb0, 0xde, 0x70, 0x6c, 0x5e, 0x60, + 0x7d, 0x08, 0x64, 0x85, 0x46, 0x22, 0xfc, 0xbd, 0xa2, 0x7b, 0x15, 0x86, 0x05, 0x48, 0x50, 0xa2, + 0xd7, 0x9d, 0x08, 0xa6, 0x6f, 0xcb, 0x32, 0x6b, 0x5b, 0x9e, 0x13, 0x5a, 0xd4, 0x09, 0xb5, 0x8d, + 0xf9, 0x3d, 0x18, 0x09, 0x04, 0x4c, 0xec, 0xcb, 0x93, 0x2a, 0xbb, 0x09, 0x82, 0xb9, 0x3d, 0x5b, + 0xe2, 0xd8, 0xea, 0x2f, 0x6b, 0x1d, 0x03, 0xc4, 0x6c, 0xad, 0x2d, 0x2d, 0x32, 0xa9, 0x0a, 0x61, + 0xc9, 0xee, 0xb8, 0x83, 0xee, 0xe9, 0x11, 0xd5, 0x1f, 0x0f, 0xa3, 0x68, 0x70, 0x92, 0x8b, 0xb0, + 0x48, 0x1a, 0x8a, 0xf5, 0x96, 0x0a, 0x37, 0x93, 0xc1, 0x2d, 0x2f, 0x4b, 0xc7, 0x26, 0x06, 0xd2, + 0x59, 0x41, 0x4f, 0x9c, 0x97, 0xd1, 0x08, 0x07, 0xe6, 0xf8, 0x36, 0xcf, 0xbe, 0x4a, 0x24, 0x1a, + 0xf4, 0xd5, 0xd2, 0xb8, 0x08, 0xa3, 0x0a, 0xa6, 0xae, 0xd5, 0xb8, 0xac, 0x0c, 0xfc, 0xbd, 0xb7, + 0xf8, 0x3b, 0xeb, 0x86, 0x62, 0x10, 0xd3, 0xb1, 0x2a, 0xf8, 0xbc, 0xfb, 0x8e, 0xab, 0x08, 0x69, + 0x10, 0x7d, 0xa7, 0x55, 0xc4, 0x91, 0x96, 0xce, 0x52, 0x85, 0x81, 0xbf, 0x37, 0x7f, 0x1a, 0x41, + 0x7d, 0xc7, 0x55, 0x30, 0x41, 0x7d, 0x77, 0x55, 0x50, 0x19, 0x92, 0x8a, 0x0f, 0xd2, 0x54, 0x25, + 0xcb, 0xe9, 0x4a, 0xa4, 0xe1, 0x3a, 0x41, 0xd1, 0xb5, 0x3f, 0x28, 0x5c, 0xe6, 0xc2, 0xfa, 0x25, + 0x54, 0xc3, 0x04, 0xf6, 0xdd, 0x56, 0xf3, 0xff, 0x16, 0x78, 0x80, 0xac, 0xda, 0x96, 0x96, 0xe2, + 0xd3, 0x7b, 0xec, 0x6b, 0xb7, 0xfe, 0xda, 0x6c, 0x7f, 0xe8, 0x7a, 0x4d, 0xfd, 0xd6, 0xdf, 0xe9, + 0x44, 0x87, 0x2a, 0x80, 0xf4, 0x13, 0xd7, 0x6b, 0xda, 0x49, 0x6c, 0xf2, 0x3e, 0x4c, 0x68, 0x20, + 0xa5, 0xad, 0xf1, 0x2c, 0x1c, 0x3a, 0xb9, 0xdb, 0xb4, 0x4d, 0x4c, 0xeb, 0xaf, 0x0b, 0x30, 0x95, + 0x91, 0x7c, 0x1a, 0x8d, 0x19, 0x78, 0x0a, 0x52, 0x0b, 0x95, 0xc8, 0x9b, 0x85, 0xb1, 0x3a, 0x8c, + 0x4d, 0x52, 0x21, 0x62, 0xfe, 0x01, 0x2d, 0x51, 0x76, 0x51, 0x4b, 0xe9, 0x96, 0x9d, 0x1c, 0x5b, + 0x47, 0x27, 0x21, 0x40, 0xdc, 0x12, 0x61, 0x36, 0xae, 0x31, 0x95, 0x56, 0xcb, 0xb2, 0xfd, 0x52, + 0xd2, 0x7c, 0x6b, 0xd5, 0x58, 0xbf, 0x5d, 0x84, 0x0b, 0x19, 0xdf, 0x5f, 0xa3, 0xd1, 0xdf, 0x84, + 0x08, 0x12, 0xb9, 0xce, 0xfb, 0x7f, 0x49, 0xb9, 0xce, 0xad, 0x7f, 0x53, 0x84, 0x0b, 0xbb, 0xed, + 0x10, 0x1f, 0x6f, 0xad, 0x79, 0x4f, 0xa9, 0x17, 0xf9, 0xc1, 0x73, 0x7c, 0x70, 0x42, 0xde, 0x81, + 0xc1, 0x55, 0xda, 0x6a, 0xf9, 0x62, 0xfc, 0x5f, 0x91, 0x8e, 0x17, 0x49, 0x6c, 0x44, 0x5a, 0xed, + 0xb3, 0x39, 0x36, 0x79, 0x1f, 0x46, 0x57, 0xa9, 0x13, 0x44, 0xfb, 0xd4, 0x91, 0x47, 0x16, 0x99, + 0x1b, 0x44, 0x23, 0x11, 0x08, 0xab, 0x7d, 0x76, 0x8c, 0x4d, 0xe6, 0xd9, 0x69, 0xde, 0x3b, 0x50, + 0x0f, 0xd5, 0x73, 0x2a, 0x64, 0x38, 0xab, 0x7d, 0x36, 0xe2, 0x92, 0x0d, 0x98, 0xa8, 0x1e, 0x50, + 0x2f, 0xda, 0xa0, 0x91, 0xd3, 0x74, 0x22, 0x47, 0xa8, 0xb6, 0xaf, 0xe6, 0x11, 0x1b, 0xc8, 0xab, + 0x7d, 0xb6, 0x49, 0x4d, 0x3e, 0x84, 0xe1, 0x15, 0xdf, 0x6f, 0xee, 0x3f, 0x97, 0x11, 0x14, 0x2a, + 0x79, 0x8c, 0x04, 0xda, 0x6a, 0x9f, 0x2d, 0x29, 0x16, 0x06, 0xa1, 0x7f, 0x23, 0x3c, 0xb0, 0x8e, + 0x0b, 0x50, 0x5e, 0xf2, 0x9f, 0x79, 0x99, 0x52, 0xfd, 0x81, 0x29, 0x55, 0xc9, 0x3e, 0x03, 0x3f, + 0x21, 0xd7, 0xb7, 0x61, 0x60, 0xdb, 0xf5, 0x0e, 0x12, 0xaa, 0x60, 0x06, 0x1d, 0xc3, 0x42, 0xf1, + 0xb8, 0xde, 0x01, 0x59, 0x97, 0x3a, 0xb8, 0xb0, 0x35, 0xf6, 0x1b, 0x8a, 0x7f, 0x06, 0xb5, 0x8e, + 0x1d, 0xeb, 0xda, 0xfc, 0xb7, 0xfc, 0xc0, 0x37, 0x60, 0x36, 0xa7, 0x5e, 0xf1, 0xf2, 0x9c, 0x7d, + 0xdb, 0x00, 0x2a, 0x36, 0xaf, 0xc3, 0x4c, 0x66, 0xff, 0xa5, 0x10, 0xff, 0x5e, 0xd6, 0x40, 0xe4, + 0x5f, 0x5e, 0x86, 0x61, 0x99, 0x34, 0x8b, 0xdb, 0x7e, 0xe4, 0x4f, 0x7c, 0x7b, 0x25, 0x27, 0xaa, + 0x0c, 0x95, 0x22, 0xe7, 0xe3, 0x9e, 0x16, 0x9a, 0x8a, 0x4f, 0xa7, 0x0f, 0xbe, 0xc5, 0xa4, 0x51, + 0xbc, 0x58, 0x9d, 0xab, 0x7e, 0x18, 0x79, 0xca, 0xa9, 0xd7, 0x56, 0xbf, 0xc9, 0x2d, 0x28, 0xc9, + 0x04, 0x19, 0x22, 0x13, 0x8f, 0xc8, 0xcc, 0x6e, 0xa7, 0xe0, 0xe4, 0x3d, 0x98, 0x4d, 0xc2, 0xe4, + 0x57, 0xf2, 0xc7, 0x73, 0x79, 0xc5, 0xd6, 0x9f, 0x15, 0x31, 0x7a, 0x78, 0x97, 0x71, 0xcd, 0xa4, + 0xbb, 0x55, 0x13, 0xd2, 0x2a, 0x6e, 0xd5, 0xc8, 0x65, 0x18, 0xdd, 0xaa, 0x19, 0x99, 0xc7, 0xec, + 0x18, 0xc0, 0x9a, 0xcd, 0x3e, 0xa1, 0x1a, 0x34, 0x0e, 0xdd, 0x88, 0x36, 0xa2, 0x4e, 0x20, 0x56, + 0x61, 0x3b, 0x05, 0x27, 0x16, 0x8c, 0xaf, 0xb4, 0xdc, 0xfd, 0x86, 0x64, 0xc6, 0x45, 0x60, 0xc0, + 0xc8, 0x6b, 0x30, 0xb9, 0xe6, 0x85, 0x91, 0xd3, 0x6a, 0x6d, 0xd0, 0xe8, 0xd0, 0x6f, 0x8a, 0xe4, + 0xa8, 0x76, 0x02, 0xca, 0xea, 0x5d, 0xf4, 0xbd, 0xc8, 0x71, 0x3d, 0x1a, 0xd8, 0x1d, 0x2f, 0x72, + 0x8f, 0xa8, 0xf8, 0xf6, 0x14, 0x9c, 0xbc, 0x0d, 0x33, 0x0a, 0xb6, 0x15, 0x34, 0x0e, 0x69, 0x18, + 0x05, 0x98, 0x8f, 0x10, 0xdd, 0x77, 0xec, 0xec, 0x42, 0xac, 0xa1, 0xe5, 0x77, 0x9a, 0xcb, 0xde, + 0x53, 0x37, 0xf0, 0x3d, 0xcc, 0xf6, 0x31, 0x22, 0x6a, 0x48, 0xc0, 0xad, 0x3f, 0x1c, 0xc9, 0x9c, + 0xb6, 0xdf, 0x66, 0x0c, 0x7e, 0x01, 0xe3, 0x8b, 0x4e, 0xdb, 0xd9, 0x77, 0x5b, 0x6e, 0xe4, 0xaa, + 0xc4, 0x6d, 0xef, 0xf4, 0x98, 0xf3, 0x32, 0x65, 0x0a, 0x6d, 0xea, 0xc4, 0xb6, 0xc1, 0x6a, 0xee, + 0xaf, 0x86, 0x60, 0x26, 0x13, 0x8f, 0xdc, 0x14, 0x19, 0xde, 0xd4, 0xba, 0x2a, 0xd2, 0x87, 0xd9, + 0x49, 0x30, 0xeb, 0x4b, 0x04, 0x2d, 0xb6, 0xa8, 0xe3, 0x75, 0x44, 0xf2, 0x30, 0xdb, 0x80, 0xb1, + 0xbe, 0x64, 0x7a, 0x83, 0xc6, 0x0c, 0x7d, 0xb2, 0xed, 0x04, 0x94, 0x5c, 0x83, 0x31, 0x06, 0x91, + 0xac, 0x06, 0xf8, 0xeb, 0x41, 0x0d, 0xc4, 0x38, 0x6d, 0xfa, 0x4d, 0xaa, 0x71, 0x1a, 0xe4, 0x9c, + 0x4c, 0x28, 0xe3, 0xc4, 0x20, 0x92, 0xd3, 0x10, 0xe7, 0xa4, 0x81, 0xc8, 0x2b, 0x30, 0x51, 0x6d, + 0xb7, 0x35, 0x46, 0x98, 0x35, 0xcc, 0x36, 0x81, 0xe4, 0x2a, 0x40, 0xb5, 0xdd, 0x96, 0x6c, 0x30, + 0x23, 0x98, 0xad, 0x41, 0xc8, 0xed, 0x38, 0x00, 0x9c, 0xc6, 0x0a, 0xaf, 0x13, 0xec, 0x8c, 0x12, + 0x26, 0x57, 0x15, 0x2d, 0x4b, 0x30, 0x05, 0x2e, 0xd7, 0x04, 0x98, 0x7c, 0x04, 0x17, 0x13, 0x7e, + 0x17, 0x5a, 0x05, 0x68, 0xea, 0xb7, 0xf3, 0x11, 0xc8, 0xbb, 0x70, 0x21, 0x51, 0x28, 0xab, 0x43, + 0xab, 0xbe, 0x9d, 0x53, 0x4a, 0x3e, 0x80, 0x72, 0xe2, 0x45, 0x78, 0x5c, 0x29, 0x5a, 0xf0, 0xed, + 0xdc, 0x72, 0x36, 0xbb, 0x12, 0x4f, 0xcb, 0x44, 0x95, 0x78, 0x59, 0x69, 0x67, 0x17, 0x92, 0x55, + 0xa8, 0x64, 0xfa, 0xb2, 0x68, 0x15, 0x63, 0xa6, 0x33, 0xbb, 0x17, 0x1a, 0x59, 0x80, 0xcb, 0x99, + 0x28, 0xb2, 0x19, 0x98, 0xff, 0xcc, 0xee, 0x8a, 0x43, 0xe6, 0x61, 0x3a, 0xf6, 0xe9, 0xd1, 0x9a, + 0x80, 0xa9, 0xcf, 0xec, 0xcc, 0x32, 0xf2, 0xa6, 0xf9, 0xee, 0x9f, 0x57, 0x86, 0x99, 0xcf, 0xec, + 0x74, 0x81, 0x75, 0x52, 0x80, 0xcb, 0x99, 0x1b, 0xa5, 0xd4, 0xe7, 0xe7, 0x92, 0x8a, 0xa3, 0xb6, + 0x16, 0xdc, 0x82, 0x01, 0x54, 0xf0, 0xb9, 0xad, 0x58, 0xba, 0xb1, 0x22, 0x3d, 0x67, 0xc5, 0x4a, + 0x6d, 0xc4, 0x21, 0x2b, 0xea, 0x6e, 0xb0, 0x1f, 0x2d, 0x19, 0x77, 0x92, 0x0a, 0x54, 0x46, 0xe5, + 0xfa, 0x1d, 0xa1, 0xbc, 0x0d, 0xfc, 0x36, 0xd7, 0x30, 0x7f, 0x56, 0x80, 0x4a, 0x0f, 0xfd, 0x40, + 0x7d, 0x53, 0xe1, 0x14, 0xdf, 0xf4, 0x40, 0x7d, 0x13, 0x7f, 0x76, 0x3b, 0x7f, 0x3a, 0x1d, 0xe4, + 0x65, 0x7f, 0xd6, 0x5f, 0x17, 0x80, 0xa4, 0xf5, 0x50, 0xf2, 0x7d, 0x18, 0xad, 0xd5, 0x56, 0x0d, + 0x8f, 0xbe, 0xd4, 0xed, 0x50, 0x8c, 0x41, 0xee, 0x9e, 0xca, 0x85, 0x4f, 0x77, 0xe0, 0xfb, 0x24, + 0xe5, 0x37, 0xd8, 0xdf, 0xd5, 0x6f, 0x30, 0xe5, 0x35, 0xb8, 0x9c, 0xe1, 0x08, 0x37, 0xd0, 0xc3, + 0x11, 0x2e, 0xed, 0xe5, 0x66, 0x2d, 0x41, 0x39, 0x4f, 0x95, 0xc5, 0x15, 0x8e, 0x87, 0x4d, 0xd3, + 0x6e, 0xb8, 0xf8, 0x0a, 0x67, 0x82, 0xad, 0x77, 0xe1, 0x82, 0xa2, 0xe6, 0xf9, 0x58, 0xb4, 0xe0, + 0x06, 0xe2, 0xfc, 0xab, 0x82, 0x28, 0xc4, 0x00, 0xeb, 0x4f, 0x07, 0x52, 0x84, 0xb5, 0xce, 0xd1, + 0x91, 0x13, 0x3c, 0x27, 0x55, 0x93, 0xb0, 0xbf, 0xe7, 0x91, 0x63, 0x61, 0xe0, 0x67, 0xc7, 0x95, + 0x3e, 0x8d, 0x3b, 0xdb, 0x17, 0x50, 0xc3, 0xf0, 0x1a, 0x94, 0xdf, 0x8d, 0x15, 0x79, 0x00, 0x27, + 0x03, 0x48, 0xf6, 0x60, 0x42, 0xec, 0xdd, 0xf8, 0x5b, 0xce, 0xb1, 0xbb, 0xc9, 0x39, 0x66, 0x34, + 0xef, 0xb6, 0x41, 0xc2, 0x47, 0xa3, 0xc9, 0x86, 0x7c, 0x01, 0x93, 0x52, 0x53, 0x13, 0x8c, 0xb9, + 0x37, 0xd3, 0xbd, 0xee, 0x8c, 0x4d, 0x1a, 0xce, 0x39, 0xc1, 0x88, 0x35, 0x59, 0x2e, 0x76, 0x9c, + 0xf3, 0xe0, 0x69, 0x9a, 0x6c, 0x90, 0x88, 0x26, 0x1b, 0xb0, 0xb9, 0x4f, 0x81, 0xa4, 0xbf, 0xab, + 0xd7, 0x74, 0x9a, 0xd0, 0xa6, 0xd3, 0x5c, 0x15, 0xa6, 0x32, 0x3e, 0xe0, 0x4c, 0x2c, 0x3e, 0x05, + 0x92, 0x6e, 0xe9, 0x59, 0x38, 0x58, 0x37, 0xe1, 0x35, 0x25, 0x02, 0x35, 0x1a, 0x0c, 0x9e, 0xd2, + 0x02, 0xfe, 0x9b, 0x45, 0xa8, 0xf4, 0x40, 0x25, 0xff, 0x7f, 0x21, 0x29, 0x6d, 0x3e, 0x1a, 0xdf, + 0x4f, 0x4a, 0x3b, 0x9b, 0x3e, 0x43, 0xec, 0x0b, 0x1f, 0xfc, 0xd6, 0x5f, 0xbc, 0xf0, 0xc9, 0x23, + 0xdd, 0x65, 0x67, 0x97, 0xd6, 0x80, 0x2e, 0x2d, 0x1b, 0xa6, 0x8d, 0x33, 0xdb, 0x69, 0x36, 0xaf, + 0xab, 0x00, 0x22, 0x7b, 0xeb, 0xba, 0x7f, 0x20, 0xf4, 0x44, 0x0d, 0x62, 0xdd, 0x87, 0x99, 0x04, + 0x4f, 0x61, 0x95, 0xff, 0x3e, 0xa8, 0x47, 0xec, 0xc8, 0xb4, 0x7f, 0xe1, 0xfc, 0x2f, 0x8e, 0x2b, + 0x13, 0x4c, 0xa5, 0xbf, 0x1d, 0xa7, 0x06, 0x90, 0x7f, 0x59, 0x1b, 0xfa, 0xbd, 0x42, 0xb5, 0xa5, + 0x07, 0xf7, 0x21, 0xf7, 0x60, 0x88, 0x43, 0x12, 0x01, 0xb8, 0x75, 0x6c, 0xb1, 0x26, 0x08, 0x44, + 0x6b, 0x06, 0x9f, 0xdc, 0xe2, 0x8f, 0x6a, 0x1c, 0x22, 0xc2, 0xda, 0xe5, 0x09, 0x69, 0x62, 0xb0, + 0x0a, 0xf2, 0x3d, 0x50, 0x8d, 0x43, 0x59, 0x48, 0x27, 0x10, 0x89, 0xe7, 0xf9, 0xcf, 0x5a, 0xb4, + 0xc9, 0x93, 0xfd, 0x2d, 0x8c, 0x0b, 0x27, 0x90, 0x01, 0x87, 0x31, 0x40, 0x32, 0xeb, 0x13, 0x98, + 0x61, 0x9a, 0x42, 0x90, 0xac, 0x0f, 0xd3, 0x50, 0x30, 0x98, 0xe9, 0x59, 0xef, 0x30, 0x10, 0x7a, + 0xd6, 0x8b, 0x42, 0x6b, 0x1d, 0x2e, 0x72, 0xab, 0xa4, 0xfe, 0x49, 0xf1, 0x1d, 0xc0, 0x20, 0xfe, + 0x4e, 0x3c, 0xd8, 0xcc, 0xf8, 0x7a, 0x8e, 0x67, 0x7d, 0x8c, 0x2f, 0x82, 0xc4, 0x20, 0x75, 0x7d, + 0x2f, 0x36, 0x41, 0x9e, 0xee, 0x09, 0xf1, 0xff, 0x0c, 0x97, 0xab, 0xed, 0x36, 0xf5, 0x9a, 0x31, + 0xe1, 0x4e, 0xe0, 0x9c, 0x32, 0xc0, 0x03, 0xa9, 0xc2, 0x20, 0x62, 0xab, 0x0b, 0x54, 0xd1, 0xdc, + 0x8c, 0xe6, 0x20, 0x9e, 0x88, 0xc8, 0x8a, 0x15, 0x70, 0x4a, 0xab, 0x09, 0xb3, 0xb5, 0xce, 0xfe, + 0x91, 0x1b, 0xa1, 0x3f, 0x3e, 0x06, 0x49, 0x91, 0x75, 0xaf, 0xc9, 0x1c, 0x62, 0x5c, 0x18, 0x37, + 0xe3, 0x97, 0x23, 0xe8, 0xd2, 0x2f, 0x02, 0xa7, 0x3c, 0xbd, 0x77, 0x3b, 0x26, 0x45, 0xf3, 0x0b, + 0xaf, 0x05, 0x8b, 0x45, 0x9e, 0x31, 0x6b, 0x0a, 0xce, 0xeb, 0x97, 0x51, 0x7c, 0x84, 0xcc, 0xc0, + 0x94, 0x79, 0xc9, 0xc4, 0xc1, 0x5f, 0xc3, 0x34, 0x37, 0x82, 0xf3, 0x88, 0xea, 0xf3, 0x71, 0xf0, + 0xf0, 0xe2, 0xde, 0x7c, 0xe2, 0x21, 0x00, 0xfa, 0x07, 0xab, 0x5c, 0x19, 0x7b, 0xf3, 0xfc, 0x55, + 0xe7, 0xd3, 0x79, 0xe3, 0x2a, 0xb3, 0xb8, 0x37, 0xbf, 0x30, 0x2c, 0x22, 0xd3, 0x32, 0xee, 0xbc, + 0xfb, 0xbf, 0x13, 0xee, 0xf3, 0x18, 0x48, 0x60, 0x95, 0x3a, 0xf8, 0xe8, 0x27, 0xfb, 0x39, 0xf6, + 0x24, 0x14, 0x55, 0x9c, 0xca, 0xa2, 0xdb, 0xb4, 0xfe, 0xa8, 0x00, 0x37, 0xb9, 0x32, 0x96, 0x4d, + 0x87, 0x37, 0x4e, 0x39, 0xc4, 0xe4, 0x3d, 0x18, 0x0c, 0x35, 0xef, 0x08, 0x4b, 0xb4, 0xbc, 0x1b, + 0x27, 0x4e, 0x40, 0xaa, 0x30, 0xae, 0xbf, 0x6d, 0x39, 0x5d, 0x08, 0x3c, 0x7b, 0xec, 0xe8, 0xb1, + 0xa3, 0xde, 0xbb, 0x3c, 0x81, 0x4b, 0xcb, 0xdf, 0xb0, 0x01, 0x21, 0x76, 0x27, 0x71, 0x72, 0x88, + 0x9f, 0xfb, 0x9e, 0xdb, 0x11, 0x23, 0xc6, 0x3c, 0xd6, 0x27, 0xc1, 0xec, 0x8c, 0x2c, 0x37, 0x38, + 0xa5, 0xbe, 0x8f, 0xda, 0x06, 0xcc, 0xfa, 0xd3, 0x02, 0x5c, 0xce, 0xae, 0x4d, 0x2c, 0x2c, 0x6b, + 0x70, 0x7e, 0xd1, 0xf1, 0x7c, 0xcf, 0x6d, 0x38, 0xad, 0x5a, 0xe3, 0x90, 0x36, 0x3b, 0x2a, 0x7e, + 0xad, 0x5a, 0x65, 0x0e, 0xa8, 0x27, 0xc9, 0x25, 0x8a, 0x9d, 0xa6, 0x62, 0xa7, 0x43, 0x7c, 0x1e, + 0xc1, 0xd7, 0xde, 0x16, 0x0d, 0x14, 0x3f, 0xde, 0xb2, 0x9c, 0x52, 0x72, 0x57, 0x5a, 0xfb, 0x9b, + 0xbb, 0x9e, 0x1b, 0x29, 0x22, 0x6e, 0xe6, 0xc9, 0x2a, 0xb2, 0xfe, 0x55, 0x01, 0x2e, 0x62, 0xca, + 0x2a, 0x23, 0x09, 0x66, 0x1c, 0xc6, 0x59, 0x46, 0x22, 0x2e, 0x18, 0xcf, 0x3d, 0x0c, 0x6c, 0x33, + 0x24, 0x31, 0x79, 0x13, 0x06, 0x6a, 0xd2, 0x5b, 0x6b, 0x32, 0x91, 0x61, 0x58, 0x50, 0xb0, 0x72, + 0x1b, 0xb1, 0xd8, 0x9e, 0xb3, 0x44, 0xc3, 0x06, 0xf5, 0x30, 0x15, 0x34, 0xb7, 0x3a, 0x68, 0x90, + 0x38, 0x1c, 0xd3, 0x40, 0x5e, 0x38, 0xa6, 0x41, 0x33, 0x1c, 0x93, 0xf5, 0x94, 0x27, 0xac, 0x4a, + 0x7e, 0x90, 0xe8, 0xa4, 0x8f, 0x53, 0x99, 0xa3, 0xf9, 0x3e, 0x70, 0x21, 0xeb, 0xcb, 0x98, 0x82, + 0x9e, 0x48, 0x0a, 0x9d, 0x1f, 0x36, 0x79, 0x1b, 0x5e, 0x31, 0x70, 0xab, 0xad, 0x96, 0xff, 0x8c, + 0x36, 0xb7, 0x03, 0xff, 0xc8, 0x8f, 0x8c, 0x84, 0x3d, 0x22, 0x75, 0x7a, 0x7c, 0x9f, 0x23, 0x46, + 0x65, 0x02, 0x6c, 0xfd, 0x4f, 0xf0, 0x6a, 0x0f, 0x8e, 0xe2, 0xa3, 0x6a, 0x70, 0xde, 0x49, 0x94, + 0x49, 0xb7, 0x9b, 0x57, 0xb3, 0xbe, 0x2b, 0xc9, 0x28, 0xb4, 0xd3, 0xf4, 0xb7, 0x76, 0x8c, 0x6c, + 0xcb, 0xa4, 0x0c, 0xd3, 0xdb, 0xf6, 0xd6, 0xd2, 0xee, 0xe2, 0x4e, 0x7d, 0xe7, 0x8b, 0xed, 0xe5, + 0xfa, 0xee, 0xe6, 0xc3, 0xcd, 0xad, 0x47, 0x9b, 0x3c, 0xee, 0xb8, 0x51, 0xb2, 0xb3, 0x5c, 0xdd, + 0x28, 0x15, 0xc8, 0x34, 0x94, 0x0c, 0xf0, 0xf2, 0xee, 0x42, 0xa9, 0x78, 0xeb, 0x6b, 0x23, 0x8b, + 0x30, 0xb9, 0x0c, 0xe5, 0xda, 0xee, 0xf6, 0xf6, 0x96, 0xad, 0xb8, 0xea, 0x51, 0xcf, 0x67, 0xe0, + 0xbc, 0x51, 0x7a, 0xdf, 0x5e, 0x5e, 0x2e, 0x15, 0x58, 0x53, 0x0c, 0xf0, 0xb6, 0xbd, 0xbc, 0xb1, + 0xb6, 0xbb, 0x51, 0x2a, 0xde, 0xaa, 0xeb, 0x6f, 0xcc, 0xc8, 0x25, 0x98, 0x5d, 0x5a, 0xde, 0x5b, + 0x5b, 0x5c, 0xce, 0xe2, 0x3d, 0x0d, 0x25, 0xbd, 0x70, 0x67, 0x6b, 0x67, 0x9b, 0xb3, 0xd6, 0xa1, + 0x8f, 0x96, 0x17, 0xaa, 0xbb, 0x3b, 0xab, 0x9b, 0xa5, 0x7e, 0x6b, 0x60, 0xa4, 0x58, 0x2a, 0xde, + 0xfa, 0xb1, 0xf1, 0x00, 0x8d, 0x35, 0x5f, 0xa0, 0xef, 0xd6, 0xaa, 0x2b, 0xf9, 0x55, 0xf0, 0xd2, + 0x8d, 0xfb, 0xd5, 0x52, 0x81, 0x5c, 0x81, 0x8b, 0x06, 0x74, 0xbb, 0x5a, 0xab, 0x3d, 0xda, 0xb2, + 0x97, 0xd6, 0x97, 0x6b, 0xb5, 0x52, 0xf1, 0xd6, 0x9e, 0x11, 0x82, 0x8e, 0xd5, 0xb0, 0x71, 0xbf, + 0x5a, 0xb7, 0x97, 0x3f, 0xdb, 0x5d, 0xb3, 0x97, 0x97, 0xd2, 0x35, 0x18, 0xa5, 0x5f, 0x2c, 0xd7, + 0x4a, 0x05, 0x32, 0x05, 0xe7, 0x0c, 0xe8, 0xe6, 0x56, 0xa9, 0x78, 0xeb, 0x35, 0x11, 0xa5, 0x8c, + 0x4c, 0x02, 0x2c, 0x2d, 0xd7, 0x16, 0x97, 0x37, 0x97, 0xd6, 0x36, 0x57, 0x4a, 0x7d, 0x64, 0x02, + 0x46, 0xab, 0xea, 0x67, 0xe1, 0xd6, 0x07, 0x70, 0x2e, 0x71, 0xb4, 0x67, 0x18, 0xea, 0x50, 0x5c, + 0xea, 0x43, 0xf1, 0xcb, 0x9f, 0x68, 0x5f, 0xe5, 0xa7, 0xf4, 0x52, 0xe1, 0xd6, 0x82, 0xcc, 0x6a, + 0xab, 0xcd, 0x73, 0x32, 0x06, 0xc3, 0x4b, 0xcb, 0xf7, 0xab, 0xbb, 0xeb, 0x3b, 0xa5, 0x3e, 0xf6, + 0x63, 0xd1, 0x5e, 0xae, 0xee, 0x2c, 0x2f, 0x95, 0x0a, 0x64, 0x14, 0x06, 0x6b, 0x3b, 0xd5, 0x9d, + 0xe5, 0x52, 0x91, 0x8c, 0xc0, 0xc0, 0x6e, 0x6d, 0xd9, 0x2e, 0xf5, 0xcf, 0xff, 0xd3, 0xff, 0xaf, + 0xc0, 0x8d, 0x8c, 0xf2, 0x31, 0xd3, 0xd7, 0xda, 0x61, 0x52, 0x2c, 0x79, 0x22, 0x85, 0x67, 0xee, + 0xc9, 0x11, 0xb5, 0x80, 0xb9, 0x2e, 0xb7, 0x2e, 0x88, 0x70, 0xb3, 0x70, 0xb7, 0x40, 0x6c, 0xf4, + 0x52, 0x49, 0x9c, 0xad, 0x14, 0xe7, 0xec, 0xe3, 0xef, 0xdc, 0x95, 0xae, 0x47, 0x32, 0xf2, 0x6b, + 0x60, 0xe9, 0x3c, 0x73, 0x4e, 0x20, 0xdf, 0x3f, 0xdd, 0x49, 0x43, 0xd6, 0xf9, 0xda, 0xe9, 0xd0, + 0xc9, 0x03, 0x98, 0x60, 0xba, 0xb9, 0x42, 0x23, 0x97, 0x92, 0x84, 0xda, 0x71, 0x60, 0xee, 0x72, + 0x76, 0xa1, 0xca, 0xb2, 0x33, 0x8e, 0x1f, 0xc2, 0x0f, 0xd6, 0x21, 0x91, 0x91, 0x2c, 0x24, 0x84, + 0xaf, 0xf8, 0x73, 0xe7, 0x13, 0xe0, 0xbd, 0x7b, 0x77, 0x0b, 0xa4, 0x86, 0x61, 0xe4, 0x0c, 0x25, + 0x9f, 0xc8, 0xd7, 0x75, 0x69, 0xed, 0x9f, 0xb7, 0xa6, 0xa2, 0x72, 0x62, 0xe6, 0x9c, 0x0e, 0x36, + 0x81, 0xa4, 0x75, 0x67, 0x72, 0x2d, 0x1e, 0x07, 0xd9, 0x6a, 0xf5, 0xdc, 0x85, 0x94, 0xf3, 0xe1, + 0x32, 0xd3, 0x9e, 0xc8, 0x32, 0x4c, 0x8a, 0x67, 0xea, 0x42, 0x9b, 0x27, 0xdd, 0xce, 0x03, 0xb9, + 0x6c, 0x56, 0x50, 0x4e, 0xea, 0x44, 0x40, 0xe6, 0xe2, 0xef, 0x48, 0x1e, 0x13, 0xe6, 0x2e, 0x65, + 0x96, 0x89, 0xef, 0xbb, 0x0f, 0x93, 0xe6, 0xe1, 0x82, 0xc8, 0x0e, 0xca, 0x3c, 0x73, 0xe4, 0x36, + 0xa8, 0x0e, 0xb3, 0x1b, 0x8e, 0x8b, 0x77, 0x25, 0xc2, 0xc5, 0x4d, 0x3a, 0xa8, 0x91, 0x4a, 0x17, + 0x8f, 0xb5, 0x1a, 0xf5, 0x9a, 0xaa, 0x13, 0xf2, 0x22, 0xe6, 0xe3, 0xb4, 0xa9, 0x49, 0x1d, 0xd9, + 0x74, 0xf0, 0x23, 0x96, 0x99, 0xe7, 0x38, 0xcb, 0x67, 0x73, 0x2e, 0xcf, 0xcd, 0x98, 0x6c, 0xa0, + 0x92, 0x9e, 0xe0, 0xa8, 0x8d, 0x89, 0x33, 0xb3, 0x2b, 0x63, 0xb0, 0x04, 0x2d, 0x3f, 0xbc, 0x28, + 0x0c, 0x49, 0x8e, 0xe0, 0x72, 0x99, 0xdd, 0x2d, 0x90, 0xaf, 0x71, 0x56, 0x67, 0xb2, 0x7b, 0xe4, + 0x46, 0x87, 0x42, 0xfb, 0xb9, 0x94, 0xc9, 0x40, 0x4c, 0x94, 0x2e, 0xdc, 0x6d, 0x98, 0xce, 0xf2, + 0x6c, 0x56, 0x02, 0xed, 0xe2, 0xf6, 0x9c, 0x3b, 0x0a, 0x6c, 0x76, 0xd4, 0x68, 0xe6, 0x77, 0x52, + 0x17, 0xc7, 0xda, 0x5c, 0x9e, 0x1f, 0xc1, 0x24, 0x1b, 0x25, 0x0f, 0x29, 0x6d, 0x57, 0x5b, 0xee, + 0x53, 0x1a, 0x12, 0x19, 0x03, 0x58, 0x81, 0xf2, 0x68, 0x6f, 0x16, 0xc8, 0xf7, 0x60, 0xec, 0x91, + 0x13, 0x35, 0x0e, 0x45, 0x2c, 0x4c, 0x19, 0x2a, 0x13, 0x61, 0x73, 0xf2, 0x17, 0x16, 0xde, 0x2d, + 0x90, 0x1f, 0xc2, 0xf0, 0x0a, 0x8d, 0xf0, 0x75, 0xf3, 0x75, 0xe5, 0xe4, 0xc7, 0x6d, 0x93, 0x6b, + 0x9e, 0x7a, 0xc2, 0x23, 0x1b, 0x9c, 0x34, 0xe4, 0x92, 0x3b, 0x00, 0x7c, 0x41, 0x40, 0x0e, 0xc9, + 0xe2, 0xb9, 0x54, 0xb3, 0xc9, 0x0a, 0x53, 0x1e, 0x5a, 0x34, 0xa2, 0xa7, 0xad, 0x32, 0x4f, 0x46, + 0xeb, 0x30, 0xa9, 0x12, 0x13, 0x6d, 0x62, 0xc8, 0x12, 0x2b, 0xc1, 0x2c, 0x3c, 0x03, 0xb7, 0x0f, + 0xd8, 0xac, 0xe0, 0x59, 0x79, 0x31, 0xb6, 0x05, 0xae, 0xa4, 0xb3, 0x7a, 0x80, 0x0c, 0x7d, 0x09, + 0x95, 0x42, 0xe4, 0x68, 0x1a, 0xed, 0xaa, 0x1f, 0x46, 0x26, 0xad, 0x82, 0x64, 0xd3, 0xfe, 0x2a, + 0xcc, 0xe9, 0xf5, 0x9a, 0xc1, 0x98, 0xe3, 0x35, 0x37, 0x2f, 0xc6, 0xf3, 0xdc, 0xf5, 0x2e, 0x18, + 0xe2, 0xfc, 0xd6, 0xff, 0x3b, 0xc5, 0x02, 0x2e, 0x27, 0x4b, 0x30, 0x25, 0xeb, 0xda, 0x6a, 0x53, + 0xaf, 0x56, 0x5b, 0xc5, 0x24, 0x34, 0xd2, 0xa5, 0x44, 0x83, 0x49, 0xee, 0x24, 0x5d, 0xc4, 0xb6, + 0x3e, 0x23, 0x86, 0x05, 0xe9, 0x16, 0xd9, 0x22, 0xde, 0xfa, 0x32, 0xa3, 0x04, 0x3f, 0xe4, 0x46, + 0x25, 0x43, 0xf9, 0xdf, 0x9b, 0x27, 0x5d, 0x0e, 0x40, 0x73, 0x39, 0x47, 0x88, 0xbb, 0x05, 0xf2, + 0x05, 0x90, 0xf4, 0x91, 0x44, 0x89, 0x30, 0xf7, 0xf8, 0xa5, 0x44, 0xd8, 0xe5, 0x3c, 0xb3, 0x02, + 0x33, 0x2a, 0x82, 0x8d, 0x56, 0xeb, 0x3c, 0xc9, 0x69, 0x4d, 0x5e, 0x2b, 0xc9, 0x27, 0x30, 0x25, + 0x06, 0xad, 0x5e, 0x40, 0x4a, 0x6a, 0xfd, 0x11, 0xa7, 0x92, 0xdc, 0x71, 0xfa, 0x00, 0x66, 0x6a, + 0x09, 0x89, 0x71, 0x4f, 0xf8, 0x8b, 0x26, 0x0b, 0x04, 0xd6, 0x68, 0xc4, 0x45, 0x96, 0xcd, 0xeb, + 0x21, 0x10, 0x6e, 0x14, 0x92, 0xec, 0x9e, 0xba, 0xf4, 0x19, 0xb9, 0x92, 0x68, 0x3a, 0x03, 0x22, + 0x1a, 0x2e, 0x60, 0xb9, 0x5f, 0xb6, 0xc3, 0x73, 0x4a, 0x23, 0xd4, 0xb8, 0x43, 0xbf, 0x66, 0x10, + 0x18, 0xd7, 0xf0, 0xa2, 0x03, 0x2e, 0xe6, 0x62, 0x90, 0xdf, 0xc0, 0xd0, 0xb1, 0xdd, 0x8f, 0x55, + 0xe4, 0x7b, 0x59, 0xa7, 0xdf, 0x9c, 0x83, 0xe1, 0xdc, 0x9b, 0xa7, 0x43, 0x56, 0x07, 0xd9, 0x89, + 0x15, 0x1a, 0x6d, 0xb7, 0x3a, 0x07, 0x2e, 0x66, 0x1b, 0x25, 0xca, 0x68, 0xa4, 0x40, 0x62, 0x5c, + 0xca, 0x88, 0x6d, 0x71, 0x41, 0x8d, 0xfe, 0x84, 0xac, 0x41, 0x89, 0xaf, 0xff, 0x1a, 0x8b, 0x2b, + 0x29, 0x16, 0x02, 0xc5, 0x09, 0x9c, 0xa3, 0x30, 0xb7, 0xb7, 0xee, 0x70, 0xa7, 0x25, 0x22, 0xe7, + 0xa4, 0xae, 0x60, 0x4e, 0x19, 0x30, 0x15, 0x4e, 0x9f, 0xf5, 0x88, 0x4d, 0x43, 0x1a, 0xc9, 0x18, + 0x35, 0x3c, 0xd7, 0xec, 0x8d, 0x78, 0xb3, 0x4f, 0x97, 0xc6, 0x53, 0x3f, 0x11, 0x4f, 0x6d, 0xef, + 0x2d, 0xa2, 0xf2, 0xef, 0x66, 0x30, 0x7d, 0xcd, 0xd0, 0x49, 0xce, 0xc6, 0xf7, 0x6d, 0xdc, 0x83, + 0x30, 0x2e, 0xcf, 0x4c, 0xdc, 0x36, 0xf6, 0x5b, 0x52, 0x4d, 0x68, 0x54, 0x7b, 0xf3, 0xb8, 0xa4, + 0xb1, 0x4d, 0x92, 0xa9, 0xb0, 0x9d, 0x20, 0xa0, 0x1e, 0x27, 0xce, 0xd3, 0x37, 0xb2, 0xa8, 0x3f, + 0xc6, 0xa5, 0x47, 0xa3, 0xe6, 0x0f, 0xf6, 0x7a, 0xb1, 0xe0, 0xb9, 0x91, 0xee, 0x16, 0xc8, 0x7b, + 0x30, 0x22, 0xda, 0xc8, 0x88, 0x8c, 0x46, 0x87, 0x5d, 0x5a, 0x8d, 0x94, 0xc0, 0x85, 0x84, 0x6d, + 0x36, 0x71, 0xf2, 0x7a, 0x9f, 0xb7, 0xf9, 0x3d, 0xb6, 0xd9, 0x36, 0x5f, 0x84, 0x72, 0x51, 0xee, + 0xba, 0x48, 0x59, 0x56, 0xb1, 0x5c, 0x24, 0xa8, 0xc7, 0xf6, 0xc8, 0x99, 0x30, 0xbd, 0x19, 0x03, + 0x22, 0xaa, 0xb8, 0x66, 0x4a, 0x6f, 0x36, 0xc0, 0xbd, 0xf6, 0xda, 0x35, 0x28, 0x55, 0x1b, 0xb8, + 0x13, 0xd4, 0xe8, 0x91, 0xd3, 0x3e, 0xf4, 0x03, 0xaa, 0x0e, 0x2d, 0xc9, 0x02, 0xc9, 0x6b, 0x46, + 0x69, 0x16, 0xa2, 0x60, 0x9d, 0x3a, 0x18, 0x35, 0x7a, 0x56, 0xa9, 0x16, 0x89, 0xa2, 0x6c, 0x8a, + 0x2e, 0x87, 0x94, 0xe9, 0x45, 0x76, 0xac, 0x6a, 0x7d, 0x3b, 0x36, 0x1f, 0xe0, 0x82, 0xa1, 0x90, + 0x43, 0xb5, 0x43, 0x28, 0x90, 0x3a, 0xce, 0xc9, 0xb7, 0x3b, 0x0a, 0xb5, 0x2a, 0xef, 0x8c, 0x63, + 0xb1, 0xe4, 0x51, 0xe7, 0x55, 0xff, 0x03, 0x98, 0x5c, 0x66, 0x0b, 0x7a, 0xa7, 0xe9, 0xf2, 0x48, + 0xf9, 0xc4, 0x0c, 0x7d, 0x9e, 0x4b, 0xb8, 0x2a, 0xd3, 0x91, 0x21, 0xa9, 0x38, 0xfa, 0xcb, 0x3d, + 0x45, 0x83, 0xc9, 0xfe, 0x98, 0x96, 0x6c, 0x45, 0xb2, 0x02, 0x3c, 0x9a, 0x8b, 0xb3, 0xfe, 0x2c, + 0xd7, 0x08, 0xab, 0xed, 0x76, 0x4b, 0x9a, 0xa4, 0xf9, 0xbd, 0xfb, 0xab, 0xc6, 0x11, 0x32, 0x55, + 0x2e, 0x79, 0xa7, 0x95, 0xc6, 0xcf, 0xb5, 0xf4, 0xc0, 0x39, 0x3c, 0x73, 0xca, 0x7b, 0x8d, 0x45, + 0x15, 0xdb, 0xba, 0xda, 0x6a, 0xa5, 0x88, 0x43, 0xf2, 0x86, 0xc9, 0x3d, 0x0b, 0xa7, 0x57, 0x0d, + 0x78, 0x44, 0xe7, 0x5a, 0x57, 0xb5, 0xdd, 0xe6, 0x8b, 0xe5, 0x55, 0xb5, 0x60, 0x98, 0x05, 0xe9, + 0x23, 0x7a, 0xb2, 0x5c, 0xac, 0xed, 0x0f, 0x70, 0x98, 0xc5, 0x39, 0x84, 0x89, 0x7e, 0xe0, 0x4d, + 0xa6, 0x50, 0x56, 0x4a, 0x58, 0xa2, 0x50, 0xed, 0x13, 0xe7, 0x50, 0xf5, 0x89, 0x13, 0x12, 0x2b, + 0xcb, 0x4c, 0x02, 0x2e, 0xf9, 0x5d, 0xcd, 0x2b, 0x56, 0x96, 0xd2, 0x52, 0x32, 0x4f, 0xbb, 0xfa, + 0xe4, 0x9c, 0xfc, 0xff, 0xea, 0x93, 0x73, 0x13, 0xbc, 0x3f, 0x80, 0x52, 0x32, 0x45, 0xb4, 0x62, + 0x9a, 0x93, 0x3b, 0x3a, 0xb7, 0x4f, 0xee, 0xc3, 0xb4, 0xde, 0xa3, 0xea, 0xbb, 0xf3, 0x56, 0xff, + 0x3c, 0x3e, 0x3b, 0x30, 0x93, 0x99, 0xd1, 0x59, 0x6d, 0xb1, 0xdd, 0xf2, 0x3d, 0xe7, 0x72, 0xa5, + 0x70, 0x21, 0x3b, 0xa9, 0x3b, 0x79, 0xc5, 0x3c, 0xf8, 0x67, 0xa7, 0xb8, 0x9e, 0x7b, 0xb5, 0x07, + 0x96, 0x10, 0xe8, 0xd7, 0xb8, 0x03, 0xa6, 0xea, 0xb8, 0xae, 0x99, 0x02, 0x72, 0x2a, 0xb0, 0xba, + 0xa1, 0xa8, 0x31, 0x30, 0x9d, 0x51, 0x9c, 0x2f, 0xe2, 0x1b, 0xf9, 0x3c, 0xe3, 0x81, 0xb5, 0x27, + 0x43, 0x38, 0xe7, 0x4a, 0xa6, 0x6b, 0xf2, 0xef, 0x2e, 0x67, 0xc9, 0x39, 0x35, 0x1e, 0x4e, 0xdf, + 0xe4, 0x3c, 0x6e, 0x4d, 0x65, 0xb6, 0x31, 0x32, 0x73, 0x27, 0xcd, 0x36, 0x59, 0x19, 0xc5, 0x95, + 0x18, 0xba, 0xe5, 0xac, 0xe7, 0xbb, 0xf1, 0x57, 0xdc, 0x8e, 0x63, 0x56, 0xa1, 0xdb, 0x71, 0x32, + 0xf9, 0x5f, 0xcb, 0x47, 0xd0, 0x99, 0x3b, 0xfc, 0xd2, 0x36, 0x91, 0x5a, 0x9c, 0xe8, 0x47, 0xa5, + 0xec, 0xb4, 0xe3, 0x6a, 0x6c, 0x64, 0xa2, 0xe8, 0x55, 0x3c, 0x92, 0x73, 0x30, 0x47, 0x4a, 0x5d, + 0xf2, 0xae, 0x77, 0x57, 0x53, 0xb6, 0xa0, 0x1c, 0x77, 0x66, 0xe2, 0x03, 0xce, 0xd8, 0x95, 0x52, + 0x18, 0x17, 0x73, 0xb3, 0xad, 0x93, 0xd7, 0x53, 0x33, 0x3d, 0x47, 0x30, 0x5d, 0xab, 0xe0, 0xeb, + 0xb9, 0x16, 0x12, 0xfa, 0x52, 0x6c, 0xc4, 0xd5, 0x13, 0xb3, 0xa7, 0xd6, 0xf3, 0x8c, 0xac, 0xed, + 0x2b, 0xa8, 0x17, 0x6b, 0x99, 0xd7, 0x73, 0xbf, 0xfa, 0x4a, 0x16, 0x9f, 0x30, 0xbd, 0xe2, 0x6a, + 0xed, 0x92, 0x7a, 0x5a, 0xb2, 0xe0, 0x2c, 0x2b, 0xee, 0x69, 0x9a, 0x96, 0xc7, 0x67, 0x09, 0xc6, + 0xb4, 0x94, 0xed, 0xe4, 0xa2, 0x21, 0x26, 0x63, 0x0f, 0x9d, 0x33, 0x3e, 0xce, 0xdc, 0x3e, 0x17, + 0xd1, 0x94, 0xac, 0x12, 0xbf, 0xe7, 0xb6, 0xe2, 0x52, 0x9a, 0x87, 0x61, 0x46, 0x56, 0x52, 0xe0, + 0xad, 0xb9, 0x9c, 0x14, 0x8e, 0xd1, 0xa0, 0xfc, 0x4f, 0x22, 0xba, 0x68, 0x7a, 0x34, 0x29, 0x5f, + 0x7f, 0x9d, 0x12, 0x79, 0x61, 0x31, 0x8f, 0x8b, 0x8c, 0xf9, 0x77, 0x41, 0xd9, 0xc4, 0x34, 0x28, + 0x1a, 0x28, 0xb2, 0xd9, 0x6c, 0xe3, 0xd3, 0x91, 0x8c, 0x1c, 0xf6, 0x6a, 0x85, 0xed, 0x9a, 0xe2, + 0x3e, 0x43, 0x77, 0x53, 0x6b, 0x76, 0x2e, 0xc7, 0xae, 0x49, 0xed, 0x73, 0x5b, 0xfa, 0x23, 0x6d, + 0xcd, 0x4e, 0x65, 0xaa, 0x27, 0x37, 0x93, 0x8a, 0x5b, 0x5e, 0x32, 0xfb, 0x2e, 0x7b, 0xc2, 0x74, + 0x56, 0x92, 0x7b, 0xcd, 0xae, 0x9b, 0x9b, 0x01, 0x3f, 0x43, 0x0a, 0xb6, 0x1c, 0xff, 0x39, 0xdc, + 0xba, 0xa4, 0xbc, 0xcf, 0x6d, 0xe1, 0x97, 0xda, 0x42, 0x97, 0x48, 0x4d, 0xaf, 0x8e, 0xe3, 0x3d, + 0x72, 0xd7, 0xe7, 0xf2, 0xde, 0xc4, 0xc7, 0x46, 0xe9, 0xbc, 0xf2, 0x4a, 0xb3, 0xe9, 0x96, 0x75, + 0x3e, 0xd3, 0xec, 0x3b, 0x93, 0xfe, 0x44, 0xc6, 0xef, 0x42, 0xc2, 0x68, 0xdb, 0xab, 0x61, 0x5f, + 0xcb, 0xc5, 0x38, 0x23, 0x1f, 0x7d, 0x62, 0x31, 0xce, 0xcf, 0x58, 0xdf, 0xe5, 0x18, 0x74, 0xae, + 0xe6, 0x1e, 0x78, 0x5a, 0x3a, 0x79, 0x75, 0x08, 0x4a, 0x67, 0xb8, 0x57, 0x4b, 0x4c, 0x56, 0xf6, + 0xf9, 0x2d, 0xa6, 0xff, 0x70, 0xed, 0x5d, 0x4f, 0x0c, 0x4e, 0xe6, 0xf2, 0xf3, 0xa1, 0xab, 0xe5, + 0x26, 0x33, 0x93, 0xb8, 0xc6, 0x50, 0xcf, 0xca, 0xad, 0x18, 0x66, 0x24, 0x08, 0x57, 0x0c, 0x33, + 0xd3, 0x78, 0xdf, 0x41, 0xab, 0x8b, 0xed, 0xb7, 0xa8, 0x6e, 0x75, 0xd1, 0xd2, 0x3c, 0x27, 0x8c, + 0x1e, 0xe4, 0x63, 0x18, 0x55, 0x69, 0xb0, 0x95, 0x7d, 0x3b, 0x99, 0x89, 0x7b, 0xae, 0x9c, 0x2e, + 0x10, 0x15, 0xbe, 0x23, 0x0d, 0x1f, 0x58, 0x67, 0xd9, 0x34, 0x18, 0xe5, 0x57, 0xfb, 0x8e, 0xb4, + 0x7a, 0x18, 0x64, 0xa9, 0x24, 0xd8, 0x49, 0xb2, 0x1f, 0xc0, 0x78, 0x9c, 0xf0, 0x7a, 0x6f, 0x5e, + 0x23, 0x4c, 0x64, 0xc1, 0x4e, 0x12, 0xbe, 0x27, 0xaf, 0x34, 0xb0, 0x3e, 0xb3, 0xb0, 0xfb, 0x2e, + 0xfe, 0xb1, 0xb4, 0xb2, 0x18, 0x2d, 0x4d, 0xa5, 0xcf, 0xee, 0xb2, 0xf8, 0x8e, 0xeb, 0xe9, 0x2a, + 0x55, 0xd7, 0x66, 0x24, 0x9c, 0x55, 0x5d, 0x9b, 0x95, 0x30, 0x36, 0x36, 0xf9, 0x7f, 0x21, 0x4d, + 0x0a, 0x31, 0xd3, 0x2b, 0x46, 0xb3, 0x52, 0x7c, 0xaf, 0xe6, 0x15, 0x27, 0x59, 0xd7, 0xa0, 0x94, + 0xcc, 0xad, 0xa9, 0xce, 0x63, 0x39, 0x49, 0x50, 0xd5, 0x21, 0x2f, 0x37, 0x29, 0xe7, 0xb6, 0xb4, + 0x8f, 0x9b, 0x7c, 0xaf, 0x67, 0x37, 0x4a, 0x67, 0x9d, 0x6f, 0x30, 0x9f, 0x30, 0xd2, 0x6c, 0xea, + 0x27, 0xe5, 0x54, 0x1a, 0x4f, 0x5d, 0xb3, 0xca, 0xc8, 0xcc, 0xe9, 0xca, 0x88, 0x4f, 0xd9, 0x49, + 0xce, 0xdf, 0x30, 0x8f, 0xb0, 0x5d, 0x62, 0xb2, 0xf7, 0xbc, 0xfe, 0x25, 0xbf, 0x02, 0xb3, 0x39, + 0x31, 0xa6, 0xc9, 0xab, 0x09, 0x4b, 0x6b, 0x76, 0x0c, 0x6a, 0x35, 0x40, 0x32, 0xf3, 0x5f, 0x6f, + 0xa0, 0xdf, 0x80, 0x11, 0xdb, 0x21, 0x75, 0x17, 0xf7, 0xc8, 0x8d, 0x0e, 0x79, 0x9a, 0x67, 0x6d, + 0xd9, 0xcc, 0x0c, 0x0a, 0x41, 0x6a, 0x78, 0x16, 0x31, 0xa0, 0x19, 0xd7, 0x71, 0x19, 0x0c, 0xe7, + 0xb2, 0x19, 0xb2, 0xb5, 0x83, 0x8d, 0x85, 0x8c, 0xc0, 0x1b, 0x6a, 0x2c, 0xe4, 0x07, 0xe5, 0xc8, + 0x6d, 0xe6, 0xb6, 0xd4, 0x91, 0xb2, 0x39, 0xe6, 0xc7, 0xe0, 0xc8, 0xe5, 0xf8, 0x80, 0x71, 0x4c, + 0x85, 0xd5, 0x20, 0x39, 0xe8, 0xdd, 0x57, 0x0f, 0x5b, 0x6e, 0xb9, 0x26, 0xd5, 0xbc, 0xd6, 0xbe, + 0xbc, 0x00, 0x1e, 0xb9, 0xed, 0x5b, 0x96, 0xf3, 0x29, 0xbb, 0x7d, 0xa7, 0xdd, 0x74, 0xd5, 0xfd, + 0x57, 0x22, 0xb2, 0x8b, 0xf1, 0xa1, 0x1a, 0x7c, 0x2e, 0x07, 0x4e, 0x36, 0xd1, 0x11, 0x28, 0x09, + 0xd5, 0x0e, 0xa5, 0xd9, 0xa1, 0x63, 0x72, 0xf9, 0xf1, 0x71, 0x6c, 0x84, 0xde, 0x38, 0xcb, 0x38, + 0x4e, 0xc4, 0xec, 0x10, 0xe3, 0xd8, 0x80, 0x9e, 0x6d, 0x1c, 0x27, 0x18, 0x9a, 0xe3, 0x38, 0xd9, + 0xcc, 0xe4, 0x49, 0x3f, 0xb7, 0x57, 0x93, 0xcd, 0x54, 0xe3, 0x38, 0x9b, 0x63, 0x7e, 0x88, 0x94, + 0x5c, 0x8e, 0x6a, 0x1c, 0x9b, 0x1c, 0x73, 0xd0, 0x4f, 0x39, 0x8e, 0x93, 0x95, 0x98, 0xe3, 0xf8, + 0x4c, 0xed, 0x53, 0xe3, 0x38, 0xbb, 0x7d, 0x67, 0x1e, 0xc7, 0x89, 0x98, 0x42, 0xc6, 0x87, 0x66, + 0x8d, 0xe3, 0x24, 0x3e, 0x1f, 0xc7, 0x49, 0x68, 0xc2, 0xb8, 0xd2, 0x65, 0x1c, 0x27, 0x29, 0x3f, + 0x43, 0x7e, 0x89, 0x78, 0x28, 0xa7, 0x19, 0xc9, 0xb9, 0xa1, 0x54, 0xc8, 0x23, 0x34, 0xef, 0x25, + 0xe0, 0xa7, 0x1b, 0xcd, 0x97, 0xf3, 0x98, 0xe2, 0x78, 0xde, 0x93, 0x42, 0x4c, 0x36, 0xd7, 0xb4, + 0x5d, 0x65, 0x87, 0x83, 0xe9, 0xd2, 0xe0, 0x3d, 0x36, 0x6e, 0x9a, 0x5d, 0xf8, 0x76, 0x8b, 0x66, + 0xd3, 0x85, 0xaf, 0x3a, 0xca, 0x24, 0xf9, 0xe6, 0x92, 0x74, 0x1f, 0xdf, 0x9f, 0xcb, 0x0b, 0x8e, + 0x24, 0xdd, 0x7c, 0xe2, 0x70, 0x74, 0xe6, 0x96, 0xaa, 0x43, 0x52, 0xb2, 0xa5, 0x67, 0x1d, 0xe7, + 0x1b, 0x52, 0x7b, 0x48, 0x85, 0xc1, 0x4a, 0x7c, 0xb4, 0x3e, 0xd6, 0x73, 0x4b, 0xc8, 0x0e, 0xda, + 0x72, 0xd3, 0x70, 0xcd, 0x0e, 0x9c, 0x17, 0x6f, 0xab, 0x27, 0xd7, 0x54, 0x40, 0x1f, 0x9d, 0x6b, + 0x5e, 0xb4, 0x1f, 0xc5, 0x35, 0x4d, 0xfd, 0x09, 0x5a, 0xbf, 0xc4, 0x6b, 0x2b, 0xef, 0xb1, 0x9f, + 0x6f, 0x49, 0x99, 0x32, 0x9c, 0x95, 0x18, 0x2e, 0xfa, 0x88, 0x7d, 0x24, 0x6e, 0xf0, 0x24, 0x30, + 0x57, 0xf8, 0x59, 0xf4, 0xe4, 0x13, 0x28, 0x89, 0xe5, 0x2d, 0x66, 0x90, 0x85, 0x98, 0xdb, 0x75, + 0x0b, 0xd2, 0xe8, 0x76, 0x8a, 0x16, 0x9c, 0xc6, 0xd8, 0x76, 0x1a, 0x49, 0xe4, 0x5b, 0xa6, 0xd8, + 0x76, 0xb8, 0x13, 0x74, 0xc2, 0x88, 0x36, 0xd3, 0x16, 0x25, 0xb3, 0x31, 0xd2, 0x33, 0xc2, 0x44, + 0xdf, 0x9b, 0x27, 0x6b, 0xb8, 0xb6, 0x99, 0xe0, 0x6e, 0x26, 0xb7, 0x6c, 0x36, 0xb8, 0xf4, 0xac, + 0xaa, 0x67, 0x3d, 0x66, 0x9b, 0xf2, 0xea, 0xce, 0x6f, 0x94, 0x12, 0xd1, 0x29, 0xbf, 0x2e, 0x4f, + 0x44, 0x1f, 0xa2, 0x1b, 0x00, 0x37, 0xff, 0xf5, 0x92, 0x4c, 0xf2, 0xa1, 0x11, 0xf9, 0x14, 0x46, + 0x25, 0x71, 0x6f, 0x81, 0x24, 0xa9, 0x51, 0x20, 0x4b, 0x30, 0x61, 0xbc, 0xa2, 0x52, 0xa7, 0x9b, + 0xac, 0xb7, 0x55, 0x5d, 0xfa, 0x79, 0xc2, 0x78, 0x2d, 0xa5, 0xb8, 0x64, 0xbd, 0xa1, 0xca, 0xe5, + 0xf2, 0x43, 0x18, 0x13, 0x22, 0xed, 0x2a, 0x8d, 0x7c, 0x7b, 0xdb, 0x8c, 0xe6, 0x91, 0xdc, 0x69, + 0xba, 0xd1, 0xa2, 0xef, 0x3d, 0x76, 0x0f, 0x7a, 0x0a, 0x26, 0x4d, 0xb2, 0x37, 0x4f, 0xbe, 0xc2, + 0xa4, 0xc8, 0x32, 0x55, 0x35, 0x8d, 0x9e, 0xf9, 0xc1, 0x13, 0xd7, 0x3b, 0xe8, 0xc1, 0xf2, 0x9a, + 0xc9, 0x32, 0x49, 0x27, 0x7d, 0x47, 0xbe, 0x82, 0xb9, 0x5a, 0x3e, 0xf3, 0x9e, 0x4c, 0xba, 0x6f, + 0x2f, 0x35, 0xb8, 0x8c, 0xde, 0x33, 0x67, 0x6d, 0x7b, 0x57, 0xa6, 0x5f, 0xf0, 0x48, 0x8a, 0xd2, + 0x56, 0xdf, 0xf0, 0x83, 0x66, 0x6f, 0x8e, 0x15, 0xd3, 0x91, 0x36, 0x41, 0x26, 0x85, 0xf1, 0x05, + 0x5c, 0xac, 0xe5, 0xb2, 0xee, 0xc5, 0xa2, 0x97, 0x26, 0x79, 0x09, 0x45, 0x71, 0xc6, 0x76, 0x77, + 0xe5, 0xb9, 0x86, 0x6b, 0x1a, 0xdb, 0x87, 0xb6, 0x03, 0xfa, 0x98, 0x06, 0xe8, 0xae, 0xdd, 0xcb, + 0x51, 0xd9, 0x44, 0x97, 0x5f, 0xbe, 0x06, 0xe7, 0x6b, 0x29, 0x56, 0x79, 0x24, 0xbd, 0xee, 0x7f, + 0xa6, 0xf0, 0x4b, 0x4f, 0xd9, 0xae, 0x1e, 0x5e, 0x42, 0x63, 0x2b, 0x34, 0xda, 0x5d, 0xeb, 0x21, + 0x25, 0xf9, 0x9e, 0x40, 0x22, 0xee, 0xdd, 0x63, 0x94, 0x35, 0x8d, 0x32, 0x8d, 0x91, 0x3b, 0x79, + 0x3f, 0x95, 0x77, 0x21, 0x3d, 0xab, 0xcd, 0xe3, 0xf0, 0x16, 0xae, 0x85, 0xc2, 0x65, 0x79, 0x36, + 0x56, 0x01, 0x38, 0x24, 0x36, 0xd5, 0x69, 0xde, 0xcb, 0x21, 0xa9, 0xf2, 0xe3, 0x1f, 0x1f, 0x1e, + 0x02, 0x76, 0x35, 0xe5, 0xca, 0xde, 0x95, 0x05, 0xb7, 0x82, 0xae, 0xfb, 0x8d, 0x27, 0xba, 0x15, + 0x54, 0x4b, 0x9b, 0x3f, 0x67, 0x26, 0xb5, 0x17, 0x2b, 0x3e, 0x66, 0xb6, 0xd7, 0x1d, 0xbf, 0xf4, + 0xc4, 0xf9, 0x73, 0xb3, 0x29, 0xb8, 0xb0, 0x20, 0xbd, 0x25, 0x6d, 0x8b, 0x58, 0xa1, 0xc9, 0x39, + 0x57, 0x34, 0xca, 0xac, 0x88, 0x44, 0xa6, 0x59, 0x51, 0x6f, 0x68, 0xbe, 0x2d, 0x9f, 0xa4, 0x73, + 0xfc, 0xab, 0xc3, 0x4a, 0x6e, 0xfa, 0xff, 0x2e, 0xfe, 0x5b, 0x53, 0xc2, 0xeb, 0xc7, 0x10, 0xbc, + 0x8a, 0x46, 0x9c, 0x2e, 0x8b, 0x45, 0xa9, 0x3b, 0x23, 0xdd, 0x2d, 0x90, 0x4d, 0xb8, 0xb0, 0x42, + 0x23, 0xb1, 0xc6, 0xd9, 0x34, 0x8c, 0x02, 0xb7, 0x11, 0x75, 0xbd, 0x18, 0x94, 0x67, 0x93, 0x0c, + 0x9a, 0xbd, 0xb7, 0x19, 0xbf, 0x5a, 0x36, 0xbf, 0xae, 0x74, 0x5d, 0x5c, 0x64, 0xc5, 0x6d, 0xc3, + 0x59, 0x9a, 0x98, 0x3f, 0xc4, 0x87, 0xb9, 0x07, 0x4e, 0x3e, 0x69, 0x29, 0x8e, 0x7c, 0x22, 0x4e, + 0x5b, 0xb7, 0x61, 0x88, 0x13, 0xe5, 0x6e, 0xa8, 0xe3, 0x3a, 0x0d, 0xb9, 0x07, 0xa3, 0xca, 0x85, + 0x86, 0x18, 0x45, 0xb9, 0xed, 0xba, 0x07, 0xa3, 0xfc, 0x68, 0x75, 0x7a, 0x92, 0x0f, 0x61, 0x54, + 0xf9, 0xdc, 0x9c, 0x79, 0xa7, 0xff, 0x04, 0x26, 0x74, 0xef, 0x9b, 0xb3, 0x0b, 0xf2, 0x87, 0x78, + 0x7d, 0x2b, 0x6f, 0x49, 0xf2, 0xe9, 0x67, 0x12, 0x01, 0x61, 0x84, 0x48, 0xf9, 0x02, 0x29, 0x81, + 0xb9, 0xcd, 0x3f, 0x9f, 0xa2, 0x26, 0x1f, 0xca, 0x97, 0x4c, 0x8a, 0x38, 0x8d, 0xd4, 0x45, 0x66, + 0x93, 0x5c, 0xcc, 0x2f, 0x42, 0xac, 0x16, 0xd8, 0x9e, 0xcd, 0x3e, 0xcd, 0x35, 0x73, 0x6f, 0xd1, + 0xe5, 0x71, 0xd9, 0x42, 0x2d, 0x2d, 0x95, 0x88, 0x2e, 0x9f, 0xd1, 0xd5, 0xfc, 0xdc, 0x75, 0xd8, + 0x19, 0x0f, 0xf0, 0x14, 0x98, 0x2a, 0xcd, 0xfd, 0xbc, 0x2e, 0xb9, 0xf0, 0xe2, 0x63, 0x6f, 0x9a, + 0x5d, 0x17, 0xb2, 0x6e, 0xa7, 0x68, 0xf1, 0x3e, 0xf3, 0xa5, 0xb0, 0x5b, 0x93, 0x4e, 0x8c, 0xa7, + 0xff, 0xd8, 0xfc, 0x96, 0x5d, 0xca, 0xb8, 0xd8, 0xee, 0xd9, 0x17, 0x79, 0xec, 0x7e, 0x05, 0xb5, + 0xc3, 0xcc, 0x88, 0x60, 0xf9, 0xcc, 0x6e, 0x6a, 0xbe, 0x11, 0x99, 0x94, 0x6a, 0xd3, 0x7b, 0x82, + 0x4f, 0xc4, 0xb2, 0x53, 0xf5, 0xbd, 0xd6, 0x83, 0x8b, 0x94, 0xc4, 0xeb, 0x3d, 0xf1, 0xd4, 0x35, + 0xe9, 0x25, 0xbe, 0xc3, 0x66, 0xd7, 0xd7, 0x23, 0xf5, 0x60, 0xc6, 0xcd, 0xb5, 0xf2, 0x10, 0xcd, + 0x66, 0x68, 0x7a, 0x88, 0x76, 0xfd, 0x86, 0x3c, 0xf1, 0x7f, 0x06, 0x95, 0xd8, 0x01, 0xe4, 0x6c, + 0x9d, 0x90, 0xef, 0x98, 0x48, 0x52, 0x92, 0x0a, 0x49, 0xb7, 0x5c, 0x3c, 0x73, 0xd7, 0xf3, 0x24, + 0xac, 0x3f, 0x83, 0x11, 0x8e, 0x6d, 0x89, 0xa4, 0x95, 0x79, 0xe9, 0x2f, 0xbb, 0xd8, 0x61, 0xc5, + 0x9b, 0xb9, 0x97, 0xc2, 0x28, 0xdd, 0xdb, 0x67, 0x67, 0xa4, 0xfc, 0x33, 0x12, 0x8c, 0xac, 0x2e, + 0xdd, 0xdb, 0xfb, 0xea, 0xb1, 0x9c, 0xd3, 0xaf, 0x67, 0xef, 0x50, 0x27, 0x7e, 0x27, 0x96, 0x08, + 0x20, 0xa8, 0xbf, 0xcd, 0x4d, 0x17, 0x25, 0x1f, 0x39, 0x65, 0x61, 0x28, 0xa7, 0xa8, 0xb2, 0xac, + 0x82, 0xc1, 0xd9, 0x51, 0xc4, 0x0f, 0xdc, 0xe8, 0xf9, 0xa2, 0xbd, 0x1e, 0x9b, 0x15, 0xf4, 0x02, + 0xc9, 0x1b, 0x64, 0xa1, 0xbd, 0x4e, 0xbe, 0xc4, 0xa5, 0x44, 0xb0, 0x5f, 0xf0, 0xfd, 0x28, 0x8c, + 0x02, 0xa7, 0x5d, 0x6b, 0x04, 0x6e, 0x3b, 0xca, 0xfd, 0xe8, 0xd8, 0x87, 0x3b, 0x8b, 0x4c, 0x73, + 0x29, 0x15, 0x01, 0xe6, 0xb3, 0x22, 0xdf, 0xa8, 0x67, 0x35, 0x59, 0x85, 0x5d, 0x4e, 0x2e, 0x35, + 0x19, 0x52, 0xfe, 0x65, 0x32, 0xad, 0xc3, 0x6c, 0x4e, 0xbc, 0x20, 0x75, 0x7b, 0xdb, 0x3d, 0x9e, + 0xd0, 0x5c, 0xf7, 0x8a, 0xc9, 0x57, 0x30, 0x93, 0x19, 0x50, 0x48, 0x59, 0xa0, 0xbb, 0x85, 0x1b, + 0xea, 0xc5, 0xfc, 0x09, 0x94, 0xf9, 0x83, 0x0e, 0xf4, 0x5b, 0x36, 0x62, 0xcb, 0xc4, 0xcf, 0x7c, + 0x72, 0x10, 0x92, 0xeb, 0x75, 0x3e, 0x9e, 0x7a, 0x6c, 0x3e, 0x8d, 0x41, 0x45, 0x12, 0xe9, 0xd6, + 0xd5, 0xc4, 0xcb, 0x2a, 0xec, 0xf6, 0x96, 0x68, 0x1b, 0x66, 0xf6, 0x68, 0xe0, 0x3e, 0x7e, 0x9e, + 0x64, 0x28, 0x25, 0x93, 0x59, 0xda, 0x8d, 0xe3, 0xe7, 0x30, 0xbb, 0xe8, 0x1f, 0xb5, 0xc5, 0xab, + 0x3d, 0x83, 0xa7, 0xba, 0x8a, 0xcf, 0x2e, 0xef, 0xed, 0xcb, 0x34, 0x97, 0x9f, 0x18, 0x5f, 0xb9, + 0xb0, 0xf5, 0xcc, 0x9d, 0xaf, 0xde, 0x9e, 0x99, 0xf4, 0x3b, 0x38, 0x08, 0xb3, 0x32, 0xe5, 0xeb, + 0x83, 0xb0, 0x4b, 0x26, 0xfd, 0x9c, 0x37, 0x60, 0xb3, 0x39, 0xc9, 0xf1, 0xbb, 0x70, 0x3d, 0x45, + 0x6b, 0x37, 0xe5, 0xde, 0x62, 0xe6, 0xfa, 0x4e, 0x38, 0x4d, 0x67, 0x26, 0x02, 0xcf, 0x6c, 0xa7, + 0x16, 0x55, 0xa1, 0xd5, 0xea, 0xa2, 0x62, 0x11, 0x3d, 0xac, 0x02, 0xc3, 0x44, 0x23, 0xfe, 0x84, + 0x4e, 0xdb, 0x6d, 0xb5, 0x4e, 0x11, 0xa3, 0x52, 0xfb, 0x01, 0x8c, 0xd7, 0xf4, 0xca, 0x33, 0x2a, + 0xc9, 0x1d, 0x14, 0xea, 0x15, 0x50, 0xef, 0xb6, 0x77, 0xf1, 0x05, 0x55, 0x1b, 0xcf, 0xa9, 0xbe, + 0x22, 0xd7, 0x75, 0xc6, 0x48, 0xdc, 0xa6, 0x76, 0x81, 0xac, 0xbc, 0x8a, 0xca, 0x75, 0x26, 0x3b, + 0xd7, 0x5b, 0x9d, 0xa7, 0x9a, 0x49, 0xa6, 0xcd, 0x24, 0x56, 0xef, 0xfc, 0xb4, 0xca, 0x27, 0xbe, + 0x6b, 0xde, 0x4d, 0xee, 0xe7, 0x13, 0xa7, 0xaa, 0xd3, 0xfd, 0x7c, 0x52, 0x09, 0xf0, 0x74, 0x3f, + 0x9f, 0x8c, 0xec, 0x76, 0xcb, 0xc8, 0x2b, 0xce, 0xd1, 0xd3, 0xc5, 0x18, 0xa1, 0xd8, 0x64, 0xa4, + 0x02, 0x7a, 0xa8, 0x07, 0xe7, 0xe0, 0x99, 0x7d, 0xba, 0xd8, 0x5a, 0x93, 0x41, 0x39, 0x12, 0xa9, + 0x80, 0xee, 0x43, 0x89, 0x27, 0x39, 0x88, 0xe3, 0x19, 0xc6, 0xae, 0x7f, 0xe9, 0xdc, 0x0b, 0x5d, + 0x3a, 0xb5, 0x94, 0x8c, 0x04, 0xa7, 0x4c, 0x66, 0x39, 0x21, 0xe2, 0xba, 0x0c, 0x55, 0x88, 0xe3, + 0xbd, 0x29, 0xc3, 0x54, 0x2a, 0x04, 0xdc, 0xdc, 0xc5, 0x8c, 0x12, 0xa5, 0x52, 0x8e, 0xeb, 0xd1, + 0xe1, 0xd4, 0x27, 0x65, 0x84, 0x8c, 0x9b, 0xbb, 0x94, 0x59, 0x26, 0x18, 0x45, 0x3c, 0x45, 0x73, + 0x76, 0x62, 0xe9, 0xf8, 0x21, 0x57, 0x17, 0x1c, 0x59, 0xcd, 0xad, 0xd3, 0xa0, 0x8a, 0x5a, 0xa9, + 0xca, 0x50, 0x94, 0x91, 0xcd, 0xfa, 0xf5, 0x8c, 0xb7, 0x16, 0x06, 0x46, 0xec, 0x0d, 0xd6, 0x3d, + 0xb5, 0x36, 0x79, 0x24, 0x33, 0xc6, 0xe4, 0xd4, 0xd4, 0x8b, 0x41, 0x6e, 0x0f, 0x3e, 0x92, 0x39, + 0x62, 0x5e, 0x36, 0xe3, 0x7d, 0xb8, 0x9c, 0x78, 0xc0, 0x61, 0x32, 0xbe, 0x95, 0xfd, 0xca, 0x23, + 0x53, 0x3c, 0xf9, 0x3a, 0xfb, 0xb5, 0xf4, 0x43, 0x8f, 0x44, 0xbf, 0x9f, 0x75, 0xcd, 0xdb, 0x80, + 0x49, 0x5c, 0x66, 0x64, 0x5e, 0xf6, 0x38, 0x36, 0x8c, 0x09, 0x4e, 0x06, 0x29, 0x4a, 0x96, 0xaa, + 0xf7, 0xe3, 0xe3, 0xe2, 0x51, 0x30, 0xcf, 0xf2, 0x3e, 0x67, 0xbe, 0x14, 0x46, 0x60, 0xd6, 0x2e, + 0x26, 0x92, 0xc7, 0x93, 0x1f, 0xc2, 0xb9, 0xf8, 0xad, 0x30, 0x67, 0x91, 0x81, 0xd6, 0xc5, 0x50, + 0x76, 0x2e, 0x7e, 0x30, 0x7c, 0x76, 0xf2, 0x55, 0xb9, 0x15, 0xc5, 0xe4, 0x57, 0x52, 0xcf, 0x5d, + 0x8c, 0x6f, 0x38, 0xcd, 0x8e, 0xa4, 0xc9, 0xf6, 0xac, 0xbd, 0xd3, 0xc0, 0xe9, 0x96, 0x1d, 0xf6, + 0x50, 0x9f, 0x6e, 0x5d, 0x43, 0x33, 0x2a, 0xf5, 0x37, 0x87, 0xcf, 0x06, 0xdc, 0xc0, 0x50, 0x29, + 0xdb, 0x3c, 0x38, 0x5e, 0x36, 0x56, 0x7e, 0xdb, 0x93, 0x01, 0x56, 0x5a, 0x70, 0xbd, 0x67, 0xdc, + 0x47, 0x72, 0xc7, 0x70, 0x71, 0xe9, 0x1d, 0x21, 0xb2, 0xcb, 0xc9, 0x63, 0x3a, 0x2b, 0x7c, 0xa2, + 0xda, 0x67, 0xbb, 0x44, 0x72, 0x54, 0xfb, 0x6c, 0xd7, 0xf8, 0x8b, 0x9f, 0x63, 0x1a, 0x26, 0xb1, + 0x47, 0x61, 0xf8, 0x23, 0xea, 0xf1, 0x80, 0xd0, 0x5d, 0xaf, 0x7d, 0xae, 0x9b, 0x97, 0xa2, 0x29, + 0x42, 0x3c, 0xd3, 0x5c, 0x15, 0x27, 0xb1, 0x3c, 0xe6, 0xbd, 0x99, 0x74, 0x71, 0xad, 0xbe, 0xca, + 0x07, 0xe0, 0x99, 0x5b, 0x9e, 0x03, 0x5f, 0x58, 0xfa, 0xd9, 0x7f, 0xb8, 0x5a, 0xf8, 0xd9, 0xcf, + 0xaf, 0x16, 0xfe, 0xf5, 0xcf, 0xaf, 0x16, 0xfe, 0xfd, 0xcf, 0xaf, 0x16, 0xbe, 0x9c, 0x3f, 0x5d, + 0x58, 0xe2, 0x46, 0xcb, 0xa5, 0x5e, 0x74, 0x87, 0xb3, 0x1b, 0xc2, 0xff, 0xde, 0xfa, 0xef, 0x01, + 0x00, 0x00, 0xff, 0xff, 0x61, 0x3e, 0x6a, 0x54, 0x91, 0xea, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -16807,10 +16805,6 @@ type AuthServiceClient interface { GetAccessRequestsV2(ctx context.Context, in *types.AccessRequestFilter, opts ...grpc.CallOption) (AuthService_GetAccessRequestsV2Client, error) // ListAccessRequests gets access requests with pagination and sorting. ListAccessRequests(ctx context.Context, in *ListAccessRequestsRequest, opts ...grpc.CallOption) (*ListAccessRequestsResponse, error) - // CreateAccessRequest creates a new access request. - // Deprecated: use CreateAccessRequestV2 instead. - // DELETE IN v15.0.0. - CreateAccessRequest(ctx context.Context, in *types.AccessRequestV3, opts ...grpc.CallOption) (*emptypb.Empty, error) // CreateAccessRequestV2 creates a new access request. CreateAccessRequestV2(ctx context.Context, in *types.AccessRequestV3, opts ...grpc.CallOption) (*types.AccessRequestV3, error) // DeleteAccessRequest deletes an access request. @@ -16975,10 +16969,6 @@ type AuthServiceClient interface { GenerateSnowflakeJWT(ctx context.Context, in *SnowflakeJWTRequest, opts ...grpc.CallOption) (*SnowflakeJWTResponse, error) // GetRole retrieves a role described by the given request. GetRole(ctx context.Context, in *GetRoleRequest, opts ...grpc.CallOption) (*types.RoleV6, error) - // GetRole retrieves all roles. - // - // DELETE IN 17.0 - GetRoles(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetRolesResponse, error) // ListRoles is a paginated role getter. ListRoles(ctx context.Context, in *ListRolesRequest, opts ...grpc.CallOption) (*ListRolesResponse, error) // CreateRole creates a new role. @@ -17894,15 +17884,6 @@ func (c *authServiceClient) ListAccessRequests(ctx context.Context, in *ListAcce return out, nil } -func (c *authServiceClient) CreateAccessRequest(ctx context.Context, in *types.AccessRequestV3, opts ...grpc.CallOption) (*emptypb.Empty, error) { - out := new(emptypb.Empty) - err := c.cc.Invoke(ctx, "/proto.AuthService/CreateAccessRequest", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *authServiceClient) CreateAccessRequestV2(ctx context.Context, in *types.AccessRequestV3, opts ...grpc.CallOption) (*types.AccessRequestV3, error) { out := new(types.AccessRequestV3) err := c.cc.Invoke(ctx, "/proto.AuthService/CreateAccessRequestV2", in, out, opts...) @@ -18604,15 +18585,6 @@ func (c *authServiceClient) GetRole(ctx context.Context, in *GetRoleRequest, opt return out, nil } -func (c *authServiceClient) GetRoles(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*GetRolesResponse, error) { - out := new(GetRolesResponse) - err := c.cc.Invoke(ctx, "/proto.AuthService/GetRoles", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *authServiceClient) ListRoles(ctx context.Context, in *ListRolesRequest, opts ...grpc.CallOption) (*ListRolesResponse, error) { out := new(ListRolesResponse) err := c.cc.Invoke(ctx, "/proto.AuthService/ListRoles", in, out, opts...) @@ -20211,10 +20183,6 @@ type AuthServiceServer interface { GetAccessRequestsV2(*types.AccessRequestFilter, AuthService_GetAccessRequestsV2Server) error // ListAccessRequests gets access requests with pagination and sorting. ListAccessRequests(context.Context, *ListAccessRequestsRequest) (*ListAccessRequestsResponse, error) - // CreateAccessRequest creates a new access request. - // Deprecated: use CreateAccessRequestV2 instead. - // DELETE IN v15.0.0. - CreateAccessRequest(context.Context, *types.AccessRequestV3) (*emptypb.Empty, error) // CreateAccessRequestV2 creates a new access request. CreateAccessRequestV2(context.Context, *types.AccessRequestV3) (*types.AccessRequestV3, error) // DeleteAccessRequest deletes an access request. @@ -20379,10 +20347,6 @@ type AuthServiceServer interface { GenerateSnowflakeJWT(context.Context, *SnowflakeJWTRequest) (*SnowflakeJWTResponse, error) // GetRole retrieves a role described by the given request. GetRole(context.Context, *GetRoleRequest) (*types.RoleV6, error) - // GetRole retrieves all roles. - // - // DELETE IN 17.0 - GetRoles(context.Context, *emptypb.Empty) (*GetRolesResponse, error) // ListRoles is a paginated role getter. ListRoles(context.Context, *ListRolesRequest) (*ListRolesResponse, error) // CreateRole creates a new role. @@ -20907,9 +20871,6 @@ func (*UnimplementedAuthServiceServer) GetAccessRequestsV2(req *types.AccessRequ func (*UnimplementedAuthServiceServer) ListAccessRequests(ctx context.Context, req *ListAccessRequestsRequest) (*ListAccessRequestsResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListAccessRequests not implemented") } -func (*UnimplementedAuthServiceServer) CreateAccessRequest(ctx context.Context, req *types.AccessRequestV3) (*emptypb.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateAccessRequest not implemented") -} func (*UnimplementedAuthServiceServer) CreateAccessRequestV2(ctx context.Context, req *types.AccessRequestV3) (*types.AccessRequestV3, error) { return nil, status.Errorf(codes.Unimplemented, "method CreateAccessRequestV2 not implemented") } @@ -21117,9 +21078,6 @@ func (*UnimplementedAuthServiceServer) GenerateSnowflakeJWT(ctx context.Context, func (*UnimplementedAuthServiceServer) GetRole(ctx context.Context, req *GetRoleRequest) (*types.RoleV6, error) { return nil, status.Errorf(codes.Unimplemented, "method GetRole not implemented") } -func (*UnimplementedAuthServiceServer) GetRoles(ctx context.Context, req *emptypb.Empty) (*GetRolesResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method GetRoles not implemented") -} func (*UnimplementedAuthServiceServer) ListRoles(ctx context.Context, req *ListRolesRequest) (*ListRolesResponse, error) { return nil, status.Errorf(codes.Unimplemented, "method ListRoles not implemented") } @@ -22180,24 +22138,6 @@ func _AuthService_ListAccessRequests_Handler(srv interface{}, ctx context.Contex return interceptor(ctx, in, info, handler) } -func _AuthService_CreateAccessRequest_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(types.AccessRequestV3) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(AuthServiceServer).CreateAccessRequest(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/proto.AuthService/CreateAccessRequest", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(AuthServiceServer).CreateAccessRequest(ctx, req.(*types.AccessRequestV3)) - } - return interceptor(ctx, in, info, handler) -} - func _AuthService_CreateAccessRequestV2_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(types.AccessRequestV3) if err := dec(in); err != nil { @@ -23454,24 +23394,6 @@ func _AuthService_GetRole_Handler(srv interface{}, ctx context.Context, dec func return interceptor(ctx, in, info, handler) } -func _AuthService_GetRoles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(emptypb.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(AuthServiceServer).GetRoles(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/proto.AuthService/GetRoles", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(AuthServiceServer).GetRoles(ctx, req.(*emptypb.Empty)) - } - return interceptor(ctx, in, info, handler) -} - func _AuthService_ListRoles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(ListRolesRequest) if err := dec(in); err != nil { @@ -26393,10 +26315,6 @@ var _AuthService_serviceDesc = grpc.ServiceDesc{ MethodName: "ListAccessRequests", Handler: _AuthService_ListAccessRequests_Handler, }, - { - MethodName: "CreateAccessRequest", - Handler: _AuthService_CreateAccessRequest_Handler, - }, { MethodName: "CreateAccessRequestV2", Handler: _AuthService_CreateAccessRequestV2_Handler, @@ -26661,10 +26579,6 @@ var _AuthService_serviceDesc = grpc.ServiceDesc{ MethodName: "GetRole", Handler: _AuthService_GetRole_Handler, }, - { - MethodName: "GetRoles", - Handler: _AuthService_GetRoles_Handler, - }, { MethodName: "ListRoles", Handler: _AuthService_ListRoles_Handler, diff --git a/api/client/proto/event.pb.go b/api/client/proto/event.pb.go index f022839dcd0c5..8cb8416436e6f 100644 --- a/api/client/proto/event.pb.go +++ b/api/client/proto/event.pb.go @@ -28,6 +28,7 @@ import ( v17 "github.com/gravitational/teleport/api/gen/proto/go/teleport/crownjewel/v1" v18 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobject/v1" v12 "github.com/gravitational/teleport/api/gen/proto/go/teleport/discoveryconfig/v1" + v114 "github.com/gravitational/teleport/api/gen/proto/go/teleport/identitycenter/v1" v15 "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" v19 "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1" v16 "github.com/gravitational/teleport/api/gen/proto/go/teleport/notifications/v1" @@ -182,6 +183,9 @@ type Event struct { // *Event_DynamicWindowsDesktop // *Event_ProvisioningPrincipalState // *Event_AutoUpdateAgentRollout + // *Event_IdentityCenterAccount + // *Event_IdentityCenterPrincipalAssignment + // *Event_IdentityCenterAccountAssignment Resource isEvent_Resource `protobuf_oneof:"Resource"` } @@ -691,6 +695,27 @@ func (x *Event) GetAutoUpdateAgentRollout() *v111.AutoUpdateAgentRollout { return nil } +func (x *Event) GetIdentityCenterAccount() *v114.Account { + if x, ok := x.GetResource().(*Event_IdentityCenterAccount); ok { + return x.IdentityCenterAccount + } + return nil +} + +func (x *Event) GetIdentityCenterPrincipalAssignment() *v114.PrincipalAssignment { + if x, ok := x.GetResource().(*Event_IdentityCenterPrincipalAssignment); ok { + return x.IdentityCenterPrincipalAssignment + } + return nil +} + +func (x *Event) GetIdentityCenterAccountAssignment() *v114.AccountAssignment { + if x, ok := x.GetResource().(*Event_IdentityCenterAccountAssignment); ok { + return x.IdentityCenterAccountAssignment + } + return nil +} + type isEvent_Resource interface { isEvent_Resource() } @@ -1029,6 +1054,23 @@ type Event_AutoUpdateAgentRollout struct { AutoUpdateAgentRollout *v111.AutoUpdateAgentRollout `protobuf:"bytes,71,opt,name=AutoUpdateAgentRollout,proto3,oneof"` } +type Event_IdentityCenterAccount struct { + // IdentityCenterAccount is a resource for tracking Identity Center accounts + IdentityCenterAccount *v114.Account `protobuf:"bytes,72,opt,name=IdentityCenterAccount,proto3,oneof"` +} + +type Event_IdentityCenterPrincipalAssignment struct { + // IdentityCenterPrincipalAssignment is a resource for tracking the AWS + // Permission Sets assigned to a Teleport user or AAccess List + IdentityCenterPrincipalAssignment *v114.PrincipalAssignment `protobuf:"bytes,73,opt,name=IdentityCenterPrincipalAssignment,proto3,oneof"` +} + +type Event_IdentityCenterAccountAssignment struct { + // IdentityCenterAccountlAssignment is a resource representing a potential + // Permission Set grant on a specific AWS account. + IdentityCenterAccountAssignment *v114.AccountAssignment `protobuf:"bytes,74,opt,name=IdentityCenterAccountAssignment,proto3,oneof"` +} + func (*Event_ResourceHeader) isEvent_Resource() {} func (*Event_CertAuthority) isEvent_Resource() {} @@ -1161,6 +1203,12 @@ func (*Event_ProvisioningPrincipalState) isEvent_Resource() {} func (*Event_AutoUpdateAgentRollout) isEvent_Resource() {} +func (*Event_IdentityCenterAccount) isEvent_Resource() {} + +func (*Event_IdentityCenterPrincipalAssignment) isEvent_Resource() {} + +func (*Event_IdentityCenterAccountAssignment) isEvent_Resource() {} + var File_teleport_legacy_client_proto_event_proto protoreflect.FileDescriptor var file_teleport_legacy_client_proto_event_proto_rawDesc = []byte{ @@ -1187,346 +1235,370 @@ var file_teleport_legacy_client_proto_event_proto_rawDesc = []byte{ 0x65, 0x63, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x31, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3b, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x77, 0x61, 0x69, 0x74, 0x69, - 0x6e, 0x67, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x6b, - 0x75, 0x62, 0x65, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 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, 0x1a, 0x28, 0x74, 0x65, - 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x69, 0x64, - 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x26, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x69, 0x64, 0x2f, 0x76, 0x31, 0x2f, 0x66, 0x65, - 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2d, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2b, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2f, - 0x76, 0x31, 0x2f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x1a, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x75, 0x73, - 0x65, 0x72, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x31, 0x2f, - 0x75, 0x73, 0x65, 0x72, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x31, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x75, - 0x73, 0x65, 0x72, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x2f, - 0x76, 0x32, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x68, 0x6f, 0x73, 0x74, 0x75, 0x73, 0x65, - 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x26, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x75, - 0x73, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, - 0xf6, 0x25, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x54, 0x79, 0x70, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, - 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x3f, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, 0x00, - 0x52, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, - 0x12, 0x3e, 0x0a, 0x0d, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, - 0x79, 0x18, 0x03, 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, 0x48, - 0x00, 0x52, 0x0d, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, - 0x12, 0x3b, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, - 0x74, 0x61, 0x74, 0x69, 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x56, 0x32, 0x48, 0x00, 0x52, - 0x0c, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x41, 0x0a, - 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x50, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x56, 0x32, 0x48, 0x00, - 0x52, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, - 0x12, 0x38, 0x0a, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0b, 0x43, - 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x04, 0x55, 0x73, - 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x55, 0x73, 0x65, 0x72, 0x56, 0x32, 0x48, 0x00, 0x52, 0x04, 0x55, 0x73, 0x65, 0x72, 0x12, - 0x23, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x56, 0x36, 0x48, 0x00, 0x52, 0x04, - 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x48, 0x00, 0x52, 0x09, 0x4e, 0x61, 0x6d, - 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x32, 0x48, 0x00, 0x52, 0x06, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x12, 0x3e, 0x0a, 0x0d, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x54, 0x75, 0x6e, 0x6e, - 0x65, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x56, 0x32, - 0x48, 0x00, 0x52, 0x0d, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x54, 0x75, 0x6e, 0x6e, 0x65, - 0x6c, 0x12, 0x47, 0x0a, 0x10, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x10, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, - 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0d, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x33, 0x48, 0x00, 0x52, 0x0d, 0x41, 0x63, 0x63, - 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x0a, 0x41, 0x70, - 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0a, 0x41, 0x70, 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x3e, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, - 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x56, 0x33, - 0x48, 0x00, 0x52, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x56, 0x33, 0x48, 0x00, 0x52, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x12, 0x35, 0x0a, 0x0a, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, - 0x2e, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, - 0x0a, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x08, 0x57, - 0x65, 0x62, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x65, 0x62, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x56, 0x33, - 0x48, 0x00, 0x52, 0x08, 0x57, 0x65, 0x62, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x5c, 0x0a, 0x17, - 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, - 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, - 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x48, - 0x00, 0x52, 0x17, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x59, 0x0a, 0x16, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, - 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x48, 0x00, 0x52, 0x16, 0x53, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2f, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x63, + 0x65, 0x6e, 0x74, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x3b, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6b, 0x75, 0x62, 0x65, 0x77, 0x61, 0x69, 0x74, + 0x69, 0x6e, 0x67, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2f, 0x76, 0x31, 0x2f, + 0x6b, 0x75, 0x62, 0x65, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 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, 0x1a, 0x28, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x69, + 0x64, 0x2f, 0x76, 0x31, 0x2f, 0x62, 0x6f, 0x74, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x26, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x2f, 0x6d, 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x69, 0x64, 0x2f, 0x76, 0x31, 0x2f, 0x66, + 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x2d, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2b, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x27, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, + 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x2f, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, 0x75, + 0x73, 0x65, 0x72, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2f, 0x76, 0x31, + 0x2f, 0x75, 0x73, 0x65, 0x72, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x31, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2f, + 0x75, 0x73, 0x65, 0x72, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, + 0x2f, 0x76, 0x32, 0x2f, 0x73, 0x74, 0x61, 0x74, 0x69, 0x63, 0x68, 0x6f, 0x73, 0x74, 0x75, 0x73, + 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x26, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2f, 0x75, 0x73, 0x65, 0x72, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x2f, 0x76, 0x31, 0x2f, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x22, 0xcf, 0x28, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x24, 0x0a, 0x04, 0x54, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x3f, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, + 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x48, + 0x00, 0x52, 0x0e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x64, 0x65, + 0x72, 0x12, 0x3e, 0x0a, 0x0d, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, + 0x74, 0x79, 0x18, 0x03, 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, + 0x48, 0x00, 0x52, 0x0d, 0x43, 0x65, 0x72, 0x74, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, + 0x79, 0x12, 0x3b, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x56, 0x32, 0x48, 0x00, + 0x52, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x41, + 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x50, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x56, 0x32, 0x48, + 0x00, 0x52, 0x0e, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, + 0x6e, 0x12, 0x38, 0x0a, 0x0b, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0b, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x04, 0x55, + 0x73, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x56, 0x32, 0x48, 0x00, 0x52, 0x04, 0x55, 0x73, 0x65, 0x72, + 0x12, 0x23, 0x0a, 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x56, 0x36, 0x48, 0x00, 0x52, + 0x04, 0x52, 0x6f, 0x6c, 0x65, 0x12, 0x30, 0x0a, 0x09, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, + 0x63, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x48, 0x00, 0x52, 0x09, 0x4e, 0x61, + 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x32, 0x48, 0x00, 0x52, 0x06, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x12, 0x3e, 0x0a, 0x0d, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x54, 0x75, 0x6e, + 0x6e, 0x65, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x56, + 0x32, 0x48, 0x00, 0x52, 0x0d, 0x52, 0x65, 0x76, 0x65, 0x72, 0x73, 0x65, 0x54, 0x75, 0x6e, 0x6e, + 0x65, 0x6c, 0x12, 0x47, 0x0a, 0x10, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x54, 0x75, 0x6e, 0x6e, 0x65, 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x10, 0x54, 0x75, 0x6e, 0x6e, 0x65, + 0x6c, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0d, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x0e, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x56, 0x33, 0x48, 0x00, 0x52, 0x0d, 0x41, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x35, 0x0a, 0x0a, 0x41, + 0x70, 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0a, 0x41, 0x70, 0x70, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x12, 0x3e, 0x0a, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x56, + 0x33, 0x48, 0x00, 0x52, 0x0d, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x12, 0x41, 0x0a, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x0e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x35, 0x0a, 0x0a, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2e, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, 0x00, + 0x52, 0x0a, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x08, + 0x57, 0x65, 0x62, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x65, 0x62, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x56, + 0x33, 0x48, 0x00, 0x52, 0x08, 0x57, 0x65, 0x62, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x5c, 0x0a, + 0x17, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, + 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, + 0x48, 0x00, 0x52, 0x17, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x65, 0x74, 0x77, 0x6f, + 0x72, 0x6b, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x59, 0x0a, 0x16, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x41, 0x0a, 0x0e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, - 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, - 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x4d, 0x0a, 0x12, 0x43, 0x6c, 0x75, 0x73, - 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x17, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, - 0x32, 0x48, 0x00, 0x52, 0x12, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, 0x69, - 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23, 0x0a, 0x04, 0x4c, 0x6f, 0x63, 0x6b, 0x18, - 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4c, 0x6f, - 0x63, 0x6b, 0x56, 0x32, 0x48, 0x00, 0x52, 0x04, 0x4c, 0x6f, 0x63, 0x6b, 0x12, 0x50, 0x0a, 0x13, - 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x56, 0x34, 0x48, 0x00, 0x52, 0x13, 0x4e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x52, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x56, - 0x0a, 0x15, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, - 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, - 0x6b, 0x74, 0x6f, 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x56, 0x33, 0x48, 0x00, 0x52, - 0x15, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x41, 0x0a, 0x0e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, - 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, + 0x64, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x56, 0x32, 0x48, 0x00, 0x52, 0x16, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x41, 0x0a, 0x0e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, + 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x65, 0x66, 0x65, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0e, 0x41, 0x75, 0x74, 0x68, 0x50, + 0x72, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x4d, 0x0a, 0x12, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, + 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x43, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x56, 0x32, 0x48, 0x00, 0x52, 0x12, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x41, 0x75, 0x64, + 0x69, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x23, 0x0a, 0x04, 0x4c, 0x6f, 0x63, 0x6b, + 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4c, + 0x6f, 0x63, 0x6b, 0x56, 0x32, 0x48, 0x00, 0x52, 0x04, 0x4c, 0x6f, 0x63, 0x6b, 0x12, 0x50, 0x0a, + 0x13, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x73, 0x74, 0x72, 0x69, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x56, 0x34, 0x48, 0x00, 0x52, 0x13, 0x4e, 0x65, 0x74, 0x77, + 0x6f, 0x72, 0x6b, 0x52, 0x65, 0x73, 0x74, 0x72, 0x69, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x56, 0x0a, 0x15, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, + 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, - 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x56, 0x33, 0x48, 0x00, 0x52, 0x0e, 0x57, 0x69, 0x6e, 0x64, 0x6f, - 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x12, 0x2f, 0x0a, 0x08, 0x44, 0x61, 0x74, - 0x61, 0x62, 0x61, 0x73, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x56, 0x33, 0x48, 0x00, - 0x52, 0x08, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x09, 0x41, 0x70, - 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, - 0x33, 0x48, 0x00, 0x52, 0x09, 0x41, 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x20, - 0x0a, 0x03, 0x41, 0x70, 0x70, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x41, 0x70, 0x70, 0x56, 0x33, 0x48, 0x00, 0x52, 0x03, 0x41, 0x70, 0x70, - 0x12, 0x41, 0x0a, 0x10, 0x53, 0x6e, 0x6f, 0x77, 0x66, 0x6c, 0x61, 0x6b, 0x65, 0x53, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x2e, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, - 0x00, 0x52, 0x10, 0x53, 0x6e, 0x6f, 0x77, 0x66, 0x6c, 0x61, 0x6b, 0x65, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x10, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, - 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, - 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, - 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x10, 0x4b, 0x75, 0x62, 0x65, - 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x4a, 0x0a, 0x11, - 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, - 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x11, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, - 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x09, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x56, 0x31, 0x48, - 0x00, 0x52, 0x09, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x44, 0x0a, 0x0f, - 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x18, - 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x61, - 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x56, 0x31, 0x48, - 0x00, 0x52, 0x0f, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x59, 0x0a, 0x16, 0x53, 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x24, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x41, 0x4d, 0x4c, 0x49, - 0x64, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, - 0x72, 0x56, 0x31, 0x48, 0x00, 0x52, 0x16, 0x53, 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x3d, 0x0a, - 0x0e, 0x53, 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, - 0x25, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x65, - 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0e, 0x53, 0x41, - 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, 0x09, - 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x26, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, - 0x70, 0x56, 0x31, 0x48, 0x00, 0x52, 0x09, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x12, 0x2f, 0x0a, 0x08, 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x27, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x55, 0x49, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x56, 0x31, 0x48, 0x00, 0x52, 0x08, 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x12, 0x41, 0x0a, 0x0e, 0x4f, 0x6b, 0x74, 0x61, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, - 0x75, 0x6c, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x2e, 0x4f, 0x6b, 0x74, 0x61, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x75, 0x6c, 0x65, - 0x56, 0x31, 0x48, 0x00, 0x52, 0x0e, 0x4f, 0x6b, 0x74, 0x61, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, - 0x52, 0x75, 0x6c, 0x65, 0x12, 0x41, 0x0a, 0x0e, 0x4f, 0x6b, 0x74, 0x61, 0x41, 0x73, 0x73, 0x69, - 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x29, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4f, 0x6b, 0x74, 0x61, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, - 0x65, 0x6e, 0x74, 0x56, 0x31, 0x48, 0x00, 0x52, 0x0e, 0x4f, 0x6b, 0x74, 0x61, 0x41, 0x73, 0x73, - 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x0b, 0x49, 0x6e, 0x74, 0x65, 0x67, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x56, 0x31, 0x48, 0x00, 0x52, 0x0b, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x38, 0x0a, 0x0b, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x2b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, - 0x61, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x56, 0x31, 0x48, 0x00, 0x52, 0x0b, - 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x57, 0x0a, 0x16, 0x48, + 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x56, 0x33, 0x48, 0x00, + 0x52, 0x15, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x41, 0x0a, 0x0e, 0x57, 0x69, 0x6e, 0x64, 0x6f, + 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x17, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, + 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x56, 0x33, 0x48, 0x00, 0x52, 0x0e, 0x57, 0x69, 0x6e, 0x64, + 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x12, 0x2f, 0x0a, 0x08, 0x44, 0x61, + 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x56, 0x33, 0x48, + 0x00, 0x52, 0x08, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x09, 0x41, + 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, + 0x56, 0x33, 0x48, 0x00, 0x52, 0x09, 0x41, 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, + 0x20, 0x0a, 0x03, 0x41, 0x70, 0x70, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x41, 0x70, 0x70, 0x56, 0x33, 0x48, 0x00, 0x52, 0x03, 0x41, 0x70, + 0x70, 0x12, 0x41, 0x0a, 0x10, 0x53, 0x6e, 0x6f, 0x77, 0x66, 0x6c, 0x61, 0x6b, 0x65, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, + 0x70, 0x65, 0x73, 0x2e, 0x57, 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x32, + 0x48, 0x00, 0x52, 0x10, 0x53, 0x6e, 0x6f, 0x77, 0x66, 0x6c, 0x61, 0x6b, 0x65, 0x53, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x47, 0x0a, 0x10, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, + 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x18, 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, + 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x10, 0x4b, 0x75, 0x62, + 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x12, 0x4a, 0x0a, + 0x11, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x56, 0x33, 0x48, 0x00, 0x52, 0x11, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, + 0x65, 0x73, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x09, 0x49, 0x6e, 0x73, + 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x56, 0x31, + 0x48, 0x00, 0x52, 0x09, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x65, 0x72, 0x12, 0x44, 0x0a, + 0x0f, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, + 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x56, 0x31, + 0x48, 0x00, 0x52, 0x0f, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, + 0x69, 0x63, 0x65, 0x12, 0x59, 0x0a, 0x16, 0x53, 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x18, 0x24, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x53, 0x41, 0x4d, 0x4c, + 0x49, 0x64, 0x50, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, + 0x65, 0x72, 0x56, 0x31, 0x48, 0x00, 0x52, 0x16, 0x53, 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x12, 0x3d, + 0x0a, 0x0e, 0x53, 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x18, 0x25, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x57, + 0x65, 0x62, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x56, 0x32, 0x48, 0x00, 0x52, 0x0e, 0x53, + 0x41, 0x4d, 0x4c, 0x49, 0x64, 0x50, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x32, 0x0a, + 0x09, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x26, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x12, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x56, 0x31, 0x48, 0x00, 0x52, 0x09, 0x55, 0x73, 0x65, 0x72, 0x47, 0x72, 0x6f, 0x75, + 0x70, 0x12, 0x2f, 0x0a, 0x08, 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x27, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x55, 0x49, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x56, 0x31, 0x48, 0x00, 0x52, 0x08, 0x55, 0x49, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x41, 0x0a, 0x0e, 0x4f, 0x6b, 0x74, 0x61, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, + 0x52, 0x75, 0x6c, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x2e, 0x4f, 0x6b, 0x74, 0x61, 0x49, 0x6d, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x75, 0x6c, + 0x65, 0x56, 0x31, 0x48, 0x00, 0x52, 0x0e, 0x4f, 0x6b, 0x74, 0x61, 0x49, 0x6d, 0x70, 0x6f, 0x72, + 0x74, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x41, 0x0a, 0x0e, 0x4f, 0x6b, 0x74, 0x61, 0x41, 0x73, 0x73, + 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x29, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x4f, 0x6b, 0x74, 0x61, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, + 0x6d, 0x65, 0x6e, 0x74, 0x56, 0x31, 0x48, 0x00, 0x52, 0x0e, 0x4f, 0x6b, 0x74, 0x61, 0x41, 0x73, + 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x0b, 0x49, 0x6e, 0x74, 0x65, + 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x56, 0x31, 0x48, 0x00, 0x52, 0x0b, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x38, 0x0a, 0x0b, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, + 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x56, 0x31, 0x48, 0x00, 0x52, + 0x0b, 0x57, 0x61, 0x74, 0x63, 0x68, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x57, 0x0a, 0x16, + 0x48, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, + 0x79, 0x70, 0x65, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, 0x74, + 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x16, 0x48, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x74, 0x79, - 0x70, 0x65, 0x73, 0x2e, 0x48, 0x65, 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, 0x74, 0x68, - 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x16, 0x48, 0x65, - 0x61, 0x64, 0x6c, 0x65, 0x73, 0x73, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x0a, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, - 0x73, 0x74, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, 0x0a, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x54, 0x0a, 0x0e, 0x55, 0x73, - 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x2e, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x75, 0x73, - 0x65, 0x72, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x48, 0x00, - 0x52, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, - 0x12, 0x4c, 0x0a, 0x10, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x18, 0x2f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, - 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x48, 0x00, 0x52, 0x10, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x58, - 0x0a, 0x0f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x18, 0x30, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x0f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, - 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x44, 0x0a, 0x0a, 0x41, 0x75, 0x64, 0x69, - 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x48, 0x00, 0x52, 0x0a, 0x41, 0x75, 0x64, 0x69, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x38, - 0x0a, 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x33, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, - 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x48, 0x00, - 0x52, 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x47, 0x0a, 0x0b, 0x52, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x34, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x12, 0x4c, 0x0a, 0x10, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x76, 0x69, 0x65, 0x77, 0x18, 0x35, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x65, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x0a, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, + 0x69, 0x73, 0x74, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, 0x74, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x48, 0x00, 0x52, + 0x0a, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x54, 0x0a, 0x0e, 0x55, + 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x2e, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x75, + 0x73, 0x65, 0x72, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, + 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x48, + 0x00, 0x52, 0x0e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x4c, 0x0a, 0x10, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, + 0x65, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x2f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, 0x73, - 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x48, 0x00, 0x52, 0x10, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x12, - 0x6d, 0x0a, 0x14, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, - 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x18, 0x36, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6d, - 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2e, 0x76, - 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, - 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x48, 0x00, 0x52, 0x14, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x7e, - 0x0a, 0x1a, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x57, 0x61, 0x69, 0x74, - 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x37, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6b, 0x75, - 0x62, 0x65, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, - 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, - 0x57, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x48, 0x00, 0x52, 0x1a, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x57, 0x61, - 0x69, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, 0x55, - 0x0a, 0x10, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x38, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x48, 0x00, 0x52, 0x10, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5f, 0x0a, 0x12, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x4e, - 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x39, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6e, 0x6f, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x6c, - 0x6f, 0x62, 0x61, 0x6c, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x48, 0x00, 0x52, 0x12, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x0a, 0x43, 0x72, 0x6f, 0x77, 0x6e, 0x4a, - 0x65, 0x77, 0x65, 0x6c, 0x18, 0x3a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x6a, 0x65, 0x77, 0x65, 0x6c, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x48, 0x00, - 0x52, 0x0a, 0x43, 0x72, 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x12, 0x4e, 0x0a, 0x0e, - 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, 0x3b, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, - 0x64, 0x62, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, 0x61, - 0x62, 0x61, 0x73, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x44, 0x61, - 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x46, 0x0a, 0x0b, - 0x42, 0x6f, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x3c, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6d, 0x61, 0x63, - 0x68, 0x69, 0x6e, 0x65, 0x69, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x74, 0x49, 0x6e, 0x73, - 0x74, 0x61, 0x6e, 0x63, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x42, 0x6f, 0x74, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6e, 0x63, 0x65, 0x12, 0x62, 0x0a, 0x13, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, - 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x3d, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, 0x75, - 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x48, 0x00, 0x52, 0x13, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x55, 0x0a, 0x10, 0x53, 0x50, 0x49, 0x46, - 0x46, 0x45, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x3e, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6d, 0x61, - 0x63, 0x68, 0x69, 0x6e, 0x65, 0x69, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x50, 0x49, 0x46, 0x46, - 0x45, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x10, 0x53, - 0x50, 0x49, 0x46, 0x46, 0x45, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, - 0x56, 0x0a, 0x10, 0x41, 0x75, 0x74, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x18, 0x40, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x75, 0x74, 0x6f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, - 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x10, 0x41, 0x75, 0x74, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x59, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x6f, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x41, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x75, - 0x74, 0x6f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, - 0x11, 0x41, 0x75, 0x74, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x5a, 0x0a, 0x10, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, - 0x55, 0x73, 0x65, 0x72, 0x56, 0x32, 0x18, 0x42, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x70, 0x72, 0x6f, 0x76, - 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x48, 0x00, 0x52, 0x10, 0x53, 0x74, - 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x56, 0x32, 0x12, 0x3d, - 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, 0x54, 0x61, 0x73, 0x6b, 0x18, 0x43, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x75, 0x73, 0x65, 0x72, - 0x74, 0x61, 0x73, 0x6b, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x54, 0x61, 0x73, - 0x6b, 0x48, 0x00, 0x52, 0x08, 0x55, 0x73, 0x65, 0x72, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x56, 0x0a, + 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x48, 0x00, 0x52, 0x10, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, + 0x58, 0x0a, 0x0f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x18, 0x30, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x63, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x0f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x44, 0x0a, 0x0a, 0x41, 0x75, 0x64, + 0x69, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x48, 0x00, 0x52, 0x0a, 0x41, 0x75, 0x64, 0x69, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, + 0x38, 0x0a, 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x33, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x48, + 0x00, 0x52, 0x06, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x47, 0x0a, 0x0b, 0x52, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x18, 0x34, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x73, 0x65, 0x63, 0x72, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x12, 0x4c, 0x0a, 0x10, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x18, 0x35, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, + 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x6c, 0x69, + 0x73, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x48, 0x00, 0x52, 0x10, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, + 0x12, 0x6d, 0x0a, 0x14, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, + 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x18, 0x36, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x72, 0x75, 0x6c, 0x65, 0x73, 0x2e, + 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, + 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x48, 0x00, 0x52, 0x14, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x52, 0x75, 0x6c, 0x65, 0x12, + 0x7e, 0x0a, 0x1a, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x57, 0x61, 0x69, + 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x18, 0x37, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x3c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6b, + 0x75, 0x62, 0x65, 0x77, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, + 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, + 0x73, 0x57, 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x48, 0x00, 0x52, 0x1a, 0x4b, 0x75, 0x62, 0x65, 0x72, 0x6e, 0x65, 0x74, 0x65, 0x73, 0x57, + 0x61, 0x69, 0x74, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x12, + 0x55, 0x0a, 0x10, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x38, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, + 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x10, 0x55, 0x73, 0x65, 0x72, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x5f, 0x0a, 0x12, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x39, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6e, 0x6f, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, + 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x48, 0x00, 0x52, 0x12, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x4e, 0x6f, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x0a, 0x43, 0x72, 0x6f, 0x77, 0x6e, + 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x18, 0x3a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x6a, 0x65, 0x77, 0x65, + 0x6c, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x48, + 0x00, 0x52, 0x0a, 0x43, 0x72, 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x12, 0x4e, 0x0a, + 0x0e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x18, + 0x3b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x2e, 0x64, 0x62, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x61, 0x74, + 0x61, 0x62, 0x61, 0x73, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x44, + 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x12, 0x46, 0x0a, + 0x0b, 0x42, 0x6f, 0x74, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x3c, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6d, 0x61, + 0x63, 0x68, 0x69, 0x6e, 0x65, 0x69, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x6f, 0x74, 0x49, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x48, 0x00, 0x52, 0x0b, 0x42, 0x6f, 0x74, 0x49, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x62, 0x0a, 0x13, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, + 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x18, 0x3d, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x63, 0x6c, + 0x75, 0x73, 0x74, 0x65, 0x72, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x73, 0x48, 0x00, 0x52, 0x13, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, + 0x68, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x55, 0x0a, 0x10, 0x53, 0x50, 0x49, + 0x46, 0x46, 0x45, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x3e, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x6d, + 0x61, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x69, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x50, 0x49, 0x46, + 0x46, 0x45, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48, 0x00, 0x52, 0x10, + 0x53, 0x50, 0x49, 0x46, 0x46, 0x45, 0x46, 0x65, 0x64, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x56, 0x0a, 0x10, 0x41, 0x75, 0x74, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x18, 0x40, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x75, 0x74, 0x6f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x10, 0x41, 0x75, 0x74, 0x6f, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x59, 0x0a, 0x11, 0x41, 0x75, 0x74, 0x6f, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x41, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, + 0x75, 0x74, 0x6f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, + 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x48, 0x00, + 0x52, 0x11, 0x41, 0x75, 0x74, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x5a, 0x0a, 0x10, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x56, 0x32, 0x18, 0x42, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, + 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x75, 0x73, 0x65, 0x72, 0x70, 0x72, 0x6f, + 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, + 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x48, 0x00, 0x52, 0x10, 0x53, + 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x56, 0x32, 0x12, + 0x3d, 0x0a, 0x08, 0x55, 0x73, 0x65, 0x72, 0x54, 0x61, 0x73, 0x6b, 0x18, 0x43, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x75, 0x73, 0x65, + 0x72, 0x74, 0x61, 0x73, 0x6b, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x54, 0x61, + 0x73, 0x6b, 0x48, 0x00, 0x52, 0x08, 0x55, 0x73, 0x65, 0x72, 0x54, 0x61, 0x73, 0x6b, 0x12, 0x56, + 0x0a, 0x15, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, + 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x18, 0x45, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, + 0x74, 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x57, 0x69, 0x6e, + 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x56, 0x31, 0x48, 0x00, 0x52, 0x15, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, - 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x18, 0x45, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x74, - 0x79, 0x70, 0x65, 0x73, 0x2e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x57, 0x69, 0x6e, 0x64, - 0x6f, 0x77, 0x73, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x56, 0x31, 0x48, 0x00, 0x52, 0x15, - 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x44, 0x65, - 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x12, 0x6a, 0x0a, 0x1a, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, - 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x18, 0x46, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, 0x6e, - 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x1a, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x69, 0x6e, 0x67, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x12, 0x68, 0x0a, 0x16, 0x41, 0x75, 0x74, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, - 0x67, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6c, 0x6c, 0x6f, 0x75, 0x74, 0x18, 0x47, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x75, 0x74, - 0x6f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6c, 0x6c, 0x6f, 0x75, - 0x74, 0x48, 0x00, 0x52, 0x16, 0x41, 0x75, 0x74, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, - 0x67, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6c, 0x6c, 0x6f, 0x75, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x4a, 0x04, 0x08, - 0x31, 0x10, 0x32, 0x4a, 0x04, 0x08, 0x3f, 0x10, 0x40, 0x4a, 0x04, 0x08, 0x44, 0x10, 0x45, 0x52, - 0x12, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x41, 0x75, - 0x64, 0x69, 0x74, 0x52, 0x0e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x55, - 0x73, 0x65, 0x72, 0x52, 0x13, 0x41, 0x75, 0x74, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, - 0x67, 0x65, 0x6e, 0x74, 0x50, 0x6c, 0x61, 0x6e, 0x2a, 0x2a, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x49, 0x54, 0x10, 0x00, 0x12, - 0x07, 0x0a, 0x03, 0x50, 0x55, 0x54, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, - 0x54, 0x45, 0x10, 0x02, 0x42, 0x34, 0x5a, 0x32, 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, 0x63, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x12, 0x6a, 0x0a, 0x1a, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, + 0x69, 0x6f, 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x18, 0x46, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x74, 0x65, 0x6c, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x69, + 0x6e, 0x67, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x53, + 0x74, 0x61, 0x74, 0x65, 0x48, 0x00, 0x52, 0x1a, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x69, 0x6e, 0x67, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x12, 0x68, 0x0a, 0x16, 0x41, 0x75, 0x74, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6c, 0x6c, 0x6f, 0x75, 0x74, 0x18, 0x47, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x61, 0x75, + 0x74, 0x6f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x6f, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6c, 0x6c, 0x6f, + 0x75, 0x74, 0x48, 0x00, 0x52, 0x16, 0x41, 0x75, 0x74, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x41, 0x67, 0x65, 0x6e, 0x74, 0x52, 0x6f, 0x6c, 0x6c, 0x6f, 0x75, 0x74, 0x12, 0x5b, 0x0a, 0x15, + 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x48, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x63, + 0x65, 0x6e, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x48, 0x00, 0x52, 0x15, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x43, 0x65, 0x6e, 0x74, + 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x7f, 0x0a, 0x21, 0x49, 0x64, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6e, 0x63, + 0x69, 0x70, 0x61, 0x6c, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x49, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x41, 0x73, 0x73, 0x69, 0x67, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x21, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, + 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x79, 0x0a, 0x1f, 0x49, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x43, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x4a, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, + 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x63, 0x65, 0x6e, 0x74, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x6d, 0x65, + 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1f, 0x49, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x43, 0x65, + 0x6e, 0x74, 0x65, 0x72, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x73, 0x73, 0x69, 0x67, + 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x0a, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x4a, 0x04, 0x08, 0x07, 0x10, 0x08, 0x4a, 0x04, 0x08, 0x31, 0x10, 0x32, 0x4a, 0x04, 0x08, + 0x3f, 0x10, 0x40, 0x4a, 0x04, 0x08, 0x44, 0x10, 0x45, 0x52, 0x12, 0x45, 0x78, 0x74, 0x65, 0x72, + 0x6e, 0x61, 0x6c, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x41, 0x75, 0x64, 0x69, 0x74, 0x52, 0x0e, 0x53, + 0x74, 0x61, 0x74, 0x69, 0x63, 0x48, 0x6f, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x52, 0x13, 0x41, + 0x75, 0x74, 0x6f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x50, 0x6c, + 0x61, 0x6e, 0x2a, 0x2a, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x49, 0x54, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x50, 0x55, 0x54, + 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x10, 0x02, 0x42, 0x34, + 0x5a, 0x32, 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, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x2f, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1609,6 +1681,9 @@ var file_teleport_legacy_client_proto_event_proto_goTypes = []any{ (*types.DynamicWindowsDesktopV1)(nil), // 62: types.DynamicWindowsDesktopV1 (*v113.PrincipalState)(nil), // 63: teleport.provisioning.v1.PrincipalState (*v111.AutoUpdateAgentRollout)(nil), // 64: teleport.autoupdate.v1.AutoUpdateAgentRollout + (*v114.Account)(nil), // 65: teleport.identitycenter.v1.Account + (*v114.PrincipalAssignment)(nil), // 66: teleport.identitycenter.v1.PrincipalAssignment + (*v114.AccountAssignment)(nil), // 67: teleport.identitycenter.v1.AccountAssignment } var file_teleport_legacy_client_proto_event_proto_depIdxs = []int32{ 0, // 0: proto.Event.Type:type_name -> proto.Operation @@ -1678,11 +1753,14 @@ var file_teleport_legacy_client_proto_event_proto_depIdxs = []int32{ 62, // 64: proto.Event.DynamicWindowsDesktop:type_name -> types.DynamicWindowsDesktopV1 63, // 65: proto.Event.ProvisioningPrincipalState:type_name -> teleport.provisioning.v1.PrincipalState 64, // 66: proto.Event.AutoUpdateAgentRollout:type_name -> teleport.autoupdate.v1.AutoUpdateAgentRollout - 67, // [67:67] is the sub-list for method output_type - 67, // [67:67] is the sub-list for method input_type - 67, // [67:67] is the sub-list for extension type_name - 67, // [67:67] is the sub-list for extension extendee - 0, // [0:67] is the sub-list for field type_name + 65, // 67: proto.Event.IdentityCenterAccount:type_name -> teleport.identitycenter.v1.Account + 66, // 68: proto.Event.IdentityCenterPrincipalAssignment:type_name -> teleport.identitycenter.v1.PrincipalAssignment + 67, // 69: proto.Event.IdentityCenterAccountAssignment:type_name -> teleport.identitycenter.v1.AccountAssignment + 70, // [70:70] is the sub-list for method output_type + 70, // [70:70] is the sub-list for method input_type + 70, // [70:70] is the sub-list for extension type_name + 70, // [70:70] is the sub-list for extension extendee + 0, // [0:70] is the sub-list for field type_name } func init() { file_teleport_legacy_client_proto_event_proto_init() } @@ -1757,6 +1835,9 @@ func file_teleport_legacy_client_proto_event_proto_init() { (*Event_DynamicWindowsDesktop)(nil), (*Event_ProvisioningPrincipalState)(nil), (*Event_AutoUpdateAgentRollout)(nil), + (*Event_IdentityCenterAccount)(nil), + (*Event_IdentityCenterPrincipalAssignment)(nil), + (*Event_IdentityCenterAccountAssignment)(nil), } type x struct{} out := protoimpl.TypeBuilder{ diff --git a/api/gen/proto/go/teleport/integration/v1/awsoidc_service.pb.go b/api/gen/proto/go/teleport/integration/v1/awsoidc_service.pb.go index b884c584f70da..8bf7ce97a4bc1 100644 --- a/api/gen/proto/go/teleport/integration/v1/awsoidc_service.pb.go +++ b/api/gen/proto/go/teleport/integration/v1/awsoidc_service.pb.go @@ -2414,8 +2414,12 @@ type PingRequest struct { unknownFields protoimpl.UnknownFields // Integration is the AWS OIDC Integration name. - // Required. + // Required if ARN is empty. Integration string `protobuf:"bytes,1,opt,name=integration,proto3" json:"integration,omitempty"` + // The AWS Role ARN to be used when generating the token. + // This is used to test another ARN before saving the Integration. + // Required if integration is empty. + RoleArn string `protobuf:"bytes,2,opt,name=role_arn,json=roleArn,proto3" json:"role_arn,omitempty"` } func (x *PingRequest) Reset() { @@ -2455,6 +2459,13 @@ func (x *PingRequest) GetIntegration() string { return "" } +func (x *PingRequest) GetRoleArn() string { + if x != nil { + return x.RoleArn + } + return "" +} + // PingResponse contains the response for the Ping operation. type PingResponse struct { state protoimpl.MessageState @@ -2855,105 +2866,107 @@ var file_teleport_integration_v1_awsoidc_service_proto_rawDesc = []byte{ 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x52, 0x08, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x2f, 0x0a, 0x0b, + 0x09, 0x52, 0x09, 0x6e, 0x65, 0x78, 0x74, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x4a, 0x0a, 0x0b, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x58, 0x0a, - 0x0c, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, - 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, - 0x61, 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x72, 0x6e, 0x12, 0x17, - 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x64, 0x32, 0xb0, 0x0a, 0x0a, 0x0e, 0x41, 0x57, 0x53, 0x4f, - 0x49, 0x44, 0x43, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x08, 0x4c, 0x69, - 0x73, 0x74, 0x45, 0x49, 0x43, 0x45, 0x12, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x49, 0x43, 0x45, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, - 0x49, 0x43, 0x45, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0a, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x49, 0x43, 0x45, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, - 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x49, 0x43, 0x45, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x49, 0x43, 0x45, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, - 0x73, 0x65, 0x73, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x7d, 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, - 0x74, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x32, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x47, - 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x74, - 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, - 0x69, 0x74, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x68, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, - 0x12, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, - 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6e, - 0x65, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x08, 0x4c, - 0x69, 0x73, 0x74, 0x56, 0x50, 0x43, 0x73, 0x12, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x50, 0x43, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, + 0x52, 0x0b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, + 0x08, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x61, 0x72, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x72, 0x6f, 0x6c, 0x65, 0x41, 0x72, 0x6e, 0x22, 0x58, 0x0a, 0x0c, 0x50, 0x69, 0x6e, 0x67, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x61, 0x72, 0x6e, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x61, 0x72, 0x6e, 0x12, 0x17, 0x0a, 0x07, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, + 0x49, 0x64, 0x32, 0xb0, 0x0a, 0x0a, 0x0e, 0x41, 0x57, 0x53, 0x4f, 0x49, 0x44, 0x43, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5f, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x49, 0x43, + 0x45, 0x12, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x56, 0x50, 0x43, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, 0x0a, - 0x15, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x35, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, - 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, - 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, 0x0d, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, - 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, - 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7a, 0x0a, 0x11, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, - 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x31, 0x2e, 0x74, 0x65, 0x6c, - 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, 0x53, 0x43, 0x6c, - 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, + 0x45, 0x49, 0x43, 0x45, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x49, 0x43, 0x45, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x65, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x45, 0x49, 0x43, 0x45, 0x12, 0x2a, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, + 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x49, 0x43, 0x45, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2b, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x45, 0x49, 0x43, 0x45, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x6e, 0x0a, + 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x12, 0x2d, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, + 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, - 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x5c, 0x0a, 0x07, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x43, 0x32, 0x12, 0x27, 0x2e, 0x74, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, + 0x62, 0x61, 0x73, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7d, 0x0a, + 0x12, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x47, 0x72, 0x6f, + 0x75, 0x70, 0x73, 0x12, 0x32, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, + 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x33, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x47, 0x72, + 0x6f, 0x75, 0x70, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0b, + 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x12, 0x2b, 0x2e, 0x74, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5f, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x50, + 0x43, 0x73, 0x12, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, + 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x56, 0x50, 0x43, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x29, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x43, 0x32, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x56, 0x50, 0x43, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x86, 0x01, 0x0a, 0x15, 0x44, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x35, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x36, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, + 0x65, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x6e, 0x0a, 0x0d, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x2d, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, + 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2e, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x70, 0x6c, 0x6f, + 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x7a, 0x0a, 0x11, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, + 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x31, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x45, 0x43, 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x74, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, - 0x72, 0x73, 0x12, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, - 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x53, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x24, 0x2e, + 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, + 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x07, + 0x4c, 0x69, 0x73, 0x74, 0x45, 0x43, 0x32, 0x12, 0x27, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, + 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x43, 0x32, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x28, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, + 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, + 0x43, 0x32, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x74, 0x0a, 0x0f, 0x4c, 0x69, + 0x73, 0x74, 0x45, 0x4b, 0x53, 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x12, 0x2f, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, - 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, - 0x6e, 0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x5a, 0x5a, 0x58, 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, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x4b, 0x53, 0x43, + 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x4b, 0x53, + 0x43, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x53, 0x0a, 0x04, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x24, 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, + 0x2e, 0x74, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x5a, 0x5a, 0x58, 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, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x2f, 0x76, 0x31, 0x3b, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x76, + 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/api/gen/proto/go/usageevents/v1/usageevents.pb.go b/api/gen/proto/go/usageevents/v1/usageevents.pb.go index 007fcdf51420e..3ac0962122ea6 100644 --- a/api/gen/proto/go/usageevents/v1/usageevents.pb.go +++ b/api/gen/proto/go/usageevents/v1/usageevents.pb.go @@ -230,6 +230,7 @@ const ( CTA_CTA_EXTERNAL_AUDIT_STORAGE CTA = 10 CTA_CTA_OKTA_USER_SYNC CTA = 11 CTA_CTA_ENTRA_ID CTA = 12 + CTA_CTA_OKTA_SCIM CTA = 13 ) var CTA_name = map[int32]string{ @@ -246,6 +247,7 @@ var CTA_name = map[int32]string{ 10: "CTA_EXTERNAL_AUDIT_STORAGE", 11: "CTA_OKTA_USER_SYNC", 12: "CTA_ENTRA_ID", + 13: "CTA_OKTA_SCIM", } var CTA_value = map[string]int32{ @@ -262,6 +264,7 @@ var CTA_value = map[string]int32{ "CTA_EXTERNAL_AUDIT_STORAGE": 10, "CTA_OKTA_USER_SYNC": 11, "CTA_ENTRA_ID": 12, + "CTA_OKTA_SCIM": 13, } func (x CTA) String() string { @@ -5443,341 +5446,342 @@ func init() { } var fileDescriptor_94cf2ca1c69fd564 = []byte{ - // 5340 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x7c, 0x4d, 0x6c, 0xe3, 0x48, - 0x76, 0xbf, 0xe8, 0x8f, 0x6e, 0xbb, 0xda, 0xed, 0x66, 0xb3, 0xdb, 0xb6, 0xdc, 0x6e, 0xf7, 0x87, - 0xfa, 0xdb, 0x33, 0x63, 0x4f, 0xbb, 0x67, 0x77, 0x7a, 0x67, 0xe6, 0xff, 0x9f, 0xd0, 0x14, 0x2d, - 0xb1, 0x2d, 0x89, 0x9a, 0x22, 0xd5, 0xbd, 0x9e, 0xc5, 0xa2, 0x42, 0x93, 0x65, 0x37, 0x63, 0x49, - 0xd4, 0x92, 0x94, 0x3d, 0x4e, 0x10, 0xec, 0xe6, 0x6b, 0x11, 0x64, 0x77, 0xb3, 0x09, 0x10, 0x2c, - 0x02, 0x2c, 0x10, 0x24, 0xc8, 0x07, 0x72, 0x08, 0x90, 0x53, 0xb0, 0xd7, 0x2c, 0x90, 0x43, 0x8e, - 0x01, 0x72, 0xcc, 0x25, 0xd8, 0x5c, 0x72, 0xcb, 0x29, 0x01, 0xf2, 0x85, 0x04, 0xf5, 0x41, 0x89, - 0x92, 0x28, 0x91, 0x33, 0xe9, 0xc5, 0x02, 0xdd, 0x37, 0xa9, 0xea, 0xbd, 0x7a, 0xbf, 0x7a, 0xf5, - 0xea, 0xd5, 0xab, 0x7a, 0x4f, 0x02, 0x8f, 0x42, 0xdc, 0xc4, 0x1d, 0xcf, 0x0f, 0xb7, 0xba, 0x81, - 0x75, 0x84, 0xf1, 0x09, 0x6e, 0x87, 0xc1, 0xd6, 0xc9, 0xe3, 0xf8, 0xd7, 0xcd, 0x8e, 0xef, 0x85, - 0x9e, 0xb4, 0x12, 0x91, 0x6e, 0xc6, 0xfb, 0x4e, 0x1e, 0x17, 0x36, 0x80, 0xd4, 0xd0, 0x76, 0xac, - 0x76, 0x1b, 0xfb, 0x4a, 0xd3, 0xb5, 0x8f, 0x55, 0xd2, 0x23, 0x5d, 0x05, 0xb3, 0x56, 0x13, 0xfb, - 0x61, 0x5e, 0xb8, 0x25, 0x3c, 0x9c, 0x87, 0xec, 0x4b, 0x61, 0x17, 0x3c, 0x6c, 0x68, 0x7a, 0xfb, - 0xc0, 0xb3, 0x7c, 0x47, 0xf1, 0x5a, 0x9d, 0x26, 0x0e, 0x71, 0xc9, 0x33, 0xbd, 0xa2, 0x15, 0xbc, - 0x64, 0x8d, 0xfd, 0x11, 0xae, 0x81, 0xb9, 0x6e, 0x80, 0xfd, 0xb6, 0xd5, 0xc2, 0x7c, 0x90, 0xde, - 0xf7, 0xc2, 0x3d, 0x70, 0xa7, 0x37, 0x8e, 0xec, 0x38, 0xbb, 0xae, 0x1f, 0x84, 0x10, 0x07, 0x5e, - 0xd7, 0xb7, 0x71, 0x7f, 0x88, 0xc2, 0x46, 0x4c, 0xdc, 0x30, 0x59, 0xc5, 0x0a, 0xe3, 0x80, 0x0b, - 0x1f, 0x83, 0xdb, 0x3d, 0x5a, 0x03, 0x87, 0x8a, 0x8f, 0x1d, 0xdc, 0x0e, 0x5d, 0xab, 0x69, 0x74, - 0x0f, 0x5a, 0x6e, 0x98, 0x8e, 0x29, 0x3e, 0xc0, 0x27, 0x5d, 0x1c, 0x84, 0xae, 0xd7, 0x6e, 0x5b, - 0xae, 0x8f, 0xb3, 0x0e, 0xf0, 0xcb, 0xe0, 0x5e, 0x6f, 0x00, 0x88, 0x8f, 0xdc, 0x80, 0x00, 0x7c, - 0x69, 0x35, 0x9b, 0xb8, 0x7d, 0x94, 0x75, 0x10, 0x69, 0x15, 0xcc, 0xb5, 0x0e, 0x2d, 0x14, 0x9e, - 0x75, 0x70, 0x7e, 0x8a, 0xf6, 0x9d, 0x6f, 0x1d, 0x5a, 0xe6, 0x59, 0x07, 0x4b, 0xeb, 0x00, 0x34, - 0xbd, 0x23, 0xb7, 0x8d, 0x0e, 0x9b, 0xde, 0x69, 0x7e, 0x9a, 0x76, 0xce, 0xd3, 0x96, 0xdd, 0xa6, - 0x77, 0xca, 0xf0, 0x43, 0x6c, 0x7b, 0x27, 0xd8, 0x3f, 0x53, 0x3c, 0x07, 0x07, 0x8a, 0xd7, 0x0e, - 0xdd, 0x76, 0x17, 0x67, 0x5c, 0x94, 0x0f, 0xc1, 0xfa, 0xc8, 0x00, 0x9d, 0xb3, 0x8c, 0xcc, 0x1f, - 0x81, 0x1b, 0x43, 0xcc, 0x75, 0xdf, 0x6d, 0x87, 0x19, 0xb9, 0x0b, 0x40, 0x2c, 0xba, 0x01, 0x65, - 0xae, 0xe2, 0xd0, 0x72, 0xac, 0xd0, 0x92, 0x16, 0xc1, 0x94, 0xeb, 0x70, 0xca, 0x29, 0xd7, 0x29, - 0x58, 0x20, 0x1f, 0xd1, 0x44, 0x36, 0xd0, 0xa3, 0x55, 0xc1, 0x9c, 0xcf, 0xdb, 0x28, 0xc7, 0xe2, - 0xf6, 0xa3, 0xcd, 0x31, 0xf6, 0xbe, 0x39, 0x3c, 0x08, 0xec, 0xb1, 0x16, 0x8e, 0x81, 0x14, 0xf5, - 0x1a, 0x21, 0xee, 0x18, 0xa1, 0x15, 0x76, 0x03, 0xe9, 0x63, 0x70, 0x2e, 0xa0, 0x9f, 0xf8, 0xd0, - 0x0f, 0x52, 0x87, 0x66, 0x8c, 0x90, 0xb3, 0x91, 0xbd, 0x84, 0x7d, 0xdf, 0xf3, 0xf9, 0x82, 0xb2, - 0x2f, 0x85, 0x3f, 0x11, 0xc0, 0x72, 0x43, 0x8b, 0xb1, 0xf8, 0x21, 0x76, 0x98, 0xaa, 0x54, 0x30, - 0xd7, 0xe2, 0x53, 0xa3, 0x32, 0x2f, 0x64, 0x98, 0x4e, 0xa4, 0x0b, 0xd8, 0x63, 0x95, 0x94, 0x1e, - 0xf0, 0x29, 0x3a, 0xc8, 0x5b, 0x19, 0x80, 0x47, 0xb3, 0x8e, 0xc0, 0x17, 0xfe, 0x5b, 0x00, 0xb7, - 0xfa, 0x30, 0x23, 0xa5, 0x19, 0xb8, 0x89, 0x6d, 0xb2, 0x43, 0x5e, 0x29, 0xe0, 0x6a, 0x6c, 0x19, - 0x19, 0xe4, 0xc7, 0x99, 0x97, 0xb1, 0x3f, 0x5c, 0x34, 0x44, 0x6c, 0xfe, 0xd3, 0x5f, 0x7c, 0xfe, - 0xbf, 0x31, 0x45, 0x9c, 0x50, 0x44, 0xa0, 0xb5, 0x43, 0x7c, 0xe4, 0x5b, 0x64, 0xe6, 0xf2, 0x0b, - 0x43, 0xd7, 0x8a, 0x8a, 0xe2, 0xb5, 0xdb, 0xd8, 0x0e, 0x5f, 0x7b, 0x3d, 0xfc, 0x68, 0x2a, 0x6e, - 0x07, 0x45, 0x2b, 0xb4, 0x0e, 0xac, 0x00, 0xc3, 0xa2, 0xa1, 0xb6, 0x7d, 0xaf, 0xd9, 0x7c, 0xdd, - 0xe7, 0x2f, 0x3d, 0x05, 0xf9, 0x80, 0x1a, 0x3d, 0x76, 0x50, 0x34, 0x72, 0x80, 0x6c, 0xaf, 0xdb, - 0x0e, 0xf3, 0x33, 0xb7, 0x84, 0x87, 0xd3, 0x70, 0x39, 0xea, 0x8f, 0xa0, 0x04, 0x0a, 0xe9, 0x2d, - 0xfc, 0xbb, 0x00, 0xae, 0xf7, 0x35, 0xb7, 0xd7, 0x3d, 0xc0, 0xea, 0xde, 0x1b, 0xa2, 0xb5, 0xc2, - 0x33, 0x90, 0x6f, 0x68, 0x8a, 0xd5, 0x6c, 0x9a, 0x9e, 0x4c, 0xfd, 0x45, 0xec, 0x40, 0xd8, 0x04, - 0xd3, 0x36, 0x9f, 0xf1, 0xe2, 0xf6, 0xf5, 0xb1, 0xa3, 0x2b, 0xa6, 0x0c, 0x09, 0x61, 0xe1, 0x7b, - 0xb3, 0x71, 0x3d, 0x16, 0x71, 0xa7, 0xe9, 0x9d, 0x19, 0xd8, 0x3f, 0x71, 0x6d, 0xfc, 0xda, 0x5b, - 0xdf, 0x11, 0xb8, 0xe8, 0xd0, 0x09, 0xa3, 0x16, 0x0e, 0x5f, 0x7a, 0x0e, 0x35, 0xb9, 0xc5, 0xed, - 0x9d, 0xb1, 0x63, 0x4d, 0x52, 0xd4, 0x26, 0x6b, 0xaa, 0xd2, 0x91, 0xe0, 0x82, 0x13, 0xfb, 0x26, - 0x59, 0xe0, 0x02, 0x17, 0x44, 0x43, 0x90, 0x59, 0x2a, 0xe6, 0xe7, 0xfe, 0x2f, 0x62, 0x48, 0xec, - 0x02, 0x81, 0xd3, 0xfb, 0x5c, 0x40, 0x60, 0x21, 0x0e, 0x40, 0x5a, 0x07, 0xab, 0x45, 0xb5, 0x5e, - 0xd1, 0xf7, 0x51, 0x55, 0x35, 0xcb, 0x7a, 0x11, 0x35, 0x6a, 0x46, 0x5d, 0x55, 0xb4, 0x5d, 0x4d, - 0x2d, 0x8a, 0x39, 0x69, 0x19, 0x48, 0x83, 0xdd, 0x72, 0xc3, 0xd4, 0x45, 0x41, 0xca, 0x83, 0xab, - 0x83, 0xed, 0x55, 0xb9, 0xd6, 0x90, 0x2b, 0xe2, 0x54, 0x01, 0x03, 0xd0, 0x17, 0x2d, 0xad, 0x81, - 0x15, 0x4e, 0x67, 0xee, 0xd7, 0xd5, 0xa1, 0xc1, 0x6f, 0x80, 0x6b, 0xf1, 0x4e, 0xad, 0x66, 0x98, - 0x72, 0xa5, 0x82, 0x0c, 0x05, 0x6a, 0x75, 0x53, 0x14, 0xa4, 0x6b, 0x60, 0x39, 0xde, 0x2f, 0x57, - 0xe5, 0x4f, 0xf5, 0x1a, 0x52, 0x15, 0x43, 0x9c, 0x2a, 0xfc, 0x70, 0x06, 0xdc, 0xed, 0xcf, 0x5f, - 0xf1, 0xb1, 0x15, 0xe2, 0xe8, 0xdb, 0x99, 0xe2, 0xb5, 0x0f, 0xdd, 0xa3, 0xd7, 0xde, 0x2e, 0x3d, - 0x70, 0xd1, 0xa6, 0x33, 0x1d, 0xb4, 0xcb, 0x67, 0x19, 0x0c, 0x66, 0xbc, 0xc2, 0x36, 0xd9, 0xe7, - 0xc8, 0x3e, 0xed, 0xd8, 0xb7, 0xc2, 0x9f, 0x09, 0x60, 0x21, 0xde, 0x4d, 0xac, 0x47, 0xd1, 0x6b, - 0xbb, 0x5a, 0x29, 0xd9, 0x7a, 0x46, 0xba, 0xe5, 0x17, 0x06, 0x52, 0x95, 0x6d, 0x64, 0x18, 0x55, - 0x51, 0x20, 0xeb, 0x9f, 0xdc, 0xad, 0x6a, 0x8a, 0x2a, 0x4e, 0x25, 0xb3, 0xc3, 0xa2, 0x41, 0x4d, - 0x60, 0x5a, 0x5a, 0x05, 0x4b, 0x09, 0xec, 0x7b, 0x86, 0x38, 0x53, 0xf8, 0x2f, 0x01, 0xdc, 0x4c, - 0x38, 0x2f, 0xf9, 0xbd, 0xe0, 0xb5, 0x77, 0xfc, 0xbf, 0x32, 0x15, 0xdf, 0x1c, 0xd1, 0xf4, 0xd9, - 0xca, 0x75, 0x7d, 0x5c, 0x35, 0x2b, 0xc6, 0x6b, 0xaf, 0x83, 0xdf, 0x9e, 0x02, 0x8f, 0xe3, 0x0e, - 0x32, 0x38, 0x0e, 0xbd, 0x0e, 0x39, 0x06, 0x4f, 0x70, 0xd1, 0xf5, 0xb1, 0x1d, 0x7a, 0xfe, 0x99, - 0xe9, 0x79, 0xcd, 0x40, 0x6b, 0x07, 0xa1, 0xf5, 0x06, 0x44, 0x03, 0xdf, 0x99, 0x02, 0x9b, 0x69, - 0x0a, 0xe9, 0x99, 0xc8, 0x6b, 0xaf, 0x8d, 0xbf, 0x98, 0x02, 0xf7, 0xfb, 0xda, 0x90, 0xbb, 0xa1, - 0x17, 0x7d, 0x8e, 0x85, 0x90, 0xaf, 0xfd, 0x09, 0xf2, 0x00, 0x5c, 0x4a, 0x0e, 0xa7, 0x17, 0xfd, - 0xc1, 0x30, 0xfa, 0x5b, 0x53, 0xe0, 0x4e, 0x5f, 0x5d, 0xaa, 0xb2, 0x4d, 0x77, 0x4d, 0xfb, 0x4d, - 0xba, 0x8b, 0xfe, 0x9b, 0x00, 0x56, 0x87, 0x23, 0x2e, 0x72, 0x50, 0xbd, 0x61, 0x13, 0x67, 0x91, - 0x43, 0xcd, 0x73, 0x5e, 0x7f, 0x1f, 0xf1, 0x9f, 0x02, 0xb8, 0x31, 0x3c, 0x71, 0xb9, 0xd3, 0x21, - 0x61, 0xf6, 0x1b, 0x10, 0x44, 0x7c, 0x7b, 0x0a, 0x3c, 0x9a, 0x10, 0x44, 0x68, 0x72, 0xb5, 0xee, - 0x35, 0x5d, 0xfb, 0xec, 0xb5, 0x57, 0xc4, 0xff, 0x08, 0xa0, 0xd0, 0x57, 0x44, 0xdd, 0x77, 0xdb, - 0xb6, 0xdb, 0xb1, 0x9a, 0xc1, 0x9b, 0x73, 0x58, 0xfe, 0x87, 0x00, 0xd6, 0xfb, 0x1a, 0x30, 0x71, - 0x10, 0xf2, 0x87, 0xb7, 0x37, 0xc1, 0xef, 0xff, 0xab, 0x00, 0xf2, 0x31, 0x2f, 0xc0, 0x13, 0x2f, - 0xce, 0x6b, 0x3f, 0xef, 0x35, 0xe2, 0xf5, 0xb9, 0xb7, 0xc7, 0xa7, 0xd0, 0x6b, 0xc6, 0x93, 0x43, - 0x37, 0x89, 0x41, 0x0c, 0x74, 0x1a, 0xd6, 0x49, 0x9c, 0xe0, 0x36, 0xb9, 0x80, 0x0d, 0x72, 0x93, - 0x70, 0xa1, 0x19, 0x23, 0x79, 0x1b, 0x6c, 0x0c, 0x91, 0x3c, 0x77, 0xf1, 0x69, 0xd1, 0xb3, 0xbb, - 0x2d, 0xdc, 0x0e, 0xad, 0xc1, 0x07, 0xab, 0xc2, 0x5f, 0x09, 0x60, 0x49, 0x0e, 0x02, 0x97, 0xd8, - 0x1e, 0x5d, 0x82, 0x9e, 0xed, 0x3d, 0x00, 0x97, 0x6c, 0xaf, 0x7d, 0x82, 0xfd, 0x80, 0xf2, 0xa0, - 0x5e, 0xe2, 0x62, 0x31, 0xde, 0xac, 0x39, 0xd2, 0x6d, 0xb0, 0x10, 0x7a, 0xa1, 0xd5, 0x44, 0xa1, - 0x77, 0x8c, 0xdb, 0xec, 0x61, 0x7e, 0x1a, 0x5e, 0xa0, 0x6d, 0x26, 0x6d, 0x92, 0xee, 0x80, 0x8b, - 0x1d, 0xdf, 0x6b, 0x75, 0xc2, 0x88, 0x66, 0x9a, 0xd2, 0x2c, 0xb0, 0x46, 0x4e, 0xf4, 0x16, 0xb8, - 0x6c, 0xf7, 0x30, 0x44, 0x84, 0x2c, 0x6e, 0x12, 0xfb, 0x1d, 0x8c, 0xb8, 0xf0, 0xf7, 0x02, 0xb8, - 0xca, 0x70, 0xab, 0x9f, 0x61, 0xbb, 0xfb, 0x05, 0x60, 0xaf, 0x03, 0xd0, 0xf6, 0x1c, 0xcc, 0xe3, - 0x33, 0x06, 0x7a, 0x9e, 0xb4, 0xd0, 0xd0, 0x6c, 0x64, 0x56, 0xd3, 0x19, 0x66, 0x35, 0x93, 0x75, - 0x56, 0xb3, 0x63, 0x66, 0xf5, 0x14, 0x5c, 0x63, 0x93, 0xaa, 0xe1, 0x53, 0x25, 0x06, 0xb7, 0x97, - 0x6d, 0xb2, 0xad, 0x10, 0x1f, 0x79, 0xfe, 0x59, 0x94, 0x6d, 0x8a, 0xbe, 0x17, 0xfe, 0x52, 0x00, - 0x57, 0x18, 0xab, 0x6c, 0xdb, 0x38, 0x08, 0x20, 0xfe, 0x46, 0x17, 0x07, 0x21, 0xc1, 0x18, 0xd9, - 0x2f, 0x7b, 0xfd, 0x62, 0x8c, 0x0b, 0x51, 0x23, 0x7d, 0x4e, 0xfa, 0x99, 0xac, 0xe0, 0x0f, 0x05, - 0xb0, 0x10, 0x21, 0x26, 0xcd, 0xd2, 0x32, 0x38, 0x67, 0xd1, 0x4f, 0x1c, 0x23, 0xff, 0xf6, 0xb3, - 0x41, 0x77, 0x17, 0x48, 0x4c, 0x91, 0x15, 0x37, 0x08, 0xc7, 0xe6, 0xef, 0xbe, 0x06, 0xc4, 0x3e, - 0x15, 0xdb, 0x73, 0x52, 0x69, 0xc4, 0x77, 0x8d, 0xf7, 0x13, 0xa3, 0x22, 0xfa, 0xde, 0x6b, 0x70, - 0xf0, 0x46, 0xc7, 0xf9, 0xe9, 0x0d, 0x5e, 0xc4, 0xc4, 0xf7, 0xbe, 0xba, 0xc1, 0x2d, 0xb0, 0x1c, - 0xef, 0x6f, 0x1d, 0x44, 0x61, 0xde, 0x4f, 0x55, 0xc4, 0xab, 0x56, 0x51, 0x82, 0x88, 0x57, 0xad, - 0xa8, 0x5f, 0x8c, 0x8b, 0x28, 0xf9, 0x56, 0x3b, 0x0c, 0x4c, 0xaf, 0x11, 0x60, 0x5f, 0xda, 0x04, - 0x57, 0xa8, 0x63, 0x42, 0xbe, 0xd7, 0xc4, 0x01, 0x3a, 0x22, 0x7d, 0x98, 0x99, 0xde, 0x2c, 0xbc, - 0x4c, 0xbb, 0x88, 0x6b, 0x0f, 0x4a, 0xac, 0x43, 0x7a, 0x17, 0x5c, 0x65, 0xf4, 0xa1, 0x6f, 0xb9, - 0x61, 0x9f, 0x61, 0x8a, 0x32, 0x48, 0xb4, 0xcf, 0xa4, 0x5d, 0x9c, 0xa3, 0xf0, 0x83, 0xe9, 0xb8, - 0x70, 0x88, 0x4f, 0x5c, 0x7c, 0xfa, 0x8a, 0x57, 0x49, 0x7a, 0x0a, 0x56, 0x1d, 0xeb, 0x2c, 0x40, - 0x1d, 0x2b, 0x08, 0x51, 0x1b, 0x7f, 0x16, 0x22, 0xab, 0xeb, 0xb8, 0x21, 0x22, 0x0b, 0xc5, 0xa1, - 0x2d, 0x11, 0x82, 0xba, 0x45, 0x5c, 0xde, 0x67, 0xa1, 0x4c, 0x7a, 0x8b, 0x04, 0xc2, 0x2e, 0xb8, - 0xd9, 0xa2, 0x2a, 0x0f, 0x5e, 0xba, 0x1d, 0xe4, 0xe3, 0x6f, 0x74, 0x5d, 0x1f, 0x93, 0x03, 0x2c, - 0x40, 0xf6, 0x4b, 0xab, 0x7d, 0x84, 0x1d, 0xba, 0xc7, 0xe7, 0xe0, 0x7a, 0x9f, 0x0c, 0xc6, 0xa8, - 0x14, 0x46, 0x24, 0x3d, 0x05, 0x79, 0x9f, 0x4e, 0x0d, 0x1d, 0x92, 0x41, 0x70, 0xdb, 0x3e, 0xeb, - 0x0d, 0x30, 0x43, 0x07, 0x58, 0x66, 0xfd, 0xbb, 0x51, 0x77, 0xc4, 0xf9, 0x11, 0x58, 0xe3, 0x9c, - 0x8e, 0x75, 0x86, 0xbc, 0x43, 0xd4, 0xf2, 0xda, 0xe1, 0xcb, 0x1e, 0xf3, 0x2c, 0x65, 0x5e, 0x61, - 0x24, 0x45, 0xeb, 0x4c, 0x3f, 0xac, 0x92, 0xfe, 0x88, 0xfb, 0x2b, 0x60, 0xb5, 0xdd, 0x25, 0xc0, - 0x08, 0xa7, 0x8f, 0x5b, 0xde, 0x09, 0x76, 0x10, 0x87, 0x9a, 0x3f, 0x47, 0x67, 0xbe, 0xcc, 0x08, - 0xf4, 0x43, 0xc8, 0xba, 0x99, 0x89, 0x05, 0x85, 0xdf, 0x13, 0x46, 0x17, 0xe6, 0x15, 0x1b, 0x9e, - 0xf4, 0x18, 0x2c, 0x59, 0xb4, 0x1f, 0x35, 0xdd, 0x20, 0x44, 0x7c, 0xa2, 0xae, 0xc3, 0xd3, 0xf9, - 0x92, 0x35, 0x24, 0x5f, 0x73, 0x0a, 0xdf, 0x15, 0xc0, 0x6a, 0x2c, 0x55, 0xcc, 0x92, 0x7d, 0xe3, - 0x3c, 0xa3, 0xb4, 0x03, 0x66, 0x8e, 0xdd, 0x36, 0x1b, 0x6f, 0x71, 0x7b, 0x73, 0x2c, 0xca, 0x91, - 0x11, 0xf7, 0xdc, 0xb6, 0x03, 0x29, 0xaf, 0xb4, 0x06, 0xe6, 0xbb, 0x01, 0xf6, 0x11, 0x2d, 0xaf, - 0x98, 0xee, 0x97, 0x57, 0xd4, 0xac, 0x16, 0x2e, 0x78, 0x24, 0x54, 0x1a, 0xe1, 0xa6, 0x25, 0x07, - 0xec, 0xb4, 0xac, 0x8d, 0xe8, 0x6a, 0x3b, 0x3b, 0x8a, 0x84, 0xbd, 0xea, 0x83, 0x5b, 0x09, 0x02, - 0xa3, 0xc0, 0xf5, 0xa7, 0x23, 0xf3, 0x1f, 0x04, 0x70, 0xa5, 0x57, 0x43, 0x44, 0xf7, 0x26, 0x93, - 0x93, 0xe9, 0x54, 0x8f, 0xbd, 0x42, 0x21, 0xcf, 0x77, 0x8f, 0xdc, 0x36, 0x5f, 0xdd, 0xde, 0x2b, - 0x94, 0x4e, 0x5b, 0xa5, 0x7b, 0x60, 0xd1, 0x6e, 0x7a, 0x5d, 0x07, 0x75, 0x7c, 0xef, 0xc4, 0x75, - 0xb0, 0xcf, 0x95, 0x7d, 0x91, 0xb6, 0xd6, 0x79, 0xa3, 0xa4, 0x83, 0x39, 0x87, 0x5f, 0x57, 0xe9, - 0xd6, 0xb9, 0xb0, 0xfd, 0x24, 0x35, 0x00, 0xc6, 0x4e, 0x74, 0xc3, 0xed, 0xcf, 0x2e, 0x1a, 0xa4, - 0xf0, 0x1c, 0x5c, 0x1b, 0x4f, 0x27, 0xad, 0x80, 0xf3, 0xce, 0x41, 0x7c, 0x76, 0xe7, 0x9c, 0x03, - 0x3a, 0xaf, 0x9b, 0xe0, 0x82, 0x73, 0x80, 0x68, 0x05, 0x98, 0xed, 0x35, 0xf9, 0x9c, 0x80, 0x73, - 0x50, 0xe7, 0x2d, 0x85, 0x7f, 0x11, 0xc0, 0xb5, 0x5d, 0x6c, 0x85, 0x5d, 0x1f, 0x43, 0x6c, 0x7b, - 0xad, 0x16, 0x6e, 0x3b, 0xb1, 0x30, 0x6a, 0xc0, 0xac, 0x84, 0x41, 0xb3, 0x92, 0x3e, 0x00, 0xe7, - 0x0f, 0x19, 0x2b, 0x37, 0xdd, 0x5b, 0x63, 0xe7, 0x18, 0x89, 0x88, 0x18, 0xa4, 0xcf, 0xc0, 0x3a, - 0xff, 0x88, 0xfc, 0x01, 0xb9, 0x28, 0x76, 0x6d, 0x58, 0xdc, 0x7e, 0x2f, 0x75, 0xc4, 0x01, 0x66, - 0x7e, 0x7f, 0x58, 0x3b, 0x1c, 0xdf, 0x59, 0x38, 0x05, 0x57, 0x4d, 0xb9, 0xc4, 0x22, 0x61, 0xfc, - 0x49, 0x17, 0xfb, 0xfc, 0xf9, 0xe0, 0x26, 0x60, 0x61, 0x12, 0x22, 0x71, 0x2d, 0xab, 0xf5, 0x99, - 0x86, 0x80, 0x36, 0xd5, 0x48, 0x4b, 0x9f, 0x00, 0x3b, 0x47, 0x38, 0x0a, 0xad, 0x18, 0x81, 0x4a, - 0x5a, 0x48, 0x94, 0xec, 0x06, 0x28, 0xe8, 0x52, 0x7f, 0xc0, 0x5d, 0xee, 0xbc, 0x1b, 0x18, 0xac, - 0xa1, 0xf0, 0xcf, 0xd3, 0x60, 0x85, 0x39, 0x9a, 0x92, 0x6f, 0x75, 0x5e, 0xca, 0x2f, 0x0c, 0xc3, - 0xb6, 0xda, 0x51, 0x2e, 0xfc, 0x0a, 0x1f, 0xdb, 0xde, 0x46, 0x2e, 0x7f, 0xd8, 0x64, 0x20, 0x66, - 0xe0, 0x65, 0x26, 0xc3, 0xee, 0xbd, 0x78, 0xc6, 0xb0, 0x90, 0xc5, 0x60, 0x58, 0x66, 0x38, 0x16, - 0x72, 0x24, 0x06, 0xfd, 0x40, 0xf0, 0xc8, 0xf7, 0xba, 0x1d, 0x86, 0x66, 0x86, 0x07, 0x82, 0x25, - 0xda, 0xd4, 0x1f, 0x83, 0x1e, 0x9b, 0xd4, 0x4c, 0xa3, 0x31, 0xe8, 0x71, 0x49, 0x6c, 0x9d, 0x11, - 0x74, 0xbc, 0xa6, 0x6b, 0xbb, 0x98, 0xc5, 0xe2, 0x33, 0xf0, 0x22, 0x6d, 0xad, 0xf3, 0x46, 0xe9, - 0x6d, 0x20, 0x71, 0xec, 0xc7, 0x01, 0xb2, 0x9b, 0xdd, 0x20, 0x8c, 0xfc, 0xf6, 0x0c, 0x14, 0x19, - 0xf4, 0xe3, 0x40, 0xe1, 0xed, 0xfd, 0x99, 0xfa, 0x4e, 0x10, 0x9b, 0xe9, 0xf9, 0xd8, 0x4c, 0xa1, - 0x13, 0xf4, 0x67, 0xfa, 0x10, 0xb0, 0x31, 0x50, 0xf0, 0x04, 0x1d, 0x74, 0xed, 0x63, 0x1c, 0x06, - 0xf9, 0x39, 0x4a, 0xcc, 0xc0, 0x19, 0x4f, 0x76, 0x58, 0x2b, 0x39, 0xd6, 0x39, 0xa5, 0xd5, 0x6a, - 0xf6, 0xf6, 0x67, 0x90, 0x9f, 0xa7, 0xd4, 0x0c, 0xa3, 0x61, 0xb5, 0x9a, 0xd1, 0x26, 0x8d, 0x71, - 0x78, 0xae, 0x63, 0xc7, 0x38, 0x40, 0x8c, 0x43, 0x77, 0x1d, 0xbb, 0xcf, 0xd1, 0x53, 0x89, 0x65, - 0xd3, 0x30, 0x21, 0xc8, 0x5f, 0x88, 0xa9, 0x44, 0xe6, 0x8d, 0x85, 0x1f, 0x08, 0xe0, 0x6e, 0x43, - 0x8b, 0x2d, 0xb6, 0xe2, 0x7b, 0xa7, 0xed, 0x67, 0xf8, 0x14, 0x37, 0x8b, 0xee, 0xe1, 0x21, 0xb9, - 0x64, 0xb2, 0x75, 0x7f, 0x0a, 0xf2, 0xd6, 0xe1, 0xe1, 0x60, 0x55, 0x09, 0x8a, 0x15, 0xb2, 0xcd, - 0xc3, 0xe5, 0xa8, 0xbf, 0x57, 0x7a, 0xc5, 0x2e, 0xd8, 0xef, 0x81, 0xe5, 0x51, 0xce, 0x58, 0xd9, - 0xe0, 0xd5, 0x61, 0x3e, 0x9a, 0x7b, 0xdf, 0x05, 0xd7, 0x0d, 0x6c, 0x77, 0x7d, 0x37, 0x3c, 0x83, - 0x74, 0x5b, 0x95, 0x70, 0x08, 0x71, 0xd0, 0x6d, 0xf2, 0x83, 0x40, 0x02, 0x33, 0xb1, 0xad, 0x4e, - 0x3f, 0x93, 0x36, 0x12, 0x77, 0xf0, 0x18, 0x84, 0x7e, 0x2e, 0x58, 0xe0, 0x4a, 0x2f, 0x73, 0xbb, - 0x8b, 0x43, 0xfb, 0x25, 0x63, 0x1f, 0xf5, 0x8e, 0x42, 0x92, 0x77, 0x1c, 0x71, 0xc9, 0x53, 0xa3, - 0x2e, 0xb9, 0xf0, 0x7d, 0x01, 0x48, 0xc4, 0x96, 0x4d, 0x2b, 0x38, 0x26, 0x5b, 0x17, 0xf7, 0x3c, - 0x52, 0x68, 0x05, 0xc7, 0x71, 0x67, 0x37, 0x47, 0x1a, 0xa2, 0x12, 0x49, 0x37, 0x08, 0xba, 0x03, - 0xa3, 0xce, 0xd3, 0x16, 0xda, 0x7d, 0x15, 0xcc, 0x12, 0xef, 0x12, 0x1d, 0x90, 0xec, 0x0b, 0xf1, - 0xfd, 0x3d, 0x3b, 0x8c, 0x65, 0x20, 0x66, 0xe1, 0x62, 0xaf, 0x99, 0x65, 0x20, 0xfe, 0xe6, 0x03, - 0x70, 0xa9, 0x41, 0xbc, 0x10, 0x45, 0xa2, 0xb7, 0xb1, 0x7e, 0x28, 0x35, 0xc0, 0xa5, 0xae, 0x8b, - 0x0e, 0x68, 0xf9, 0x2c, 0xb2, 0x9b, 0xae, 0x7d, 0x9c, 0x1a, 0x6c, 0x8c, 0x56, 0xdb, 0x96, 0x73, - 0xf0, 0x62, 0xd7, 0x8d, 0xb5, 0x4a, 0x3f, 0x14, 0xc0, 0xa3, 0xae, 0x8b, 0x3c, 0x56, 0x4d, 0x8a, - 0xf8, 0x95, 0x0b, 0xa3, 0x23, 0x0f, 0x85, 0x1e, 0x72, 0xa2, 0x72, 0x5b, 0x2e, 0x91, 0x3d, 0xb1, - 0xc8, 0x13, 0x24, 0x66, 0xab, 0xd9, 0x2d, 0xe7, 0xe0, 0x9d, 0xae, 0x9b, 0x4a, 0x2b, 0x7d, 0x47, - 0x00, 0x77, 0x62, 0xe8, 0x2c, 0xc7, 0x41, 0x87, 0xae, 0x4f, 0x63, 0x23, 0xbe, 0xaa, 0x0c, 0x17, - 0x3b, 0xf9, 0x3e, 0x4a, 0xc7, 0x35, 0xbe, 0x06, 0xb8, 0x9c, 0x83, 0x37, 0x7a, 0x90, 0x12, 0xc9, - 0x86, 0x75, 0x95, 0x80, 0xa6, 0x69, 0x85, 0xbd, 0xd5, 0x99, 0xcd, 0xaa, 0xab, 0x94, 0x82, 0xe3, - 0x01, 0x5d, 0x8d, 0xa7, 0x95, 0x7e, 0x5d, 0x00, 0xb7, 0x62, 0xe8, 0x02, 0x1c, 0x22, 0xbb, 0x57, - 0x9b, 0x8c, 0x02, 0x5a, 0x16, 0x4c, 0x9d, 0xe5, 0x85, 0xed, 0x0f, 0xd2, 0x41, 0x8d, 0xab, 0x6c, - 0x2e, 0xe7, 0xe0, 0xf5, 0x1e, 0x9a, 0x04, 0x22, 0xe9, 0x77, 0x04, 0x70, 0x37, 0x06, 0xc3, 0xe7, - 0x75, 0x08, 0x24, 0x44, 0x67, 0x05, 0xca, 0x11, 0x94, 0xf3, 0x14, 0xca, 0xff, 0x4f, 0x87, 0x32, - 0xa9, 0xc4, 0xb9, 0x9c, 0x83, 0xb7, 0x7a, 0x70, 0xc6, 0x10, 0x46, 0x9a, 0xf1, 0x79, 0xd1, 0x30, - 0xb2, 0xc9, 0x29, 0x8b, 0x6c, 0x5e, 0xb4, 0xcc, 0x97, 0x6b, 0x2e, 0x55, 0x33, 0x29, 0x25, 0xcf, - 0x4c, 0x33, 0xe3, 0x89, 0xa4, 0xcf, 0xc0, 0xf5, 0x24, 0x14, 0x9d, 0x33, 0x8e, 0x60, 0x9e, 0x22, - 0xf8, 0x72, 0x76, 0x04, 0xf1, 0x9a, 0xe9, 0x72, 0x0e, 0xe6, 0x47, 0xa4, 0x73, 0x02, 0xe9, 0x97, - 0xc0, 0xfa, 0xa8, 0xe4, 0x8e, 0xef, 0xb6, 0x43, 0x2e, 0x1a, 0x50, 0xd1, 0xef, 0x67, 0x15, 0x3d, - 0x54, 0x71, 0x5d, 0xce, 0xc1, 0xd5, 0x21, 0xd9, 0x7d, 0x0a, 0xa9, 0x09, 0x56, 0xbb, 0x2e, 0x72, - 0xb8, 0x13, 0x27, 0x51, 0x97, 0x4f, 0x8e, 0x12, 0x3a, 0x38, 0x3d, 0xd4, 0x2e, 0x6c, 0x6f, 0x65, - 0xa8, 0xe2, 0x89, 0xd7, 0x2d, 0x97, 0x73, 0x70, 0xb9, 0xeb, 0x26, 0x56, 0x34, 0x7f, 0x87, 0x99, - 0x5f, 0x4f, 0x5c, 0xff, 0xac, 0x8b, 0x92, 0xb7, 0x5c, 0xf2, 0x02, 0x95, 0xfc, 0x95, 0x0c, 0x92, - 0x93, 0x4b, 0x91, 0x99, 0xe5, 0xa5, 0x94, 0x2b, 0x7f, 0x93, 0x1a, 0x5e, 0x0f, 0x0c, 0x2f, 0x78, - 0x0b, 0x58, 0xed, 0x1a, 0x07, 0x72, 0x91, 0x02, 0xf9, 0xd2, 0x17, 0xaa, 0x7c, 0x63, 0x36, 0x37, - 0xa1, 0x52, 0xf1, 0x37, 0x99, 0x03, 0xed, 0x23, 0xe0, 0x01, 0x7d, 0x7f, 0x5f, 0x32, 0x10, 0x8b, - 0x14, 0xc4, 0xd3, 0x2c, 0x20, 0x92, 0x0a, 0x8c, 0xca, 0x39, 0x78, 0x33, 0x86, 0x23, 0xb1, 0x06, - 0xe9, 0xf7, 0x99, 0xf7, 0x1c, 0x85, 0x62, 0x47, 0xb9, 0x25, 0xd4, 0x0a, 0x9b, 0x01, 0x07, 0x74, - 0x89, 0x02, 0xfa, 0x7f, 0x9f, 0x03, 0xd0, 0x68, 0xc9, 0x4f, 0x39, 0x07, 0xef, 0x8e, 0xa2, 0xea, - 0xd3, 0x85, 0x4d, 0x5e, 0xf5, 0xf0, 0x63, 0x01, 0x3c, 0x1d, 0x5c, 0x27, 0x5a, 0x30, 0x82, 0x2c, - 0x5a, 0x31, 0x82, 0x9c, 0xa8, 0x64, 0x04, 0x85, 0x9e, 0xd7, 0xe4, 0xc1, 0x64, 0xb3, 0xc9, 0x91, - 0x8a, 0x14, 0xe9, 0xb3, 0x4c, 0xeb, 0x97, 0xa9, 0x30, 0xa7, 0x9c, 0x83, 0x8f, 0xe3, 0x8b, 0x9a, - 0xad, 0x9a, 0xe7, 0x47, 0x02, 0x78, 0x2f, 0xd3, 0x1c, 0xfa, 0xea, 0x66, 0xf8, 0x2f, 0x53, 0xfc, - 0xa5, 0x2f, 0x8c, 0x7f, 0x30, 0x35, 0x58, 0xce, 0xc1, 0xcd, 0x34, 0xf0, 0x43, 0xc9, 0xc4, 0x3f, - 0x10, 0xc0, 0x5b, 0x71, 0xe4, 0x56, 0x97, 0x44, 0x1e, 0xbd, 0x3b, 0x68, 0xac, 0x08, 0x9a, 0x01, - 0x96, 0x28, 0xe0, 0x8f, 0x33, 0x00, 0x9e, 0x54, 0xea, 0x52, 0xce, 0xc1, 0xfb, 0x7d, 0xa0, 0x13, - 0x8b, 0x62, 0xfe, 0x5c, 0x00, 0x5b, 0x29, 0x96, 0xeb, 0x5a, 0x2d, 0x76, 0x79, 0x39, 0xe3, 0x20, - 0xaf, 0x50, 0x90, 0x3b, 0x5f, 0xc4, 0x7e, 0x07, 0xb3, 0xcd, 0xe5, 0x1c, 0x7c, 0x34, 0xc1, 0x88, - 0x35, 0xab, 0x15, 0x4f, 0x4d, 0xff, 0xae, 0x00, 0xee, 0xc7, 0xa1, 0x76, 0x7a, 0x19, 0xdc, 0x91, - 0x75, 0xbf, 0x4a, 0x11, 0x7e, 0x98, 0x01, 0xe1, 0xb8, 0x34, 0x70, 0x39, 0x07, 0x0b, 0x7d, 0x68, - 0x63, 0x93, 0xc5, 0xbf, 0x2a, 0x80, 0xdb, 0x71, 0x4c, 0x21, 0x0e, 0x42, 0x82, 0xa6, 0x3d, 0xe0, - 0x8f, 0x97, 0x52, 0x4f, 0xbf, 0x09, 0x39, 0xd9, 0x72, 0x0e, 0xae, 0xf7, 0x91, 0x24, 0x25, 0x6d, - 0x7d, 0xb0, 0x16, 0xc7, 0x10, 0xc5, 0xb9, 0xd1, 0x39, 0xb4, 0x9c, 0x92, 0x88, 0x1c, 0x97, 0x14, - 0x65, 0xc7, 0xee, 0x98, 0x84, 0x69, 0x13, 0xe4, 0xbb, 0x2e, 0x09, 0xc2, 0xac, 0x10, 0xa3, 0x36, - 0x3e, 0xa5, 0xf7, 0x5f, 0x7e, 0xe2, 0xae, 0xa4, 0x3c, 0x44, 0x8d, 0x4d, 0x47, 0x96, 0x73, 0xf0, - 0x6a, 0xd7, 0x1d, 0xed, 0x94, 0xce, 0xe8, 0x21, 0x3f, 0x2c, 0x2d, 0xb0, 0x4e, 0x22, 0x91, 0xf9, - 0x54, 0x0d, 0x4f, 0x48, 0x72, 0xb2, 0x89, 0x26, 0x13, 0x48, 0xdf, 0x04, 0x37, 0x93, 0x26, 0x4a, - 0x93, 0xa0, 0x5c, 0xf8, 0x6a, 0xea, 0x01, 0x33, 0x31, 0x81, 0x5a, 0xce, 0xc1, 0x6b, 0xc3, 0xb3, - 0xee, 0x93, 0x48, 0x7f, 0xc4, 0x5c, 0xc8, 0x30, 0x02, 0xf6, 0x50, 0x1c, 0x4f, 0xb2, 0x72, 0x34, - 0xd7, 0x28, 0x1a, 0x25, 0x2b, 0x9a, 0x09, 0xb9, 0xda, 0x72, 0x0e, 0xde, 0x1b, 0x02, 0x96, 0x4c, - 0x2d, 0xfd, 0xa9, 0x00, 0x36, 0xe3, 0x26, 0xe8, 0xf6, 0x9f, 0x1a, 0x91, 0x75, 0x1a, 0xb0, 0xa7, - 0x01, 0xbe, 0x2d, 0xb8, 0x55, 0xae, 0xa5, 0x5e, 0x21, 0xb2, 0xfd, 0x5c, 0xa8, 0x9c, 0x83, 0x0f, - 0xfb, 0x56, 0x1a, 0xa7, 0x3d, 0x0d, 0x74, 0xd7, 0xb1, 0x07, 0x7e, 0x5a, 0xf4, 0x5d, 0x01, 0xdc, - 0x4b, 0x0e, 0x19, 0x9c, 0x00, 0x61, 0xfa, 0x28, 0xca, 0xe1, 0x5d, 0xcf, 0x1c, 0x42, 0x25, 0xff, - 0x8a, 0x67, 0x30, 0x84, 0xea, 0xd1, 0x38, 0x41, 0xfc, 0x37, 0x2b, 0x21, 0x33, 0x6b, 0x72, 0xde, - 0x86, 0x1e, 0x62, 0xd9, 0x47, 0xb6, 0x8a, 0x1c, 0xc5, 0x7a, 0xea, 0xd6, 0x4d, 0xfe, 0x59, 0x08, - 0xb7, 0xe8, 0xe4, 0x9f, 0x8c, 0x7c, 0x1d, 0x5c, 0xb6, 0x68, 0x1a, 0x14, 0xf5, 0x93, 0x90, 0xf9, - 0x1b, 0x54, 0xd2, 0xf8, 0x67, 0xf3, 0xc4, 0x94, 0x7d, 0x39, 0x07, 0x45, 0x6b, 0xa8, 0x23, 0x72, - 0x89, 0x71, 0x13, 0xe0, 0x9a, 0xa5, 0xe1, 0x31, 0x9f, 0xd9, 0xcd, 0xd4, 0x0d, 0x3b, 0xe1, 0xa9, - 0x9d, 0xb9, 0xc4, 0x49, 0x6f, 0xf1, 0x3c, 0x54, 0x4e, 0x00, 0xd1, 0x7b, 0x05, 0x60, 0x38, 0x6e, - 0xa5, 0xae, 0xf3, 0xe4, 0x17, 0x78, 0xb6, 0xce, 0x29, 0xaf, 0xf4, 0xbf, 0x26, 0x50, 0x27, 0x12, - 0xdd, 0x1b, 0xbf, 0x11, 0xff, 0x61, 0x6c, 0x74, 0x65, 0xbc, 0x9d, 0xf5, 0xf6, 0x3a, 0xee, 0x67, - 0xb5, 0x03, 0xb7, 0xd7, 0x04, 0x22, 0xe9, 0x53, 0xc0, 0x17, 0x0b, 0xe1, 0xa8, 0x82, 0x21, 0x5f, - 0xa0, 0x52, 0xdf, 0x49, 0x59, 0xf6, 0xc1, 0x8a, 0x87, 0x72, 0x0e, 0x5e, 0xb2, 0x06, 0xdb, 0xa5, - 0x16, 0x58, 0xe1, 0x63, 0x13, 0x07, 0x15, 0x2f, 0x7c, 0xc8, 0xdf, 0x49, 0x79, 0xb9, 0x1f, 0x5f, - 0x7f, 0x50, 0xce, 0xc1, 0x25, 0x2b, 0xa9, 0x57, 0x3a, 0x00, 0x4b, 0xfd, 0x57, 0x12, 0xe6, 0x18, - 0xd9, 0x72, 0xde, 0xa5, 0xc2, 0xde, 0x1e, 0x2b, 0x2c, 0x21, 0xb7, 0x51, 0xce, 0xc1, 0x2b, 0x7e, - 0x42, 0xca, 0xe3, 0x14, 0x5c, 0x1f, 0xf3, 0xb8, 0xce, 0x44, 0xdd, 0x4b, 0x99, 0xd7, 0xf8, 0x84, - 0x00, 0x71, 0xf8, 0x87, 0xe3, 0xd3, 0x05, 0x07, 0x80, 0xcf, 0x1a, 0xf1, 0x8c, 0x99, 0xcf, 0x4a, - 0x2b, 0xf2, 0xf7, 0x53, 0x26, 0x97, 0x50, 0x8e, 0x41, 0x26, 0x67, 0x25, 0x54, 0x69, 0x54, 0xc0, - 0xc5, 0x9e, 0x0c, 0xba, 0x4a, 0x0f, 0xe8, 0xd8, 0xf7, 0x52, 0xc7, 0x26, 0xc4, 0xe5, 0x1c, 0x5c, - 0xb0, 0xe2, 0x85, 0x14, 0xfb, 0x40, 0x8a, 0x27, 0xf7, 0xd8, 0x8a, 0xe4, 0x1f, 0xa6, 0xd4, 0x51, - 0x0d, 0x17, 0x32, 0x50, 0x6f, 0x32, 0x5c, 0xdc, 0x30, 0x34, 0x74, 0x97, 0xa6, 0xdc, 0xf3, 0x8f, - 0x32, 0x0f, 0xcd, 0x72, 0xf4, 0x83, 0x43, 0xf3, 0xbc, 0xfd, 0xd0, 0xd0, 0x0e, 0xcd, 0x78, 0xe6, - 0x37, 0x32, 0x0f, 0xcd, 0x52, 0xa4, 0x83, 0x43, 0xf3, 0xb4, 0x69, 0x13, 0xac, 0xc6, 0x87, 0x66, - 0x69, 0xd8, 0x48, 0x2f, 0x6f, 0xa5, 0xbc, 0x0b, 0x24, 0x57, 0x32, 0x94, 0x73, 0x70, 0xd9, 0x4a, - 0xae, 0x71, 0x48, 0x96, 0xc6, 0x55, 0xf5, 0xf6, 0xe7, 0x94, 0xd6, 0x53, 0xd8, 0x88, 0x34, 0xae, - 0xb6, 0x64, 0x69, 0x5c, 0x7b, 0xef, 0x7c, 0x4e, 0x69, 0x3d, 0x1d, 0x8e, 0x48, 0xe3, 0x9a, 0x6c, - 0x81, 0x6b, 0x71, 0x69, 0xb4, 0xca, 0x20, 0x20, 0xa7, 0x65, 0x37, 0xc0, 0x7e, 0x7e, 0x33, 0xb3, - 0xb8, 0x78, 0xad, 0xc3, 0xa0, 0xb8, 0x81, 0x2a, 0x88, 0xdf, 0x12, 0x40, 0x21, 0x1e, 0x20, 0xc4, - 0x33, 0x49, 0xfd, 0x67, 0x96, 0xfc, 0x56, 0xea, 0x9b, 0x6c, 0x6a, 0x89, 0x3d, 0x7b, 0x93, 0xed, - 0x91, 0xd9, 0xa3, 0x64, 0xd2, 0x31, 0x58, 0x49, 0x78, 0x61, 0xc1, 0xae, 0x8d, 0xf3, 0xef, 0xa6, - 0x86, 0xd8, 0x63, 0x0a, 0xdc, 0x59, 0x88, 0x3d, 0xd4, 0xe9, 0xda, 0x78, 0x58, 0x58, 0x14, 0x6e, - 0x7a, 0x0e, 0xce, 0x3f, 0xce, 0x2c, 0x6c, 0xa8, 0xa8, 0x7c, 0x50, 0x58, 0xbf, 0x53, 0xfa, 0x1a, - 0xb8, 0x1c, 0x5a, 0x47, 0xfc, 0x1c, 0xc2, 0xe4, 0x40, 0xf4, 0xcf, 0xf2, 0xdb, 0x29, 0x67, 0x51, - 0x52, 0xc2, 0x91, 0x9c, 0x45, 0xa1, 0x75, 0x14, 0x6f, 0x97, 0x42, 0x70, 0x2d, 0xe0, 0xe9, 0x19, - 0xe4, 0xd3, 0x91, 0xd0, 0x11, 0xa6, 0x0f, 0xd9, 0xdd, 0x66, 0x98, 0x7f, 0x92, 0xf2, 0x24, 0x35, - 0x29, 0xb3, 0x53, 0xce, 0xc1, 0x95, 0x20, 0xb9, 0x7f, 0x78, 0x5b, 0xf0, 0x02, 0x07, 0xbe, 0xe5, - 0xdf, 0xcb, 0x6c, 0xa7, 0xf1, 0xb2, 0x98, 0x41, 0x3b, 0x1d, 0x28, 0x98, 0x49, 0x96, 0xc6, 0x37, - 0xe1, 0x97, 0x3e, 0xa7, 0xb4, 0xa4, 0x4d, 0x38, 0x50, 0x05, 0x72, 0x00, 0x96, 0x22, 0xc3, 0x38, - 0x43, 0x87, 0x38, 0xb4, 0x5f, 0xf2, 0x33, 0xf0, 0xcb, 0x29, 0x27, 0x52, 0x42, 0x7a, 0x8b, 0x9c, - 0x48, 0x4e, 0x42, 0xd6, 0xeb, 0x7b, 0x43, 0xaf, 0x79, 0xdc, 0x00, 0xfb, 0x72, 0xd9, 0x1d, 0x3f, - 0xff, 0x7e, 0xe6, 0xc7, 0xb3, 0xf1, 0xbf, 0x8d, 0x1c, 0x7c, 0xd2, 0x4b, 0xa4, 0x93, 0xbe, 0x35, - 0x74, 0xb3, 0x3f, 0xee, 0x1e, 0x60, 0x9a, 0x9c, 0x1d, 0xb8, 0x26, 0x3c, 0xcd, 0xfc, 0xc0, 0x39, - 0xfa, 0x93, 0xf5, 0xc1, 0x07, 0x4e, 0xda, 0x7f, 0x3c, 0x70, 0x3d, 0xf8, 0x76, 0xb2, 0x4a, 0xac, - 0x4e, 0x87, 0x3e, 0xb3, 0xf6, 0x1e, 0x38, 0xbf, 0x92, 0xfa, 0xc2, 0x3d, 0xe9, 0xb7, 0x0f, 0x83, - 0x8e, 0x28, 0xf1, 0xd7, 0x11, 0x1d, 0xb0, 0xc6, 0xad, 0xed, 0xc8, 0xb7, 0x3a, 0x2f, 0xe9, 0x95, - 0x2e, 0xb0, 0xad, 0x28, 0x12, 0xfa, 0x80, 0xca, 0x7f, 0x37, 0xc5, 0xde, 0x46, 0xf2, 0xf5, 0x64, - 0x37, 0x59, 0xb1, 0xae, 0xd3, 0xa0, 0x9f, 0xca, 0xff, 0x3e, 0xbb, 0xa8, 0x0d, 0x48, 0xb5, 0x7d, - 0xef, 0xb4, 0x8d, 0x7e, 0x01, 0x9f, 0xe2, 0x26, 0x72, 0xdc, 0xc3, 0x43, 0x7a, 0x05, 0xce, 0x7f, - 0x98, 0x6a, 0x0f, 0xe9, 0x19, 0x64, 0x66, 0x0f, 0x13, 0xe9, 0xa4, 0x9f, 0x07, 0x4b, 0xb4, 0x88, - 0x83, 0xe6, 0x4d, 0x69, 0xce, 0x93, 0xcf, 0xfe, 0xa3, 0xb4, 0x4c, 0xe5, 0x48, 0xfa, 0xb5, 0x9c, - 0x83, 0x52, 0x77, 0xa4, 0x75, 0xe7, 0x3c, 0x98, 0xa5, 0x5c, 0xcf, 0x66, 0xe6, 0xa6, 0xc4, 0x69, - 0x62, 0x1b, 0xbd, 0x1b, 0x03, 0xf1, 0x5f, 0x51, 0x72, 0x81, 0xde, 0x0f, 0x37, 0xfe, 0xfa, 0x52, - 0xff, 0xdf, 0x5e, 0xa2, 0xa0, 0x56, 0xba, 0x0d, 0xd6, 0x8b, 0x9a, 0xa1, 0xe8, 0xcf, 0x55, 0x88, - 0xa0, 0x6a, 0xe8, 0x0d, 0xa8, 0x0c, 0xff, 0x56, 0xfb, 0x3a, 0xc8, 0x8f, 0x92, 0x18, 0x2a, 0x7c, - 0xae, 0x42, 0x51, 0x90, 0x6e, 0x81, 0xeb, 0xa3, 0xbd, 0x7b, 0x8d, 0x1d, 0x15, 0xd6, 0x54, 0x53, - 0x35, 0xc4, 0x29, 0xe9, 0x09, 0xd8, 0x1a, 0xa5, 0x28, 0xca, 0xa6, 0xbc, 0x23, 0x1b, 0x2a, 0xaa, - 0xeb, 0x86, 0x59, 0x82, 0xaa, 0x81, 0x0c, 0xb5, 0xb2, 0x8b, 0xca, 0xba, 0x61, 0xaa, 0x45, 0x71, - 0x5a, 0x7a, 0x17, 0xbc, 0x3d, 0x81, 0xa9, 0xba, 0x6f, 0x7c, 0x52, 0x19, 0xe0, 0x98, 0x91, 0xb6, - 0xc1, 0xe6, 0x24, 0x0e, 0xbd, 0x56, 0xd2, 0x8b, 0x3b, 0x03, 0x3c, 0xb3, 0xd2, 0x5b, 0xe0, 0x41, - 0x16, 0x68, 0xb0, 0x68, 0x88, 0xe7, 0xa4, 0x87, 0xe0, 0x6e, 0x2a, 0x24, 0x42, 0x79, 0x5e, 0xba, - 0x0f, 0x0a, 0xa3, 0x94, 0x72, 0xbd, 0x5e, 0xd1, 0x14, 0xd9, 0xd4, 0xf4, 0x1a, 0x2a, 0x9b, 0x66, - 0x5d, 0x9c, 0x93, 0xee, 0x81, 0xdb, 0x93, 0xe9, 0x4c, 0xa5, 0x2e, 0xce, 0x27, 0x93, 0xbd, 0xd0, - 0x6a, 0x45, 0xfd, 0x85, 0x81, 0x8a, 0xaa, 0xb1, 0x67, 0xea, 0x75, 0x11, 0x48, 0x6f, 0x83, 0x87, - 0x13, 0xf0, 0x19, 0x9f, 0x54, 0xd8, 0x9a, 0x51, 0x8c, 0x17, 0x52, 0x14, 0xdc, 0x9f, 0xba, 0x5a, - 0x34, 0xca, 0xda, 0xae, 0x29, 0x2e, 0x48, 0xef, 0x81, 0x77, 0x33, 0x8d, 0x1f, 0x57, 0xf1, 0xc5, - 0x14, 0x39, 0x50, 0x2d, 0x6a, 0x83, 0x4b, 0xbf, 0x98, 0x75, 0x51, 0x4a, 0x4a, 0x5d, 0xbc, 0x94, - 0x69, 0x51, 0x08, 0xa5, 0x98, 0x59, 0x3d, 0x84, 0xfa, 0xb2, 0xf4, 0x21, 0x78, 0xff, 0xf3, 0xa8, - 0x87, 0xef, 0x87, 0x8a, 0x6a, 0x18, 0xa2, 0x24, 0xbd, 0x03, 0x1e, 0x65, 0x61, 0x96, 0x3f, 0x6d, - 0x40, 0x55, 0xbc, 0x22, 0x3d, 0x00, 0x77, 0x26, 0x90, 0x17, 0xf7, 0x6b, 0x72, 0x55, 0x2f, 0xee, - 0x88, 0x57, 0x53, 0x4c, 0x5c, 0x91, 0x0d, 0x43, 0xae, 0x15, 0xa1, 0x8c, 0xf6, 0xd4, 0x7d, 0xa3, - 0x2e, 0x2b, 0xaa, 0x21, 0x2e, 0xa5, 0xac, 0x5a, 0x9f, 0x27, 0xbe, 0x06, 0xcb, 0xd2, 0x53, 0xf0, - 0xde, 0x04, 0x2e, 0xb5, 0x22, 0x1b, 0xa6, 0xa6, 0x18, 0xaa, 0x0c, 0x95, 0xf2, 0x00, 0xe7, 0x4a, - 0xa6, 0xf5, 0xe6, 0xfc, 0xb2, 0x52, 0x56, 0xc5, 0x7c, 0x8a, 0xb6, 0x18, 0x47, 0x55, 0xad, 0xea, - 0x70, 0xbf, 0xb8, 0x23, 0xae, 0x66, 0x12, 0x40, 0x35, 0x8b, 0x98, 0x80, 0x6b, 0x29, 0x93, 0x61, - 0x1c, 0x4a, 0xa5, 0x61, 0x98, 0x43, 0xc6, 0xbb, 0x26, 0x6d, 0x80, 0xfb, 0xa9, 0xd6, 0xc5, 0x56, - 0xf1, 0xba, 0xb4, 0x09, 0x36, 0x32, 0xd9, 0x17, 0xa3, 0x5f, 0x4f, 0x59, 0xcc, 0x3e, 0x7d, 0x55, - 0x53, 0xa0, 0x6e, 0xe8, 0xbb, 0xa6, 0x78, 0x43, 0xfa, 0x32, 0xd8, 0x9e, 0xb4, 0x98, 0xba, 0xb2, - 0x07, 0x75, 0x59, 0x29, 0x0f, 0xf9, 0xb9, 0x9b, 0x29, 0xb6, 0x1f, 0xf9, 0x46, 0xd9, 0xac, 0xc8, - 0x86, 0x78, 0x2b, 0x65, 0x4f, 0x19, 0x35, 0xfd, 0xc5, 0x6e, 0x45, 0xde, 0x53, 0xc5, 0xdb, 0x63, - 0xc6, 0xd5, 0x95, 0x98, 0x76, 0x8b, 0x06, 0xaa, 0x43, 0xfd, 0xab, 0xfb, 0x62, 0x61, 0x8c, 0x29, - 0xc6, 0xa9, 0xcb, 0x5a, 0xa9, 0x8c, 0xe4, 0xe7, 0xb2, 0x56, 0x91, 0x77, 0xb4, 0x8a, 0x66, 0xee, - 0x8b, 0x77, 0xa4, 0xf7, 0xc1, 0x93, 0x14, 0x2e, 0xba, 0x43, 0x34, 0x05, 0x41, 0xb5, 0xa4, 0x19, - 0x26, 0xa4, 0xae, 0x53, 0xbc, 0x9b, 0xec, 0x85, 0x0d, 0xb9, 0x5a, 0x89, 0xbb, 0x58, 0xf1, 0x9e, - 0x54, 0x00, 0x37, 0x46, 0xe9, 0x54, 0x65, 0x9b, 0xfd, 0x2b, 0x49, 0x4d, 0x51, 0xc5, 0xfb, 0x63, - 0x8c, 0x4e, 0x57, 0x86, 0xdd, 0x30, 0xaa, 0xe9, 0x35, 0x24, 0x17, 0xc5, 0x07, 0xd2, 0x5d, 0x70, - 0x6b, 0xd2, 0xb9, 0x48, 0xff, 0xad, 0xe2, 0x61, 0xb2, 0xed, 0xc7, 0x4f, 0x00, 0xf9, 0x85, 0x81, - 0x14, 0xbd, 0x66, 0xe8, 0x15, 0x55, 0x7c, 0xb4, 0xf1, 0xc7, 0x02, 0x58, 0x1c, 0xfc, 0xb3, 0x33, - 0xe9, 0x26, 0x58, 0xeb, 0x8d, 0x60, 0x98, 0xb2, 0xd9, 0x30, 0x86, 0x8e, 0xef, 0x35, 0xb0, 0x32, - 0x4c, 0x60, 0x34, 0x14, 0x85, 0x78, 0x2a, 0x21, 0xb1, 0x73, 0x4f, 0xab, 0xd7, 0xd5, 0xa2, 0x38, - 0x25, 0xad, 0x82, 0xa5, 0xe1, 0x4e, 0x15, 0x42, 0x1d, 0x8a, 0xd3, 0x49, 0x7c, 0xf2, 0x8e, 0x0e, - 0xe9, 0x49, 0xbc, 0xf1, 0xe3, 0x29, 0x30, 0xad, 0x98, 0xb2, 0x74, 0x05, 0x5c, 0x52, 0x4c, 0x79, - 0xf4, 0x6f, 0x65, 0x48, 0xa3, 0xdc, 0x30, 0xcb, 0x64, 0x62, 0x35, 0x55, 0x31, 0x75, 0x12, 0x47, - 0xac, 0x80, 0x2b, 0xb4, 0x5d, 0x31, 0xb5, 0xe7, 0x24, 0xbc, 0x30, 0x0c, 0x4d, 0xaf, 0x91, 0xf0, - 0xa1, 0xd7, 0x41, 0x20, 0x23, 0xa8, 0x7e, 0xd2, 0x50, 0x0d, 0xd3, 0x10, 0xa7, 0xa3, 0x8e, 0x3a, - 0x54, 0xab, 0x5a, 0xa3, 0x8a, 0x8c, 0x46, 0xbd, 0xae, 0x43, 0x53, 0x9c, 0x89, 0x3a, 0x4c, 0x48, - 0xb6, 0x74, 0x11, 0x15, 0xd5, 0xe7, 0x1a, 0xf1, 0x85, 0xb3, 0x91, 0xec, 0x46, 0xbd, 0x04, 0xe5, - 0xa2, 0x8a, 0x76, 0xe4, 0x5a, 0x4d, 0x85, 0xe2, 0xb9, 0x88, 0x61, 0x47, 0xab, 0x54, 0xb4, 0x5a, - 0x09, 0x19, 0x8d, 0x6a, 0x55, 0x86, 0xfb, 0xe2, 0xf9, 0x68, 0x06, 0x5c, 0x76, 0x45, 0x33, 0x4c, - 0x71, 0x8e, 0xfe, 0xf9, 0x48, 0xbf, 0xb1, 0xaa, 0xd7, 0x34, 0x53, 0x87, 0x5a, 0xad, 0x24, 0xce, - 0xd3, 0xbf, 0x35, 0x31, 0x65, 0xa4, 0x7e, 0xd5, 0x54, 0x61, 0x4d, 0xae, 0x20, 0xb9, 0x51, 0xd4, - 0x4c, 0x64, 0x98, 0x3a, 0x94, 0x4b, 0xaa, 0x08, 0x22, 0x00, 0xfa, 0x1e, 0x41, 0x61, 0x10, 0xdd, - 0xed, 0xd7, 0x14, 0xf1, 0x82, 0x24, 0x82, 0x05, 0xca, 0x57, 0x33, 0xa1, 0x8c, 0xb4, 0xa2, 0xb8, - 0xb0, 0xf1, 0x4f, 0x73, 0x60, 0x29, 0xb1, 0xee, 0x9c, 0x9c, 0x16, 0x5a, 0xcd, 0x54, 0x4b, 0xcc, - 0xce, 0x91, 0x5a, 0x83, 0x7a, 0xa5, 0x82, 0xf6, 0xb4, 0xda, 0xf0, 0x5f, 0xb0, 0xdc, 0x06, 0xeb, - 0xe3, 0x08, 0x8d, 0x8a, 0xac, 0xec, 0x89, 0x02, 0x31, 0xd2, 0x71, 0x24, 0xc4, 0xf0, 0x74, 0xad, - 0xa8, 0x88, 0x53, 0x24, 0xfe, 0x18, 0x47, 0x55, 0x97, 0x4b, 0x2a, 0x2c, 0x36, 0xcc, 0x7d, 0x71, - 0x7a, 0x92, 0x3c, 0xb5, 0x2a, 0x6b, 0x15, 0x71, 0x86, 0x04, 0x8b, 0xe3, 0x48, 0x9e, 0x69, 0x50, - 0x16, 0x67, 0xa5, 0x3b, 0xe0, 0xe6, 0x38, 0x0a, 0x6a, 0x70, 0xb0, 0x28, 0x9e, 0x23, 0x3b, 0x7b, - 0x1c, 0x51, 0x55, 0x36, 0x4d, 0x15, 0x56, 0x75, 0xc3, 0x14, 0xcf, 0x4f, 0x9a, 0x5e, 0xd5, 0x40, - 0xa6, 0x2a, 0x57, 0x0d, 0x71, 0x6e, 0x12, 0x95, 0x5e, 0x37, 0x4a, 0x6a, 0x4d, 0x53, 0xc5, 0xf9, - 0x49, 0xd0, 0xc9, 0x72, 0x8a, 0x60, 0xe2, 0xe4, 0xe4, 0xea, 0xae, 0x78, 0x61, 0x32, 0x6e, 0xa5, - 0xac, 0xd5, 0x54, 0xba, 0xf8, 0xd2, 0x97, 0xc0, 0xe3, 0x74, 0x3a, 0x54, 0xd2, 0xcc, 0x72, 0x63, - 0x87, 0xee, 0x18, 0xb2, 0x53, 0x2e, 0x4a, 0x5b, 0xe0, 0xad, 0x0c, 0x6c, 0x8a, 0x06, 0x95, 0x8a, - 0xaa, 0x68, 0xe2, 0x22, 0xf1, 0x3e, 0xd9, 0xe4, 0x54, 0xe4, 0x1d, 0xf1, 0x12, 0x39, 0xe1, 0x32, - 0x90, 0x3f, 0x53, 0x6b, 0x7b, 0x5a, 0xcd, 0x10, 0xc5, 0x8c, 0xf4, 0x72, 0xcd, 0xd0, 0x76, 0x2a, - 0xaa, 0x78, 0x79, 0x92, 0x7a, 0xc8, 0x59, 0xa8, 0x29, 0x6a, 0x4d, 0x7f, 0x21, 0x4a, 0x93, 0x16, - 0xac, 0xb7, 0x83, 0xae, 0x90, 0x73, 0x63, 0xac, 0x25, 0xc9, 0xa6, 0x5c, 0xd4, 0x4b, 0x48, 0xab, - 0x29, 0x5a, 0x51, 0xad, 0x99, 0xa8, 0x2a, 0xd7, 0xe4, 0x92, 0x5a, 0x55, 0x6b, 0xa6, 0x78, 0x95, - 0x1c, 0xfa, 0x59, 0x60, 0xbf, 0x20, 0xd1, 0x55, 0x36, 0x5a, 0x12, 0x52, 0x2e, 0x93, 0xc3, 0x32, - 0xcb, 0xb8, 0x34, 0x3c, 0xa0, 0x71, 0x54, 0x06, 0x6a, 0x1a, 0xe6, 0x55, 0x48, 0x7c, 0x9e, 0x97, - 0x1e, 0x83, 0x77, 0x32, 0x70, 0xc4, 0xae, 0x66, 0xab, 0x1b, 0x1f, 0x83, 0xf3, 0x3c, 0xe7, 0x40, - 0x7c, 0xe0, 0xae, 0x2a, 0x9b, 0x24, 0x6e, 0x1a, 0x39, 0x3f, 0xa2, 0x8e, 0x61, 0x8f, 0x2a, 0x6c, - 0xfc, 0xa1, 0x00, 0xd6, 0x26, 0xfc, 0x22, 0x80, 0x58, 0x58, 0xc4, 0x0c, 0x55, 0x45, 0xaf, 0x56, - 0xd5, 0x5a, 0x91, 0xc1, 0x4b, 0x3c, 0xab, 0x36, 0xc0, 0xfd, 0xc9, 0xe4, 0x35, 0xdd, 0x64, 0xb4, - 0x02, 0xb1, 0x96, 0xc9, 0xb4, 0x45, 0xbd, 0xa6, 0x8a, 0x53, 0x3b, 0x5f, 0xff, 0xdb, 0x9f, 0xdc, - 0x10, 0xfe, 0xee, 0x27, 0x37, 0x84, 0x7f, 0xfc, 0xc9, 0x0d, 0xe1, 0x53, 0xfd, 0xc8, 0x0d, 0x5f, - 0x76, 0x0f, 0x36, 0x6d, 0xaf, 0xb5, 0x75, 0xe4, 0x5b, 0x27, 0x2e, 0xcb, 0x49, 0x5b, 0xcd, 0xad, - 0xde, 0x5f, 0xfa, 0x5a, 0x1d, 0x77, 0xeb, 0x08, 0xb7, 0xb7, 0xe8, 0xaf, 0x37, 0xb6, 0x8e, 0xbc, - 0xa1, 0xff, 0xf8, 0xfd, 0x30, 0xf6, 0xf5, 0xe4, 0xf1, 0xc1, 0x39, 0x4a, 0xf6, 0xe4, 0x7f, 0x03, - 0x00, 0x00, 0xff, 0xff, 0x30, 0xe3, 0x6d, 0x74, 0x13, 0x58, 0x00, 0x00, + // 5350 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x7c, 0x4d, 0x8c, 0xdb, 0x48, + 0x76, 0xbf, 0xd8, 0x1f, 0x76, 0xbb, 0x6c, 0xb7, 0x69, 0xda, 0x6e, 0xab, 0xdd, 0x6e, 0x7f, 0xc8, + 0xdf, 0x3d, 0x33, 0xdd, 0xe3, 0xf6, 0xec, 0x8e, 0x77, 0x66, 0xfe, 0xff, 0x09, 0x9b, 0x62, 0x4b, + 0x74, 0x4b, 0xa2, 0xa6, 0x48, 0xd9, 0xdb, 0xb3, 0x58, 0x54, 0xd8, 0x64, 0x75, 0x9b, 0x69, 0x49, + 0xd4, 0x92, 0x54, 0xf7, 0x74, 0x82, 0x60, 0x37, 0x5f, 0x8b, 0x20, 0xbb, 0x9b, 0x4d, 0x80, 0x60, + 0x11, 0x60, 0x81, 0x20, 0x41, 0x3e, 0x90, 0x43, 0x80, 0x9c, 0x82, 0xbd, 0x26, 0x40, 0x0e, 0x39, + 0x06, 0x48, 0x6e, 0xb9, 0x04, 0x9b, 0x4b, 0x6e, 0x39, 0x25, 0x40, 0xbe, 0x90, 0xa0, 0x3e, 0x48, + 0x51, 0x12, 0x25, 0x72, 0x26, 0x5e, 0x2c, 0x60, 0xdf, 0xa4, 0xaa, 0xf7, 0xea, 0xfd, 0xea, 0xd5, + 0xab, 0x57, 0xaf, 0xea, 0x3d, 0x09, 0x3c, 0x0a, 0x71, 0x1b, 0xf7, 0x3c, 0x3f, 0xdc, 0xe8, 0x07, + 0xd6, 0x01, 0xc6, 0x47, 0xb8, 0x1b, 0x06, 0x1b, 0x47, 0x8f, 0x93, 0x5f, 0xd7, 0x7b, 0xbe, 0x17, + 0x7a, 0xd2, 0xd5, 0x88, 0x74, 0x3d, 0xd9, 0x77, 0xf4, 0xb8, 0xb4, 0x06, 0xa4, 0x96, 0xb6, 0x65, + 0x75, 0xbb, 0xd8, 0x57, 0xda, 0xae, 0x7d, 0xa8, 0x92, 0x1e, 0xe9, 0x32, 0x98, 0xb7, 0xda, 0xd8, + 0x0f, 0x8b, 0xc2, 0x2d, 0xe1, 0xe1, 0x19, 0xc8, 0xbe, 0x94, 0xb6, 0xc1, 0xc3, 0x96, 0xa6, 0x77, + 0xf7, 0x3c, 0xcb, 0x77, 0x14, 0xaf, 0xd3, 0x6b, 0xe3, 0x10, 0x57, 0x3c, 0xd3, 0x2b, 0x5b, 0xc1, + 0x4b, 0xd6, 0x38, 0x18, 0xe1, 0x1a, 0x58, 0xe8, 0x07, 0xd8, 0xef, 0x5a, 0x1d, 0xcc, 0x07, 0x89, + 0xbf, 0x97, 0xee, 0x81, 0x3b, 0xf1, 0x38, 0xb2, 0xe3, 0x6c, 0xbb, 0x7e, 0x10, 0x42, 0x1c, 0x78, + 0x7d, 0xdf, 0xc6, 0x83, 0x21, 0x4a, 0x6b, 0x09, 0x71, 0xa3, 0x64, 0x35, 0x2b, 0x4c, 0x02, 0x2e, + 0x7d, 0x0c, 0x6e, 0xc7, 0xb4, 0x06, 0x0e, 0x15, 0x1f, 0x3b, 0xb8, 0x1b, 0xba, 0x56, 0xdb, 0xe8, + 0xef, 0x75, 0xdc, 0x30, 0x1b, 0x53, 0x72, 0x80, 0x4f, 0xfa, 0x38, 0x08, 0x5d, 0xaf, 0xdb, 0xb5, + 0x5c, 0x1f, 0xe7, 0x1d, 0xe0, 0x17, 0xc1, 0xbd, 0x78, 0x00, 0x88, 0x0f, 0xdc, 0x80, 0x00, 0x7c, + 0x69, 0xb5, 0xdb, 0xb8, 0x7b, 0x90, 0x77, 0x10, 0x69, 0x19, 0x2c, 0x74, 0xf6, 0x2d, 0x14, 0x9e, + 0xf4, 0x70, 0x71, 0x86, 0xf6, 0x9d, 0xee, 0xec, 0x5b, 0xe6, 0x49, 0x0f, 0x4b, 0xab, 0x00, 0xb4, + 0xbd, 0x03, 0xb7, 0x8b, 0xf6, 0xdb, 0xde, 0x71, 0x71, 0x96, 0x76, 0x9e, 0xa1, 0x2d, 0xdb, 0x6d, + 0xef, 0x98, 0xe1, 0x87, 0xd8, 0xf6, 0x8e, 0xb0, 0x7f, 0xa2, 0x78, 0x0e, 0x0e, 0x14, 0xaf, 0x1b, + 0xba, 0xdd, 0x3e, 0xce, 0xb9, 0x28, 0x1f, 0x82, 0xd5, 0xb1, 0x01, 0x7a, 0x27, 0x39, 0x99, 0x3f, + 0x02, 0x37, 0x46, 0x98, 0x9b, 0xbe, 0xdb, 0x0d, 0x73, 0x72, 0x97, 0x80, 0x58, 0x76, 0x03, 0xca, + 0x5c, 0xc7, 0xa1, 0xe5, 0x58, 0xa1, 0x25, 0x2d, 0x82, 0x19, 0xd7, 0xe1, 0x94, 0x33, 0xae, 0x53, + 0xb2, 0x40, 0x31, 0xa2, 0x89, 0x6c, 0x20, 0xa6, 0x55, 0xc1, 0x82, 0xcf, 0xdb, 0x28, 0xc7, 0xe2, + 0xe6, 0xa3, 0xf5, 0x09, 0xf6, 0xbe, 0x3e, 0x3a, 0x08, 0x8c, 0x59, 0x4b, 0x87, 0x40, 0x8a, 0x7a, + 0x8d, 0x10, 0xf7, 0x8c, 0xd0, 0x0a, 0xfb, 0x81, 0xf4, 0x31, 0x38, 0x15, 0xd0, 0x4f, 0x7c, 0xe8, + 0x07, 0x99, 0x43, 0x33, 0x46, 0xc8, 0xd9, 0xc8, 0x5e, 0xc2, 0xbe, 0xef, 0xf9, 0x7c, 0x41, 0xd9, + 0x97, 0xd2, 0x1f, 0x09, 0x60, 0xa9, 0xa5, 0x25, 0x58, 0xfc, 0x10, 0x3b, 0x4c, 0x55, 0x2a, 0x58, + 0xe8, 0xf0, 0xa9, 0x51, 0x99, 0x67, 0x73, 0x4c, 0x27, 0xd2, 0x05, 0x8c, 0x59, 0x25, 0x25, 0x06, + 0x3e, 0x43, 0x07, 0x79, 0x2b, 0x07, 0xf0, 0x68, 0xd6, 0x11, 0xf8, 0xd2, 0x7f, 0x0b, 0xe0, 0xd6, + 0x00, 0x66, 0xa4, 0x34, 0x03, 0xb7, 0xb1, 0x4d, 0x76, 0xc8, 0x2b, 0x05, 0x5c, 0x4f, 0x2c, 0x23, + 0x83, 0xfc, 0x38, 0xf7, 0x32, 0x0e, 0x86, 0x8b, 0x86, 0x48, 0xcc, 0x7f, 0xf6, 0x8b, 0xcf, 0xff, + 0xd7, 0x66, 0x88, 0x13, 0x8a, 0x08, 0xb4, 0x6e, 0x88, 0x0f, 0x7c, 0x8b, 0xcc, 0x5c, 0x7e, 0x61, + 0xe8, 0x5a, 0x59, 0x51, 0xbc, 0x6e, 0x17, 0xdb, 0xe1, 0x6b, 0xaf, 0x87, 0x1f, 0xcd, 0x24, 0xed, + 0xa0, 0x6c, 0x85, 0xd6, 0x9e, 0x15, 0x60, 0x58, 0x36, 0xd4, 0xae, 0xef, 0xb5, 0xdb, 0xaf, 0xfb, + 0xfc, 0xa5, 0xa7, 0xa0, 0x18, 0x50, 0xa3, 0xc7, 0x0e, 0x8a, 0x46, 0x0e, 0x90, 0xed, 0xf5, 0xbb, + 0x61, 0x71, 0xee, 0x96, 0xf0, 0x70, 0x16, 0x2e, 0x45, 0xfd, 0x11, 0x94, 0x40, 0x21, 0xbd, 0xa5, + 0x7f, 0x17, 0xc0, 0xf5, 0x81, 0xe6, 0x76, 0xfa, 0x7b, 0x58, 0xdd, 0x79, 0x43, 0xb4, 0x56, 0x7a, + 0x06, 0x8a, 0x2d, 0x4d, 0xb1, 0xda, 0x6d, 0xd3, 0x93, 0xa9, 0xbf, 0x48, 0x1c, 0x08, 0xeb, 0x60, + 0xd6, 0xe6, 0x33, 0x5e, 0xdc, 0xbc, 0x3e, 0x71, 0x74, 0xc5, 0x94, 0x21, 0x21, 0x2c, 0x7d, 0x6f, + 0x3e, 0xa9, 0xc7, 0x32, 0xee, 0xb5, 0xbd, 0x13, 0x03, 0xfb, 0x47, 0xae, 0x8d, 0x5f, 0x7b, 0xeb, + 0x3b, 0x00, 0xe7, 0x1d, 0x3a, 0x61, 0xd4, 0xc1, 0xe1, 0x4b, 0xcf, 0xa1, 0x26, 0xb7, 0xb8, 0xb9, + 0x35, 0x71, 0xac, 0x69, 0x8a, 0x5a, 0x67, 0x4d, 0x75, 0x3a, 0x12, 0x3c, 0xe7, 0x24, 0xbe, 0x49, + 0x16, 0x38, 0xcb, 0x05, 0xd1, 0x10, 0x64, 0x9e, 0x8a, 0xf9, 0x99, 0xff, 0x8b, 0x18, 0x12, 0xbb, + 0x40, 0xe0, 0xc4, 0x9f, 0x4b, 0x08, 0x9c, 0x4b, 0x02, 0x90, 0x56, 0xc1, 0x72, 0x59, 0x6d, 0xd6, + 0xf4, 0x5d, 0x54, 0x57, 0xcd, 0xaa, 0x5e, 0x46, 0xad, 0x86, 0xd1, 0x54, 0x15, 0x6d, 0x5b, 0x53, + 0xcb, 0x62, 0x41, 0x5a, 0x02, 0xd2, 0x70, 0xb7, 0xdc, 0x32, 0x75, 0x51, 0x90, 0x8a, 0xe0, 0xf2, + 0x70, 0x7b, 0x5d, 0x6e, 0xb4, 0xe4, 0x9a, 0x38, 0x53, 0xc2, 0x00, 0x0c, 0x44, 0x4b, 0x2b, 0xe0, + 0x2a, 0xa7, 0x33, 0x77, 0x9b, 0xea, 0xc8, 0xe0, 0x37, 0xc0, 0xb5, 0x64, 0xa7, 0xd6, 0x30, 0x4c, + 0xb9, 0x56, 0x43, 0x86, 0x02, 0xb5, 0xa6, 0x29, 0x0a, 0xd2, 0x35, 0xb0, 0x94, 0xec, 0x97, 0xeb, + 0xf2, 0xa7, 0x7a, 0x03, 0xa9, 0x8a, 0x21, 0xce, 0x94, 0x7e, 0x38, 0x07, 0xee, 0x0e, 0xe6, 0xaf, + 0xf8, 0xd8, 0x0a, 0x71, 0xf4, 0xed, 0x44, 0xf1, 0xba, 0xfb, 0xee, 0xc1, 0x6b, 0x6f, 0x97, 0x1e, + 0x38, 0x6f, 0xd3, 0x99, 0x0e, 0xdb, 0xe5, 0xb3, 0x1c, 0x06, 0x33, 0x59, 0x61, 0xeb, 0xec, 0x73, + 0x64, 0x9f, 0x76, 0xe2, 0x5b, 0xe9, 0x4f, 0x04, 0x70, 0x2e, 0xd9, 0x4d, 0xac, 0x47, 0xd1, 0x1b, + 0xdb, 0x5a, 0x25, 0xdd, 0x7a, 0xc6, 0xba, 0xe5, 0x17, 0x06, 0x52, 0x95, 0x4d, 0x64, 0x18, 0x75, + 0x51, 0x20, 0xeb, 0x9f, 0xde, 0xad, 0x6a, 0x8a, 0x2a, 0xce, 0xa4, 0xb3, 0xc3, 0xb2, 0x41, 0x4d, + 0x60, 0x56, 0x5a, 0x06, 0x57, 0x52, 0xd8, 0x77, 0x0c, 0x71, 0xae, 0xf4, 0x5f, 0x02, 0xb8, 0x99, + 0x72, 0x5e, 0xf2, 0x7b, 0xc1, 0x6b, 0xef, 0xf8, 0x7f, 0x69, 0x26, 0xb9, 0x39, 0xa2, 0xe9, 0xb3, + 0x95, 0xeb, 0xfb, 0xb8, 0x6e, 0xd6, 0x8c, 0xd7, 0x5e, 0x07, 0xbf, 0x39, 0x03, 0x1e, 0x27, 0x1d, + 0x64, 0x70, 0x18, 0x7a, 0x3d, 0x72, 0x0c, 0x1e, 0xe1, 0xb2, 0xeb, 0x63, 0x3b, 0xf4, 0xfc, 0x13, + 0xd3, 0xf3, 0xda, 0x81, 0xd6, 0x0d, 0x42, 0xeb, 0x0d, 0x88, 0x06, 0xbe, 0x33, 0x03, 0xd6, 0xb3, + 0x14, 0x12, 0x9b, 0xc8, 0x6b, 0xaf, 0x8d, 0x3f, 0x9b, 0x01, 0xf7, 0x07, 0xda, 0x90, 0xfb, 0xa1, + 0x17, 0x7d, 0x4e, 0x84, 0x90, 0xaf, 0xfd, 0x09, 0xf2, 0x00, 0x5c, 0x48, 0x0f, 0xa7, 0x17, 0xfd, + 0xe1, 0x30, 0xfa, 0x5b, 0x33, 0xe0, 0xce, 0x40, 0x5d, 0xaa, 0xb2, 0x49, 0x77, 0x4d, 0xf7, 0x4d, + 0xba, 0x8b, 0xfe, 0x9b, 0x00, 0x96, 0x47, 0x23, 0x2e, 0x72, 0x50, 0xbd, 0x61, 0x13, 0x67, 0x91, + 0x43, 0xc3, 0x73, 0x5e, 0x7f, 0x1f, 0xf1, 0x9f, 0x02, 0xb8, 0x31, 0x3a, 0x71, 0xb9, 0xd7, 0x23, + 0x61, 0xf6, 0x1b, 0x10, 0x44, 0x7c, 0x7b, 0x06, 0x3c, 0x9a, 0x12, 0x44, 0x68, 0x72, 0xbd, 0xe9, + 0xb5, 0x5d, 0xfb, 0xe4, 0xb5, 0x57, 0xc4, 0xff, 0x08, 0xa0, 0x34, 0x50, 0x44, 0xd3, 0x77, 0xbb, + 0xb6, 0xdb, 0xb3, 0xda, 0xc1, 0x9b, 0x73, 0x58, 0xfe, 0x87, 0x00, 0x56, 0x07, 0x1a, 0x30, 0x71, + 0x10, 0xf2, 0x87, 0xb7, 0x37, 0xc1, 0xef, 0xff, 0xab, 0x00, 0x8a, 0x09, 0x2f, 0xc0, 0x13, 0x2f, + 0xce, 0x6b, 0x3f, 0xef, 0x15, 0xe2, 0xf5, 0xb9, 0xb7, 0xc7, 0xc7, 0xd0, 0x6b, 0x27, 0x93, 0x43, + 0x37, 0x89, 0x41, 0x0c, 0x75, 0x1a, 0xd6, 0x51, 0x92, 0xe0, 0x36, 0xb9, 0x80, 0x0d, 0x73, 0x93, + 0x70, 0xa1, 0x9d, 0x20, 0x79, 0x1b, 0xac, 0x8d, 0x90, 0x3c, 0x77, 0xf1, 0x71, 0xd9, 0xb3, 0xfb, + 0x1d, 0xdc, 0x0d, 0xad, 0xe1, 0x07, 0xab, 0xd2, 0x5f, 0x08, 0xe0, 0x8a, 0x1c, 0x04, 0x2e, 0xb1, + 0x3d, 0xba, 0x04, 0xb1, 0xed, 0x3d, 0x00, 0x17, 0x6c, 0xaf, 0x7b, 0x84, 0xfd, 0x80, 0xf2, 0xa0, + 0x38, 0x71, 0xb1, 0x98, 0x6c, 0xd6, 0x1c, 0xe9, 0x36, 0x38, 0x17, 0x7a, 0xa1, 0xd5, 0x46, 0xa1, + 0x77, 0x88, 0xbb, 0xec, 0x61, 0x7e, 0x16, 0x9e, 0xa5, 0x6d, 0x26, 0x6d, 0x92, 0xee, 0x80, 0xf3, + 0x3d, 0xdf, 0xeb, 0xf4, 0xc2, 0x88, 0x66, 0x96, 0xd2, 0x9c, 0x63, 0x8d, 0x9c, 0xe8, 0x2d, 0x70, + 0xd1, 0x8e, 0x31, 0x44, 0x84, 0x2c, 0x6e, 0x12, 0x07, 0x1d, 0x8c, 0xb8, 0xf4, 0x77, 0x02, 0xb8, + 0xcc, 0x70, 0xab, 0x9f, 0x61, 0xbb, 0xff, 0x05, 0x60, 0xaf, 0x02, 0xd0, 0xf5, 0x1c, 0xcc, 0xe3, + 0x33, 0x06, 0xfa, 0x0c, 0x69, 0xa1, 0xa1, 0xd9, 0xd8, 0xac, 0x66, 0x73, 0xcc, 0x6a, 0x2e, 0xef, + 0xac, 0xe6, 0x27, 0xcc, 0xea, 0x29, 0xb8, 0xc6, 0x26, 0xd5, 0xc0, 0xc7, 0x4a, 0x02, 0x6e, 0x9c, + 0x6d, 0xb2, 0xad, 0x10, 0x1f, 0x78, 0xfe, 0x49, 0x94, 0x6d, 0x8a, 0xbe, 0x97, 0xfe, 0x5c, 0x00, + 0x97, 0x18, 0xab, 0x6c, 0xdb, 0x38, 0x08, 0x20, 0xfe, 0x46, 0x1f, 0x07, 0x21, 0xc1, 0x18, 0xd9, + 0x2f, 0x7b, 0xfd, 0x62, 0x8c, 0xe7, 0xa2, 0x46, 0xfa, 0x9c, 0xf4, 0x53, 0x59, 0xc1, 0x1f, 0x0a, + 0xe0, 0x5c, 0x84, 0x98, 0x34, 0x4b, 0x4b, 0xe0, 0x94, 0x45, 0x3f, 0x71, 0x8c, 0xfc, 0xdb, 0x4f, + 0x07, 0xdd, 0x5d, 0x20, 0x31, 0x45, 0xd6, 0xdc, 0x20, 0x9c, 0x98, 0xbf, 0xfb, 0x1a, 0x10, 0x07, + 0x54, 0x6c, 0xcf, 0x49, 0x95, 0x31, 0xdf, 0x35, 0xd9, 0x4f, 0x8c, 0x8b, 0x18, 0x78, 0xaf, 0xe1, + 0xc1, 0x5b, 0x3d, 0xe7, 0x27, 0x37, 0x78, 0x19, 0x13, 0xdf, 0xfb, 0xea, 0x06, 0xb7, 0xc0, 0x52, + 0xb2, 0xbf, 0xb3, 0x17, 0x85, 0x79, 0x3f, 0x51, 0x11, 0xaf, 0x5a, 0x45, 0x29, 0x22, 0x5e, 0xb5, + 0xa2, 0x7e, 0x3e, 0x29, 0xa2, 0xe2, 0x5b, 0xdd, 0x30, 0x30, 0xbd, 0x56, 0x80, 0x7d, 0x69, 0x1d, + 0x5c, 0xa2, 0x8e, 0x09, 0xf9, 0x5e, 0x1b, 0x07, 0xe8, 0x80, 0xf4, 0x61, 0x66, 0x7a, 0xf3, 0xf0, + 0x22, 0xed, 0x22, 0xae, 0x3d, 0xa8, 0xb0, 0x0e, 0xe9, 0x5d, 0x70, 0x99, 0xd1, 0x87, 0xbe, 0xe5, + 0x86, 0x03, 0x86, 0x19, 0xca, 0x20, 0xd1, 0x3e, 0x93, 0x76, 0x71, 0x8e, 0xd2, 0x0f, 0x66, 0x93, + 0xc2, 0x21, 0x3e, 0x72, 0xf1, 0xf1, 0x2b, 0x5e, 0x25, 0xe9, 0x29, 0x58, 0x76, 0xac, 0x93, 0x00, + 0xf5, 0xac, 0x20, 0x44, 0x5d, 0xfc, 0x59, 0x88, 0xac, 0xbe, 0xe3, 0x86, 0x88, 0x2c, 0x14, 0x87, + 0x76, 0x85, 0x10, 0x34, 0x2d, 0xe2, 0xf2, 0x3e, 0x0b, 0x65, 0xd2, 0x5b, 0x26, 0x10, 0xb6, 0xc1, + 0xcd, 0x0e, 0x55, 0x79, 0xf0, 0xd2, 0xed, 0x21, 0x1f, 0x7f, 0xa3, 0xef, 0xfa, 0x98, 0x1c, 0x60, + 0x01, 0xb2, 0x5f, 0x5a, 0xdd, 0x03, 0xec, 0xd0, 0x3d, 0xbe, 0x00, 0x57, 0x07, 0x64, 0x30, 0x41, + 0xa5, 0x30, 0x22, 0xe9, 0x29, 0x28, 0xfa, 0x74, 0x6a, 0x68, 0x9f, 0x0c, 0x82, 0xbb, 0xf6, 0x49, + 0x3c, 0xc0, 0x1c, 0x1d, 0x60, 0x89, 0xf5, 0x6f, 0x47, 0xdd, 0x11, 0xe7, 0x47, 0x60, 0x85, 0x73, + 0x3a, 0xd6, 0x09, 0xf2, 0xf6, 0x51, 0xc7, 0xeb, 0x86, 0x2f, 0x63, 0xe6, 0x79, 0xca, 0x7c, 0x95, + 0x91, 0x94, 0xad, 0x13, 0x7d, 0xbf, 0x4e, 0xfa, 0x23, 0xee, 0xaf, 0x80, 0xe5, 0x6e, 0x9f, 0x00, + 0x23, 0x9c, 0x3e, 0xee, 0x78, 0x47, 0xd8, 0x41, 0x1c, 0x6a, 0xf1, 0x14, 0x9d, 0xf9, 0x12, 0x23, + 0xd0, 0xf7, 0x21, 0xeb, 0x66, 0x26, 0x16, 0x94, 0x7e, 0x47, 0x18, 0x5f, 0x98, 0x57, 0x6c, 0x78, + 0xd2, 0x63, 0x70, 0xc5, 0xa2, 0xfd, 0xa8, 0xed, 0x06, 0x21, 0xe2, 0x13, 0x75, 0x1d, 0x9e, 0xce, + 0x97, 0xac, 0x11, 0xf9, 0x9a, 0x53, 0xfa, 0xae, 0x00, 0x96, 0x13, 0xa9, 0x62, 0x96, 0xec, 0x9b, + 0xe4, 0x19, 0xa5, 0x2d, 0x30, 0x77, 0xe8, 0x76, 0xd9, 0x78, 0x8b, 0x9b, 0xeb, 0x13, 0x51, 0x8e, + 0x8d, 0xb8, 0xe3, 0x76, 0x1d, 0x48, 0x79, 0xa5, 0x15, 0x70, 0xa6, 0x1f, 0x60, 0x1f, 0xd1, 0xf2, + 0x8a, 0xd9, 0x41, 0x79, 0x45, 0xc3, 0xea, 0xe0, 0x92, 0x47, 0x42, 0xa5, 0x31, 0x6e, 0x5a, 0x72, + 0xc0, 0x4e, 0xcb, 0xc6, 0x98, 0xae, 0x36, 0xf3, 0xa3, 0x48, 0xd9, 0xab, 0x3e, 0xb8, 0x95, 0x22, + 0x30, 0x0a, 0x5c, 0x7f, 0x32, 0x32, 0xff, 0x41, 0x00, 0x97, 0xe2, 0x1a, 0x22, 0xba, 0x37, 0x99, + 0x9c, 0x5c, 0xa7, 0x7a, 0xe2, 0x15, 0x0a, 0x79, 0xbe, 0x7b, 0xe0, 0x76, 0xf9, 0xea, 0xc6, 0xaf, + 0x50, 0x3a, 0x6d, 0x95, 0xee, 0x81, 0x45, 0xbb, 0xed, 0xf5, 0x1d, 0xd4, 0xf3, 0xbd, 0x23, 0xd7, + 0xc1, 0x3e, 0x57, 0xf6, 0x79, 0xda, 0xda, 0xe4, 0x8d, 0x92, 0x0e, 0x16, 0x1c, 0x7e, 0x5d, 0xa5, + 0x5b, 0xe7, 0xec, 0xe6, 0x93, 0xcc, 0x00, 0x18, 0x3b, 0xd1, 0x0d, 0x77, 0x30, 0xbb, 0x68, 0x90, + 0xd2, 0x73, 0x70, 0x6d, 0x32, 0x9d, 0x74, 0x15, 0x9c, 0x76, 0xf6, 0x92, 0xb3, 0x3b, 0xe5, 0xec, + 0xd1, 0x79, 0xdd, 0x04, 0x67, 0x9d, 0x3d, 0x44, 0x2b, 0xc0, 0x6c, 0xaf, 0xcd, 0xe7, 0x04, 0x9c, + 0xbd, 0x26, 0x6f, 0x29, 0xfd, 0x8b, 0x00, 0xae, 0x6d, 0x63, 0x2b, 0xec, 0xfb, 0x18, 0x62, 0xdb, + 0xeb, 0x74, 0x70, 0xd7, 0x49, 0x84, 0x51, 0x43, 0x66, 0x25, 0x0c, 0x9b, 0x95, 0xf4, 0x01, 0x38, + 0xbd, 0xcf, 0x58, 0xb9, 0xe9, 0xde, 0x9a, 0x38, 0xc7, 0x48, 0x44, 0xc4, 0x20, 0x7d, 0x06, 0x56, + 0xf9, 0x47, 0xe4, 0x0f, 0xc9, 0x45, 0x89, 0x6b, 0xc3, 0xe2, 0xe6, 0x7b, 0x99, 0x23, 0x0e, 0x31, + 0xf3, 0xfb, 0xc3, 0xca, 0xfe, 0xe4, 0xce, 0xd2, 0x31, 0xb8, 0x6c, 0xca, 0x15, 0x16, 0x09, 0xe3, + 0x4f, 0xfa, 0xd8, 0xe7, 0xcf, 0x07, 0x37, 0x01, 0x0b, 0x93, 0x10, 0x89, 0x6b, 0x59, 0xad, 0xcf, + 0x2c, 0x04, 0xb4, 0xa9, 0x41, 0x5a, 0x06, 0x04, 0xd8, 0x39, 0xc0, 0x51, 0x68, 0xc5, 0x08, 0x54, + 0xd2, 0x42, 0xa2, 0x64, 0x37, 0x40, 0x41, 0x9f, 0xfa, 0x03, 0xee, 0x72, 0xcf, 0xb8, 0x81, 0xc1, + 0x1a, 0x4a, 0xff, 0x3c, 0x0b, 0xae, 0x32, 0x47, 0x53, 0xf1, 0xad, 0xde, 0x4b, 0xf9, 0x85, 0x61, + 0xd8, 0x56, 0x37, 0xca, 0x85, 0x5f, 0xe2, 0x63, 0xdb, 0x9b, 0xc8, 0xe5, 0x0f, 0x9b, 0x0c, 0xc4, + 0x1c, 0xbc, 0xc8, 0x64, 0xd8, 0xf1, 0x8b, 0x67, 0x02, 0x0b, 0x59, 0x0c, 0x86, 0x65, 0x8e, 0x63, + 0x21, 0x47, 0x62, 0x30, 0x08, 0x04, 0x0f, 0x7c, 0xaf, 0xdf, 0x63, 0x68, 0xe6, 0x78, 0x20, 0x58, + 0xa1, 0x4d, 0x83, 0x31, 0xe8, 0xb1, 0x49, 0xcd, 0x34, 0x1a, 0x83, 0x1e, 0x97, 0xc4, 0xd6, 0x19, + 0x41, 0xcf, 0x6b, 0xbb, 0xb6, 0x8b, 0x59, 0x2c, 0x3e, 0x07, 0xcf, 0xd3, 0xd6, 0x26, 0x6f, 0x94, + 0xde, 0x06, 0x12, 0xc7, 0x7e, 0x18, 0x20, 0xbb, 0xdd, 0x0f, 0xc2, 0xc8, 0x6f, 0xcf, 0x41, 0x91, + 0x41, 0x3f, 0x0c, 0x14, 0xde, 0x3e, 0x98, 0xa9, 0xef, 0x04, 0x89, 0x99, 0x9e, 0x4e, 0xcc, 0x14, + 0x3a, 0xc1, 0x60, 0xa6, 0x0f, 0x01, 0x1b, 0x03, 0x05, 0x4f, 0xd0, 0x5e, 0xdf, 0x3e, 0xc4, 0x61, + 0x50, 0x5c, 0xa0, 0xc4, 0x0c, 0x9c, 0xf1, 0x64, 0x8b, 0xb5, 0x92, 0x63, 0x9d, 0x53, 0x5a, 0x9d, + 0x76, 0xbc, 0x3f, 0x83, 0xe2, 0x19, 0x4a, 0xcd, 0x30, 0x1a, 0x56, 0xa7, 0x1d, 0x6d, 0xd2, 0x04, + 0x87, 0xe7, 0x3a, 0x76, 0x82, 0x03, 0x24, 0x38, 0x74, 0xd7, 0xb1, 0x07, 0x1c, 0xb1, 0x4a, 0x2c, + 0x9b, 0x86, 0x09, 0x41, 0xf1, 0x6c, 0x42, 0x25, 0x32, 0x6f, 0x2c, 0xfd, 0x40, 0x00, 0x77, 0x5b, + 0x5a, 0x62, 0xb1, 0x15, 0xdf, 0x3b, 0xee, 0x3e, 0xc3, 0xc7, 0xb8, 0x5d, 0x76, 0xf7, 0xf7, 0xc9, + 0x25, 0x93, 0xad, 0xfb, 0x53, 0x50, 0xb4, 0xf6, 0xf7, 0x87, 0xab, 0x4a, 0x50, 0xa2, 0x90, 0xed, + 0x0c, 0x5c, 0x8a, 0xfa, 0xe3, 0xd2, 0x2b, 0x76, 0xc1, 0x7e, 0x0f, 0x2c, 0x8d, 0x73, 0x26, 0xca, + 0x06, 0x2f, 0x8f, 0xf2, 0xd1, 0xdc, 0xfb, 0x36, 0xb8, 0x6e, 0x60, 0xbb, 0xef, 0xbb, 0xe1, 0x09, + 0xa4, 0xdb, 0xaa, 0x82, 0x43, 0x88, 0x83, 0x7e, 0x9b, 0x1f, 0x04, 0x12, 0x98, 0x4b, 0x6c, 0x75, + 0xfa, 0x99, 0xb4, 0x91, 0xb8, 0x83, 0xc7, 0x20, 0xf4, 0x73, 0xc9, 0x02, 0x97, 0xe2, 0xcc, 0xed, + 0x36, 0x0e, 0xed, 0x97, 0x8c, 0x7d, 0xdc, 0x3b, 0x0a, 0x69, 0xde, 0x71, 0xcc, 0x25, 0xcf, 0x8c, + 0xbb, 0xe4, 0xd2, 0xf7, 0x05, 0x20, 0x11, 0x5b, 0x36, 0xad, 0xe0, 0x90, 0x6c, 0x5d, 0x1c, 0x7b, + 0xa4, 0xd0, 0x0a, 0x0e, 0x93, 0xce, 0x6e, 0x81, 0x34, 0x44, 0x25, 0x92, 0x6e, 0x10, 0xf4, 0x87, + 0x46, 0x3d, 0x43, 0x5b, 0x68, 0xf7, 0x65, 0x30, 0x4f, 0xbc, 0x4b, 0x74, 0x40, 0xb2, 0x2f, 0xc4, + 0xf7, 0xc7, 0x76, 0x98, 0xc8, 0x40, 0xcc, 0xc3, 0xc5, 0xb8, 0x99, 0x65, 0x20, 0xfe, 0xfa, 0x03, + 0x70, 0xa1, 0x45, 0xbc, 0x10, 0x45, 0xa2, 0x77, 0xb1, 0xbe, 0x2f, 0xb5, 0xc0, 0x85, 0xbe, 0x8b, + 0xf6, 0x68, 0xf9, 0x2c, 0xb2, 0xdb, 0xae, 0x7d, 0x98, 0x19, 0x6c, 0x8c, 0x57, 0xdb, 0x56, 0x0b, + 0xf0, 0x7c, 0xdf, 0x4d, 0xb4, 0x4a, 0x3f, 0x14, 0xc0, 0xa3, 0xbe, 0x8b, 0x3c, 0x56, 0x4d, 0x8a, + 0xf8, 0x95, 0x0b, 0xa3, 0x03, 0x0f, 0x85, 0x1e, 0x72, 0xa2, 0x72, 0x5b, 0x2e, 0x91, 0x3d, 0xb1, + 0xc8, 0x53, 0x24, 0xe6, 0xab, 0xd9, 0xad, 0x16, 0xe0, 0x9d, 0xbe, 0x9b, 0x49, 0x2b, 0x7d, 0x47, + 0x00, 0x77, 0x12, 0xe8, 0x2c, 0xc7, 0x41, 0xfb, 0xae, 0x4f, 0x63, 0x23, 0xbe, 0xaa, 0x0c, 0x17, + 0x3b, 0xf9, 0x3e, 0xca, 0xc6, 0x35, 0xb9, 0x06, 0xb8, 0x5a, 0x80, 0x37, 0x62, 0x48, 0xa9, 0x64, + 0xa3, 0xba, 0x4a, 0x41, 0xd3, 0xb6, 0xc2, 0x78, 0x75, 0xe6, 0xf3, 0xea, 0x2a, 0xa3, 0xe0, 0x78, + 0x48, 0x57, 0x93, 0x69, 0xa5, 0x5f, 0x15, 0xc0, 0xad, 0x04, 0xba, 0x00, 0x87, 0xc8, 0x8e, 0x6b, + 0x93, 0x51, 0x40, 0xcb, 0x82, 0xa9, 0xb3, 0x3c, 0xbb, 0xf9, 0x41, 0x36, 0xa8, 0x49, 0x95, 0xcd, + 0xd5, 0x02, 0xbc, 0x1e, 0xa3, 0x49, 0x21, 0x92, 0x7e, 0x4b, 0x00, 0x77, 0x13, 0x30, 0x7c, 0x5e, + 0x87, 0x40, 0x42, 0x74, 0x56, 0xa0, 0x1c, 0x41, 0x39, 0x4d, 0xa1, 0xfc, 0xff, 0x6c, 0x28, 0xd3, + 0x4a, 0x9c, 0xab, 0x05, 0x78, 0x2b, 0x86, 0x33, 0x81, 0x30, 0xd2, 0x8c, 0xcf, 0x8b, 0x86, 0x91, + 0x4d, 0x4e, 0x59, 0x64, 0xf3, 0xa2, 0x65, 0xbe, 0x5c, 0x0b, 0x99, 0x9a, 0xc9, 0x28, 0x79, 0x66, + 0x9a, 0x99, 0x4c, 0x24, 0x7d, 0x06, 0xae, 0xa7, 0xa1, 0xe8, 0x9d, 0x70, 0x04, 0x67, 0x28, 0x82, + 0x2f, 0xe7, 0x47, 0x90, 0xac, 0x99, 0xae, 0x16, 0x60, 0x71, 0x4c, 0x3a, 0x27, 0x90, 0x7e, 0x01, + 0xac, 0x8e, 0x4b, 0xee, 0xf9, 0x6e, 0x37, 0xe4, 0xa2, 0x01, 0x15, 0xfd, 0x7e, 0x5e, 0xd1, 0x23, + 0x15, 0xd7, 0xd5, 0x02, 0x5c, 0x1e, 0x91, 0x3d, 0xa0, 0x90, 0xda, 0x60, 0xb9, 0xef, 0x22, 0x87, + 0x3b, 0x71, 0x12, 0x75, 0xf9, 0xe4, 0x28, 0xa1, 0x83, 0xd3, 0x43, 0xed, 0xec, 0xe6, 0x46, 0x8e, + 0x2a, 0x9e, 0x64, 0xdd, 0x72, 0xb5, 0x00, 0x97, 0xfa, 0x6e, 0x6a, 0x45, 0xf3, 0x77, 0x98, 0xf9, + 0xc5, 0xe2, 0x06, 0x67, 0x5d, 0x94, 0xbc, 0xe5, 0x92, 0xcf, 0x51, 0xc9, 0x5f, 0xc9, 0x21, 0x39, + 0xbd, 0x14, 0x99, 0x59, 0x5e, 0x46, 0xb9, 0xf2, 0x37, 0xa9, 0xe1, 0xc5, 0x60, 0x78, 0xc1, 0x5b, + 0xc0, 0x6a, 0xd7, 0x38, 0x90, 0xf3, 0x14, 0xc8, 0x97, 0xbe, 0x50, 0xe5, 0x1b, 0xb3, 0xb9, 0x29, + 0x95, 0x8a, 0xbf, 0xce, 0x1c, 0xe8, 0x00, 0x01, 0x0f, 0xe8, 0x07, 0xfb, 0x92, 0x81, 0x58, 0xa4, + 0x20, 0x9e, 0xe6, 0x01, 0x91, 0x56, 0x60, 0x54, 0x2d, 0xc0, 0x9b, 0x09, 0x1c, 0xa9, 0x35, 0x48, + 0xbf, 0xcb, 0xbc, 0xe7, 0x38, 0x14, 0x3b, 0xca, 0x2d, 0xa1, 0x4e, 0xd8, 0x0e, 0x38, 0xa0, 0x0b, + 0x14, 0xd0, 0xff, 0xfb, 0x1c, 0x80, 0xc6, 0x4b, 0x7e, 0xaa, 0x05, 0x78, 0x77, 0x1c, 0xd5, 0x80, + 0x2e, 0x6c, 0xf3, 0xaa, 0x87, 0xbf, 0x12, 0xc0, 0xd3, 0xe1, 0x75, 0xa2, 0x05, 0x23, 0xc8, 0xa2, + 0x15, 0x23, 0xc8, 0x89, 0x4a, 0x46, 0x50, 0xe8, 0x79, 0x6d, 0x1e, 0x4c, 0xb6, 0xdb, 0x1c, 0xa9, + 0x48, 0x91, 0x3e, 0xcb, 0xb5, 0x7e, 0xb9, 0x0a, 0x73, 0xaa, 0x05, 0xf8, 0x38, 0xb9, 0xa8, 0xf9, + 0xaa, 0x79, 0x7e, 0x24, 0x80, 0xf7, 0x72, 0xcd, 0x61, 0xa0, 0x6e, 0x86, 0xff, 0x22, 0xc5, 0x5f, + 0xf9, 0xc2, 0xf8, 0x87, 0x53, 0x83, 0xd5, 0x02, 0x5c, 0xcf, 0x02, 0x3f, 0x92, 0x4c, 0xfc, 0x3d, + 0x01, 0xbc, 0x95, 0x44, 0x6e, 0xf5, 0x49, 0xe4, 0x11, 0xdf, 0x41, 0x13, 0x45, 0xd0, 0x0c, 0xb0, + 0x44, 0x01, 0x7f, 0x9c, 0x03, 0xf0, 0xb4, 0x52, 0x97, 0x6a, 0x01, 0xde, 0x1f, 0x00, 0x9d, 0x5a, + 0x14, 0xf3, 0xa7, 0x02, 0xd8, 0xc8, 0xb0, 0x5c, 0xd7, 0xea, 0xb0, 0xcb, 0xcb, 0x09, 0x07, 0x79, + 0x89, 0x82, 0xdc, 0xfa, 0x22, 0xf6, 0x3b, 0x9c, 0x6d, 0xae, 0x16, 0xe0, 0xa3, 0x29, 0x46, 0xac, + 0x59, 0x9d, 0x64, 0x6a, 0xfa, 0xb7, 0x05, 0x70, 0x3f, 0x09, 0xb5, 0x17, 0x67, 0x70, 0xc7, 0xd6, + 0xfd, 0x32, 0x45, 0xf8, 0x61, 0x0e, 0x84, 0x93, 0xd2, 0xc0, 0xd5, 0x02, 0x2c, 0x0d, 0xa0, 0x4d, + 0x4c, 0x16, 0xff, 0xb2, 0x00, 0x6e, 0x27, 0x31, 0x85, 0x38, 0x08, 0x09, 0x9a, 0xee, 0x90, 0x3f, + 0xbe, 0x92, 0x79, 0xfa, 0x4d, 0xc9, 0xc9, 0x56, 0x0b, 0x70, 0x75, 0x80, 0x24, 0x2d, 0x69, 0xeb, + 0x83, 0x95, 0x24, 0x86, 0x28, 0xce, 0x8d, 0xce, 0xa1, 0xa5, 0x8c, 0x44, 0xe4, 0xa4, 0xa4, 0x28, + 0x3b, 0x76, 0x27, 0x24, 0x4c, 0xdb, 0xa0, 0xd8, 0x77, 0x49, 0x10, 0x66, 0x85, 0x18, 0x75, 0xf1, + 0x31, 0xbd, 0xff, 0xf2, 0x13, 0xf7, 0x6a, 0xc6, 0x43, 0xd4, 0xc4, 0x74, 0x64, 0xb5, 0x00, 0x2f, + 0xf7, 0xdd, 0xf1, 0x4e, 0xe9, 0x84, 0x1e, 0xf2, 0xa3, 0xd2, 0x02, 0xeb, 0x28, 0x12, 0x59, 0xcc, + 0xd4, 0xf0, 0x94, 0x24, 0x27, 0x9b, 0x68, 0x3a, 0x81, 0xf4, 0x4d, 0x70, 0x33, 0x6d, 0xa2, 0x34, + 0x09, 0xca, 0x85, 0x2f, 0x67, 0x1e, 0x30, 0x53, 0x13, 0xa8, 0xd5, 0x02, 0xbc, 0x36, 0x3a, 0xeb, + 0x01, 0x89, 0xf4, 0x07, 0xcc, 0x85, 0x8c, 0x22, 0x60, 0x0f, 0xc5, 0xc9, 0x24, 0x2b, 0x47, 0x73, + 0x8d, 0xa2, 0x51, 0xf2, 0xa2, 0x99, 0x92, 0xab, 0xad, 0x16, 0xe0, 0xbd, 0x11, 0x60, 0xe9, 0xd4, + 0xd2, 0x1f, 0x0b, 0x60, 0x3d, 0x69, 0x82, 0xee, 0xe0, 0xa9, 0x11, 0x59, 0xc7, 0x01, 0x7b, 0x1a, + 0xe0, 0xdb, 0x82, 0x5b, 0xe5, 0x4a, 0xe6, 0x15, 0x22, 0xdf, 0xcf, 0x85, 0xaa, 0x05, 0xf8, 0x70, + 0x60, 0xa5, 0x49, 0xda, 0xe3, 0x40, 0x77, 0x1d, 0x7b, 0xe8, 0xa7, 0x45, 0xdf, 0x15, 0xc0, 0xbd, + 0xf4, 0x90, 0xc1, 0x09, 0x10, 0xa6, 0x8f, 0xa2, 0x1c, 0xde, 0xf5, 0xdc, 0x21, 0x54, 0xfa, 0xaf, + 0x78, 0x86, 0x43, 0xa8, 0x98, 0xc6, 0x09, 0x92, 0xbf, 0x59, 0x09, 0x99, 0x59, 0x93, 0xf3, 0x36, + 0xf4, 0x10, 0xcb, 0x3e, 0xb2, 0x55, 0xe4, 0x28, 0x56, 0x33, 0xb7, 0x6e, 0xfa, 0xcf, 0x42, 0xb8, + 0x45, 0xa7, 0xff, 0x64, 0xe4, 0xeb, 0xe0, 0xa2, 0x45, 0xd3, 0xa0, 0x68, 0x90, 0x84, 0x2c, 0xde, + 0xa0, 0x92, 0x26, 0x3f, 0x9b, 0xa7, 0xa6, 0xec, 0xab, 0x05, 0x28, 0x5a, 0x23, 0x1d, 0x91, 0x4b, + 0x4c, 0x9a, 0x00, 0xd7, 0x2c, 0x0d, 0x8f, 0xf9, 0xcc, 0x6e, 0x66, 0x6e, 0xd8, 0x29, 0x4f, 0xed, + 0xcc, 0x25, 0x4e, 0x7b, 0x8b, 0xe7, 0xa1, 0x72, 0x0a, 0x88, 0xf8, 0x15, 0x80, 0xe1, 0xb8, 0x95, + 0xb9, 0xce, 0xd3, 0x5f, 0xe0, 0xd9, 0x3a, 0x67, 0xbc, 0xd2, 0xff, 0x8a, 0x40, 0x9d, 0x48, 0x74, + 0x6f, 0xfc, 0x46, 0xf2, 0x87, 0xb1, 0xd1, 0x95, 0xf1, 0x76, 0xde, 0xdb, 0xeb, 0xa4, 0x9f, 0xd5, + 0x0e, 0xdd, 0x5e, 0x53, 0x88, 0xa4, 0x4f, 0x01, 0x5f, 0x2c, 0x84, 0xa3, 0x0a, 0x86, 0x62, 0x89, + 0x4a, 0x7d, 0x27, 0x63, 0xd9, 0x87, 0x2b, 0x1e, 0xaa, 0x05, 0x78, 0xc1, 0x1a, 0x6e, 0x97, 0x3a, + 0xe0, 0x2a, 0x1f, 0x9b, 0x38, 0xa8, 0x64, 0xe1, 0x43, 0xf1, 0x4e, 0xc6, 0xcb, 0xfd, 0xe4, 0xfa, + 0x83, 0x6a, 0x01, 0x5e, 0xb1, 0xd2, 0x7a, 0xa5, 0x3d, 0x70, 0x65, 0xf0, 0x4a, 0xc2, 0x1c, 0x23, + 0x5b, 0xce, 0xbb, 0x54, 0xd8, 0xdb, 0x13, 0x85, 0xa5, 0xe4, 0x36, 0xaa, 0x05, 0x78, 0xc9, 0x4f, + 0x49, 0x79, 0x1c, 0x83, 0xeb, 0x13, 0x1e, 0xd7, 0x99, 0xa8, 0x7b, 0x19, 0xf3, 0x9a, 0x9c, 0x10, + 0x20, 0x0e, 0x7f, 0x7f, 0x72, 0xba, 0x60, 0x0f, 0xf0, 0x59, 0x23, 0x9e, 0x31, 0xf3, 0x59, 0x69, + 0x45, 0xf1, 0x7e, 0xc6, 0xe4, 0x52, 0xca, 0x31, 0xc8, 0xe4, 0xac, 0x94, 0x2a, 0x8d, 0x1a, 0x38, + 0x1f, 0xcb, 0xa0, 0xab, 0xf4, 0x80, 0x8e, 0x7d, 0x2f, 0x73, 0x6c, 0x42, 0x5c, 0x2d, 0xc0, 0x73, + 0x56, 0xb2, 0x90, 0x62, 0x17, 0x48, 0xc9, 0xe4, 0x1e, 0x5b, 0x91, 0xe2, 0xc3, 0x8c, 0x3a, 0xaa, + 0xd1, 0x42, 0x06, 0xea, 0x4d, 0x46, 0x8b, 0x1b, 0x46, 0x86, 0xee, 0xd3, 0x94, 0x7b, 0xf1, 0x51, + 0xee, 0xa1, 0x59, 0x8e, 0x7e, 0x78, 0x68, 0x9e, 0xb7, 0x1f, 0x19, 0xda, 0xa1, 0x19, 0xcf, 0xe2, + 0x5a, 0xee, 0xa1, 0x59, 0x8a, 0x74, 0x78, 0x68, 0x9e, 0x36, 0x6d, 0x83, 0xe5, 0xe4, 0xd0, 0x2c, + 0x0d, 0x1b, 0xe9, 0xe5, 0xad, 0x8c, 0x77, 0x81, 0xf4, 0x4a, 0x86, 0x6a, 0x01, 0x2e, 0x59, 0xe9, + 0x35, 0x0e, 0xe9, 0xd2, 0xb8, 0xaa, 0xde, 0xfe, 0x9c, 0xd2, 0x62, 0x85, 0x8d, 0x49, 0xe3, 0x6a, + 0x4b, 0x97, 0xc6, 0xb5, 0xf7, 0xce, 0xe7, 0x94, 0x16, 0xeb, 0x70, 0x4c, 0x1a, 0xd7, 0x64, 0x07, + 0x5c, 0x4b, 0x4a, 0xa3, 0x55, 0x06, 0x01, 0x39, 0x2d, 0xfb, 0x01, 0xf6, 0x8b, 0xeb, 0xb9, 0xc5, + 0x25, 0x6b, 0x1d, 0x86, 0xc5, 0x0d, 0x55, 0x41, 0xfc, 0x86, 0x00, 0x4a, 0xc9, 0x00, 0x21, 0x99, + 0x49, 0x1a, 0x3c, 0xb3, 0x14, 0x37, 0x32, 0xdf, 0x64, 0x33, 0x4b, 0xec, 0xd9, 0x9b, 0x6c, 0x4c, + 0x66, 0x8f, 0x93, 0x49, 0x87, 0xe0, 0x6a, 0xca, 0x0b, 0x0b, 0x76, 0x6d, 0x5c, 0x7c, 0x37, 0x33, + 0xc4, 0x9e, 0x50, 0xe0, 0xce, 0x42, 0xec, 0x91, 0x4e, 0xd7, 0xc6, 0xa3, 0xc2, 0xa2, 0x70, 0xd3, + 0x73, 0x70, 0xf1, 0x71, 0x6e, 0x61, 0x23, 0x45, 0xe5, 0xc3, 0xc2, 0x06, 0x9d, 0xd2, 0xd7, 0xc0, + 0xc5, 0xd0, 0x3a, 0xe0, 0xe7, 0x10, 0x26, 0x07, 0xa2, 0x7f, 0x52, 0xdc, 0xcc, 0x38, 0x8b, 0xd2, + 0x12, 0x8e, 0xe4, 0x2c, 0x0a, 0xad, 0x83, 0x64, 0xbb, 0x14, 0x82, 0x6b, 0x01, 0x4f, 0xcf, 0x20, + 0x9f, 0x8e, 0x84, 0x0e, 0x30, 0x7d, 0xc8, 0xee, 0xb7, 0xc3, 0xe2, 0x93, 0x8c, 0x27, 0xa9, 0x69, + 0x99, 0x9d, 0x6a, 0x01, 0x5e, 0x0d, 0xd2, 0xfb, 0x47, 0xb7, 0x05, 0x2f, 0x70, 0xe0, 0x5b, 0xfe, + 0xbd, 0xdc, 0x76, 0x9a, 0x2c, 0x8b, 0x19, 0xb6, 0xd3, 0xa1, 0x82, 0x99, 0x74, 0x69, 0x7c, 0x13, + 0x7e, 0xe9, 0x73, 0x4a, 0x4b, 0xdb, 0x84, 0x43, 0x55, 0x20, 0x7b, 0xe0, 0x4a, 0x64, 0x18, 0x27, + 0x68, 0x1f, 0x87, 0xf6, 0x4b, 0x7e, 0x06, 0x7e, 0x39, 0xe3, 0x44, 0x4a, 0x49, 0x6f, 0x91, 0x13, + 0xc9, 0x49, 0xc9, 0x7a, 0x7d, 0x6f, 0xe4, 0x35, 0x8f, 0x1b, 0xe0, 0x40, 0x2e, 0xbb, 0xe3, 0x17, + 0xdf, 0xcf, 0xfd, 0x78, 0x36, 0xf9, 0xb7, 0x91, 0xc3, 0x4f, 0x7a, 0xa9, 0x74, 0xd2, 0xb7, 0x46, + 0x6e, 0xf6, 0x87, 0xfd, 0x3d, 0x4c, 0x93, 0xb3, 0x43, 0xd7, 0x84, 0xa7, 0xb9, 0x1f, 0x38, 0xc7, + 0x7f, 0xb2, 0x3e, 0xfc, 0xc0, 0x49, 0xfb, 0x0f, 0x87, 0xae, 0x07, 0xdf, 0x4e, 0x57, 0x89, 0xd5, + 0xeb, 0xd1, 0x67, 0xd6, 0xf8, 0x81, 0xf3, 0x2b, 0x99, 0x2f, 0xdc, 0xd3, 0x7e, 0xfb, 0x30, 0xec, + 0x88, 0x52, 0x7f, 0x1d, 0xd1, 0x03, 0x2b, 0xdc, 0xda, 0x0e, 0x7c, 0xab, 0xf7, 0x92, 0x5e, 0xe9, + 0x02, 0xdb, 0x8a, 0x22, 0xa1, 0x0f, 0xa8, 0xfc, 0x77, 0x33, 0xec, 0x6d, 0x2c, 0x5f, 0x4f, 0x76, + 0x93, 0x95, 0xe8, 0x3a, 0x0e, 0x06, 0xa9, 0xfc, 0xef, 0xb3, 0x8b, 0xda, 0x90, 0x54, 0xdb, 0xf7, + 0x8e, 0xbb, 0xe8, 0xe7, 0xf0, 0x31, 0x6e, 0x23, 0xc7, 0xdd, 0xdf, 0xa7, 0x57, 0xe0, 0xe2, 0x87, + 0x99, 0xf6, 0x90, 0x9d, 0x41, 0x66, 0xf6, 0x30, 0x95, 0x4e, 0xfa, 0x59, 0x70, 0x85, 0x16, 0x71, + 0xd0, 0xbc, 0x29, 0xcd, 0x79, 0xf2, 0xd9, 0x7f, 0x94, 0x95, 0xa9, 0x1c, 0x4b, 0xbf, 0x56, 0x0b, + 0x50, 0xea, 0x8f, 0xb5, 0x6e, 0x9d, 0x06, 0xf3, 0x94, 0xeb, 0xd9, 0xdc, 0xc2, 0x8c, 0x38, 0x4b, + 0x6c, 0x23, 0xbe, 0x31, 0x10, 0xff, 0x15, 0x25, 0x17, 0xe8, 0xfd, 0x70, 0xed, 0x2f, 0x2f, 0x0c, + 0xfe, 0xed, 0x25, 0x0a, 0x6a, 0xa5, 0xdb, 0x60, 0xb5, 0xac, 0x19, 0x8a, 0xfe, 0x5c, 0x85, 0x08, + 0xaa, 0x86, 0xde, 0x82, 0xca, 0xe8, 0x6f, 0xb5, 0xaf, 0x83, 0xe2, 0x38, 0x89, 0xa1, 0xc2, 0xe7, + 0x2a, 0x14, 0x05, 0xe9, 0x16, 0xb8, 0x3e, 0xde, 0xbb, 0xd3, 0xda, 0x52, 0x61, 0x43, 0x35, 0x55, + 0x43, 0x9c, 0x91, 0x9e, 0x80, 0x8d, 0x71, 0x8a, 0xb2, 0x6c, 0xca, 0x5b, 0xb2, 0xa1, 0xa2, 0xa6, + 0x6e, 0x98, 0x15, 0xa8, 0x1a, 0xc8, 0x50, 0x6b, 0xdb, 0xa8, 0xaa, 0x1b, 0xa6, 0x5a, 0x16, 0x67, + 0xa5, 0x77, 0xc1, 0xdb, 0x53, 0x98, 0xea, 0xbb, 0xc6, 0x27, 0xb5, 0x21, 0x8e, 0x39, 0x69, 0x13, + 0xac, 0x4f, 0xe3, 0xd0, 0x1b, 0x15, 0xbd, 0xbc, 0x35, 0xc4, 0x33, 0x2f, 0xbd, 0x05, 0x1e, 0xe4, + 0x81, 0x06, 0xcb, 0x86, 0x78, 0x4a, 0x7a, 0x08, 0xee, 0x66, 0x42, 0x22, 0x94, 0xa7, 0xa5, 0xfb, + 0xa0, 0x34, 0x4e, 0x29, 0x37, 0x9b, 0x35, 0x4d, 0x91, 0x4d, 0x4d, 0x6f, 0xa0, 0xaa, 0x69, 0x36, + 0xc5, 0x05, 0xe9, 0x1e, 0xb8, 0x3d, 0x9d, 0xce, 0x54, 0x9a, 0xe2, 0x99, 0x74, 0xb2, 0x17, 0x5a, + 0xa3, 0xac, 0xbf, 0x30, 0x50, 0x59, 0x35, 0x76, 0x4c, 0xbd, 0x29, 0x02, 0xe9, 0x6d, 0xf0, 0x70, + 0x0a, 0x3e, 0xe3, 0x93, 0x1a, 0x5b, 0x33, 0x8a, 0xf1, 0x6c, 0x86, 0x82, 0x07, 0x53, 0x57, 0xcb, + 0x46, 0x55, 0xdb, 0x36, 0xc5, 0x73, 0xd2, 0x7b, 0xe0, 0xdd, 0x5c, 0xe3, 0x27, 0x55, 0x7c, 0x3e, + 0x43, 0x0e, 0x54, 0xcb, 0xda, 0xf0, 0xd2, 0x2f, 0xe6, 0x5d, 0x94, 0x8a, 0xd2, 0x14, 0x2f, 0xe4, + 0x5a, 0x14, 0x42, 0x29, 0xe6, 0x56, 0x0f, 0xa1, 0xbe, 0x28, 0x7d, 0x08, 0xde, 0xff, 0x3c, 0xea, + 0xe1, 0xfb, 0xa1, 0xa6, 0x1a, 0x86, 0x28, 0x49, 0xef, 0x80, 0x47, 0x79, 0x98, 0xe5, 0x4f, 0x5b, + 0x50, 0x15, 0x2f, 0x49, 0x0f, 0xc0, 0x9d, 0x29, 0xe4, 0xe5, 0xdd, 0x86, 0x5c, 0xd7, 0xcb, 0x5b, + 0xe2, 0xe5, 0x0c, 0x13, 0x57, 0x64, 0xc3, 0x90, 0x1b, 0x65, 0x28, 0xa3, 0x1d, 0x75, 0xd7, 0x68, + 0xca, 0x8a, 0x6a, 0x88, 0x57, 0x32, 0x56, 0x6d, 0xc0, 0x93, 0x5c, 0x83, 0x25, 0xe9, 0x29, 0x78, + 0x6f, 0x0a, 0x97, 0x5a, 0x93, 0x0d, 0x53, 0x53, 0x0c, 0x55, 0x86, 0x4a, 0x75, 0x88, 0xf3, 0x6a, + 0xae, 0xf5, 0xe6, 0xfc, 0xb2, 0x52, 0x55, 0xc5, 0x62, 0x86, 0xb6, 0x18, 0x47, 0x5d, 0xad, 0xeb, + 0x70, 0xb7, 0xbc, 0x25, 0x2e, 0xe7, 0x12, 0x40, 0x35, 0x8b, 0x98, 0x80, 0x6b, 0x19, 0x93, 0x61, + 0x1c, 0x4a, 0xad, 0x65, 0x98, 0x23, 0xc6, 0xbb, 0x22, 0xad, 0x81, 0xfb, 0x99, 0xd6, 0xc5, 0x56, + 0xf1, 0xba, 0xb4, 0x0e, 0xd6, 0x72, 0xd9, 0x17, 0xa3, 0x5f, 0xcd, 0x58, 0xcc, 0x01, 0x7d, 0x5d, + 0x53, 0xa0, 0x6e, 0xe8, 0xdb, 0xa6, 0x78, 0x43, 0xfa, 0x32, 0xd8, 0x9c, 0xb6, 0x98, 0xba, 0xb2, + 0x03, 0x75, 0x59, 0xa9, 0x8e, 0xf8, 0xb9, 0x9b, 0x19, 0xb6, 0x1f, 0xf9, 0x46, 0xd9, 0xac, 0xc9, + 0x86, 0x78, 0x2b, 0x63, 0x4f, 0x19, 0x0d, 0xfd, 0xc5, 0x76, 0x4d, 0xde, 0x51, 0xc5, 0xdb, 0x13, + 0xc6, 0xd5, 0x95, 0x84, 0x76, 0xcb, 0x06, 0x6a, 0x42, 0xfd, 0xab, 0xbb, 0x62, 0x69, 0x82, 0x29, + 0x26, 0xa9, 0xab, 0x5a, 0xa5, 0x8a, 0xe4, 0xe7, 0xb2, 0x56, 0x93, 0xb7, 0xb4, 0x9a, 0x66, 0xee, + 0x8a, 0x77, 0xa4, 0xf7, 0xc1, 0x93, 0x0c, 0x2e, 0xba, 0x43, 0x34, 0x05, 0x41, 0xb5, 0xa2, 0x19, + 0x26, 0xa4, 0xae, 0x53, 0xbc, 0x9b, 0xee, 0x85, 0x0d, 0xb9, 0x5e, 0x4b, 0xba, 0x58, 0xf1, 0x9e, + 0x54, 0x02, 0x37, 0xc6, 0xe9, 0x54, 0x65, 0x93, 0xfd, 0x2b, 0x49, 0x43, 0x51, 0xc5, 0xfb, 0x13, + 0x8c, 0x4e, 0x57, 0x46, 0xdd, 0x30, 0x6a, 0xe8, 0x0d, 0x24, 0x97, 0xc5, 0x07, 0xd2, 0x5d, 0x70, + 0x6b, 0xda, 0xb9, 0x48, 0xff, 0xad, 0xe2, 0x61, 0xba, 0xed, 0x27, 0x4f, 0x00, 0xf9, 0x85, 0x81, + 0x14, 0xbd, 0x61, 0xe8, 0x35, 0x55, 0x7c, 0xb4, 0xf6, 0x87, 0x02, 0x58, 0x1c, 0xfe, 0xb3, 0x33, + 0xe9, 0x26, 0x58, 0x89, 0x47, 0x30, 0x4c, 0xd9, 0x6c, 0x19, 0x23, 0xc7, 0xf7, 0x0a, 0xb8, 0x3a, + 0x4a, 0x60, 0xb4, 0x14, 0x85, 0x78, 0x2a, 0x21, 0xb5, 0x73, 0x47, 0x6b, 0x36, 0xd5, 0xb2, 0x38, + 0x23, 0x2d, 0x83, 0x2b, 0xa3, 0x9d, 0x2a, 0x84, 0x3a, 0x14, 0x67, 0xd3, 0xf8, 0xe4, 0x2d, 0x1d, + 0xd2, 0x93, 0x78, 0xed, 0xef, 0x67, 0xc0, 0xac, 0x62, 0xca, 0xd2, 0x25, 0x70, 0x41, 0x31, 0xe5, + 0xf1, 0xbf, 0x95, 0x21, 0x8d, 0x72, 0xcb, 0xac, 0x92, 0x89, 0x35, 0x54, 0xc5, 0xd4, 0x49, 0x1c, + 0x71, 0x15, 0x5c, 0xa2, 0xed, 0x8a, 0xa9, 0x3d, 0x27, 0xe1, 0x85, 0x61, 0x68, 0x7a, 0x83, 0x84, + 0x0f, 0x71, 0x07, 0x81, 0x8c, 0xa0, 0xfa, 0x49, 0x4b, 0x35, 0x4c, 0x43, 0x9c, 0x8d, 0x3a, 0x9a, + 0x50, 0xad, 0x6b, 0xad, 0x3a, 0x32, 0x5a, 0xcd, 0xa6, 0x0e, 0x4d, 0x71, 0x2e, 0xea, 0x30, 0x21, + 0xd9, 0xd2, 0x65, 0x54, 0x56, 0x9f, 0x6b, 0xc4, 0x17, 0xce, 0x47, 0xb2, 0x5b, 0xcd, 0x0a, 0x94, + 0xcb, 0x2a, 0xda, 0x92, 0x1b, 0x0d, 0x15, 0x8a, 0xa7, 0x22, 0x86, 0x2d, 0xad, 0x56, 0xd3, 0x1a, + 0x15, 0x64, 0xb4, 0xea, 0x75, 0x19, 0xee, 0x8a, 0xa7, 0xa3, 0x19, 0x70, 0xd9, 0x35, 0xcd, 0x30, + 0xc5, 0x05, 0xfa, 0xe7, 0x23, 0x83, 0xc6, 0xba, 0xde, 0xd0, 0x4c, 0x1d, 0x6a, 0x8d, 0x8a, 0x78, + 0x86, 0xfe, 0xad, 0x89, 0x29, 0x23, 0xf5, 0xab, 0xa6, 0x0a, 0x1b, 0x72, 0x0d, 0xc9, 0xad, 0xb2, + 0x66, 0x22, 0xc3, 0xd4, 0xa1, 0x5c, 0x51, 0x45, 0x10, 0x01, 0xd0, 0x77, 0x08, 0x0a, 0x83, 0xe8, + 0x6e, 0xb7, 0xa1, 0x88, 0x67, 0x25, 0x11, 0x9c, 0xa3, 0x7c, 0x0d, 0x13, 0xca, 0x48, 0x2b, 0x8b, + 0xe7, 0xa4, 0x8b, 0xe0, 0x7c, 0x4c, 0x69, 0x28, 0x5a, 0x5d, 0x3c, 0xbf, 0xf6, 0x4f, 0x0b, 0xe0, + 0x4a, 0x6a, 0x29, 0x3a, 0x39, 0x40, 0xb4, 0x86, 0xa9, 0x56, 0x98, 0xe9, 0x23, 0xb5, 0x01, 0xf5, + 0x5a, 0x0d, 0xed, 0x68, 0x8d, 0xd1, 0x7f, 0x65, 0xb9, 0x0d, 0x56, 0x27, 0x11, 0x1a, 0x35, 0x59, + 0xd9, 0x11, 0x05, 0x62, 0xb7, 0x93, 0x48, 0x88, 0x2d, 0xea, 0x5a, 0x59, 0x11, 0x67, 0x48, 0x48, + 0x32, 0x89, 0xaa, 0x29, 0x57, 0x54, 0x58, 0x6e, 0x99, 0xbb, 0xe2, 0xec, 0x34, 0x79, 0x6a, 0x5d, + 0xd6, 0x6a, 0xe2, 0x1c, 0x89, 0x1f, 0x27, 0x91, 0x3c, 0xd3, 0xa0, 0x2c, 0xce, 0x4b, 0x77, 0xc0, + 0xcd, 0x49, 0x14, 0xd4, 0x06, 0x61, 0x59, 0x3c, 0x45, 0x36, 0xfb, 0x24, 0xa2, 0xba, 0x6c, 0x9a, + 0x2a, 0xac, 0xeb, 0x86, 0x29, 0x9e, 0x9e, 0x36, 0xbd, 0xba, 0x81, 0x4c, 0x55, 0xae, 0x1b, 0xe2, + 0xc2, 0x34, 0x2a, 0xbd, 0x69, 0x54, 0xd4, 0x86, 0xa6, 0x8a, 0x67, 0xa6, 0x41, 0x27, 0xeb, 0x26, + 0x82, 0xa9, 0x93, 0x93, 0xeb, 0xdb, 0xe2, 0xd9, 0xe9, 0xb8, 0x95, 0xaa, 0xd6, 0x50, 0x99, 0x3d, + 0x7c, 0x09, 0x3c, 0xce, 0xa6, 0x43, 0x15, 0xcd, 0xac, 0xb6, 0xb6, 0xe8, 0x26, 0x22, 0x9b, 0xe7, + 0xbc, 0xb4, 0x01, 0xde, 0xca, 0xc1, 0xa6, 0x68, 0x50, 0xa9, 0xa9, 0x8a, 0x26, 0x2e, 0x12, 0x87, + 0x94, 0x4f, 0x4e, 0x4d, 0xde, 0x12, 0x2f, 0x90, 0x43, 0x2f, 0x07, 0xf9, 0x33, 0xb5, 0xb1, 0xa3, + 0x35, 0x0c, 0x51, 0xcc, 0x49, 0x2f, 0x37, 0x0c, 0x6d, 0xab, 0xa6, 0x8a, 0x17, 0xa7, 0xa9, 0x87, + 0x1c, 0x8f, 0x9a, 0xa2, 0x36, 0xf4, 0x17, 0xa2, 0x34, 0x6d, 0xc1, 0xe2, 0x4d, 0x75, 0x89, 0x1c, + 0x25, 0x13, 0x2d, 0x49, 0x36, 0xe5, 0xb2, 0x5e, 0x41, 0x5a, 0x43, 0xd1, 0xca, 0x6a, 0xc3, 0x44, + 0x75, 0xb9, 0x21, 0x57, 0xd4, 0xba, 0xda, 0x30, 0xc5, 0xcb, 0x24, 0x0e, 0xc8, 0x03, 0xfb, 0x05, + 0x09, 0xb8, 0xf2, 0xd1, 0x92, 0x28, 0x73, 0x89, 0x9c, 0x9f, 0x79, 0xc6, 0xa5, 0x11, 0x03, 0x0d, + 0xad, 0x72, 0x50, 0xd3, 0xc8, 0xaf, 0x46, 0x42, 0xf6, 0xa2, 0xf4, 0x18, 0xbc, 0x93, 0x83, 0x23, + 0x71, 0x5b, 0x5b, 0x5e, 0xfb, 0x18, 0x9c, 0xe6, 0x69, 0x08, 0xe2, 0x16, 0xb7, 0x55, 0xd9, 0x24, + 0xa1, 0xd4, 0xd8, 0x91, 0x12, 0x75, 0x8c, 0x3a, 0x59, 0x61, 0xed, 0xf7, 0x05, 0xb0, 0x32, 0xe5, + 0x47, 0x02, 0xc4, 0xc2, 0x22, 0x66, 0xa8, 0x2a, 0x7a, 0xbd, 0xae, 0x36, 0xca, 0x0c, 0x5e, 0xea, + 0xf1, 0xb5, 0x06, 0xee, 0x4f, 0x27, 0x6f, 0xe8, 0x26, 0xa3, 0x15, 0x88, 0xb5, 0x4c, 0xa7, 0x2d, + 0xeb, 0x0d, 0x55, 0x9c, 0xd9, 0xfa, 0xfa, 0xdf, 0xfc, 0xf8, 0x86, 0xf0, 0xb7, 0x3f, 0xbe, 0x21, + 0xfc, 0xe3, 0x8f, 0x6f, 0x08, 0x9f, 0xea, 0x07, 0x6e, 0xf8, 0xb2, 0xbf, 0xb7, 0x6e, 0x7b, 0x9d, + 0x8d, 0x03, 0xdf, 0x3a, 0x72, 0x59, 0x9a, 0xda, 0x6a, 0x6f, 0xc4, 0xff, 0xf2, 0x6b, 0xf5, 0xdc, + 0x8d, 0x03, 0xdc, 0xdd, 0xa0, 0x3f, 0xe8, 0xd8, 0x38, 0xf0, 0x46, 0xfe, 0xf6, 0xf7, 0xc3, 0xc4, + 0xd7, 0xa3, 0xc7, 0x7b, 0xa7, 0x28, 0xd9, 0x93, 0xff, 0x0d, 0x00, 0x00, 0xff, 0xff, 0x1d, 0x20, + 0x6f, 0x36, 0x26, 0x58, 0x00, 0x00, } func (m *UIBannerClickEvent) Marshal() (dAtA []byte, err error) { diff --git a/api/proto/teleport/integration/v1/awsoidc_service.proto b/api/proto/teleport/integration/v1/awsoidc_service.proto index 30b9033a7ae07..699b6721d86ab 100644 --- a/api/proto/teleport/integration/v1/awsoidc_service.proto +++ b/api/proto/teleport/integration/v1/awsoidc_service.proto @@ -529,8 +529,13 @@ message ListEKSClustersResponse { // PingRequest is a request for doing an health check against the configured integration. message PingRequest { // Integration is the AWS OIDC Integration name. - // Required. + // Required if ARN is empty. string integration = 1; + + // The AWS Role ARN to be used when generating the token. + // This is used to test another ARN before saving the Integration. + // Required if integration is empty. + string role_arn = 2; } // PingResponse contains the response for the Ping operation. diff --git a/api/proto/teleport/legacy/client/proto/authservice.proto b/api/proto/teleport/legacy/client/proto/authservice.proto index 4f4a4dff614bf..44faf9dd1993a 100644 --- a/api/proto/teleport/legacy/client/proto/authservice.proto +++ b/api/proto/teleport/legacy/client/proto/authservice.proto @@ -2832,10 +2832,6 @@ service AuthService { // ListAccessRequests gets access requests with pagination and sorting. rpc ListAccessRequests(ListAccessRequestsRequest) returns (ListAccessRequestsResponse); - // CreateAccessRequest creates a new access request. - // Deprecated: use CreateAccessRequestV2 instead. - // DELETE IN v15.0.0. - rpc CreateAccessRequest(types.AccessRequestV3) returns (google.protobuf.Empty); // CreateAccessRequestV2 creates a new access request. rpc CreateAccessRequestV2(types.AccessRequestV3) returns (types.AccessRequestV3); // DeleteAccessRequest deletes an access request. @@ -3043,10 +3039,6 @@ service AuthService { // GetRole retrieves a role described by the given request. rpc GetRole(GetRoleRequest) returns (types.RoleV6); - // GetRole retrieves all roles. - // - // DELETE IN 17.0 - rpc GetRoles(google.protobuf.Empty) returns (GetRolesResponse); // ListRoles is a paginated role getter. rpc ListRoles(ListRolesRequest) returns (ListRolesResponse); // CreateRole creates a new role. diff --git a/api/proto/teleport/legacy/client/proto/event.proto b/api/proto/teleport/legacy/client/proto/event.proto index f88d95a926ac5..7c0cd043eb13d 100644 --- a/api/proto/teleport/legacy/client/proto/event.proto +++ b/api/proto/teleport/legacy/client/proto/event.proto @@ -23,6 +23,7 @@ import "teleport/clusterconfig/v1/access_graph_settings.proto"; import "teleport/crownjewel/v1/crownjewel.proto"; import "teleport/dbobject/v1/dbobject.proto"; import "teleport/discoveryconfig/v1/discoveryconfig.proto"; +import "teleport/identitycenter/v1/identitycenter.proto"; import "teleport/kubewaitingcontainer/v1/kubewaitingcontainer.proto"; import "teleport/legacy/types/types.proto"; import "teleport/machineid/v1/bot_instance.proto"; @@ -197,5 +198,13 @@ message Event { teleport.provisioning.v1.PrincipalState ProvisioningPrincipalState = 70; // AutoUpdateVersion is a resource for controlling the autoupdate agent rollout. teleport.autoupdate.v1.AutoUpdateAgentRollout AutoUpdateAgentRollout = 71; + // IdentityCenterAccount is a resource for tracking Identity Center accounts + teleport.identitycenter.v1.Account IdentityCenterAccount = 72; + // IdentityCenterPrincipalAssignment is a resource for tracking the AWS + // Permission Sets assigned to a Teleport user or AAccess List + teleport.identitycenter.v1.PrincipalAssignment IdentityCenterPrincipalAssignment = 73; + // IdentityCenterAccountlAssignment is a resource representing a potential + // Permission Set grant on a specific AWS account. + teleport.identitycenter.v1.AccountAssignment IdentityCenterAccountAssignment = 74; } } diff --git a/api/proto/teleport/usageevents/v1/usageevents.proto b/api/proto/teleport/usageevents/v1/usageevents.proto index a37045088eb8c..8962e740b9a71 100644 --- a/api/proto/teleport/usageevents/v1/usageevents.proto +++ b/api/proto/teleport/usageevents/v1/usageevents.proto @@ -242,6 +242,7 @@ enum CTA { CTA_EXTERNAL_AUDIT_STORAGE = 10; CTA_OKTA_USER_SYNC = 11; CTA_ENTRA_ID = 12; + CTA_OKTA_SCIM = 13; } // UIDiscoverDeployServiceEvent is emitted after the user installs a Teleport Agent. diff --git a/api/types/plugin.go b/api/types/plugin.go index 001b854c49e0f..535933d3017f2 100644 --- a/api/types/plugin.go +++ b/api/types/plugin.go @@ -520,7 +520,8 @@ func (p *PluginV1) GetType() PluginType { return PluginTypeSCIM case *PluginSpecV1_Datadog: return PluginTypeDatadog - + case *PluginSpecV1_AwsIc: + return PluginTypeAWSIdentityCenter default: return PluginTypeUnknown } diff --git a/docs/pages/enroll-resources/desktop-access/rbac.mdx b/docs/pages/enroll-resources/desktop-access/rbac.mdx index f03ff9012b1e9..b6c27aaa34f40 100644 --- a/docs/pages/enroll-resources/desktop-access/rbac.mdx +++ b/docs/pages/enroll-resources/desktop-access/rbac.mdx @@ -11,7 +11,7 @@ desktop access: ```yaml kind: role -version: v4 +version: v5 metadata: name: developer spec: @@ -31,6 +31,12 @@ spec: # the clipboard, then it will be disabled. desktop_clipboard: true + # Specify whether directory sharing should be allowed from the + # local machine to remote desktop (requires a supported browser). Defaults to true + # if unspecified. If one or more of the user's roles has disabled + # directory sharing, then it will be disabled. + desktop_directory_sharing: true + # Specify whether local users should be created automatically at connection # time. By default, this feature is disabled, and the user must already exist. # Note: this is applicable to local users only and is not supported in Active diff --git a/docs/pages/includes/role-spec.mdx b/docs/pages/includes/role-spec.mdx index 77c15fd482c47..3030a255d21f0 100644 --- a/docs/pages/includes/role-spec.mdx +++ b/docs/pages/includes/role-spec.mdx @@ -88,6 +88,11 @@ spec: # if unspecified. If one or more of the user's roles has disabled # the clipboard, then it will be disabled. desktop_clipboard: true + # Specify whether directory sharing should be allowed from the + # local machine to remote desktop (requires a supported browser). Defaults to true + # if unspecified. If one or more of the user's roles has disabled + # directory sharing, then it will be disabled. + desktop_directory_sharing: true # enterprise-only: when enabled, the source IP that was used to log in is embedded in the user # certificates, preventing a compromised certificate from being used on another # network. The default is false. diff --git a/docs/pages/reference/access-controls/roles.mdx b/docs/pages/reference/access-controls/roles.mdx index 8975dc1896abd..2b17fd62d9189 100644 --- a/docs/pages/reference/access-controls/roles.mdx +++ b/docs/pages/reference/access-controls/roles.mdx @@ -68,6 +68,7 @@ user: | `max_kubernetes_connections` | Defines the maximum number of concurrent Kubernetes sessions per user | | | `record_session` |Defines the [Session recording mode](../monitoring/audit.mdx).|The strictest value takes precedence.| | `desktop_clipboard` | Allow clipboard sharing for desktop sessions | Logical "AND" i.e. evaluates to "yes" if all roles enable clipboard sharing | +| `desktop_directory_sharing` | Allows sharing local workstation directory to remote desktop | Logical "AND" i.e. evaluates to "yes" if all roles enable directory sharing | | `pin_source_ip` | Enable source IP pinning for SSH certificates. | Logical "OR" i.e. evaluates to "yes" if at least one role requires session termination | | `cert_extensions` | Specifies extensions to be included in SSH certificates | | | `create_host_user_mode` | Allow users to be automatically created on a host | Logical "AND" i.e. if all roles matching a server specify host user creation (`off`, `keep`, `insecure-drop`), it will evaluate to the option specified by all of the roles. If some roles specify both `insecure-drop` or `keep` it will evaluate to `keep`| diff --git a/docs/pages/usage-billing.mdx b/docs/pages/usage-billing.mdx index f3a0f1a2ab4c9..3465c5a84bbc7 100644 --- a/docs/pages/usage-billing.mdx +++ b/docs/pages/usage-billing.mdx @@ -64,25 +64,6 @@ Set the `TELEPORT_REPORTING_HTTPS_PROXY` and `TELEPORT_REPORTING_HTTP_PROXY` environment variables to your proxy address. That will apply as the HTTP connect proxy setting overriding `HTTPS_PROXY` and `HTTP_PROXY` just for outbound usage reporting. -### Validating usage reports - -The system that Teleport uses for submitting usage reports is independent of the -system that Teleport uses for submitting audit events. - -Teleport processes submit audit events to the Teleport Auth Service, which -stores them on its audit event backend for retrieval by Teleport API clients. In -contrast, usage reports are aggregated on a submission service that runs either -on self-hosted Teleport infrastructure or Teleport Cloud, depending on the -user's plan. The submission service persists usage reports in the case of a -submission failure. After a successful submission, the submission service -deletes the reports. - -It is not possible for Teleport users to independently validate usage event -data, as there is no way to set up a third-party usage event destination or -retrieve usage events from a Teleport backend. Reach out to -support@goteleport.com if you have questions about usage reporting on your -Teleport account. - ## Billing metrics Teleport uses the anonymized usage data described in the previous section to @@ -144,6 +125,11 @@ to compute a daily TPR. Then we average the daily TPR over a monthly period, which starts on the subscription start date and ends on each monthly anniversary thereafter. +If you recreate a single resource more than once an hour, this will affect the +hourly average. For example, if were to create then delete 10 servers three +times in one hour, Teleport would display 10 servers at any given time. However, +for the entire hour, Teleport would report 30 protected servers. + ## Usage measurement for billing We aggregate all counts of the billing metrics on a monthly basis starting on @@ -155,3 +141,50 @@ Subscription, also known as a high water mark calculation. Reach out to sales@goteleport.com if you have questions about the commercial editions of Teleport. + +## Troubleshooting usage and billing + +Teleport aggregates usage reports on a submission service that runs either on +self-hosted Teleport infrastructure or Teleport Cloud, depending on the user's +plan. The submission service persists usage reports in the case of a submission +failure, and deletes the reports after a successful submission. It is not +possible to set up a third-party destination for usage events to independently +verify usage event data. + +If you are using Teleport Enterprise (Cloud), your usage data is accurate as +long as Teleport-managed reporting infrastructure works as expected (check the +[status page](https://status.teleport.sh/) for any incidents). On self-hosted +Teleport Enterprise clusters, some conditions can interfere with data reporting. +This section describes some scenarios that can lead to inaccurate data on +self-hosted clusters. + +If you suspect that any of these scenarios describe your Teleport cluster, or +your usage data appears inaccurate, reach out to support@goteleport.com. + +### Multiple Teleport clusters + +In versions older than v14.3.1, Teleport does not de-duplicate users as expected +across multiple Teleport clusters that belong to the same account. If you are +running multiple Teleport clusters with affected versions, the count of active +users may be higher than expected. + +### Unexpected license differences + +When distributing copies of your Teleport Enterprise (Self-Hosted) license +across Auth Service instances, you must not download a license multiple times +from your Teleport account. Instead, you must download a license once and copy +that license across Auth Service instances. Otherwise, the Teleport usage +reporting infrastructure will identify multiple licenses and misrepresent your +usage numbers. + +### SSO users + +In Teleport, single sign-on (SSO) users are +[ephemeral](reference/user-types.mdx#temporary-users). Teleport deletes an SSO user +when its session expires. To count the number of SSO users in your cluster, you +can examine Teleport audit events for unique SSO users that have authenticated +to Teleport during a given time period. The Teleport documentation includes +[how-to guides](./admin-guides/management/export-audit-events/export-audit-events.mdx) for +exporting audit events to common log management solutions so you can identify +users that have authenticated using an SSO provider. + diff --git a/e b/e index fc67d20733894..c8b2aed1f1c9d 160000 --- a/e +++ b/e @@ -1 +1 @@ -Subproject commit fc67d20733894f45e37aeebba64494085ef7667c +Subproject commit c8b2aed1f1c9d059e8853163486214778dcb08b0 diff --git a/e_imports.go b/e_imports.go index d2edd07def844..0934f476e1e07 100644 --- a/e_imports.go +++ b/e_imports.go @@ -61,7 +61,6 @@ import ( _ "github.com/aws/aws-sdk-go-v2/service/sts" _ "github.com/aws/aws-sdk-go-v2/service/sts/types" _ "github.com/beevik/etree" - _ "github.com/cloudflare/cfssl/csr" _ "github.com/coreos/go-oidc/jose" _ "github.com/coreos/go-oidc/oauth2" _ "github.com/coreos/go-oidc/oidc" @@ -80,7 +79,6 @@ import ( _ "github.com/google/safetext/shsprintf" _ "github.com/google/uuid" _ "github.com/gravitational/license" - _ "github.com/gravitational/license/authority" _ "github.com/gravitational/license/constants" _ "github.com/gravitational/license/generate" _ "github.com/gravitational/roundtrip" @@ -186,6 +184,7 @@ import ( _ "github.com/gravitational/teleport/api/types/accessgraph" _ "github.com/gravitational/teleport/api/types/accesslist" _ "github.com/gravitational/teleport/api/types/accesslist/convert/v1" + _ "github.com/gravitational/teleport/api/types/common" _ "github.com/gravitational/teleport/api/types/discoveryconfig" _ "github.com/gravitational/teleport/api/types/events" _ "github.com/gravitational/teleport/api/types/externalauditstorage" @@ -193,6 +192,7 @@ import ( _ "github.com/gravitational/teleport/api/types/header" _ "github.com/gravitational/teleport/api/types/header/convert/legacy" _ "github.com/gravitational/teleport/api/types/header/convert/v1" + _ "github.com/gravitational/teleport/api/types/samlsp" _ "github.com/gravitational/teleport/api/types/secreports" _ "github.com/gravitational/teleport/api/types/secreports/convert/v1" _ "github.com/gravitational/teleport/api/types/trait" diff --git a/gen/proto/go/prehog/v1alpha/teleport.pb.go b/gen/proto/go/prehog/v1alpha/teleport.pb.go index afe507fd85c71..ec0f5d87bf9e2 100644 --- a/gen/proto/go/prehog/v1alpha/teleport.pb.go +++ b/gen/proto/go/prehog/v1alpha/teleport.pb.go @@ -431,6 +431,7 @@ const ( CTA_CTA_EXTERNAL_AUDIT_STORAGE CTA = 10 CTA_CTA_OKTA_USER_SYNC CTA = 11 CTA_CTA_ENTRA_ID CTA = 12 + CTA_CTA_OKTA_SCIM CTA = 13 ) // Enum value maps for CTA. @@ -449,6 +450,7 @@ var ( 10: "CTA_EXTERNAL_AUDIT_STORAGE", 11: "CTA_OKTA_USER_SYNC", 12: "CTA_ENTRA_ID", + 13: "CTA_OKTA_SCIM", } CTA_value = map[string]int32{ "CTA_UNSPECIFIED": 0, @@ -464,6 +466,7 @@ var ( "CTA_EXTERNAL_AUDIT_STORAGE": 10, "CTA_OKTA_USER_SYNC": 11, "CTA_ENTRA_ID": 12, + "CTA_OKTA_SCIM": 13, } ) @@ -496,10 +499,6 @@ func (CTA) EnumDescriptor() ([]byte, []int) { // IntegrationEnrollKind represents the types of integration that // can be enrolled. -// -// Note: IntegrationEnrollKind enum must be kept in sync with the values defined -// in api/proto/teleport/usageevents/v1/usageevents.proto. Values 18-25 have -// become out of sync and are manually mapped to each other. type IntegrationEnrollKind int32 const ( @@ -7322,6 +7321,84 @@ func (x *DatabaseUserPermissionsUpdateEvent) GetNumTablesPermissions() int32 { return 0 } +// SessionRecordingAccessEvent is emitted when the user accesses a session +// recording. +// +// PostHog event: tp.recording.access +type SessionRecordingAccessEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // session_type is type of the session, should be + // "ssh"/"k8s"/"db"/"app"/"desktop" (matching the values for + // api/types.SessionKind). + // + // PostHog property: tp.session_type + SessionType string `protobuf:"bytes,1,opt,name=session_type,json=sessionType,proto3" json:"session_type,omitempty"` + // user_name is the anonymized Teleport username, 32 bytes (HMAC-SHA-256) + // encoded in base64. + // + // PostHog property: tp.user_name + UserName string `protobuf:"bytes,2,opt,name=user_name,json=userName,proto3" json:"user_name,omitempty"` + // format is the format the session recording was accessed. + // One of text/json/yaml/pty. pty being the interactive session player. + // + // PostHog property: tp.recording.format + Format string `protobuf:"bytes,3,opt,name=format,proto3" json:"format,omitempty"` +} + +func (x *SessionRecordingAccessEvent) Reset() { + *x = SessionRecordingAccessEvent{} + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[96] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *SessionRecordingAccessEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SessionRecordingAccessEvent) ProtoMessage() {} + +func (x *SessionRecordingAccessEvent) ProtoReflect() protoreflect.Message { + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[96] + 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 SessionRecordingAccessEvent.ProtoReflect.Descriptor instead. +func (*SessionRecordingAccessEvent) Descriptor() ([]byte, []int) { + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{96} +} + +func (x *SessionRecordingAccessEvent) GetSessionType() string { + if x != nil { + return x.SessionType + } + return "" +} + +func (x *SessionRecordingAccessEvent) GetUserName() string { + if x != nil { + return x.UserName + } + return "" +} + +func (x *SessionRecordingAccessEvent) GetFormat() string { + if x != nil { + return x.Format + } + return "" +} + // UserTaskStateEvent is emitted when a UserTask state changes. // This can happen when the Task is created, when it's manually // resolved by the user or when it changes back to being open @@ -7357,7 +7434,7 @@ type UserTaskStateEvent struct { func (x *UserTaskStateEvent) Reset() { *x = UserTaskStateEvent{} - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[96] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[97] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7369,7 +7446,7 @@ func (x *UserTaskStateEvent) String() string { func (*UserTaskStateEvent) ProtoMessage() {} func (x *UserTaskStateEvent) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[96] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[97] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7382,7 +7459,7 @@ func (x *UserTaskStateEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use UserTaskStateEvent.ProtoReflect.Descriptor instead. func (*UserTaskStateEvent) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{96} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{97} } func (x *UserTaskStateEvent) GetTaskType() string { @@ -7519,13 +7596,14 @@ type SubmitEventRequest struct { // *SubmitEventRequest_AccessGraphAccessPathChanged // *SubmitEventRequest_AccessGraphCrownJewelCreate // *SubmitEventRequest_UiAccessGraphCrownJewelDiffView + // *SubmitEventRequest_SessionRecordingAccess // *SubmitEventRequest_UserTaskState Event isSubmitEventRequest_Event `protobuf_oneof:"event"` } func (x *SubmitEventRequest) Reset() { *x = SubmitEventRequest{} - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[97] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[98] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -7537,7 +7615,7 @@ func (x *SubmitEventRequest) String() string { func (*SubmitEventRequest) ProtoMessage() {} func (x *SubmitEventRequest) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[97] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[98] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -7550,7 +7628,7 @@ func (x *SubmitEventRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitEventRequest.ProtoReflect.Descriptor instead. func (*SubmitEventRequest) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{97} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{98} } func (x *SubmitEventRequest) GetClusterName() string { @@ -8197,6 +8275,13 @@ func (x *SubmitEventRequest) GetUiAccessGraphCrownJewelDiffView() *UIAccessGraph return nil } +func (x *SubmitEventRequest) GetSessionRecordingAccess() *SessionRecordingAccessEvent { + if x, ok := x.GetEvent().(*SubmitEventRequest_SessionRecordingAccess); ok { + return x.SessionRecordingAccess + } + return nil +} + func (x *SubmitEventRequest) GetUserTaskState() *UserTaskStateEvent { if x, ok := x.GetEvent().(*SubmitEventRequest_UserTaskState); ok { return x.UserTaskState @@ -8569,6 +8654,10 @@ type SubmitEventRequest_UiAccessGraphCrownJewelDiffView struct { UiAccessGraphCrownJewelDiffView *UIAccessGraphCrownJewelDiffViewEvent `protobuf:"bytes,92,opt,name=ui_access_graph_crown_jewel_diff_view,json=uiAccessGraphCrownJewelDiffView,proto3,oneof"` } +type SubmitEventRequest_SessionRecordingAccess struct { + SessionRecordingAccess *SessionRecordingAccessEvent `protobuf:"bytes,93,opt,name=session_recording_access,json=sessionRecordingAccess,proto3,oneof"` +} + type SubmitEventRequest_UserTaskState struct { UserTaskState *UserTaskStateEvent `protobuf:"bytes,94,opt,name=user_task_state,json=userTaskState,proto3,oneof"` } @@ -8753,6 +8842,8 @@ func (*SubmitEventRequest_AccessGraphCrownJewelCreate) isSubmitEventRequest_Even func (*SubmitEventRequest_UiAccessGraphCrownJewelDiffView) isSubmitEventRequest_Event() {} +func (*SubmitEventRequest_SessionRecordingAccess) isSubmitEventRequest_Event() {} + func (*SubmitEventRequest_UserTaskState) isSubmitEventRequest_Event() {} type SubmitEventResponse struct { @@ -8763,7 +8854,7 @@ type SubmitEventResponse struct { func (x *SubmitEventResponse) Reset() { *x = SubmitEventResponse{} - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[98] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[99] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8775,7 +8866,7 @@ func (x *SubmitEventResponse) String() string { func (*SubmitEventResponse) ProtoMessage() {} func (x *SubmitEventResponse) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[98] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[99] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8788,7 +8879,7 @@ func (x *SubmitEventResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitEventResponse.ProtoReflect.Descriptor instead. func (*SubmitEventResponse) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{98} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{99} } type SubmitEventsRequest struct { @@ -8802,7 +8893,7 @@ type SubmitEventsRequest struct { func (x *SubmitEventsRequest) Reset() { *x = SubmitEventsRequest{} - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[99] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[100] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8814,7 +8905,7 @@ func (x *SubmitEventsRequest) String() string { func (*SubmitEventsRequest) ProtoMessage() {} func (x *SubmitEventsRequest) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[99] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[100] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8827,7 +8918,7 @@ func (x *SubmitEventsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitEventsRequest.ProtoReflect.Descriptor instead. func (*SubmitEventsRequest) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{99} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{100} } func (x *SubmitEventsRequest) GetEvents() []*SubmitEventRequest { @@ -8845,7 +8936,7 @@ type SubmitEventsResponse struct { func (x *SubmitEventsResponse) Reset() { *x = SubmitEventsResponse{} - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[100] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[101] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8857,7 +8948,7 @@ func (x *SubmitEventsResponse) String() string { func (*SubmitEventsResponse) ProtoMessage() {} func (x *SubmitEventsResponse) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[100] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[101] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8870,7 +8961,7 @@ func (x *SubmitEventsResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use SubmitEventsResponse.ProtoReflect.Descriptor instead. func (*SubmitEventsResponse) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{100} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{101} } type HelloTeleportRequest struct { @@ -8881,7 +8972,7 @@ type HelloTeleportRequest struct { func (x *HelloTeleportRequest) Reset() { *x = HelloTeleportRequest{} - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[101] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[102] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8893,7 +8984,7 @@ func (x *HelloTeleportRequest) String() string { func (*HelloTeleportRequest) ProtoMessage() {} func (x *HelloTeleportRequest) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[101] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[102] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8906,7 +8997,7 @@ func (x *HelloTeleportRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use HelloTeleportRequest.ProtoReflect.Descriptor instead. func (*HelloTeleportRequest) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{101} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{102} } type HelloTeleportResponse struct { @@ -8917,7 +9008,7 @@ type HelloTeleportResponse struct { func (x *HelloTeleportResponse) Reset() { *x = HelloTeleportResponse{} - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[102] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[103] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -8929,7 +9020,7 @@ func (x *HelloTeleportResponse) String() string { func (*HelloTeleportResponse) ProtoMessage() {} func (x *HelloTeleportResponse) ProtoReflect() protoreflect.Message { - mi := &file_prehog_v1alpha_teleport_proto_msgTypes[102] + mi := &file_prehog_v1alpha_teleport_proto_msgTypes[103] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -8942,7 +9033,7 @@ func (x *HelloTeleportResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use HelloTeleportResponse.ProtoReflect.Descriptor instead. func (*HelloTeleportResponse) Descriptor() ([]byte, []int) { - return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{102} + return file_prehog_v1alpha_teleport_proto_rawDescGZIP(), []int{103} } var File_prehog_v1alpha_teleport_proto protoreflect.FileDescriptor @@ -9958,634 +10049,648 @@ var file_prehog_v1alpha_teleport_proto_rawDesc = []byte{ 0x16, 0x6e, 0x75, 0x6d, 0x5f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x6e, 0x75, 0x6d, 0x54, 0x61, 0x62, 0x6c, 0x65, 0x73, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x73, 0x22, 0x8f, 0x01, 0x0a, 0x12, 0x55, 0x73, 0x65, 0x72, 0x54, 0x61, 0x73, 0x6b, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x61, - 0x73, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, - 0x61, 0x73, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x73, 0x73, 0x75, 0x65, - 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x73, 0x73, - 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x27, 0x0a, 0x0f, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x9b, 0x4e, 0x0a, 0x12, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, - 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, - 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 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, 0x09, - 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x3f, 0x0a, 0x0a, 0x75, 0x73, 0x65, - 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, - 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, - 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x3f, 0x0a, 0x0a, 0x73, 0x73, - 0x6f, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, - 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x53, 0x53, 0x4f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, - 0x52, 0x09, 0x73, 0x73, 0x6f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x4e, 0x0a, 0x0f, 0x72, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x48, 0x0a, 0x0d, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x4c, 0x0a, 0x0f, 0x75, 0x69, 0x5f, 0x62, 0x61, 0x6e, 0x6e, - 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, - 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x55, 0x49, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x75, 0x69, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x6c, - 0x69, 0x63, 0x6b, 0x12, 0x92, 0x01, 0x0a, 0x29, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, - 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x67, 0x6f, 0x5f, 0x74, - 0x6f, 0x5f, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x6c, 0x69, 0x63, - 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, - 0x72, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x6f, 0x54, 0x6f, 0x44, 0x61, - 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x48, 0x00, 0x52, 0x23, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x6f, 0x54, 0x6f, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, - 0x61, 0x72, 0x64, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x82, 0x01, 0x0a, 0x23, 0x75, 0x69, 0x5f, - 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x66, 0x69, 0x72, 0x73, - 0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, - 0x64, 0x41, 0x64, 0x64, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1e, 0x75, - 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x92, 0x01, - 0x0a, 0x29, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x61, 0x64, 0x64, - 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, - 0x6c, 0x61, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x0b, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, 0x46, - 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x61, 0x74, 0x65, - 0x72, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x23, 0x75, - 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, 0x46, 0x69, 0x72, 0x73, 0x74, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x69, - 0x63, 0x6b, 0x12, 0x7b, 0x0a, 0x20, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, - 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, - 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, - 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, - 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, - 0x74, 0x69, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, - 0x00, 0x52, 0x1c, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, 0x74, 0x43, - 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, - 0x87, 0x01, 0x0a, 0x24, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x72, - 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, - 0x65, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, + 0x6f, 0x6e, 0x73, 0x22, 0x75, 0x0a, 0x1b, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x63, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x67, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, + 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, + 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x22, 0x8f, 0x01, 0x0a, 0x12, 0x55, + 0x73, 0x65, 0x72, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x61, 0x73, 0x6b, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, + 0x0a, 0x0a, 0x69, 0x73, 0x73, 0x75, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x69, 0x73, 0x73, 0x75, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, + 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x12, 0x27, 0x0a, 0x0f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x69, 0x6e, + 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x84, 0x4f, 0x0a, + 0x12, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6c, 0x75, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x6e, + 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6c, 0x75, 0x73, 0x74, + 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 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, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x12, 0x3f, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x6f, 0x67, 0x69, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x6f, 0x67, 0x69, + 0x6e, 0x12, 0x3f, 0x0a, 0x0a, 0x73, 0x73, 0x6f, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x53, 0x4f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x09, 0x73, 0x73, 0x6f, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x12, 0x4e, 0x0a, 0x0f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x72, + 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x48, 0x00, 0x52, 0x0e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x12, 0x48, 0x0a, 0x0d, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, 0x68, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0c, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x12, 0x4c, 0x0a, 0x0f, + 0x75, 0x69, 0x5f, 0x62, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x43, + 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x75, 0x69, 0x42, + 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x92, 0x01, 0x0a, 0x29, 0x75, + 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, + 0x74, 0x65, 0x5f, 0x67, 0x6f, 0x5f, 0x74, 0x6f, 0x5f, 0x64, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, + 0x72, 0x64, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, - 0x72, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x20, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, - 0x72, 0x64, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, - 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0x7b, 0x0a, 0x20, 0x75, 0x69, 0x5f, - 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x5f, 0x63, - 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x0e, 0x20, + 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, + 0x65, 0x47, 0x6f, 0x54, 0x6f, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x43, 0x6c, + 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x23, 0x75, 0x69, 0x4f, 0x6e, + 0x62, 0x6f, 0x61, 0x72, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x47, 0x6f, 0x54, + 0x6f, 0x44, 0x61, 0x73, 0x68, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, + 0x82, 0x01, 0x0a, 0x23, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x61, + 0x64, 0x64, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, + 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, + 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, 0x46, 0x69, 0x72, 0x73, 0x74, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1e, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, + 0x64, 0x64, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x43, + 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x92, 0x01, 0x0a, 0x29, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, + 0x61, 0x72, 0x64, 0x5f, 0x61, 0x64, 0x64, 0x5f, 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x72, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x6c, 0x61, 0x74, 0x65, 0x72, 0x5f, 0x63, 0x6c, 0x69, + 0x63, 0x6b, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, + 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, + 0x61, 0x72, 0x64, 0x41, 0x64, 0x64, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, + 0x72, 0x63, 0x65, 0x4c, 0x61, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x48, 0x00, 0x52, 0x23, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x41, + 0x64, 0x64, 0x46, 0x69, 0x72, 0x73, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x4c, + 0x61, 0x74, 0x65, 0x72, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x7b, 0x0a, 0x20, 0x75, 0x69, 0x5f, + 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x73, 0x65, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x64, + 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x53, 0x65, + 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1c, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, + 0x61, 0x72, 0x64, 0x53, 0x65, 0x74, 0x43, 0x72, 0x65, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, + 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0x87, 0x01, 0x0a, 0x24, 0x75, 0x69, 0x5f, 0x6f, 0x6e, + 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x63, + 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x18, + 0x0d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, + 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, + 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x20, + 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, + 0x72, 0x43, 0x68, 0x61, 0x6c, 0x6c, 0x65, 0x6e, 0x67, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x12, 0x7b, 0x0a, 0x20, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, + 0x63, 0x6f, 0x64, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x5f, 0x63, + 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x65, + 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x52, 0x65, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x69, + 0x6e, 0x75, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, + 0x1c, 0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, + 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x6f, 0x0a, + 0x1c, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x70, 0x79, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x0f, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, - 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, 0x65, 0x43, 0x6c, 0x69, 0x63, - 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1c, 0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x74, 0x69, 0x6e, 0x75, - 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x6f, 0x0a, 0x1c, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x70, 0x79, - 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, - 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, - 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x70, - 0x79, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x18, 0x75, - 0x69, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, - 0x70, 0x79, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x72, 0x0a, 0x1d, 0x75, 0x69, 0x5f, 0x72, 0x65, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x73, 0x5f, 0x70, 0x72, 0x69, - 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, - 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x55, 0x49, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x50, - 0x72, 0x69, 0x6e, 0x74, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, - 0x52, 0x19, 0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, - 0x73, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x63, 0x0a, 0x19, 0x75, - 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x65, 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, - 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, - 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x16, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x12, 0x82, 0x01, 0x0a, 0x24, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x30, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x48, 0x00, 0x52, 0x20, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x6f, 0x0a, 0x1d, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x65, - 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, - 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, - 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x73, - 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x49, 0x73, 0x73, - 0x75, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1a, 0x75, 0x73, 0x65, 0x72, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x49, 0x73, 0x73, 0x75, 0x65, - 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x4d, 0x0a, 0x10, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x76, 0x32, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x72, 0x74, 0x56, 0x32, 0x12, 0x76, 0x0a, 0x20, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2c, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x1c, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x70, 0x6c, 0x6f, - 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x7f, 0x0a, - 0x23, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, - 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x18, 0x16, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x65, - 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, - 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, - 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1f, 0x75, - 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, - 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x8f, - 0x01, 0x0a, 0x29, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, - 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x65, 0x5f, 0x6d, 0x74, 0x6c, 0x73, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x17, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, - 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x4d, - 0x54, 0x4c, 0x53, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x24, 0x75, 0x69, 0x44, 0x69, - 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x4d, 0x74, 0x6c, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x12, 0xb8, 0x01, 0x0a, 0x38, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x5f, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, - 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x5f, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x18, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, - 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x44, 0x69, 0x72, 0x65, - 0x63, 0x74, 0x6f, 0x72, 0x79, 0x54, 0x6f, 0x6f, 0x6c, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, - 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x31, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, - 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x54, 0x6f, 0x6f, 0x6c, 0x73, 0x49, - 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0xae, 0x01, 0x0a, 0x34, - 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x6b, - 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x5f, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x18, 0x19, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3e, 0x2e, 0x70, 0x72, 0x65, + 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x70, 0x79, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x48, 0x00, 0x52, 0x18, 0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, + 0x43, 0x6f, 0x64, 0x65, 0x73, 0x43, 0x6f, 0x70, 0x79, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x72, + 0x0a, 0x1d, 0x75, 0x69, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x63, 0x6f, + 0x64, 0x65, 0x73, 0x5f, 0x70, 0x72, 0x69, 0x6e, 0x74, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, + 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x52, 0x65, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x43, 0x6c, 0x69, 0x63, 0x6b, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x19, 0x75, 0x69, 0x52, 0x65, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x79, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x50, 0x72, 0x69, 0x6e, 0x74, 0x43, 0x6c, 0x69, + 0x63, 0x6b, 0x12, 0x63, 0x0a, 0x19, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, + 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, + 0x16, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x82, 0x01, 0x0a, 0x24, 0x75, 0x69, 0x5f, 0x64, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x20, 0x75, 0x69, 0x44, 0x69, + 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x53, 0x65, + 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x6f, 0x0a, 0x1d, + 0x75, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x13, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x65, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, + 0x00, 0x52, 0x1a, 0x75, 0x73, 0x65, 0x72, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x4d, 0x0a, + 0x10, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x76, + 0x32, 0x18, 0x14, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0e, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x56, 0x32, 0x12, 0x76, 0x0a, 0x20, + 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x70, 0x6c, + 0x6f, 0x79, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1c, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x12, 0x7f, 0x0a, 0x23, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x65, 0x67, + 0x69, 0x73, 0x74, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x16, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, + 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1f, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x65, 0x67, 0x69, 0x73, 0x74, 0x65, 0x72, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x8f, 0x01, 0x0a, 0x29, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x5f, 0x6d, 0x74, 0x6c, 0x73, 0x5f, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x70, 0x72, 0x65, 0x68, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x4d, 0x54, 0x4c, 0x53, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, + 0x00, 0x52, 0x24, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, + 0x61, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x4d, 0x74, + 0x6c, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0xb8, 0x01, 0x0a, 0x38, 0x75, 0x69, 0x5f, 0x64, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x5f, + 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, + 0x5f, 0x74, 0x6f, 0x6f, 0x6c, 0x73, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x5f, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x18, 0x18, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x41, 0x63, 0x74, - 0x69, 0x76, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x2e, 0x75, 0x69, - 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x41, - 0x63, 0x74, 0x69, 0x76, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x95, 0x01, 0x0a, - 0x2b, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x61, 0x75, 0x74, - 0x6f, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x1a, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, 0x75, - 0x74, 0x6f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x26, 0x75, 0x69, - 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x12, 0x9f, 0x01, 0x0a, 0x2f, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x5f, 0x69, 0x61, 0x6d, 0x5f, 0x70, 0x6f, 0x6c, 0x69, - 0x63, 0x79, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x1b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, + 0x69, 0x76, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x54, 0x6f, 0x6f, 0x6c, + 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, + 0x31, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, 0x6b, 0x74, + 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, + 0x79, 0x54, 0x6f, 0x6f, 0x6c, 0x73, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x12, 0xae, 0x01, 0x0a, 0x34, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x5f, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x76, + 0x65, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x19, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x3e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x73, + 0x6b, 0x74, 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, + 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x48, 0x00, 0x52, 0x2e, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, + 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x41, 0x63, 0x74, 0x69, 0x76, 0x65, 0x44, 0x69, 0x72, 0x65, + 0x63, 0x74, 0x6f, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x12, 0x95, 0x01, 0x0a, 0x2b, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x5f, 0x61, 0x75, 0x74, 0x6f, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x5f, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x18, 0x1a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, 0x2e, 0x70, 0x72, 0x65, 0x68, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, 0x75, 0x74, 0x6f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x48, 0x00, 0x52, 0x26, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x41, + 0x75, 0x74, 0x6f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x65, 0x64, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x9f, 0x01, 0x0a, 0x2f, + 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, + 0x62, 0x61, 0x73, 0x65, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x5f, 0x69, + 0x61, 0x6d, 0x5f, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, + 0x1b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x65, 0x49, 0x41, 0x4d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x48, 0x00, 0x52, 0x29, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, + 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x49, + 0x61, 0x6d, 0x50, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x88, 0x01, + 0x0a, 0x26, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x72, + 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, - 0x73, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x49, 0x41, 0x4d, 0x50, 0x6f, - 0x6c, 0x69, 0x63, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x29, 0x75, 0x69, 0x44, - 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x49, 0x61, 0x6d, 0x50, 0x6f, 0x6c, 0x69, 0x63, - 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x88, 0x01, 0x0a, 0x26, 0x75, 0x69, 0x5f, 0x64, 0x69, - 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, - 0x73, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x18, 0x1c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x22, 0x75, - 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, - 0x61, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x79, 0x0a, 0x21, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x5f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x1d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, - 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, - 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1d, 0x75, - 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, - 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x69, 0x0a, 0x1b, - 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x1e, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6d, - 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x18, 0x75, - 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, - 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x42, 0x0a, 0x0b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, - 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x1f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, - 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x6f, - 0x6c, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x0a, 0x72, 0x6f, 0x6c, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x63, 0x0a, 0x18, 0x75, - 0x69, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, - 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x20, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, - 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, - 0x49, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x6c, - 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x14, 0x75, 0x69, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, - 0x12, 0x70, 0x0a, 0x1d, 0x75, 0x69, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x65, - 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x73, 0x61, 0x76, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x63, - 0x6b, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, + 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, + 0x70, 0x61, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x48, 0x00, 0x52, 0x22, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x50, 0x72, 0x69, 0x6e, 0x63, 0x69, 0x70, 0x61, 0x6c, 0x73, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x79, 0x0a, 0x21, 0x75, 0x69, 0x5f, 0x64, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6e, + 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x1d, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x54, + 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1d, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x54, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x12, 0x69, 0x0a, 0x1b, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x5f, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x18, 0x1e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, + 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, + 0x6f, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x48, 0x00, 0x52, 0x18, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x42, + 0x0a, 0x0b, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x1f, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0a, 0x72, 0x6f, 0x6c, 0x65, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x12, 0x63, 0x0a, 0x18, 0x75, 0x69, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, + 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x20, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, + 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, + 0x00, 0x52, 0x14, 0x75, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, + 0x6c, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x70, 0x0a, 0x1d, 0x75, 0x69, 0x5f, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x73, 0x61, + 0x76, 0x65, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x21, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, + 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, + 0x55, 0x49, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x53, + 0x61, 0x76, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, + 0x18, 0x75, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, + 0x53, 0x61, 0x76, 0x65, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x76, 0x0a, 0x1f, 0x75, 0x69, 0x5f, + 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, + 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x22, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, + 0x6f, 0x6c, 0x65, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1a, 0x75, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, + 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x43, 0x6c, 0x69, 0x63, + 0x6b, 0x12, 0x98, 0x01, 0x0a, 0x2b, 0x75, 0x69, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, + 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x64, 0x6f, + 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6c, 0x69, 0x63, + 0x6b, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3a, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x43, 0x6c, 0x69, 0x63, - 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x18, 0x75, 0x69, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x53, 0x61, 0x76, 0x65, 0x43, 0x6c, 0x69, - 0x63, 0x6b, 0x12, 0x76, 0x0a, 0x1f, 0x75, 0x69, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, - 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, 0x65, 0x5f, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x5f, - 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x22, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, - 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x43, 0x61, 0x6e, 0x63, - 0x65, 0x6c, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1a, - 0x75, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x43, - 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x98, 0x01, 0x0a, 0x2b, 0x75, - 0x69, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x72, 0x6f, 0x6c, - 0x65, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x18, 0x23, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x3a, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x2e, 0x55, 0x49, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, - 0x65, 0x56, 0x69, 0x65, 0x77, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x25, - 0x75, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x56, - 0x69, 0x65, 0x77, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x45, 0x0a, 0x0c, 0x6b, 0x75, 0x62, 0x65, 0x5f, 0x72, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x24, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, - 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4b, 0x75, 0x62, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x0b, 0x6b, 0x75, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04, - 0x73, 0x66, 0x74, 0x70, 0x18, 0x25, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x65, - 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x46, 0x54, 0x50, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x04, 0x73, 0x66, 0x74, 0x70, 0x12, 0x56, 0x0a, - 0x14, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x26, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, - 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x67, 0x65, - 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, - 0x00, 0x52, 0x12, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x57, 0x0a, 0x12, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x18, 0x27, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x72, 0x74, - 0x62, 0x65, 0x61, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x9c, - 0x01, 0x0a, 0x2e, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x69, - 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x61, 0x77, 0x73, 0x5f, 0x6f, - 0x69, 0x64, 0x63, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x57, - 0x53, 0x4f, 0x49, 0x44, 0x43, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x48, 0x00, 0x52, 0x28, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x49, - 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x77, 0x73, 0x4f, 0x69, 0x64, - 0x63, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x83, 0x01, - 0x0a, 0x25, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x61, - 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x64, 0x73, 0x5f, 0x65, 0x6e, 0x72, 0x6f, 0x6c, - 0x6c, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x29, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, - 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, - 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, - 0x65, 0x52, 0x44, 0x53, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, - 0x00, 0x52, 0x20, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, - 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x64, 0x73, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x12, 0x6b, 0x0a, 0x1d, 0x75, 0x69, 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x74, - 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x5f, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x18, 0x2a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x72, 0x65, - 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x43, 0x61, - 0x6c, 0x6c, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x18, 0x75, 0x69, 0x43, 0x61, 0x6c, 0x6c, 0x54, 0x6f, - 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x12, 0x54, 0x0a, 0x11, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, - 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x2b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, - 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x73, 0x73, - 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x79, 0x0a, 0x21, 0x75, 0x69, 0x5f, 0x69, 0x6e, 0x74, - 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, - 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x2c, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x55, 0x49, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x48, 0x00, 0x52, 0x1d, 0x75, 0x69, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x53, 0x74, 0x61, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x82, 0x01, 0x0a, 0x24, 0x75, 0x69, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x63, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x30, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x2e, 0x55, 0x49, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, - 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x20, 0x75, 0x69, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, - 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x53, 0x0a, 0x13, 0x65, 0x64, 0x69, 0x74, 0x6f, 0x72, - 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x2e, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, - 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x65, 0x64, 0x69, 0x74, 0x6f, 0x72, - 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x3f, 0x0a, 0x0a, 0x62, - 0x6f, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x2f, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x42, 0x6f, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, - 0x00, 0x52, 0x09, 0x62, 0x6f, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x7a, 0x0a, 0x1f, - 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x69, 0x6f, 0x6e, 0x6e, 0x61, 0x69, 0x72, 0x65, 0x5f, 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x18, - 0x30, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, - 0x51, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x61, 0x69, 0x72, 0x65, 0x53, 0x75, 0x62, - 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1c, 0x75, 0x69, 0x4f, 0x6e, - 0x62, 0x6f, 0x61, 0x72, 0x64, 0x51, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x61, 0x69, - 0x72, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, 0x39, 0x0a, 0x08, 0x62, 0x6f, 0x74, 0x5f, - 0x6a, 0x6f, 0x69, 0x6e, 0x18, 0x31, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x65, - 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x42, 0x6f, 0x74, 0x4a, - 0x6f, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x07, 0x62, 0x6f, 0x74, 0x4a, - 0x6f, 0x69, 0x6e, 0x12, 0x51, 0x0a, 0x10, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x5f, 0x65, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x32, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, - 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, - 0x73, 0x73, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0f, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, - 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x64, 0x0a, 0x17, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, - 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x63, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x18, 0x33, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x4e, - 0x65, 0x77, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x15, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, - 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x65, 0x0a, 0x19, - 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x34, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x27, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, - 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x17, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x12, 0x6e, 0x0a, 0x1c, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x72, - 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x18, 0x35, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x65, 0x68, - 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, - 0x72, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1a, 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, - 0x52, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x12, 0x5e, 0x0a, 0x15, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x36, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x13, - 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x48, 0x0a, 0x0d, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x37, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, - 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x73, 0x73, 0x69, - 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x0c, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x53, 0x0a, - 0x13, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x18, 0x38, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, - 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x11, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x12, 0x53, 0x0a, 0x13, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6c, 0x69, - 0x6d, 0x69, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x39, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x21, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x6c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x55, 0x0a, 0x12, 0x61, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x3a, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x55, - 0x0a, 0x12, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x75, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x18, 0x3b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, 0x65, - 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x48, 0x00, 0x52, 0x10, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x55, 0x0a, 0x12, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, - 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x3c, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x61, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x68, 0x0a, 0x19, - 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x3d, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2b, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, - 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x16, - 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x68, 0x0a, 0x19, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x75, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x18, 0x3e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x65, 0x68, - 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x16, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, - 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x12, 0x68, 0x0a, 0x19, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, - 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x3f, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x48, 0x00, 0x52, 0x16, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x69, 0x0a, 0x1a, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, - 0x5f, 0x74, 0x6f, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x18, 0x40, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, + 0x65, 0x4e, 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x56, 0x69, 0x65, 0x77, 0x44, 0x6f, 0x63, 0x75, + 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x25, 0x75, 0x69, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, + 0x65, 0x77, 0x52, 0x6f, 0x6c, 0x65, 0x56, 0x69, 0x65, 0x77, 0x44, 0x6f, 0x63, 0x75, 0x6d, 0x65, + 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x12, 0x45, 0x0a, 0x0c, + 0x6b, 0x75, 0x62, 0x65, 0x5f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x18, 0x24, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x4b, 0x75, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0b, 0x6b, 0x75, 0x62, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x2f, 0x0a, 0x04, 0x73, 0x66, 0x74, 0x70, 0x18, 0x25, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x53, 0x46, 0x54, 0x50, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x04, + 0x73, 0x66, 0x74, 0x70, 0x12, 0x56, 0x0a, 0x14, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x26, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, + 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x12, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x57, 0x0a, 0x12, + 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x5f, 0x68, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, + 0x61, 0x74, 0x18, 0x27, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, + 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x48, 0x65, 0x61, 0x72, 0x74, 0x62, 0x65, 0x61, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x48, 0x00, 0x52, 0x11, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x48, 0x65, 0x61, 0x72, + 0x74, 0x62, 0x65, 0x61, 0x74, 0x12, 0x9c, 0x01, 0x0a, 0x2e, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x61, 0x77, 0x73, 0x5f, 0x6f, 0x69, 0x64, 0x63, 0x5f, 0x63, 0x6f, 0x6e, 0x6e, 0x65, + 0x63, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x28, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, - 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x16, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x54, - 0x6f, 0x55, 0x73, 0x65, 0x72, 0x12, 0x81, 0x01, 0x0a, 0x22, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x65, 0x63, 0x32, 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x41, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x43, - 0x32, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1e, 0x75, 0x69, 0x44, 0x69, 0x73, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x63, 0x32, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x62, 0x0a, 0x17, 0x75, 0x69, 0x5f, - 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x5f, - 0x65, 0x69, 0x63, 0x65, 0x18, 0x42, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x65, - 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, - 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x45, 0x49, 0x43, 0x45, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x14, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x45, 0x69, 0x63, 0x65, 0x12, 0x62, 0x0a, - 0x17, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, 0x43, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, + 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x41, 0x57, 0x53, 0x4f, 0x49, 0x44, 0x43, 0x43, 0x6f, 0x6e, 0x6e, + 0x65, 0x63, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x28, 0x75, 0x69, 0x44, 0x69, + 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x41, 0x77, 0x73, 0x4f, 0x69, 0x64, 0x63, 0x43, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x12, 0x83, 0x01, 0x0a, 0x25, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, + 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x72, 0x64, + 0x73, 0x5f, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x29, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x44, 0x53, 0x45, 0x6e, 0x72, 0x6f, 0x6c, + 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x20, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, + 0x6f, 0x76, 0x65, 0x72, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x52, 0x64, 0x73, 0x45, + 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x6b, 0x0a, 0x1d, 0x75, 0x69, + 0x5f, 0x63, 0x61, 0x6c, 0x6c, 0x5f, 0x74, 0x6f, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x63, 0x6c, 0x69, 0x63, 0x6b, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x2a, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x55, 0x49, 0x43, 0x61, 0x6c, 0x6c, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x43, 0x6c, 0x69, 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x18, 0x75, + 0x69, 0x43, 0x61, 0x6c, 0x6c, 0x54, 0x6f, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x69, + 0x63, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x54, 0x0a, 0x11, 0x61, 0x73, 0x73, 0x69, 0x73, + 0x74, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x2b, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, + 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x61, 0x73, 0x73, + 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x79, 0x0a, + 0x21, 0x75, 0x69, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, + 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x18, 0x2c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, + 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x49, 0x6e, 0x74, 0x65, + 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1d, 0x75, 0x69, 0x49, 0x6e, 0x74, + 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x82, 0x01, 0x0a, 0x24, 0x75, 0x69, 0x5f, + 0x69, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x72, 0x6f, + 0x6c, 0x6c, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x18, 0x2d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x49, 0x6e, 0x74, 0x65, 0x67, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x43, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x20, 0x75, 0x69, 0x49, + 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, + 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x53, 0x0a, + 0x13, 0x65, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x18, 0x2e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, + 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x64, 0x69, 0x74, + 0x6f, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, + 0x11, 0x65, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x12, 0x3f, 0x0a, 0x0a, 0x62, 0x6f, 0x74, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x18, 0x2f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x42, 0x6f, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x09, 0x62, 0x6f, 0x74, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x12, 0x7a, 0x0a, 0x1f, 0x75, 0x69, 0x5f, 0x6f, 0x6e, 0x62, 0x6f, 0x61, 0x72, + 0x64, 0x5f, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x61, 0x69, 0x72, 0x65, 0x5f, + 0x73, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x18, 0x30, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, + 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, + 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x51, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x6e, + 0x61, 0x69, 0x72, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, + 0x00, 0x52, 0x1c, 0x75, 0x69, 0x4f, 0x6e, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x51, 0x75, 0x65, 0x73, + 0x74, 0x69, 0x6f, 0x6e, 0x6e, 0x61, 0x69, 0x72, 0x65, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x12, + 0x39, 0x0a, 0x08, 0x62, 0x6f, 0x74, 0x5f, 0x6a, 0x6f, 0x69, 0x6e, 0x18, 0x31, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1c, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x42, 0x6f, 0x74, 0x4a, 0x6f, 0x69, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, + 0x00, 0x52, 0x07, 0x62, 0x6f, 0x74, 0x4a, 0x6f, 0x69, 0x6e, 0x12, 0x51, 0x0a, 0x10, 0x61, 0x73, + 0x73, 0x69, 0x73, 0x74, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x32, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, + 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0f, 0x61, 0x73, + 0x73, 0x69, 0x73, 0x74, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x64, 0x0a, + 0x17, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x63, 0x6f, 0x6e, 0x76, + 0x65, 0x72, 0x73, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x33, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x4e, 0x6f, 0x64, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x14, 0x75, 0x69, 0x44, - 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, - 0x65, 0x12, 0x64, 0x0a, 0x17, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x5f, 0x64, 0x69, 0x72, - 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x73, 0x68, 0x61, 0x72, 0x65, 0x18, 0x44, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x44, 0x69, 0x72, 0x65, 0x63, - 0x74, 0x6f, 0x72, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, - 0x52, 0x15, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, - 0x72, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x12, 0x65, 0x0a, 0x1a, 0x64, 0x65, 0x73, 0x6b, 0x74, - 0x6f, 0x70, 0x5f, 0x63, 0x6c, 0x69, 0x70, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x5f, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x66, 0x65, 0x72, 0x18, 0x45, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, - 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x65, 0x73, - 0x6b, 0x74, 0x6f, 0x70, 0x43, 0x6c, 0x69, 0x70, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x18, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x43, 0x6c, 0x69, - 0x70, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x12, 0x52, - 0x0a, 0x11, 0x74, 0x61, 0x67, 0x5f, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x5f, 0x71, 0x75, - 0x65, 0x72, 0x79, 0x18, 0x46, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x70, 0x72, 0x65, 0x68, - 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x54, 0x41, 0x47, 0x45, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, - 0x00, 0x52, 0x0f, 0x74, 0x61, 0x67, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x51, 0x75, 0x65, - 0x72, 0x79, 0x12, 0x86, 0x01, 0x0a, 0x23, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, - 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x5f, 0x61, 0x75, - 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x47, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x35, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x64, 0x69, 0x74, 0x53, + 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x15, 0x61, 0x73, + 0x73, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x43, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x73, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x65, 0x0a, 0x19, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x61, 0x75, + 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x18, 0x34, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, + 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, + 0x00, 0x52, 0x17, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x6e, 0x0a, 0x1c, 0x66, 0x65, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x35, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, + 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1a, + 0x66, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x5e, 0x0a, 0x15, 0x61, 0x73, + 0x73, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x18, 0x36, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x72, 0x65, 0x68, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x73, + 0x74, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x13, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x48, 0x0a, 0x0d, 0x61, 0x73, + 0x73, 0x69, 0x73, 0x74, 0x5f, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x37, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x73, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0c, 0x61, 0x73, 0x73, 0x69, 0x73, 0x74, 0x41, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x53, 0x0a, 0x13, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x65, + 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x38, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x45, 0x6e, + 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x53, 0x0a, 0x13, 0x6c, 0x69, 0x63, + 0x65, 0x6e, 0x73, 0x65, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x18, 0x39, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4c, + 0x69, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x6c, 0x69, 0x63, + 0x65, 0x6e, 0x73, 0x65, 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x55, + 0x0a, 0x12, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x63, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x18, 0x3a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, 0x65, + 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x48, 0x00, 0x52, 0x10, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x55, 0x0a, 0x12, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, + 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x3b, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x55, 0x0a, 0x12, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x18, 0x3c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, + 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, + 0x00, 0x52, 0x10, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x12, 0x68, 0x0a, 0x19, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, + 0x73, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x18, 0x3d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, + 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x16, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, + 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x68, 0x0a, + 0x19, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x6d, 0x65, 0x6d, + 0x62, 0x65, 0x72, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x3e, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, + 0x65, 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, + 0x16, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, + 0x72, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x68, 0x0a, 0x19, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x64, 0x65, + 0x6c, 0x65, 0x74, 0x65, 0x18, 0x3f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x65, + 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, + 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x16, 0x61, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x12, 0x69, 0x0a, 0x1a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, + 0x5f, 0x67, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x5f, 0x74, 0x6f, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x18, + 0x40, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, + 0x74, 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x48, 0x00, 0x52, 0x16, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, + 0x47, 0x72, 0x61, 0x6e, 0x74, 0x73, 0x54, 0x6f, 0x55, 0x73, 0x65, 0x72, 0x12, 0x81, 0x01, 0x0a, + 0x22, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x65, 0x63, 0x32, + 0x5f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x65, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x41, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x33, 0x2e, 0x70, 0x72, 0x65, 0x68, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x43, 0x32, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, + 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, + 0x52, 0x1e, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x45, 0x63, 0x32, 0x49, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x62, 0x0a, 0x17, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, + 0x64, 0x65, 0x70, 0x6c, 0x6f, 0x79, 0x5f, 0x65, 0x69, 0x63, 0x65, 0x18, 0x42, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x70, + 0x6c, 0x6f, 0x79, 0x45, 0x49, 0x43, 0x45, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x14, + 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x44, 0x65, 0x70, 0x6c, 0x6f, 0x79, + 0x45, 0x69, 0x63, 0x65, 0x12, 0x62, 0x0a, 0x17, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, + 0x76, 0x65, 0x72, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x6e, 0x6f, 0x64, 0x65, 0x18, + 0x43, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, + 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x48, 0x00, 0x52, 0x14, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x64, 0x65, 0x12, 0x64, 0x0a, 0x17, 0x64, 0x65, 0x73, 0x6b, + 0x74, 0x6f, 0x70, 0x5f, 0x64, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x5f, 0x73, 0x68, + 0x61, 0x72, 0x65, 0x18, 0x44, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x65, 0x68, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x65, 0x73, 0x6b, 0x74, + 0x6f, 0x70, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x15, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, + 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x79, 0x53, 0x68, 0x61, 0x72, 0x65, 0x12, 0x65, + 0x0a, 0x1a, 0x64, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x5f, 0x63, 0x6c, 0x69, 0x70, 0x62, 0x6f, + 0x61, 0x72, 0x64, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x18, 0x45, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x44, 0x65, 0x73, 0x6b, 0x74, 0x6f, 0x70, 0x43, 0x6c, 0x69, 0x70, 0x62, + 0x6f, 0x61, 0x72, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x18, 0x64, 0x65, 0x73, + 0x6b, 0x74, 0x6f, 0x70, 0x43, 0x6c, 0x69, 0x70, 0x62, 0x6f, 0x61, 0x72, 0x64, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x66, 0x65, 0x72, 0x12, 0x52, 0x0a, 0x11, 0x74, 0x61, 0x67, 0x5f, 0x65, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x65, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x46, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x24, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x54, 0x41, 0x47, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x51, 0x75, 0x65, 0x72, + 0x79, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0f, 0x74, 0x61, 0x67, 0x45, 0x78, 0x65, + 0x63, 0x75, 0x74, 0x65, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x86, 0x01, 0x0a, 0x23, 0x65, 0x78, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x73, 0x74, 0x6f, + 0x72, 0x61, 0x67, 0x65, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, + 0x65, 0x18, 0x47, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x35, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x41, 0x75, 0x64, 0x69, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x41, 0x75, 0x74, + 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, + 0x52, 0x20, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x64, 0x69, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, - 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x20, 0x65, 0x78, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x64, 0x69, 0x74, 0x53, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x41, - 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x6b, 0x0a, 0x1a, 0x73, - 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x72, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x67, - 0x65, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x48, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x2c, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x47, - 0x65, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x17, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x47, - 0x65, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x4c, 0x0a, 0x0f, 0x61, 0x75, 0x64, 0x69, - 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x72, 0x75, 0x6e, 0x18, 0x49, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x75, 0x6e, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0d, 0x61, 0x75, 0x64, 0x69, 0x74, 0x51, 0x75, - 0x65, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x59, 0x0a, 0x15, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, - 0x65, 0x72, 0x79, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, - 0x4a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, - 0x46, 0x65, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x13, 0x64, 0x69, + 0x74, 0x65, 0x12, 0x6b, 0x0a, 0x1a, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x5f, 0x72, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x5f, 0x67, 0x65, 0x74, 0x5f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, + 0x18, 0x48, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x17, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, + 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, + 0x4c, 0x0a, 0x0f, 0x61, 0x75, 0x64, 0x69, 0x74, 0x5f, 0x71, 0x75, 0x65, 0x72, 0x79, 0x5f, 0x72, + 0x75, 0x6e, 0x18, 0x49, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, + 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x74, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x0d, + 0x61, 0x75, 0x64, 0x69, 0x74, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, 0x75, 0x6e, 0x12, 0x59, 0x0a, + 0x15, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x66, 0x65, 0x74, 0x63, 0x68, + 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x4a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x70, + 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x65, 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x68, 0x0a, 0x19, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, - 0x5f, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x4b, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, - 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x48, 0x00, 0x52, 0x16, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, - 0x65, 0x76, 0x69, 0x65, 0x77, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x68, 0x0a, 0x19, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x65, - 0x77, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, 0x4c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, + 0x74, 0x48, 0x00, 0x52, 0x13, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x46, 0x65, + 0x74, 0x63, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x68, 0x0a, 0x19, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x63, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x4b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, + 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x16, 0x61, 0x63, 0x63, 0x65, + 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x12, 0x68, 0x0a, 0x19, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, + 0x74, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x18, + 0x4c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x48, 0x00, 0x52, 0x16, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, + 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x74, 0x0a, 0x1d, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x76, 0x69, + 0x65, 0x77, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x4d, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, + 0x65, 0x76, 0x69, 0x65, 0x77, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, + 0x63, 0x65, 0x12, 0x62, 0x0a, 0x18, 0x6d, 0x66, 0x61, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, + 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x4e, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4d, 0x46, 0x41, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, + 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x16, + 0x6d, 0x66, 0x61, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x55, 0x0a, 0x12, 0x73, 0x70, 0x69, 0x66, 0x66, 0x65, + 0x5f, 0x73, 0x76, 0x69, 0x64, 0x5f, 0x69, 0x73, 0x73, 0x75, 0x65, 0x64, 0x18, 0x4f, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, + 0x70, 0x68, 0x61, 0x2e, 0x53, 0x50, 0x49, 0x46, 0x46, 0x45, 0x53, 0x56, 0x49, 0x44, 0x49, 0x73, + 0x73, 0x75, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x73, 0x70, 0x69, + 0x66, 0x66, 0x65, 0x53, 0x76, 0x69, 0x64, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x12, 0x5c, 0x0a, + 0x15, 0x6f, 0x6b, 0x74, 0x61, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, + 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x18, 0x50, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, + 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4f, 0x6b, + 0x74, 0x61, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x79, 0x6e, 0x63, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x12, 0x6f, 0x6b, 0x74, 0x61, 0x41, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x5e, 0x0a, 0x15, 0x64, + 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x18, 0x51, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x72, 0x65, + 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, + 0x62, 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x13, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, + 0x55, 0x73, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x12, 0x7f, 0x0a, 0x21, 0x64, + 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x70, 0x65, 0x72, + 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, + 0x18, 0x52, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, + 0x55, 0x73, 0x65, 0x72, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1e, 0x64, 0x61, + 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x84, 0x01, 0x0a, + 0x23, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x18, 0x53, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x70, 0x72, 0x65, + 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, + 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x63, + 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x48, 0x00, 0x52, 0x1f, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x77, 0x0a, 0x21, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, + 0x65, 0x72, 0x5f, 0x6b, 0x75, 0x62, 0x65, 0x5f, 0x65, 0x6b, 0x73, 0x5f, 0x65, 0x6e, 0x72, 0x6f, + 0x6c, 0x6c, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x54, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, - 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x16, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x44, - 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x74, 0x0a, 0x1d, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, - 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x72, 0x65, 0x76, 0x69, 0x65, 0x77, 0x5f, 0x63, 0x6f, 0x6d, 0x70, - 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x4d, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2f, 0x2e, 0x70, - 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x65, 0x77, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x1a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x76, 0x69, 0x65, - 0x77, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x69, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x62, 0x0a, 0x18, 0x6d, - 0x66, 0x61, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x4e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x26, 0x2e, - 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4d, - 0x46, 0x41, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x16, 0x6d, 0x66, 0x61, 0x41, 0x75, 0x74, 0x68, - 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, - 0x55, 0x0a, 0x12, 0x73, 0x70, 0x69, 0x66, 0x66, 0x65, 0x5f, 0x73, 0x76, 0x69, 0x64, 0x5f, 0x69, - 0x73, 0x73, 0x75, 0x65, 0x64, 0x18, 0x4f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x70, 0x72, - 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x50, 0x49, - 0x46, 0x46, 0x45, 0x53, 0x56, 0x49, 0x44, 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x73, 0x70, 0x69, 0x66, 0x66, 0x65, 0x53, 0x76, 0x69, 0x64, - 0x49, 0x73, 0x73, 0x75, 0x65, 0x64, 0x12, 0x5c, 0x0a, 0x15, 0x6f, 0x6b, 0x74, 0x61, 0x5f, 0x61, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x5f, 0x73, 0x79, 0x6e, 0x63, 0x18, - 0x50, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, - 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x4f, 0x6b, 0x74, 0x61, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x79, 0x6e, 0x63, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, - 0x52, 0x12, 0x6f, 0x6b, 0x74, 0x61, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, - 0x53, 0x79, 0x6e, 0x63, 0x12, 0x5e, 0x0a, 0x15, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, - 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x18, 0x51, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, - 0x13, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x64, 0x12, 0x7f, 0x0a, 0x21, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, - 0x5f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, - 0x73, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x64, 0x18, 0x52, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x32, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x55, 0x73, 0x65, 0x72, 0x50, 0x65, 0x72, - 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1e, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x55, - 0x73, 0x65, 0x72, 0x50, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x64, 0x12, 0x84, 0x01, 0x0a, 0x23, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x64, 0x69, 0x73, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x53, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1f, 0x75, 0x69, 0x44, - 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, - 0x63, 0x6f, 0x76, 0x65, 0x72, 0x79, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x77, 0x0a, 0x21, - 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x6b, 0x75, 0x62, 0x65, - 0x5f, 0x65, 0x6b, 0x73, 0x5f, 0x65, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x5f, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x18, 0x54, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x4b, 0x75, 0x62, 0x65, 0x45, 0x4b, 0x53, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1c, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x4b, 0x75, 0x62, 0x65, 0x45, 0x6b, 0x73, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x7d, 0x0a, 0x23, 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, - 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x5f, - 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x55, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1e, 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x12, 0x65, 0x0a, 0x18, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, - 0x72, 0x61, 0x70, 0x68, 0x5f, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x5f, 0x73, 0x63, 0x61, 0x6e, - 0x18, 0x56, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, - 0x61, 0x70, 0x68, 0x47, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x53, 0x63, 0x61, 0x6e, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x15, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, - 0x68, 0x47, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x53, 0x63, 0x61, 0x6e, 0x12, 0x94, 0x01, 0x0a, 0x29, - 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x73, 0x65, 0x63, - 0x72, 0x65, 0x74, 0x73, 0x5f, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, - 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x57, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x39, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x63, 0x72, - 0x65, 0x74, 0x73, 0x53, 0x63, 0x61, 0x6e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, - 0x64, 0x4b, 0x65, 0x79, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x24, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, - 0x53, 0x63, 0x61, 0x6e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x4b, 0x65, - 0x79, 0x73, 0x12, 0x95, 0x01, 0x0a, 0x2a, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, + 0x55, 0x49, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x4b, 0x75, 0x62, 0x65, 0x45, 0x4b, + 0x53, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1c, + 0x75, 0x69, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x4b, 0x75, 0x62, 0x65, 0x45, 0x6b, + 0x73, 0x45, 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x7d, 0x0a, 0x23, + 0x75, 0x69, 0x5f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x63, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x5f, 0x61, 0x70, 0x70, 0x5f, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x18, 0x55, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x70, 0x72, 0x65, 0x68, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x44, 0x69, 0x73, + 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1e, 0x75, 0x69, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x65, 0x0a, 0x18, 0x61, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x67, 0x69, 0x74, 0x6c, + 0x61, 0x62, 0x5f, 0x73, 0x63, 0x61, 0x6e, 0x18, 0x56, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, + 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, + 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x47, 0x69, 0x74, 0x6c, 0x61, 0x62, + 0x53, 0x63, 0x61, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x15, 0x61, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x47, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x53, 0x63, + 0x61, 0x6e, 0x12, 0x94, 0x01, 0x0a, 0x29, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x5f, 0x73, 0x63, 0x61, 0x6e, - 0x5f, 0x73, 0x73, 0x68, 0x5f, 0x70, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, - 0x73, 0x18, 0x58, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, - 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, - 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x53, 0x63, 0x61, 0x6e, 0x53, - 0x53, 0x48, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x24, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, - 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x53, 0x63, 0x61, 0x6e, 0x53, 0x73, 0x68, 0x50, - 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x5c, 0x0a, 0x15, 0x61, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x61, 0x77, 0x73, 0x5f, 0x73, - 0x63, 0x61, 0x6e, 0x18, 0x59, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x70, 0x72, 0x65, 0x68, - 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, - 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x41, 0x57, 0x53, 0x53, 0x63, 0x61, 0x6e, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x48, 0x00, 0x52, 0x12, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, - 0x68, 0x41, 0x77, 0x73, 0x53, 0x63, 0x61, 0x6e, 0x12, 0x7b, 0x0a, 0x20, 0x61, 0x63, 0x63, 0x65, - 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, - 0x70, 0x61, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x18, 0x5a, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x41, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x50, 0x61, 0x74, 0x68, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1c, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, - 0x72, 0x61, 0x70, 0x68, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x50, 0x61, 0x74, 0x68, 0x43, 0x68, - 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x78, 0x0a, 0x1f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, - 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x5f, 0x6a, 0x65, 0x77, 0x65, - 0x6c, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, 0x5b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, + 0x5f, 0x61, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x5f, 0x6b, 0x65, 0x79, 0x73, + 0x18, 0x57, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, + 0x61, 0x70, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x53, 0x63, 0x61, 0x6e, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x48, 0x00, 0x52, 0x24, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, + 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x53, 0x63, 0x61, 0x6e, 0x41, 0x75, 0x74, 0x68, 0x6f, + 0x72, 0x69, 0x7a, 0x65, 0x64, 0x4b, 0x65, 0x79, 0x73, 0x12, 0x95, 0x01, 0x0a, 0x2a, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x73, 0x5f, 0x73, 0x63, 0x61, 0x6e, 0x5f, 0x73, 0x73, 0x68, 0x5f, 0x70, 0x72, 0x69, 0x76, + 0x61, 0x74, 0x65, 0x5f, 0x6b, 0x65, 0x79, 0x73, 0x18, 0x58, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x39, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x72, 0x6f, 0x77, 0x6e, - 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x48, 0x00, 0x52, 0x1b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, - 0x72, 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, - 0x86, 0x01, 0x0a, 0x25, 0x75, 0x69, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, - 0x61, 0x70, 0x68, 0x5f, 0x63, 0x72, 0x6f, 0x77, 0x6e, 0x5f, 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x5f, - 0x64, 0x69, 0x66, 0x66, 0x5f, 0x76, 0x69, 0x65, 0x77, 0x18, 0x5c, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x34, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, - 0x2e, 0x55, 0x49, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x72, - 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x44, 0x69, 0x66, 0x66, 0x56, 0x69, 0x65, 0x77, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1f, 0x75, 0x69, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, + 0x74, 0x73, 0x53, 0x63, 0x61, 0x6e, 0x53, 0x53, 0x48, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, + 0x4b, 0x65, 0x79, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x24, 0x61, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x53, + 0x63, 0x61, 0x6e, 0x53, 0x73, 0x68, 0x50, 0x72, 0x69, 0x76, 0x61, 0x74, 0x65, 0x4b, 0x65, 0x79, + 0x73, 0x12, 0x5c, 0x0a, 0x15, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, + 0x68, 0x5f, 0x61, 0x77, 0x73, 0x5f, 0x73, 0x63, 0x61, 0x6e, 0x18, 0x59, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x27, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, + 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x41, 0x57, 0x53, + 0x53, 0x63, 0x61, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x12, 0x61, 0x63, 0x63, + 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x41, 0x77, 0x73, 0x53, 0x63, 0x61, 0x6e, 0x12, + 0x7b, 0x0a, 0x20, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x5f, 0x63, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x64, 0x18, 0x5a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x31, 0x2e, 0x70, 0x72, 0x65, 0x68, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x50, 0x61, 0x74, 0x68, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1c, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x41, 0x63, 0x63, 0x65, 0x73, + 0x73, 0x50, 0x61, 0x74, 0x68, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x78, 0x0a, 0x1f, + 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x63, 0x72, 0x6f, + 0x77, 0x6e, 0x5f, 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x5f, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x18, + 0x5b, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x30, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, + 0x70, 0x68, 0x43, 0x72, 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1b, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x72, 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, - 0x44, 0x69, 0x66, 0x66, 0x56, 0x69, 0x65, 0x77, 0x12, 0x4c, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x72, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x86, 0x01, 0x0a, 0x25, 0x75, 0x69, 0x5f, 0x61, 0x63, + 0x63, 0x65, 0x73, 0x73, 0x5f, 0x67, 0x72, 0x61, 0x70, 0x68, 0x5f, 0x63, 0x72, 0x6f, 0x77, 0x6e, + 0x5f, 0x6a, 0x65, 0x77, 0x65, 0x6c, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x76, 0x69, 0x65, 0x77, + 0x18, 0x5c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x49, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, + 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x72, 0x6f, 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x44, + 0x69, 0x66, 0x66, 0x56, 0x69, 0x65, 0x77, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x1f, + 0x75, 0x69, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x47, 0x72, 0x61, 0x70, 0x68, 0x43, 0x72, 0x6f, + 0x77, 0x6e, 0x4a, 0x65, 0x77, 0x65, 0x6c, 0x44, 0x69, 0x66, 0x66, 0x56, 0x69, 0x65, 0x77, 0x12, + 0x67, 0x0a, 0x18, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65, 0x63, 0x6f, 0x72, + 0x64, 0x69, 0x6e, 0x67, 0x5f, 0x61, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x5d, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x2b, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, + 0x69, 0x6e, 0x67, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, + 0x52, 0x16, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x63, 0x6f, 0x72, 0x64, 0x69, + 0x6e, 0x67, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x12, 0x4c, 0x0a, 0x0f, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x74, 0x61, 0x73, 0x6b, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x5e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x54, 0x61, 0x73, 0x6b, 0x53, 0x74, 0x61, 0x74, 0x65, @@ -10760,7 +10865,7 @@ var file_prehog_v1alpha_teleport_proto_rawDesc = []byte{ 0x12, 0x19, 0x0a, 0x15, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x1b, 0x0a, 0x17, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x56, 0x45, 0x52, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x41, - 0x42, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x04, 0x2a, 0xc1, 0x02, 0x0a, 0x03, 0x43, 0x54, 0x41, + 0x42, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x04, 0x2a, 0xd4, 0x02, 0x0a, 0x03, 0x43, 0x54, 0x41, 0x12, 0x13, 0x0a, 0x0f, 0x43, 0x54, 0x41, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x54, 0x41, 0x5f, 0x41, 0x55, 0x54, 0x48, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x17, 0x0a, @@ -10780,142 +10885,143 @@ var file_prehog_v1alpha_teleport_proto_rawDesc = []byte{ 0x41, 0x4c, 0x5f, 0x41, 0x55, 0x44, 0x49, 0x54, 0x5f, 0x53, 0x54, 0x4f, 0x52, 0x41, 0x47, 0x45, 0x10, 0x0a, 0x12, 0x16, 0x0a, 0x12, 0x43, 0x54, 0x41, 0x5f, 0x4f, 0x4b, 0x54, 0x41, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x5f, 0x53, 0x59, 0x4e, 0x43, 0x10, 0x0b, 0x12, 0x10, 0x0a, 0x0c, 0x43, 0x54, - 0x41, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x41, 0x5f, 0x49, 0x44, 0x10, 0x0c, 0x2a, 0xe3, 0x08, 0x0a, - 0x15, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x72, 0x6f, - 0x6c, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x27, 0x0a, 0x23, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, - 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, - 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x21, 0x0a, 0x1d, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, - 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x53, 0x4c, 0x41, 0x43, 0x4b, - 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x41, 0x57, - 0x53, 0x5f, 0x4f, 0x49, 0x44, 0x43, 0x10, 0x02, 0x12, 0x25, 0x0a, 0x21, 0x49, 0x4e, 0x54, 0x45, - 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, - 0x49, 0x4e, 0x44, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x52, 0x44, 0x55, 0x54, 0x59, 0x10, 0x03, 0x12, - 0x21, 0x0a, 0x1d, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, - 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x45, 0x4d, 0x41, 0x49, 0x4c, - 0x10, 0x04, 0x12, 0x20, 0x0a, 0x1c, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4a, 0x49, - 0x52, 0x41, 0x10, 0x05, 0x12, 0x23, 0x0a, 0x1f, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, - 0x44, 0x49, 0x53, 0x43, 0x4f, 0x52, 0x44, 0x10, 0x06, 0x12, 0x26, 0x0a, 0x22, 0x49, 0x4e, 0x54, + 0x41, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x41, 0x5f, 0x49, 0x44, 0x10, 0x0c, 0x12, 0x11, 0x0a, 0x0d, + 0x43, 0x54, 0x41, 0x5f, 0x4f, 0x4b, 0x54, 0x41, 0x5f, 0x53, 0x43, 0x49, 0x4d, 0x10, 0x0d, 0x2a, + 0xe3, 0x08, 0x0a, 0x15, 0x49, 0x6e, 0x74, 0x65, 0x67, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x45, + 0x6e, 0x72, 0x6f, 0x6c, 0x6c, 0x4b, 0x69, 0x6e, 0x64, 0x12, 0x27, 0x0a, 0x23, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, - 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x54, 0x54, 0x45, 0x52, 0x4d, 0x4f, 0x53, 0x54, 0x10, - 0x07, 0x12, 0x24, 0x0a, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x53, 0x5f, - 0x54, 0x45, 0x41, 0x4d, 0x53, 0x10, 0x08, 0x12, 0x24, 0x0a, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, + 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x21, 0x0a, 0x1d, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x53, 0x4c, + 0x41, 0x43, 0x4b, 0x10, 0x01, 0x12, 0x24, 0x0a, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, + 0x5f, 0x41, 0x57, 0x53, 0x5f, 0x4f, 0x49, 0x44, 0x43, 0x10, 0x02, 0x12, 0x25, 0x0a, 0x21, 0x49, + 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, + 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x50, 0x41, 0x47, 0x45, 0x52, 0x44, 0x55, 0x54, 0x59, + 0x10, 0x03, 0x12, 0x21, 0x0a, 0x1d, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x45, 0x4d, + 0x41, 0x49, 0x4c, 0x10, 0x04, 0x12, 0x20, 0x0a, 0x1c, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, + 0x5f, 0x4a, 0x49, 0x52, 0x41, 0x10, 0x05, 0x12, 0x23, 0x0a, 0x1f, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, - 0x4e, 0x44, 0x5f, 0x4f, 0x50, 0x53, 0x47, 0x45, 0x4e, 0x49, 0x45, 0x10, 0x09, 0x12, 0x20, 0x0a, - 0x1c, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, - 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4f, 0x4b, 0x54, 0x41, 0x10, 0x0a, 0x12, - 0x20, 0x0a, 0x1c, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, - 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4a, 0x41, 0x4d, 0x46, 0x10, - 0x0b, 0x12, 0x26, 0x0a, 0x22, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, - 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x10, 0x0c, 0x12, 0x35, 0x0a, 0x31, 0x49, 0x4e, 0x54, - 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, - 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, - 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x53, 0x10, 0x0d, - 0x12, 0x2f, 0x0a, 0x2b, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, - 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x43, 0x49, 0x52, 0x43, 0x4c, 0x45, 0x43, 0x49, 0x10, - 0x0e, 0x12, 0x2d, 0x0a, 0x29, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, - 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x47, 0x49, 0x54, 0x4c, 0x41, 0x42, 0x10, 0x0f, - 0x12, 0x2e, 0x0a, 0x2a, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, - 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x4a, 0x45, 0x4e, 0x4b, 0x49, 0x4e, 0x53, 0x10, 0x10, - 0x12, 0x2e, 0x0a, 0x2a, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, - 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x41, 0x4e, 0x53, 0x49, 0x42, 0x4c, 0x45, 0x10, 0x11, - 0x12, 0x2a, 0x0a, 0x26, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, - 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x41, 0x57, 0x53, 0x10, 0x12, 0x12, 0x2a, 0x0a, 0x26, + 0x4e, 0x44, 0x5f, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x52, 0x44, 0x10, 0x06, 0x12, 0x26, 0x0a, 0x22, + 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, + 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x54, 0x54, 0x45, 0x52, 0x4d, 0x4f, + 0x53, 0x54, 0x10, 0x07, 0x12, 0x24, 0x0a, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, + 0x4d, 0x53, 0x5f, 0x54, 0x45, 0x41, 0x4d, 0x53, 0x10, 0x08, 0x12, 0x24, 0x0a, 0x20, 0x49, 0x4e, + 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, + 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4f, 0x50, 0x53, 0x47, 0x45, 0x4e, 0x49, 0x45, 0x10, 0x09, + 0x12, 0x20, 0x0a, 0x1c, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, + 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4f, 0x4b, 0x54, 0x41, + 0x10, 0x0a, 0x12, 0x20, 0x0a, 0x1c, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4a, 0x41, + 0x4d, 0x46, 0x10, 0x0b, 0x12, 0x26, 0x0a, 0x22, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, + 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x10, 0x0c, 0x12, 0x35, 0x0a, 0x31, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, - 0x49, 0x44, 0x5f, 0x47, 0x43, 0x50, 0x10, 0x13, 0x12, 0x2c, 0x0a, 0x28, 0x49, 0x4e, 0x54, 0x45, - 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, - 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x41, - 0x5a, 0x55, 0x52, 0x45, 0x10, 0x14, 0x12, 0x30, 0x0a, 0x2c, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, - 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, - 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x53, 0x50, 0x41, - 0x43, 0x45, 0x4c, 0x49, 0x46, 0x54, 0x10, 0x15, 0x12, 0x31, 0x0a, 0x2d, 0x49, 0x4e, 0x54, 0x45, - 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, - 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x4b, - 0x55, 0x42, 0x45, 0x52, 0x4e, 0x45, 0x54, 0x45, 0x53, 0x10, 0x16, 0x12, 0x24, 0x0a, 0x20, 0x49, + 0x49, 0x44, 0x5f, 0x47, 0x49, 0x54, 0x48, 0x55, 0x42, 0x5f, 0x41, 0x43, 0x54, 0x49, 0x4f, 0x4e, + 0x53, 0x10, 0x0d, 0x12, 0x2f, 0x0a, 0x2b, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, + 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x43, 0x49, 0x52, 0x43, 0x4c, 0x45, + 0x43, 0x49, 0x10, 0x0e, 0x12, 0x2d, 0x0a, 0x29, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, + 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x47, 0x49, 0x54, 0x4c, 0x41, + 0x42, 0x10, 0x0f, 0x12, 0x2e, 0x0a, 0x2a, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, + 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x4a, 0x45, 0x4e, 0x4b, 0x49, 0x4e, + 0x53, 0x10, 0x10, 0x12, 0x2e, 0x0a, 0x2a, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, + 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x41, 0x4e, 0x53, 0x49, 0x42, 0x4c, + 0x45, 0x10, 0x11, 0x12, 0x2a, 0x0a, 0x26, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, + 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x41, 0x57, 0x53, 0x10, 0x12, 0x12, + 0x2a, 0x0a, 0x26, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, + 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, + 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, 0x47, 0x43, 0x50, 0x10, 0x13, 0x12, 0x2c, 0x0a, 0x28, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, - 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x41, 0x5f, 0x49, 0x44, 0x10, - 0x17, 0x12, 0x37, 0x0a, 0x33, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x44, 0x41, 0x54, - 0x41, 0x44, 0x4f, 0x47, 0x5f, 0x49, 0x4e, 0x43, 0x49, 0x44, 0x45, 0x4e, 0x54, 0x5f, 0x4d, 0x41, - 0x4e, 0x41, 0x47, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x18, 0x12, 0x26, 0x0a, 0x22, 0x49, 0x4e, - 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, - 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, 0x4e, 0x4f, 0x57, - 0x10, 0x19, 0x2a, 0x88, 0x01, 0x0a, 0x12, 0x45, 0x64, 0x69, 0x74, 0x6f, 0x72, 0x43, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x24, 0x0a, 0x20, 0x45, 0x44, 0x49, + 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, + 0x44, 0x5f, 0x41, 0x5a, 0x55, 0x52, 0x45, 0x10, 0x14, 0x12, 0x30, 0x0a, 0x2c, 0x49, 0x4e, 0x54, + 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, + 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, 0x44, 0x5f, + 0x53, 0x50, 0x41, 0x43, 0x45, 0x4c, 0x49, 0x46, 0x54, 0x10, 0x15, 0x12, 0x31, 0x0a, 0x2d, 0x49, + 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, + 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x4d, 0x41, 0x43, 0x48, 0x49, 0x4e, 0x45, 0x5f, 0x49, + 0x44, 0x5f, 0x4b, 0x55, 0x42, 0x45, 0x52, 0x4e, 0x45, 0x54, 0x45, 0x53, 0x10, 0x16, 0x12, 0x24, + 0x0a, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, + 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x45, 0x4e, 0x54, 0x52, 0x41, 0x5f, + 0x49, 0x44, 0x10, 0x17, 0x12, 0x37, 0x0a, 0x33, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, + 0x44, 0x41, 0x54, 0x41, 0x44, 0x4f, 0x47, 0x5f, 0x49, 0x4e, 0x43, 0x49, 0x44, 0x45, 0x4e, 0x54, + 0x5f, 0x4d, 0x41, 0x4e, 0x41, 0x47, 0x45, 0x4d, 0x45, 0x4e, 0x54, 0x10, 0x18, 0x12, 0x26, 0x0a, + 0x22, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x52, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x4e, 0x52, + 0x4f, 0x4c, 0x4c, 0x5f, 0x4b, 0x49, 0x4e, 0x44, 0x5f, 0x53, 0x45, 0x52, 0x56, 0x49, 0x43, 0x45, + 0x4e, 0x4f, 0x57, 0x10, 0x19, 0x2a, 0x88, 0x01, 0x0a, 0x12, 0x45, 0x64, 0x69, 0x74, 0x6f, 0x72, + 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x24, 0x0a, 0x20, + 0x45, 0x44, 0x49, 0x54, 0x4f, 0x52, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, + 0x41, 0x54, 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, + 0x10, 0x00, 0x12, 0x25, 0x0a, 0x21, 0x45, 0x44, 0x49, 0x54, 0x4f, 0x52, 0x5f, 0x43, 0x48, 0x41, + 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, + 0x47, 0x52, 0x41, 0x4e, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x25, 0x0a, 0x21, 0x45, 0x44, 0x49, 0x54, 0x4f, 0x52, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, - 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x25, 0x0a, 0x21, 0x45, 0x44, 0x49, 0x54, 0x4f, 0x52, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, - 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x47, 0x52, 0x41, - 0x4e, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x25, 0x0a, 0x21, 0x45, 0x44, 0x49, 0x54, 0x4f, 0x52, - 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x52, - 0x4f, 0x4c, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x02, 0x2a, 0x3f, 0x0a, - 0x07, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x46, 0x45, 0x41, 0x54, - 0x55, 0x52, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x54, 0x52, 0x55, - 0x53, 0x54, 0x45, 0x44, 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x53, 0x10, 0x01, 0x2a, 0xa0, - 0x01, 0x0a, 0x1b, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x63, 0x6f, 0x6d, 0x6d, - 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2d, - 0x0a, 0x29, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x4f, 0x4d, 0x4d, - 0x45, 0x4e, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, - 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x2a, 0x0a, - 0x26, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x4f, 0x4d, 0x4d, 0x45, - 0x4e, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x4e, - 0x4f, 0x54, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x01, 0x12, 0x26, 0x0a, 0x22, 0x46, 0x45, 0x41, - 0x54, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x4f, 0x4d, 0x4d, 0x45, 0x4e, 0x44, 0x41, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x44, 0x4f, 0x4e, 0x45, 0x10, - 0x02, 0x2a, 0x82, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x4c, 0x69, 0x6d, - 0x69, 0x74, 0x12, 0x1d, 0x0a, 0x19, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x5f, 0x4c, 0x49, - 0x4d, 0x49, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x28, 0x0a, 0x24, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x5f, 0x4c, 0x49, 0x4d, - 0x49, 0x54, 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x54, 0x52, 0x55, 0x53, 0x54, 0x5f, - 0x54, 0x45, 0x41, 0x4d, 0x5f, 0x4a, 0x41, 0x4d, 0x46, 0x10, 0x01, 0x12, 0x29, 0x0a, 0x25, 0x4c, - 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x5f, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x5f, 0x44, 0x45, 0x56, - 0x49, 0x43, 0x45, 0x5f, 0x54, 0x52, 0x55, 0x53, 0x54, 0x5f, 0x54, 0x45, 0x41, 0x4d, 0x5f, 0x55, - 0x53, 0x41, 0x47, 0x45, 0x10, 0x02, 0x32, 0xb4, 0x02, 0x0a, 0x18, 0x54, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, 0x65, 0x72, 0x76, - 0x69, 0x63, 0x65, 0x12, 0x5b, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, - 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, - 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, 0x88, 0x02, 0x01, - 0x12, 0x5b, 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, - 0x12, 0x23, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, - 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, + 0x53, 0x5f, 0x52, 0x4f, 0x4c, 0x45, 0x5f, 0x52, 0x45, 0x4d, 0x4f, 0x56, 0x45, 0x44, 0x10, 0x02, + 0x2a, 0x3f, 0x0a, 0x07, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x46, + 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, + 0x54, 0x52, 0x55, 0x53, 0x54, 0x45, 0x44, 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x53, 0x10, + 0x01, 0x2a, 0xa0, 0x01, 0x0a, 0x1b, 0x46, 0x65, 0x61, 0x74, 0x75, 0x72, 0x65, 0x52, 0x65, 0x63, + 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x2d, 0x0a, 0x29, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x43, + 0x4f, 0x4d, 0x4d, 0x45, 0x4e, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, + 0x55, 0x53, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, + 0x12, 0x2a, 0x0a, 0x26, 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x4f, + 0x4d, 0x4d, 0x45, 0x4e, 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, + 0x53, 0x5f, 0x4e, 0x4f, 0x54, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x01, 0x12, 0x26, 0x0a, 0x22, + 0x46, 0x45, 0x41, 0x54, 0x55, 0x52, 0x45, 0x5f, 0x52, 0x45, 0x43, 0x4f, 0x4d, 0x4d, 0x45, 0x4e, + 0x44, 0x41, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x53, 0x54, 0x41, 0x54, 0x55, 0x53, 0x5f, 0x44, 0x4f, + 0x4e, 0x45, 0x10, 0x02, 0x2a, 0x82, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, + 0x4c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x1d, 0x0a, 0x19, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, + 0x5f, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x28, 0x0a, 0x24, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x5f, + 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x5f, 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x54, 0x52, 0x55, + 0x53, 0x54, 0x5f, 0x54, 0x45, 0x41, 0x4d, 0x5f, 0x4a, 0x41, 0x4d, 0x46, 0x10, 0x01, 0x12, 0x29, + 0x0a, 0x25, 0x4c, 0x49, 0x43, 0x45, 0x4e, 0x53, 0x45, 0x5f, 0x4c, 0x49, 0x4d, 0x49, 0x54, 0x5f, + 0x44, 0x45, 0x56, 0x49, 0x43, 0x45, 0x5f, 0x54, 0x52, 0x55, 0x53, 0x54, 0x5f, 0x54, 0x45, 0x41, + 0x4d, 0x5f, 0x55, 0x53, 0x41, 0x47, 0x45, 0x10, 0x02, 0x32, 0xb4, 0x02, 0x0a, 0x18, 0x54, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x53, + 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5b, 0x0a, 0x0b, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x22, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, - 0x0d, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x24, - 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, - 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, - 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0xc9, 0x01, - 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x42, 0x0d, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x50, 0x72, - 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x4b, 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, 0x67, 0x65, 0x6e, 0x2f, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2f, 0x76, 0x31, 0x61, - 0x6c, 0x70, 0x68, 0x61, 0x3b, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x76, 0x31, 0x61, 0x6c, 0x70, - 0x68, 0x61, 0xa2, 0x02, 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, 0x0e, 0x50, 0x72, 0x65, 0x68, 0x6f, - 0x67, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0xca, 0x02, 0x0e, 0x50, 0x72, 0x65, 0x68, - 0x6f, 0x67, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0xe2, 0x02, 0x1a, 0x50, 0x72, 0x65, - 0x68, 0x6f, 0x67, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5c, 0x47, 0x50, 0x42, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0f, 0x50, 0x72, 0x65, 0x68, 0x6f, 0x67, - 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x70, 0x72, 0x65, 0x68, + 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, + 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x03, + 0x88, 0x02, 0x01, 0x12, 0x5b, 0x0a, 0x0c, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x73, 0x12, 0x23, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, + 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, + 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x53, 0x75, 0x62, 0x6d, 0x69, 0x74, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x5e, 0x0a, 0x0d, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x12, 0x24, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, + 0x68, 0x61, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, + 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x2e, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x54, 0x65, + 0x6c, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x42, 0xc9, 0x01, 0x0a, 0x12, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2e, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x42, 0x0d, 0x54, 0x65, 0x6c, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x4b, 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, 0x67, 0x65, 0x6e, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x2f, + 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x3b, 0x70, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x76, 0x31, + 0x61, 0x6c, 0x70, 0x68, 0x61, 0xa2, 0x02, 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, 0x0e, 0x50, 0x72, + 0x65, 0x68, 0x6f, 0x67, 0x2e, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0xca, 0x02, 0x0e, 0x50, + 0x72, 0x65, 0x68, 0x6f, 0x67, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0xe2, 0x02, 0x1a, + 0x50, 0x72, 0x65, 0x68, 0x6f, 0x67, 0x5c, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x5c, 0x47, + 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x0f, 0x50, 0x72, 0x65, + 0x68, 0x6f, 0x67, 0x3a, 0x3a, 0x56, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -10931,7 +11037,7 @@ func file_prehog_v1alpha_teleport_proto_rawDescGZIP() []byte { } var file_prehog_v1alpha_teleport_proto_enumTypes = make([]protoimpl.EnumInfo, 13) -var file_prehog_v1alpha_teleport_proto_msgTypes = make([]protoimpl.MessageInfo, 103) +var file_prehog_v1alpha_teleport_proto_msgTypes = make([]protoimpl.MessageInfo, 104) var file_prehog_v1alpha_teleport_proto_goTypes = []any{ (ResourceKind)(0), // 0: prehog.v1alpha.ResourceKind (UserKind)(0), // 1: prehog.v1alpha.UserKind @@ -11042,15 +11148,16 @@ var file_prehog_v1alpha_teleport_proto_goTypes = []any{ (*OktaAccessListSyncEvent)(nil), // 106: prehog.v1alpha.OktaAccessListSyncEvent (*DatabaseUserCreatedEvent)(nil), // 107: prehog.v1alpha.DatabaseUserCreatedEvent (*DatabaseUserPermissionsUpdateEvent)(nil), // 108: prehog.v1alpha.DatabaseUserPermissionsUpdateEvent - (*UserTaskStateEvent)(nil), // 109: prehog.v1alpha.UserTaskStateEvent - (*SubmitEventRequest)(nil), // 110: prehog.v1alpha.SubmitEventRequest - (*SubmitEventResponse)(nil), // 111: prehog.v1alpha.SubmitEventResponse - (*SubmitEventsRequest)(nil), // 112: prehog.v1alpha.SubmitEventsRequest - (*SubmitEventsResponse)(nil), // 113: prehog.v1alpha.SubmitEventsResponse - (*HelloTeleportRequest)(nil), // 114: prehog.v1alpha.HelloTeleportRequest - (*HelloTeleportResponse)(nil), // 115: prehog.v1alpha.HelloTeleportResponse - (*durationpb.Duration)(nil), // 116: google.protobuf.Duration - (*timestamppb.Timestamp)(nil), // 117: google.protobuf.Timestamp + (*SessionRecordingAccessEvent)(nil), // 109: prehog.v1alpha.SessionRecordingAccessEvent + (*UserTaskStateEvent)(nil), // 110: prehog.v1alpha.UserTaskStateEvent + (*SubmitEventRequest)(nil), // 111: prehog.v1alpha.SubmitEventRequest + (*SubmitEventResponse)(nil), // 112: prehog.v1alpha.SubmitEventResponse + (*SubmitEventsRequest)(nil), // 113: prehog.v1alpha.SubmitEventsRequest + (*SubmitEventsResponse)(nil), // 114: prehog.v1alpha.SubmitEventsResponse + (*HelloTeleportRequest)(nil), // 115: prehog.v1alpha.HelloTeleportRequest + (*HelloTeleportResponse)(nil), // 116: prehog.v1alpha.HelloTeleportResponse + (*durationpb.Duration)(nil), // 117: google.protobuf.Duration + (*timestamppb.Timestamp)(nil), // 118: google.protobuf.Timestamp } var file_prehog_v1alpha_teleport_proto_depIdxs = []int32{ 17, // 0: prehog.v1alpha.ResourceCreateEvent.database:type_name -> prehog.v1alpha.DiscoveredDatabaseMetadata @@ -11058,7 +11165,7 @@ var file_prehog_v1alpha_teleport_proto_depIdxs = []int32{ 20, // 2: prehog.v1alpha.SessionStartEvent.database:type_name -> prehog.v1alpha.SessionStartDatabaseMetadata 21, // 3: prehog.v1alpha.SessionStartEvent.desktop:type_name -> prehog.v1alpha.SessionStartDesktopMetadata 1, // 4: prehog.v1alpha.SessionStartEvent.user_kind:type_name -> prehog.v1alpha.UserKind - 116, // 5: prehog.v1alpha.UserCertificateIssuedEvent.ttl:type_name -> google.protobuf.Duration + 117, // 5: prehog.v1alpha.UserCertificateIssuedEvent.ttl:type_name -> google.protobuf.Duration 1, // 6: prehog.v1alpha.SPIFFESVIDIssuedEvent.user_kind:type_name -> prehog.v1alpha.UserKind 2, // 7: prehog.v1alpha.DiscoverResourceMetadata.resource:type_name -> prehog.v1alpha.DiscoverResource 3, // 8: prehog.v1alpha.DiscoverStepStatus.status:type_name -> prehog.v1alpha.DiscoverStatus @@ -11144,7 +11251,7 @@ var file_prehog_v1alpha_teleport_proto_depIdxs = []int32{ 9, // 88: prehog.v1alpha.LicenseLimitEvent.license_limit:type_name -> prehog.v1alpha.LicenseLimit 20, // 89: prehog.v1alpha.DatabaseUserCreatedEvent.database:type_name -> prehog.v1alpha.SessionStartDatabaseMetadata 20, // 90: prehog.v1alpha.DatabaseUserPermissionsUpdateEvent.database:type_name -> prehog.v1alpha.SessionStartDatabaseMetadata - 117, // 91: prehog.v1alpha.SubmitEventRequest.timestamp:type_name -> google.protobuf.Timestamp + 118, // 91: prehog.v1alpha.SubmitEventRequest.timestamp:type_name -> google.protobuf.Timestamp 13, // 92: prehog.v1alpha.SubmitEventRequest.user_login:type_name -> prehog.v1alpha.UserLoginEvent 15, // 93: prehog.v1alpha.SubmitEventRequest.sso_create:type_name -> prehog.v1alpha.SSOCreateEvent 16, // 94: prehog.v1alpha.SubmitEventRequest.resource_create:type_name -> prehog.v1alpha.ResourceCreateEvent @@ -11234,19 +11341,20 @@ var file_prehog_v1alpha_teleport_proto_depIdxs = []int32{ 99, // 178: prehog.v1alpha.SubmitEventRequest.access_graph_access_path_changed:type_name -> prehog.v1alpha.AccessGraphAccessPathChangedEvent 101, // 179: prehog.v1alpha.SubmitEventRequest.access_graph_crown_jewel_create:type_name -> prehog.v1alpha.AccessGraphCrownJewelCreateEvent 100, // 180: prehog.v1alpha.SubmitEventRequest.ui_access_graph_crown_jewel_diff_view:type_name -> prehog.v1alpha.UIAccessGraphCrownJewelDiffViewEvent - 109, // 181: prehog.v1alpha.SubmitEventRequest.user_task_state:type_name -> prehog.v1alpha.UserTaskStateEvent - 110, // 182: prehog.v1alpha.SubmitEventsRequest.events:type_name -> prehog.v1alpha.SubmitEventRequest - 110, // 183: prehog.v1alpha.TeleportReportingService.SubmitEvent:input_type -> prehog.v1alpha.SubmitEventRequest - 112, // 184: prehog.v1alpha.TeleportReportingService.SubmitEvents:input_type -> prehog.v1alpha.SubmitEventsRequest - 114, // 185: prehog.v1alpha.TeleportReportingService.HelloTeleport:input_type -> prehog.v1alpha.HelloTeleportRequest - 111, // 186: prehog.v1alpha.TeleportReportingService.SubmitEvent:output_type -> prehog.v1alpha.SubmitEventResponse - 113, // 187: prehog.v1alpha.TeleportReportingService.SubmitEvents:output_type -> prehog.v1alpha.SubmitEventsResponse - 115, // 188: prehog.v1alpha.TeleportReportingService.HelloTeleport:output_type -> prehog.v1alpha.HelloTeleportResponse - 186, // [186:189] is the sub-list for method output_type - 183, // [183:186] is the sub-list for method input_type - 183, // [183:183] is the sub-list for extension type_name - 183, // [183:183] is the sub-list for extension extendee - 0, // [0:183] is the sub-list for field type_name + 109, // 181: prehog.v1alpha.SubmitEventRequest.session_recording_access:type_name -> prehog.v1alpha.SessionRecordingAccessEvent + 110, // 182: prehog.v1alpha.SubmitEventRequest.user_task_state:type_name -> prehog.v1alpha.UserTaskStateEvent + 111, // 183: prehog.v1alpha.SubmitEventsRequest.events:type_name -> prehog.v1alpha.SubmitEventRequest + 111, // 184: prehog.v1alpha.TeleportReportingService.SubmitEvent:input_type -> prehog.v1alpha.SubmitEventRequest + 113, // 185: prehog.v1alpha.TeleportReportingService.SubmitEvents:input_type -> prehog.v1alpha.SubmitEventsRequest + 115, // 186: prehog.v1alpha.TeleportReportingService.HelloTeleport:input_type -> prehog.v1alpha.HelloTeleportRequest + 112, // 187: prehog.v1alpha.TeleportReportingService.SubmitEvent:output_type -> prehog.v1alpha.SubmitEventResponse + 114, // 188: prehog.v1alpha.TeleportReportingService.SubmitEvents:output_type -> prehog.v1alpha.SubmitEventsResponse + 116, // 189: prehog.v1alpha.TeleportReportingService.HelloTeleport:output_type -> prehog.v1alpha.HelloTeleportResponse + 187, // [187:190] is the sub-list for method output_type + 184, // [184:187] is the sub-list for method input_type + 184, // [184:184] is the sub-list for extension type_name + 184, // [184:184] is the sub-list for extension extendee + 0, // [0:184] is the sub-list for field type_name } func init() { file_prehog_v1alpha_teleport_proto_init() } @@ -11254,7 +11362,7 @@ func file_prehog_v1alpha_teleport_proto_init() { if File_prehog_v1alpha_teleport_proto != nil { return } - file_prehog_v1alpha_teleport_proto_msgTypes[97].OneofWrappers = []any{ + file_prehog_v1alpha_teleport_proto_msgTypes[98].OneofWrappers = []any{ (*SubmitEventRequest_UserLogin)(nil), (*SubmitEventRequest_SsoCreate)(nil), (*SubmitEventRequest_ResourceCreate)(nil), @@ -11344,6 +11452,7 @@ func file_prehog_v1alpha_teleport_proto_init() { (*SubmitEventRequest_AccessGraphAccessPathChanged)(nil), (*SubmitEventRequest_AccessGraphCrownJewelCreate)(nil), (*SubmitEventRequest_UiAccessGraphCrownJewelDiffView)(nil), + (*SubmitEventRequest_SessionRecordingAccess)(nil), (*SubmitEventRequest_UserTaskState)(nil), } type x struct{} @@ -11352,7 +11461,7 @@ func file_prehog_v1alpha_teleport_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_prehog_v1alpha_teleport_proto_rawDesc, NumEnums: 13, - NumMessages: 103, + NumMessages: 104, NumExtensions: 0, NumServices: 1, }, diff --git a/gen/proto/ts/prehog/v1alpha/teleport_pb.ts b/gen/proto/ts/prehog/v1alpha/teleport_pb.ts index fb7416a23cef0..5b089b63528df 100644 --- a/gen/proto/ts/prehog/v1alpha/teleport_pb.ts +++ b/gen/proto/ts/prehog/v1alpha/teleport_pb.ts @@ -2529,6 +2529,44 @@ export interface DatabaseUserPermissionsUpdateEvent { */ numTablesPermissions: number; } +/** + * SessionRecordingAccessEvent is emitted when the user accesses a session + * recording. + * + * PostHog event: tp.recording.access + * + * @generated from protobuf message prehog.v1alpha.SessionRecordingAccessEvent + */ +export interface SessionRecordingAccessEvent { + /** + * session_type is type of the session, should be + * "ssh"/"k8s"/"db"/"app"/"desktop" (matching the values for + * api/types.SessionKind). + * + * PostHog property: tp.session_type + * + * @generated from protobuf field: string session_type = 1; + */ + sessionType: string; + /** + * user_name is the anonymized Teleport username, 32 bytes (HMAC-SHA-256) + * encoded in base64. + * + * PostHog property: tp.user_name + * + * @generated from protobuf field: string user_name = 2; + */ + userName: string; + /** + * format is the format the session recording was accessed. + * One of text/json/yaml/pty. pty being the interactive session player. + * + * PostHog property: tp.recording.format + * + * @generated from protobuf field: string format = 3; + */ + format: string; +} /** * UserTaskStateEvent is emitted when a UserTask state changes. * This can happen when the Task is created, when it's manually @@ -3141,6 +3179,12 @@ export interface SubmitEventRequest { * @generated from protobuf field: prehog.v1alpha.UIAccessGraphCrownJewelDiffViewEvent ui_access_graph_crown_jewel_diff_view = 92; */ uiAccessGraphCrownJewelDiffView: UIAccessGraphCrownJewelDiffViewEvent; + } | { + oneofKind: "sessionRecordingAccess"; + /** + * @generated from protobuf field: prehog.v1alpha.SessionRecordingAccessEvent session_recording_access = 93; + */ + sessionRecordingAccess: SessionRecordingAccessEvent; } | { oneofKind: "userTaskState"; /** @@ -3554,16 +3598,16 @@ export enum CTA { /** * @generated from protobuf enum value: CTA_ENTRA_ID = 12; */ - CTA_ENTRA_ID = 12 + CTA_ENTRA_ID = 12, + /** + * @generated from protobuf enum value: CTA_OKTA_SCIM = 13; + */ + CTA_OKTA_SCIM = 13 } /** * IntegrationEnrollKind represents the types of integration that * can be enrolled. * - * Note: IntegrationEnrollKind enum must be kept in sync with the values defined - * in api/proto/teleport/usageevents/v1/usageevents.proto. Values 18-25 have - * become out of sync and are manually mapped to each other. - * * @generated from protobuf enum prehog.v1alpha.IntegrationEnrollKind */ export enum IntegrationEnrollKind { @@ -9688,6 +9732,69 @@ class DatabaseUserPermissionsUpdateEvent$Type extends MessageType { + constructor() { + super("prehog.v1alpha.SessionRecordingAccessEvent", [ + { no: 1, name: "session_type", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, + { no: 2, name: "user_name", kind: "scalar", T: 9 /*ScalarType.STRING*/ }, + { no: 3, name: "format", kind: "scalar", T: 9 /*ScalarType.STRING*/ } + ]); + } + create(value?: PartialMessage): SessionRecordingAccessEvent { + const message = globalThis.Object.create((this.messagePrototype!)); + message.sessionType = ""; + message.userName = ""; + message.format = ""; + if (value !== undefined) + reflectionMergePartial(this, message, value); + return message; + } + internalBinaryRead(reader: IBinaryReader, length: number, options: BinaryReadOptions, target?: SessionRecordingAccessEvent): SessionRecordingAccessEvent { + let message = target ?? this.create(), end = reader.pos + length; + while (reader.pos < end) { + let [fieldNo, wireType] = reader.tag(); + switch (fieldNo) { + case /* string session_type */ 1: + message.sessionType = reader.string(); + break; + case /* string user_name */ 2: + message.userName = reader.string(); + break; + case /* string format */ 3: + message.format = reader.string(); + break; + default: + let u = options.readUnknownField; + if (u === "throw") + throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`); + let d = reader.skip(wireType); + if (u !== false) + (u === true ? UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d); + } + } + return message; + } + internalBinaryWrite(message: SessionRecordingAccessEvent, writer: IBinaryWriter, options: BinaryWriteOptions): IBinaryWriter { + /* string session_type = 1; */ + if (message.sessionType !== "") + writer.tag(1, WireType.LengthDelimited).string(message.sessionType); + /* string user_name = 2; */ + if (message.userName !== "") + writer.tag(2, WireType.LengthDelimited).string(message.userName); + /* string format = 3; */ + if (message.format !== "") + writer.tag(3, WireType.LengthDelimited).string(message.format); + let u = options.writeUnknownFields; + if (u !== false) + (u == true ? UnknownFieldHandler.onWrite : u)(this.typeName, message, writer); + return writer; + } +} +/** + * @generated MessageType for protobuf message prehog.v1alpha.SessionRecordingAccessEvent + */ +export const SessionRecordingAccessEvent = new SessionRecordingAccessEvent$Type(); +// @generated message type with reflection information, may provide speed optimized methods class UserTaskStateEvent$Type extends MessageType { constructor() { super("prehog.v1alpha.UserTaskStateEvent", [ @@ -9853,6 +9960,7 @@ class SubmitEventRequest$Type extends MessageType { { no: 90, name: "access_graph_access_path_changed", kind: "message", oneof: "event", T: () => AccessGraphAccessPathChangedEvent }, { no: 91, name: "access_graph_crown_jewel_create", kind: "message", oneof: "event", T: () => AccessGraphCrownJewelCreateEvent }, { no: 92, name: "ui_access_graph_crown_jewel_diff_view", kind: "message", oneof: "event", T: () => UIAccessGraphCrownJewelDiffViewEvent }, + { no: 93, name: "session_recording_access", kind: "message", oneof: "event", T: () => SessionRecordingAccessEvent }, { no: 94, name: "user_task_state", kind: "message", oneof: "event", T: () => UserTaskStateEvent } ]); } @@ -10409,6 +10517,12 @@ class SubmitEventRequest$Type extends MessageType { uiAccessGraphCrownJewelDiffView: UIAccessGraphCrownJewelDiffViewEvent.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).uiAccessGraphCrownJewelDiffView) }; break; + case /* prehog.v1alpha.SessionRecordingAccessEvent session_recording_access */ 93: + message.event = { + oneofKind: "sessionRecordingAccess", + sessionRecordingAccess: SessionRecordingAccessEvent.internalBinaryRead(reader, reader.uint32(), options, (message.event as any).sessionRecordingAccess) + }; + break; case /* prehog.v1alpha.UserTaskStateEvent user_task_state */ 94: message.event = { oneofKind: "userTaskState", @@ -10700,6 +10814,9 @@ class SubmitEventRequest$Type extends MessageType { /* prehog.v1alpha.UIAccessGraphCrownJewelDiffViewEvent ui_access_graph_crown_jewel_diff_view = 92; */ if (message.event.oneofKind === "uiAccessGraphCrownJewelDiffView") UIAccessGraphCrownJewelDiffViewEvent.internalBinaryWrite(message.event.uiAccessGraphCrownJewelDiffView, writer.tag(92, WireType.LengthDelimited).fork(), options).join(); + /* prehog.v1alpha.SessionRecordingAccessEvent session_recording_access = 93; */ + if (message.event.oneofKind === "sessionRecordingAccess") + SessionRecordingAccessEvent.internalBinaryWrite(message.event.sessionRecordingAccess, writer.tag(93, WireType.LengthDelimited).fork(), options).join(); /* prehog.v1alpha.UserTaskStateEvent user_task_state = 94; */ if (message.event.oneofKind === "userTaskState") UserTaskStateEvent.internalBinaryWrite(message.event.userTaskState, writer.tag(94, WireType.LengthDelimited).fork(), options).join(); diff --git a/go.mod b/go.mod index e338706f376e5..0775645a53dd4 100644 --- a/go.mod +++ b/go.mod @@ -76,7 +76,6 @@ require ( github.com/charmbracelet/bubbles v0.20.0 github.com/charmbracelet/bubbletea v1.1.0 github.com/charmbracelet/lipgloss v0.13.0 - github.com/cloudflare/cfssl v1.6.4 github.com/coreos/go-oidc v2.2.1+incompatible // replaced github.com/coreos/go-semver v0.3.1 github.com/creack/pty v1.1.23 @@ -287,6 +286,7 @@ require ( github.com/chai2010/gettext-go v1.0.2 // indirect github.com/charmbracelet/x/ansi v0.2.3 // indirect github.com/charmbracelet/x/term v0.2.0 // indirect + github.com/cloudflare/cfssl v1.6.4 // indirect github.com/cncf/xds/go v0.0.0-20240822171458-6449f94b4d59 // indirect github.com/containerd/containerd v1.7.18 // indirect github.com/containerd/errdefs v0.1.0 // indirect diff --git a/lib/auth/accesspoint/accesspoint.go b/lib/auth/accesspoint/accesspoint.go index 3cf7c1d2e86aa..5b0d4b6084f07 100644 --- a/lib/auth/accesspoint/accesspoint.go +++ b/lib/auth/accesspoint/accesspoint.go @@ -202,6 +202,7 @@ func NewCache(cfg Config) (*cache.Cache, error) { WebToken: cfg.WebToken, WindowsDesktops: cfg.WindowsDesktops, ProvisioningStates: cfg.ProvisioningStates, + IdentityCenter: cfg.IdentityCenter, } return cache.New(cfg.Setup(cacheCfg)) diff --git a/lib/auth/auth.go b/lib/auth/auth.go index bea574ef75039..fa7ae3d46cca0 100644 --- a/lib/auth/auth.go +++ b/lib/auth/auth.go @@ -482,6 +482,7 @@ func NewServer(cfg *InitConfig, opts ...ServerOption) (*Server, error) { SPIFFEFederations: cfg.SPIFFEFederations, StaticHostUser: cfg.StaticHostUsers, ProvisioningStates: cfg.ProvisioningStates, + IdentityCenter: cfg.IdentityCenter, } as := Server{ diff --git a/lib/auth/integration/integrationv1/awsoidc.go b/lib/auth/integration/integrationv1/awsoidc.go index 47ae836ead17c..abc6446662182 100644 --- a/lib/auth/integration/integrationv1/awsoidc.go +++ b/lib/auth/integration/integrationv1/awsoidc.go @@ -157,35 +157,48 @@ func NewAWSOIDCService(cfg *AWSOIDCServiceConfig) (*AWSOIDCService, error) { var _ integrationpb.AWSOIDCServiceServer = (*AWSOIDCService)(nil) -func (s *AWSOIDCService) awsClientReq(ctx context.Context, integrationName, region string) (*awsoidc.AWSClientRequest, error) { +func (s *AWSOIDCService) roleARNForIntegration(ctx context.Context, integrationName string) (string, error) { integration, err := s.integrationService.GetIntegration(ctx, &integrationpb.GetIntegrationRequest{ Name: integrationName, }) if err != nil { - return nil, trace.Wrap(err) + return "", trace.Wrap(err) } if integration.GetSubKind() != types.IntegrationSubKindAWSOIDC { - return nil, trace.BadParameter("integration subkind (%s) mismatch", integration.GetSubKind()) + return "", trace.BadParameter("integration subkind (%s) mismatch", integration.GetSubKind()) } if integration.GetAWSOIDCIntegrationSpec() == nil { - return nil, trace.BadParameter("missing spec fields for %q (%q) integration", integration.GetName(), integration.GetSubKind()) + return "", trace.BadParameter("missing spec fields for %q (%q) integration", integration.GetName(), integration.GetSubKind()) } + return integration.GetAWSOIDCIntegrationSpec().RoleARN, nil +} + +func (s *AWSOIDCService) awsClientReqWithARN(ctx context.Context, integrationName, region, arn string) (*awsoidc.AWSClientRequest, error) { token, err := s.integrationService.generateAWSOIDCTokenWithoutAuthZ(ctx, integrationName) if err != nil { return nil, trace.Wrap(err) } return &awsoidc.AWSClientRequest{ - IntegrationName: integrationName, - Token: token.Token, - RoleARN: integration.GetAWSOIDCIntegrationSpec().RoleARN, - Region: region, + Token: token.Token, + RoleARN: arn, + Region: region, }, nil } +func (s *AWSOIDCService) awsClientReq(ctx context.Context, integrationName, region string) (*awsoidc.AWSClientRequest, error) { + roleARN, err := s.roleARNForIntegration(ctx, integrationName) + if err != nil { + return nil, trace.Wrap(err) + } + + return s.awsClientReqWithARN(ctx, integrationName, region, roleARN) + +} + // ListEICE returns a paginated list of EC2 Instance Connect Endpoints. func (s *AWSOIDCService) ListEICE(ctx context.Context, req *integrationpb.ListEICERequest) (*integrationpb.ListEICEResponse, error) { authCtx, err := s.authorizer.Authorize(ctx) @@ -788,15 +801,20 @@ func (s *AWSOIDCService) Ping(ctx context.Context, req *integrationpb.PingReques return nil, trace.Wrap(err) } - if req.Integration == "" { - return nil, trace.BadParameter("integration is required") - } - - // Instead of asking the user for a region (or storing a default region), we use the sentinel value for the global region. - // This improves the UX, because it is one less input we require from the user. - awsClientReq, err := s.awsClientReq(ctx, req.Integration, awsutils.AWSGlobalRegion) - if err != nil { - return nil, trace.Wrap(err) + var awsClientReq *awsoidc.AWSClientRequest + switch { + case req.GetRoleArn() != "": + awsClientReq, err = s.awsClientReqWithARN(ctx, req.Integration, awsutils.AWSGlobalRegion, req.GetRoleArn()) + if err != nil { + return nil, trace.Wrap(err) + } + case req.GetIntegration() != "": + awsClientReq, err = s.awsClientReq(ctx, req.GetIntegration(), awsutils.AWSGlobalRegion) + if err != nil { + return nil, trace.Wrap(err) + } + default: + return nil, trace.BadParameter("one of arn and integration is required") } awsClient, err := awsoidc.NewPingClient(ctx, awsClientReq) diff --git a/lib/auth/integration/integrationv1/awsoidc_test.go b/lib/auth/integration/integrationv1/awsoidc_test.go index eaa4c5c51fdba..b0ecdc525acd8 100644 --- a/lib/auth/integration/integrationv1/awsoidc_test.go +++ b/lib/auth/integration/integrationv1/awsoidc_test.go @@ -124,11 +124,6 @@ func TestGenerateAWSOIDCToken(t *testing.T) { }) require.NoError(t, err) - t.Run("without integration (v15 and lower clients) returns an error", func(t *testing.T) { - _, err := resourceSvc.GenerateAWSOIDCToken(ctx, &integrationv1.GenerateAWSOIDCTokenRequest{}) - require.Error(t, err) - }) - t.Run("with integration in rpc call but no issuer defined", func(t *testing.T) { resp, err := resourceSvc.GenerateAWSOIDCToken(ctx, &integrationv1.GenerateAWSOIDCTokenRequest{ Integration: integrationNameWithoutIssuer, @@ -323,6 +318,16 @@ func TestRBAC(t *testing.T) { return err }, }, + { + name: "Ping with arn", + fn: func() error { + _, err := awsoidService.Ping(userCtx, &integrationv1.PingRequest{ + Integration: integrationName, + RoleArn: "some-arn", + }) + return err + }, + }, } { t.Run(tt.name, func(t *testing.T) { err := tt.fn() diff --git a/lib/auth/keystore/aws_kms.go b/lib/auth/keystore/aws_kms.go index 3024dad363832..fc27478c3e031 100644 --- a/lib/auth/keystore/aws_kms.go +++ b/lib/auth/keystore/aws_kms.go @@ -57,12 +57,13 @@ const ( ) type awsKMSKeystore struct { - kms kmsClient - clusterName types.ClusterName - awsAccount string - awsRegion string - clock clockwork.Clock - logger *slog.Logger + kms kmsClient + clusterName types.ClusterName + awsAccount string + awsRegion string + multiRegionEnabled bool + clock clockwork.Clock + logger *slog.Logger } func newAWSKMSKeystore(ctx context.Context, cfg *servicecfg.AWSKMSConfig, opts *Options) (*awsKMSKeystore, error) { @@ -99,12 +100,13 @@ func newAWSKMSKeystore(ctx context.Context, cfg *servicecfg.AWSKMSConfig, opts * clock = clockwork.NewRealClock() } return &awsKMSKeystore{ - clusterName: opts.ClusterName, - awsAccount: cfg.AWSAccount, - awsRegion: cfg.AWSRegion, - kms: kmsClient, - clock: clock, - logger: opts.Logger, + clusterName: opts.ClusterName, + awsAccount: cfg.AWSAccount, + awsRegion: cfg.AWSRegion, + multiRegionEnabled: cfg.MultiRegion.Enabled, + kms: kmsClient, + clock: clock, + logger: opts.Logger, }, nil } @@ -126,7 +128,9 @@ func (a *awsKMSKeystore) generateKey(ctx context.Context, algorithm cryptosuites return nil, nil, trace.Wrap(err) } - a.logger.InfoContext(ctx, "Creating new AWS KMS keypair.", "algorithm", alg) + a.logger.InfoContext(ctx, "Creating new AWS KMS keypair.", + slog.Any("algorithm", algorithm), + slog.Bool("multi_region", a.multiRegionEnabled)) output, err := a.kms.CreateKey(ctx, &kms.CreateKeyInput{ Description: aws.String("Teleport CA key"), @@ -138,6 +142,7 @@ func (a *awsKMSKeystore) generateKey(ctx context.Context, algorithm cryptosuites TagValue: aws.String(a.clusterName.GetClusterName()), }, }, + MultiRegion: aws.Bool(a.multiRegionEnabled), }) if err != nil { return nil, nil, trace.Wrap(err) diff --git a/lib/auth/keystore/aws_kms_test.go b/lib/auth/keystore/aws_kms_test.go index b09a3f5a11c86..dd5940b170979 100644 --- a/lib/auth/keystore/aws_kms_test.go +++ b/lib/auth/keystore/aws_kms_test.go @@ -211,6 +211,60 @@ func TestAWSKMS_RetryWhilePending(t *testing.T) { require.Error(t, err) } +// TestMultiRegionKeys asserts that a keystore created with multi-region enabled +// correctly passes this argument to the AWS client. This gives very little real +// coverage since the AWS KMS service here is faked, but at least we know the +// keystore passed the bool to the client correctly. TestBackends and +// TestManager are both able to run with a real AWS KMS client and you can +// confirm the keys are really multi-region there. +func TestMultiRegionKeys(t *testing.T) { + ctx := context.Background() + clock := clockwork.NewFakeClock() + + const pageSize int = 4 + fakeKMS := newFakeAWSKMSService(t, clock, "123456789012", "us-west-2", pageSize) + clusterName, err := services.NewClusterNameWithRandomID(types.ClusterNameSpecV2{ClusterName: "test-cluster"}) + require.NoError(t, err) + opts := &Options{ + ClusterName: clusterName, + HostUUID: "uuid", + AuthPreferenceGetter: &fakeAuthPreferenceGetter{types.SignatureAlgorithmSuite_SIGNATURE_ALGORITHM_SUITE_HSM_V1}, + awsKMSClient: fakeKMS, + awsSTSClient: &fakeAWSSTSClient{ + account: "123456789012", + }, + clockworkOverride: clock, + } + + for _, multiRegion := range []bool{false, true} { + t.Run(fmt.Sprint(multiRegion), func(t *testing.T) { + cfg := servicecfg.KeystoreConfig{ + AWSKMS: servicecfg.AWSKMSConfig{ + AWSAccount: "123456789012", + AWSRegion: "us-west-2", + MultiRegion: struct{ Enabled bool }{ + Enabled: multiRegion, + }, + }, + } + keyStore, err := NewManager(ctx, &cfg, opts) + require.NoError(t, err) + + sshKeyPair, err := keyStore.NewSSHKeyPair(ctx, cryptosuites.UserCASSH) + require.NoError(t, err) + + keyID, err := parseAWSKMSKeyID(sshKeyPair.PrivateKey) + require.NoError(t, err) + + if multiRegion { + assert.Contains(t, keyID.arn, "mrk-") + } else { + assert.NotContains(t, keyID.arn, "mrk-") + } + }) + } +} + type fakeAWSKMSService struct { keys []*fakeAWSKMSKey clock clockwork.Clock @@ -239,6 +293,10 @@ type fakeAWSKMSKey struct { func (f *fakeAWSKMSService) CreateKey(_ context.Context, input *kms.CreateKeyInput, _ ...func(*kms.Options)) (*kms.CreateKeyOutput, error) { id := uuid.NewString() + if aws.ToBool(input.MultiRegion) { + // AWS does this https://docs.aws.amazon.com/kms/latest/developerguide/concepts.html#key-id-key-ARN + id = "mrk-" + id + } a := arn.ARN{ Partition: "aws", Service: "kms", diff --git a/lib/auth/keystore/keystore_test.go b/lib/auth/keystore/keystore_test.go index 0b9e880677762..3780c73296157 100644 --- a/lib/auth/keystore/keystore_test.go +++ b/lib/auth/keystore/keystore_test.go @@ -604,6 +604,7 @@ func newTestPack(ctx context.Context, t *testing.T) *testPack { }) } + // Test with real GCP account if environment is enabled. if config, ok := gcpKMSTestConfig(t); ok { opts := baseOpts opts.kmsClient = nil @@ -621,6 +622,7 @@ func newTestPack(ctx context.Context, t *testing.T) *testPack { }.marshal(), }) } + // Always test with fake GCP client. fakeGCPKMSConfig := servicecfg.KeystoreConfig{ GCPKMS: servicecfg.GCPKMSConfig{ ProtectionLevel: "HSM", @@ -640,61 +642,78 @@ func newTestPack(ctx context.Context, t *testing.T) *testPack { }.marshal(), }) - if config, ok := awsKMSTestConfig(t); ok { - opts := baseOpts - // Unset the fake clients so this test can use the real AWS clients. - opts.awsKMSClient = nil - opts.awsSTSClient = nil - - backend, err := newAWSKMSKeystore(ctx, &config.AWSKMS, &opts) + // Test AWS with and without multi-region keys + for _, multiRegion := range []bool{false, true} { + // Test with real AWS account if environment is enabled. + if config, ok := awsKMSTestConfig(t); ok { + config.AWSKMS.MultiRegion.Enabled = multiRegion + opts := baseOpts + // Unset the fake clients so this test can use the real AWS clients. + opts.awsKMSClient = nil + opts.awsSTSClient = nil + + backend, err := newAWSKMSKeystore(ctx, &config.AWSKMS, &opts) + require.NoError(t, err) + name := "aws_kms" + if multiRegion { + name += "_multi_region" + } + backends = append(backends, &backendDesc{ + name: name, + config: config, + opts: &opts, + backend: backend, + expectedKeyType: types.PrivateKeyType_AWS_KMS, + unusedRawKey: awsKMSKeyID{ + arn: arn.ARN{ + Partition: "aws", + Service: "kms", + Region: config.AWSKMS.AWSRegion, + AccountID: config.AWSKMS.AWSAccount, + Resource: "unused", + }.String(), + account: config.AWSKMS.AWSAccount, + region: config.AWSKMS.AWSRegion, + }.marshal(), + }) + } + + // Always test with fake AWS client. + fakeAWSKMSConfig := servicecfg.KeystoreConfig{ + AWSKMS: servicecfg.AWSKMSConfig{ + AWSAccount: "123456789012", + AWSRegion: "us-west-2", + MultiRegion: struct{ Enabled bool }{ + Enabled: multiRegion, + }, + }, + } + fakeAWSKMSBackend, err := newAWSKMSKeystore(ctx, &fakeAWSKMSConfig.AWSKMS, &baseOpts) require.NoError(t, err) + name := "fake_aws_kms" + if multiRegion { + name += "_multi_region" + } backends = append(backends, &backendDesc{ - name: "aws_kms", - config: config, - opts: &opts, - backend: backend, + name: name, + config: fakeAWSKMSConfig, + opts: &baseOpts, + backend: fakeAWSKMSBackend, expectedKeyType: types.PrivateKeyType_AWS_KMS, unusedRawKey: awsKMSKeyID{ arn: arn.ARN{ Partition: "aws", Service: "kms", - Region: config.AWSKMS.AWSRegion, - AccountID: config.AWSKMS.AWSAccount, + Region: "us-west-2", + AccountID: "123456789012", Resource: "unused", }.String(), - account: config.AWSKMS.AWSAccount, - region: config.AWSKMS.AWSRegion, + account: "123456789012", + region: "us-west-2", }.marshal(), }) } - fakeAWSKMSConfig := servicecfg.KeystoreConfig{ - AWSKMS: servicecfg.AWSKMSConfig{ - AWSAccount: "123456789012", - AWSRegion: "us-west-2", - }, - } - fakeAWSKMSBackend, err := newAWSKMSKeystore(ctx, &fakeAWSKMSConfig.AWSKMS, &baseOpts) - require.NoError(t, err) - backends = append(backends, &backendDesc{ - name: "fake_aws_kms", - config: fakeAWSKMSConfig, - opts: &baseOpts, - backend: fakeAWSKMSBackend, - expectedKeyType: types.PrivateKeyType_AWS_KMS, - unusedRawKey: awsKMSKeyID{ - arn: arn.ARN{ - Partition: "aws", - Service: "kms", - Region: "us-west-2", - AccountID: "123456789012", - Resource: "unused", - }.String(), - account: "123456789012", - region: "us-west-2", - }.marshal(), - }) - return &testPack{ backends: backends, clock: clock, diff --git a/lib/autoupdate/agent/installer.go b/lib/autoupdate/agent/installer.go index e31813866eacf..4da41e8e55509 100644 --- a/lib/autoupdate/agent/installer.go +++ b/lib/autoupdate/agent/installer.go @@ -34,6 +34,7 @@ import ( "text/template" "time" + "github.com/google/renameio/v2" "github.com/gravitational/trace" "github.com/gravitational/teleport/lib/utils" @@ -44,11 +45,33 @@ const ( checksumHexLen = sha256.Size * 2 // bytes to hex ) +var ( + // tgzExtractPaths describes how to extract the Teleport tgz. + // See utils.Extract for more details on how this list is parsed. + // Paths must use tarball-style / separators (not filepath). + tgzExtractPaths = []utils.ExtractPath{ + {Src: "teleport/examples/systemd/teleport.service", Dst: "etc/systemd/teleport.service"}, + {Src: "teleport/examples", Skip: true}, + {Src: "teleport/install", Skip: true}, + {Src: "teleport/README.md", Dst: "share/README.md"}, + {Src: "teleport/CHANGELOG.md", Dst: "share/CHANGELOG.md"}, + {Src: "teleport/VERSION", Dst: "share/VERSION"}, + {Src: "teleport", Dst: "bin"}, + } + + // servicePath contains the path to the Teleport SystemD service within the version directory. + servicePath = filepath.Join("etc", "systemd", "teleport.service") +) + // LocalInstaller manages the creation and removal of installations // of Teleport. type LocalInstaller struct { // InstallDir contains each installation, named by version. InstallDir string + // LinkBinDir contains symlinks to the linked installation's binaries. + LinkBinDir string + // LinkServiceDir contains a symlink to the linked installation's systemd service. + LinkServiceDir string // HTTP is an HTTP client for downloading Teleport. HTTP *http.Client // Log contains a logger. @@ -59,15 +82,32 @@ type LocalInstaller struct { ReservedFreeInstallDisk uint64 } +// ErrLinked is returned when a linked version cannot be removed. +var ErrLinked = errors.New("linked version cannot be removed") + // Remove a Teleport version directory from InstallDir. // This function is idempotent. func (li *LocalInstaller) Remove(ctx context.Context, version string) error { - versionDir := filepath.Join(li.InstallDir, version) - sumPath := filepath.Join(versionDir, checksumType) + // os.RemoveAll is dangerous because it can remove an entire directory tree. + // We must validate the version to ensure that we remove only a single path + // element under the InstallDir, and not InstallDir or its parents. + // versionDir performs these validations. + versionDir, err := li.versionDir(version) + if err != nil { + return trace.Wrap(err) + } + + linked, err := li.isLinked(versionDir) + if err != nil && !errors.Is(err, os.ErrNotExist) { + return trace.Errorf("failed to determine if linked: %w", err) + } + if linked { + return trace.Wrap(ErrLinked) + } // invalidate checksum first, to protect against partially-removed // directory with valid checksum. - err := os.Remove(sumPath) + err = os.Remove(filepath.Join(versionDir, checksumType)) if err != nil && !errors.Is(err, os.ErrNotExist) { return trace.Wrap(err) } @@ -80,7 +120,10 @@ func (li *LocalInstaller) Remove(ctx context.Context, version string) error { // Install a Teleport version directory in InstallDir. // This function is idempotent. func (li *LocalInstaller) Install(ctx context.Context, version, template string, flags InstallFlags) error { - versionDir := filepath.Join(li.InstallDir, version) + versionDir, err := li.versionDir(version) + if err != nil { + return trace.Wrap(err) + } sumPath := filepath.Join(versionDir, checksumType) // generate download URI from template @@ -154,7 +197,7 @@ func (li *LocalInstaller) Install(ctx context.Context, version, template string, return trace.Errorf("failed to extract teleport: %w", err) } // Write the checksum last. This marks the version directory as valid. - err = os.WriteFile(sumPath, []byte(hex.EncodeToString(newSum)), 0755) + err = renameio.WriteFile(sumPath, []byte(hex.EncodeToString(newSum)), 0755) if err != nil { return trace.Errorf("failed to write checksum: %w", err) } @@ -208,6 +251,7 @@ func readChecksum(path string) ([]byte, error) { func (li *LocalInstaller) getChecksum(ctx context.Context, url string) ([]byte, error) { ctx, cancel := context.WithTimeout(ctx, 30*time.Second) defer cancel() + req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil) if err != nil { return nil, trace.Wrap(err) @@ -292,8 +336,7 @@ func (li *LocalInstaller) extract(ctx context.Context, dstDir string, src io.Rea } li.Log.InfoContext(ctx, "Extracting Teleport tarball.", "path", dstDir, "size", max) - // TODO(sclevine): add variadic arg to Extract to extract teleport/ subdir into bin/. - err = utils.Extract(zr, dstDir) + err = utils.Extract(zr, dstDir, tgzExtractPaths...) if err != nil { return trace.Wrap(err) } @@ -315,3 +358,108 @@ func uncompressedSize(f io.Reader) (int64, error) { } return n, nil } + +// List installed versions of Teleport. +func (li *LocalInstaller) List(ctx context.Context) (versions []string, err error) { + entries, err := os.ReadDir(li.InstallDir) + if err != nil { + return nil, trace.Wrap(err) + } + for _, entry := range entries { + if !entry.IsDir() { + continue + } + versions = append(versions, entry.Name()) + } + return versions, nil +} + +// Link the specified version into the system LinkBinDir. +func (li *LocalInstaller) Link(ctx context.Context, version string) error { + versionDir, err := li.versionDir(version) + if err != nil { + return trace.Wrap(err) + } + + // ensure target directories exist before trying to create links + err = os.MkdirAll(li.LinkBinDir, 0755) + if err != nil { + return trace.Wrap(err) + } + err = os.MkdirAll(li.LinkServiceDir, 0755) + if err != nil { + return trace.Wrap(err) + } + + // create binary links + binDir := filepath.Join(versionDir, "bin") + entries, err := os.ReadDir(binDir) + if err != nil { + return trace.Errorf("failed to find Teleport binary directory: %w", err) + } + var linked int + for _, entry := range entries { + if entry.IsDir() { + continue + } + err := renameio.Symlink(filepath.Join(binDir, entry.Name()), filepath.Join(li.LinkBinDir, entry.Name())) + if err != nil { + return trace.Wrap(err) + } + linked++ + } + if linked == 0 { + return trace.Errorf("no binaries available to link") + } + + // create systemd service link + service := filepath.Join(versionDir, servicePath) + err = renameio.Symlink(service, filepath.Join(li.LinkServiceDir, filepath.Base(servicePath))) + if err != nil { + return trace.Wrap(err) + } + return nil +} + +// versionDir returns the storage directory for a Teleport version. +// versionDir will fail if the version cannot be used to construct the directory name. +// For example, it ensures that ".." cannot be provided to return a system directory. +func (li *LocalInstaller) versionDir(version string) (string, error) { + installDir, err := filepath.Abs(li.InstallDir) + if err != nil { + return "", trace.Wrap(err) + } + versionDir := filepath.Join(installDir, version) + if filepath.Dir(versionDir) != filepath.Clean(installDir) { + return "", trace.Errorf("refusing to directory outside of version directory") + } + return versionDir, nil +} + +// isLinked returns true if any binaries or services in versionDir are linked. +// Returns os.ErrNotExist error if the versionDir does not exist. +func (li *LocalInstaller) isLinked(versionDir string) (bool, error) { + binDir := filepath.Join(versionDir, "bin") + entries, err := os.ReadDir(binDir) + if err != nil { + return false, trace.Wrap(err) + } + for _, entry := range entries { + if entry.IsDir() { + continue + } + v, err := os.Readlink(filepath.Join(li.LinkBinDir, entry.Name())) + if err != nil { + continue + } + if filepath.Clean(v) == filepath.Join(binDir, entry.Name()) { + return true, nil + } + } + v, err := os.Readlink(filepath.Join(li.LinkServiceDir, filepath.Base(servicePath))) + if err != nil { + return false, nil + } + return filepath.Clean(v) == + filepath.Join(versionDir, servicePath), nil +} diff --git a/lib/autoupdate/agent/installer_test.go b/lib/autoupdate/agent/installer_test.go index be778f7bcf16a..2602704208855 100644 --- a/lib/autoupdate/agent/installer_test.go +++ b/lib/autoupdate/agent/installer_test.go @@ -40,7 +40,7 @@ import ( "github.com/stretchr/testify/require" ) -func TestTeleportInstaller_Install(t *testing.T) { +func TestLocalInstaller_Install(t *testing.T) { t.Parallel() const version = "new-version" @@ -136,13 +136,15 @@ func TestTeleportInstaller_Install(t *testing.T) { require.Equal(t, expectedPath, dlPath) require.Equal(t, expectedPath+"."+checksumType, shaPath) - teleportVersion, err := os.ReadFile(filepath.Join(dir, version, "teleport")) - require.NoError(t, err) - require.Equal(t, version, string(teleportVersion)) - - tshVersion, err := os.ReadFile(filepath.Join(dir, version, "tsh")) - require.NoError(t, err) - require.Equal(t, version, string(tshVersion)) + for _, p := range []string{ + filepath.Join(dir, version, "etc", "systemd", "teleport.service"), + filepath.Join(dir, version, "bin", "teleport"), + filepath.Join(dir, version, "bin", "tsh"), + } { + v, err := os.ReadFile(p) + require.NoError(t, err) + require.Equal(t, version, string(v)) + } sum, err := os.ReadFile(filepath.Join(dir, version, checksumType)) require.NoError(t, err) @@ -163,8 +165,9 @@ func testTGZ(t *testing.T, version string) (tgz *bytes.Buffer, shasum string) { var files = []struct { Name, Body string }{ - {"teleport", version}, - {"tsh", version}, + {"teleport/examples/systemd/teleport.service", version}, + {"teleport/teleport", version}, + {"teleport/tsh", version}, } for _, file := range files { hdr := &tar.Header{ @@ -187,3 +190,247 @@ func testTGZ(t *testing.T, version string) (tgz *bytes.Buffer, shasum string) { } return &buf, hex.EncodeToString(sha.Sum(nil)) } + +func TestLocalInstaller_Link(t *testing.T) { + t.Parallel() + const version = "new-version" + + tests := []struct { + name string + dirs []string + files []string + + links []string + errMatch string + }{ + { + name: "present", + dirs: []string{ + "bin", + "bin/somedir", + "etc", + "etc/systemd", + "etc/systemd/somedir", + "somedir", + }, + files: []string{ + "bin/teleport", + "bin/tsh", + "bin/tbot", + servicePath, + "README", + }, + + links: []string{ + "bin/teleport", + "bin/tsh", + "bin/tbot", + "lib/systemd/system/teleport.service", + }, + }, + { + name: "no links", + files: []string{"README"}, + dirs: []string{"bin"}, + + errMatch: "no binaries", + }, + { + name: "no bin directory", + files: []string{"README"}, + + errMatch: "binary directory", + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + versionsDir := t.TempDir() + versionDir := filepath.Join(versionsDir, version) + err := os.MkdirAll(versionDir, 0o755) + require.NoError(t, err) + + for _, d := range tt.dirs { + err := os.Mkdir(filepath.Join(versionDir, d), os.ModePerm) + require.NoError(t, err) + } + for _, n := range tt.files { + err := os.WriteFile(filepath.Join(versionDir, n), []byte(filepath.Base(n)), os.ModePerm) + require.NoError(t, err) + } + + linkDir := t.TempDir() + + installer := &LocalInstaller{ + InstallDir: versionsDir, + LinkBinDir: filepath.Join(linkDir, "bin"), + LinkServiceDir: filepath.Join(linkDir, "lib/systemd/system"), + Log: slog.Default(), + } + ctx := context.Background() + err = installer.Link(ctx, version) + if tt.errMatch != "" { + require.Error(t, err) + assert.Contains(t, err.Error(), tt.errMatch) + return + } + require.NoError(t, err) + + for _, link := range tt.links { + v, err := os.ReadFile(filepath.Join(linkDir, link)) + require.NoError(t, err) + require.Equal(t, filepath.Base(link), string(v)) + } + }) + } +} + +func TestLocalInstaller_Remove(t *testing.T) { + t.Parallel() + const version = "existing-version" + + tests := []struct { + name string + dirs []string + files []string + createVersion string + linkedVersion string + removeVersion string + + errMatch string + }{ + { + name: "present", + dirs: []string{"bin", "bin/somedir", "somedir"}, + files: []string{checksumType, "bin/teleport", "bin/tsh", "bin/tbot", "README"}, + createVersion: version, + removeVersion: version, + }, + { + name: "present missing checksum", + dirs: []string{"bin", "bin/somedir", "somedir"}, + files: []string{"bin/teleport", "bin/tsh", "bin/tbot", "README"}, + createVersion: version, + removeVersion: version, + }, + { + name: "not present", + dirs: []string{"bin", "bin/somedir", "somedir"}, + files: []string{checksumType, "bin/teleport", "bin/tsh", "bin/tbot", "README"}, + createVersion: version, + removeVersion: "missing-version", + }, + { + name: "version linked", + dirs: []string{"bin", "bin/somedir", "somedir"}, + files: []string{checksumType, "bin/teleport", "bin/tsh", "bin/tbot", "README"}, + createVersion: version, + linkedVersion: version, + removeVersion: version, + + errMatch: ErrLinked.Error(), + }, + { + name: "version empty", + dirs: []string{"bin", "bin/somedir", "somedir"}, + files: []string{checksumType, "bin/teleport", "bin/tsh", "bin/tbot", "README"}, + createVersion: version, + removeVersion: "", + + errMatch: "outside", + }, + { + name: "version has path", + dirs: []string{"bin", "bin/somedir", "somedir"}, + files: []string{checksumType, "bin/teleport", "bin/tsh", "bin/tbot", "README"}, + createVersion: version, + removeVersion: "one/two", + + errMatch: "outside", + }, + { + name: "version is ..", + dirs: []string{"bin", "bin/somedir", "somedir"}, + files: []string{checksumType, "bin/teleport", "bin/tsh", "bin/tbot", "README"}, + createVersion: version, + removeVersion: "..", + + errMatch: "outside", + }, + { + name: "version is .", + dirs: []string{"bin", "bin/somedir", "somedir"}, + files: []string{checksumType, "bin/teleport", "bin/tsh", "bin/tbot", "README"}, + createVersion: version, + removeVersion: ".", + + errMatch: "outside", + }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + versionsDir := t.TempDir() + versionDir := filepath.Join(versionsDir, tt.createVersion) + err := os.MkdirAll(versionDir, 0o755) + require.NoError(t, err) + + for _, d := range tt.dirs { + err := os.Mkdir(filepath.Join(versionDir, d), os.ModePerm) + require.NoError(t, err) + } + for _, n := range tt.files { + err := os.WriteFile(filepath.Join(versionDir, n), []byte(filepath.Base(n)), os.ModePerm) + require.NoError(t, err) + } + + linkDir := t.TempDir() + + installer := &LocalInstaller{ + InstallDir: versionsDir, + LinkBinDir: linkDir, + LinkServiceDir: linkDir, + Log: slog.Default(), + } + ctx := context.Background() + + if tt.linkedVersion != "" { + err = installer.Link(ctx, tt.linkedVersion) + require.NoError(t, err) + } + err = installer.Remove(ctx, tt.removeVersion) + if tt.errMatch != "" { + require.Error(t, err) + assert.Contains(t, err.Error(), tt.errMatch) + return + } + require.NoError(t, err) + _, err = os.Stat(filepath.Join(versionDir, "bin", tt.removeVersion)) + require.ErrorIs(t, err, os.ErrNotExist) + }) + } +} + +func TestLocalInstaller_List(t *testing.T) { + installDir := t.TempDir() + versions := []string{"v1", "v2"} + + for _, d := range versions { + err := os.Mkdir(filepath.Join(installDir, d), os.ModePerm) + require.NoError(t, err) + } + for _, n := range []string{"file1", "file2"} { + err := os.WriteFile(filepath.Join(installDir, n), []byte(filepath.Base(n)), os.ModePerm) + require.NoError(t, err) + } + installer := &LocalInstaller{ + InstallDir: installDir, + Log: slog.Default(), + } + ctx := context.Background() + versions, err := installer.List(ctx) + require.NoError(t, err) + require.Equal(t, []string{"v1", "v2"}, versions) +} diff --git a/lib/autoupdate/agent/testdata/TestUpdater_Disable/already_disabled.golden b/lib/autoupdate/agent/testdata/TestUpdater_Disable/already_disabled.golden index e8773a6d88b7f..2ddb840b01794 100644 --- a/lib/autoupdate/agent/testdata/TestUpdater_Disable/already_disabled.golden +++ b/lib/autoupdate/agent/testdata/TestUpdater_Disable/already_disabled.golden @@ -7,3 +7,4 @@ spec: enabled: false status: active_version: "" + backup_version: "" diff --git a/lib/autoupdate/agent/testdata/TestUpdater_Disable/enabled.golden b/lib/autoupdate/agent/testdata/TestUpdater_Disable/enabled.golden index e8773a6d88b7f..2ddb840b01794 100644 --- a/lib/autoupdate/agent/testdata/TestUpdater_Disable/enabled.golden +++ b/lib/autoupdate/agent/testdata/TestUpdater_Disable/enabled.golden @@ -7,3 +7,4 @@ spec: enabled: false status: active_version: "" + backup_version: "" diff --git a/lib/autoupdate/agent/testdata/TestUpdater_Enable/already_enabled.golden b/lib/autoupdate/agent/testdata/TestUpdater_Enable/already_enabled.golden index e03f369eb1017..9dd03b7888da4 100644 --- a/lib/autoupdate/agent/testdata/TestUpdater_Enable/already_enabled.golden +++ b/lib/autoupdate/agent/testdata/TestUpdater_Enable/already_enabled.golden @@ -7,3 +7,4 @@ spec: enabled: true status: active_version: 16.3.0 + backup_version: old-version diff --git a/lib/autoupdate/agent/testdata/TestUpdater_Enable/backup_version_kept_for_validation.golden b/lib/autoupdate/agent/testdata/TestUpdater_Enable/backup_version_kept_for_validation.golden new file mode 100644 index 0000000000000..77829fb91706a --- /dev/null +++ b/lib/autoupdate/agent/testdata/TestUpdater_Enable/backup_version_kept_for_validation.golden @@ -0,0 +1,10 @@ +version: v1 +kind: update_config +spec: + proxy: localhost + group: "" + url_template: "" + enabled: true +status: + active_version: 16.3.0 + backup_version: backup-version diff --git a/lib/autoupdate/agent/testdata/TestUpdater_Enable/backup_version_removed_on_install.golden b/lib/autoupdate/agent/testdata/TestUpdater_Enable/backup_version_removed_on_install.golden new file mode 100644 index 0000000000000..9dd03b7888da4 --- /dev/null +++ b/lib/autoupdate/agent/testdata/TestUpdater_Enable/backup_version_removed_on_install.golden @@ -0,0 +1,10 @@ +version: v1 +kind: update_config +spec: + proxy: localhost + group: "" + url_template: "" + enabled: true +status: + active_version: 16.3.0 + backup_version: old-version diff --git a/lib/autoupdate/agent/testdata/TestUpdater_Enable/config_does_not_exist.golden b/lib/autoupdate/agent/testdata/TestUpdater_Enable/config_does_not_exist.golden index e03f369eb1017..d9e09a2c95d71 100644 --- a/lib/autoupdate/agent/testdata/TestUpdater_Enable/config_does_not_exist.golden +++ b/lib/autoupdate/agent/testdata/TestUpdater_Enable/config_does_not_exist.golden @@ -7,3 +7,4 @@ spec: enabled: true status: active_version: 16.3.0 + backup_version: "" diff --git a/lib/autoupdate/agent/testdata/TestUpdater_Enable/config_from_file.golden b/lib/autoupdate/agent/testdata/TestUpdater_Enable/config_from_file.golden index b172d858bc55a..61e41f76ca234 100644 --- a/lib/autoupdate/agent/testdata/TestUpdater_Enable/config_from_file.golden +++ b/lib/autoupdate/agent/testdata/TestUpdater_Enable/config_from_file.golden @@ -7,3 +7,4 @@ spec: enabled: true status: active_version: 16.3.0 + backup_version: old-version diff --git a/lib/autoupdate/agent/testdata/TestUpdater_Enable/config_from_user.golden b/lib/autoupdate/agent/testdata/TestUpdater_Enable/config_from_user.golden index bb9ce8b9d8fa8..c1f0fd166b497 100644 --- a/lib/autoupdate/agent/testdata/TestUpdater_Enable/config_from_user.golden +++ b/lib/autoupdate/agent/testdata/TestUpdater_Enable/config_from_user.golden @@ -7,3 +7,4 @@ spec: enabled: true status: active_version: new-version + backup_version: old-version diff --git a/lib/autoupdate/agent/testdata/TestUpdater_Enable/version_already_installed.golden b/lib/autoupdate/agent/testdata/TestUpdater_Enable/version_already_installed.golden index e03f369eb1017..d9e09a2c95d71 100644 --- a/lib/autoupdate/agent/testdata/TestUpdater_Enable/version_already_installed.golden +++ b/lib/autoupdate/agent/testdata/TestUpdater_Enable/version_already_installed.golden @@ -7,3 +7,4 @@ spec: enabled: true status: active_version: 16.3.0 + backup_version: "" diff --git a/lib/autoupdate/agent/updater.go b/lib/autoupdate/agent/updater.go index 59df5f0b3ba85..ade0704607cb9 100644 --- a/lib/autoupdate/agent/updater.go +++ b/lib/autoupdate/agent/updater.go @@ -86,6 +86,8 @@ type UpdateSpec struct { type UpdateStatus struct { // ActiveVersion is the currently active Teleport version. ActiveVersion string `yaml:"active_version"` + // BackupVersion is the last working version of Teleport. + BackupVersion string `yaml:"backup_version"` } // NewLocalUpdater returns a new Updater that auto-updates local @@ -112,15 +114,23 @@ func NewLocalUpdater(cfg LocalUpdaterConfig) (*Updater, error) { if cfg.Log == nil { cfg.Log = slog.Default() } + if cfg.LinkDir == "" { + cfg.LinkDir = "/usr/local" + } + if cfg.VersionsDir == "" { + cfg.VersionsDir = filepath.Join(libdefaults.DataDir, "versions") + } return &Updater{ Log: cfg.Log, Pool: certPool, InsecureSkipVerify: cfg.InsecureSkipVerify, ConfigPath: filepath.Join(cfg.VersionsDir, updateConfigName), Installer: &LocalInstaller{ - InstallDir: cfg.VersionsDir, - HTTP: client, - Log: cfg.Log, + InstallDir: cfg.VersionsDir, + LinkBinDir: filepath.Join(cfg.LinkDir, "bin"), + LinkServiceDir: filepath.Join(cfg.LinkDir, "lib", "systemd", "system"), + HTTP: client, + Log: cfg.Log, ReservedFreeTmpDisk: reservedFreeDisk, ReservedFreeInstallDisk: reservedFreeDisk, @@ -140,6 +150,8 @@ type LocalUpdaterConfig struct { DownloadTimeout time.Duration // VersionsDir for installing Teleport (usually /var/lib/teleport/versions). VersionsDir string + // LinkDir for installing Teleport (usually /usr/local). + LinkDir string } // Updater implements the agent-local logic for Teleport agent auto-updates. @@ -161,6 +173,11 @@ type Installer interface { // Install the Teleport agent at version from the download template. // This function must be idempotent. Install(ctx context.Context, version, template string, flags InstallFlags) error + // Link the Teleport agent at version into the system location. + // This function must be idempotent. + Link(ctx context.Context, version string) error + // List the installed versions of Teleport. + List(ctx context.Context) (versions []string, err error) // Remove the Teleport agent at version. // This function must be idempotent. Remove(ctx context.Context, version string) error @@ -242,6 +259,19 @@ func (u *Updater) Enable(ctx context.Context, override OverrideConfig) error { if desiredVersion == "" { return trace.Errorf("agent version not available from Teleport cluster") } + switch cfg.Status.BackupVersion { + case "", desiredVersion, cfg.Status.ActiveVersion: + default: + if desiredVersion == cfg.Status.ActiveVersion { + // Keep backup version if we are only verifying active version + break + } + err := u.Installer.Remove(ctx, cfg.Status.BackupVersion) + if err != nil { + // this could happen if it was already removed due to a failed installation + u.Log.WarnContext(ctx, "Failed to remove backup version of Teleport before new install.", "error", err) + } + } // If the active version and target don't match, kick off upgrade. template := cfg.Spec.URLTemplate if template == "" { @@ -249,14 +279,30 @@ func (u *Updater) Enable(ctx context.Context, override OverrideConfig) error { } err = u.Installer.Install(ctx, desiredVersion, template, 0) // TODO(sclevine): add web API for flags if err != nil { - return trace.Wrap(err) + return trace.Errorf("failed to install: %w", err) + } + err = u.Installer.Link(ctx, desiredVersion) + if err != nil { + return trace.Errorf("failed to link: %w", err) } if cfg.Status.ActiveVersion != desiredVersion { + cfg.Status.BackupVersion = cfg.Status.ActiveVersion + cfg.Status.ActiveVersion = desiredVersion u.Log.InfoContext(ctx, "Target version successfully installed.", "version", desiredVersion) } else { u.Log.InfoContext(ctx, "Target version successfully validated.", "version", desiredVersion) } - cfg.Status.ActiveVersion = desiredVersion + if v := cfg.Status.BackupVersion; v != "" { + u.Log.InfoContext(ctx, "Backup version set.", "version", v) + } + + versions, err := u.Installer.List(ctx) + if err != nil { + return trace.Errorf("failed to list installed versions: %w", err) + } + if n := len(versions); n > 2 { + u.Log.WarnContext(ctx, "More than 2 versions of Teleport installed. Version directory may need cleanup to save space.", "count", n) + } // Always write the configuration file if enable succeeds. if err := u.writeConfig(u.ConfigPath, cfg); err != nil { diff --git a/lib/autoupdate/agent/updater_test.go b/lib/autoupdate/agent/updater_test.go index 6568fbaede9e2..d6d0128316c20 100644 --- a/lib/autoupdate/agent/updater_test.go +++ b/lib/autoupdate/agent/updater_test.go @@ -130,6 +130,7 @@ func TestUpdater_Enable(t *testing.T) { userCfg OverrideConfig installErr error + removedVersion string installedVersion string installedTemplate string errMatch string @@ -221,6 +222,34 @@ func TestUpdater_Enable(t *testing.T) { installedVersion: "16.3.0", installedTemplate: cdnURITemplate, }, + { + name: "backup version removed on install", + cfg: &UpdateConfig{ + Version: updateConfigVersion, + Kind: updateConfigKind, + Status: UpdateStatus{ + ActiveVersion: "old-version", + BackupVersion: "backup-version", + }, + }, + installedVersion: "16.3.0", + installedTemplate: cdnURITemplate, + removedVersion: "backup-version", + }, + { + name: "backup version kept for validation", + cfg: &UpdateConfig{ + Version: updateConfigVersion, + Kind: updateConfigKind, + Status: UpdateStatus{ + ActiveVersion: "16.3.0", + BackupVersion: "backup-version", + }, + }, + installedVersion: "16.3.0", + installedTemplate: cdnURITemplate, + removedVersion: "", + }, { name: "config does not exist", installedVersion: "16.3.0", @@ -263,13 +292,29 @@ func TestUpdater_Enable(t *testing.T) { }) require.NoError(t, err) - var installedVersion, installedTemplate string + var ( + installedVersion string + installedTemplate string + linkedVersion string + removedVersion string + ) updater.Installer = &testInstaller{ FuncInstall: func(_ context.Context, version, template string, _ InstallFlags) error { installedVersion = version installedTemplate = template return tt.installErr }, + FuncLink: func(_ context.Context, version string) error { + linkedVersion = version + return nil + }, + FuncList: func(_ context.Context) (versions []string, err error) { + return []string{"old"}, nil + }, + FuncRemove: func(_ context.Context, version string) error { + removedVersion = version + return nil + }, } ctx := context.Background() @@ -282,6 +327,8 @@ func TestUpdater_Enable(t *testing.T) { require.NoError(t, err) require.Equal(t, tt.installedVersion, installedVersion) require.Equal(t, tt.installedTemplate, installedTemplate) + require.Equal(t, tt.installedVersion, linkedVersion) + require.Equal(t, tt.removedVersion, removedVersion) data, err := os.ReadFile(cfgPath) require.NoError(t, err) @@ -304,6 +351,8 @@ func blankTestAddr(s []byte) []byte { type testInstaller struct { FuncInstall func(ctx context.Context, version, template string, flags InstallFlags) error FuncRemove func(ctx context.Context, version string) error + FuncLink func(ctx context.Context, version string) error + FuncList func(ctx context.Context) (versions []string, err error) } func (ti *testInstaller) Install(ctx context.Context, version, template string, flags InstallFlags) error { @@ -313,3 +362,11 @@ func (ti *testInstaller) Install(ctx context.Context, version, template string, func (ti *testInstaller) Remove(ctx context.Context, version string) error { return ti.FuncRemove(ctx, version) } + +func (ti *testInstaller) Link(ctx context.Context, version string) error { + return ti.FuncLink(ctx, version) +} + +func (ti *testInstaller) List(ctx context.Context) (versions []string, err error) { + return ti.FuncList(ctx) +} diff --git a/lib/cache/cache.go b/lib/cache/cache.go index 40c71ca1094e6..e9273cfb0e8a8 100644 --- a/lib/cache/cache.go +++ b/lib/cache/cache.go @@ -193,6 +193,9 @@ func ForAuth(cfg Config) Config { {Kind: types.KindAutoUpdateAgentRollout}, {Kind: types.KindUserTask}, {Kind: types.KindProvisioningPrincipalState}, + {Kind: types.KindIdentityCenterAccount}, + {Kind: types.KindIdentityCenterPrincipalAssignment}, + {Kind: types.KindIdentityCenterAccountAssignment}, } cfg.QueueSize = defaults.AuthQueueSize // We don't want to enable partial health for auth cache because auth uses an event stream @@ -544,6 +547,7 @@ type Cache struct { spiffeFederationCache spiffeFederationCacher staticHostUsersCache *local.StaticHostUserService provisioningStatesCache *local.ProvisioningStateService + identityCenterCache *local.IdentityCenterService // closed indicates that the cache has been closed closed atomic.Bool @@ -775,6 +779,9 @@ type Config struct { // ProvisioningStates is the upstream ProvisioningStates service that we're // caching ProvisioningStates services.ProvisioningStates + + // IdentityCenter is the upstream Identity Center service that we're caching + IdentityCenter services.IdentityCenter } // CheckAndSetDefaults checks parameters and sets default values @@ -1007,6 +1014,13 @@ func New(config Config) (*Cache, error) { return nil, trace.Wrap(err) } + identityCenterCache, err := local.NewIdentityCenterService(local.IdentityCenterServiceConfig{ + Backend: config.Backend}) + if err != nil { + cancel() + return nil, trace.Wrap(err) + } + cs := &Cache{ ctx: ctx, cancel: cancel, @@ -1053,6 +1067,7 @@ func New(config Config) (*Cache, error) { spiffeFederationCache: spiffeFederationCache, staticHostUsersCache: staticHostUserCache, provisioningStatesCache: provisioningStatesCache, + identityCenterCache: identityCenterCache, Logger: log.WithFields(log.Fields{ teleport.ComponentKey: config.Component, }), diff --git a/lib/cache/cache_test.go b/lib/cache/cache_test.go index 1139a68ecaeb4..9c11b4f3a1145 100644 --- a/lib/cache/cache_test.go +++ b/lib/cache/cache_test.go @@ -139,6 +139,7 @@ type testPack struct { staticHostUsers services.StaticHostUser autoUpdateService services.AutoUpdateService provisioningStates services.ProvisioningStates + identityCenter services.IdentityCenter } // testFuncs are functions to support testing an object in a cache. @@ -387,6 +388,13 @@ func newPackWithoutCache(dir string, opts ...packOption) (*testPack, error) { return nil, trace.Wrap(err) } + p.identityCenter, err = local.NewIdentityCenterService(local.IdentityCenterServiceConfig{ + Backend: p.backend, + }) + if err != nil { + return nil, trace.Wrap(err) + } + return p, nil } @@ -438,6 +446,7 @@ func newPack(dir string, setupConfig func(c Config) Config, opts ...packOption) StaticHostUsers: p.staticHostUsers, AutoUpdateService: p.autoUpdateService, ProvisioningStates: p.provisioningStates, + IdentityCenter: p.identityCenter, MaxRetryPeriod: 200 * time.Millisecond, EventsC: p.eventsC, })) @@ -848,6 +857,7 @@ func TestCompletenessInit(t *testing.T) { AutoUpdateService: p.autoUpdateService, ProvisioningStates: p.provisioningStates, MaxRetryPeriod: 200 * time.Millisecond, + IdentityCenter: p.identityCenter, EventsC: p.eventsC, })) require.NoError(t, err) @@ -929,6 +939,7 @@ func TestCompletenessReset(t *testing.T) { StaticHostUsers: p.staticHostUsers, AutoUpdateService: p.autoUpdateService, ProvisioningStates: p.provisioningStates, + IdentityCenter: p.identityCenter, MaxRetryPeriod: 200 * time.Millisecond, EventsC: p.eventsC, })) @@ -1137,6 +1148,7 @@ func TestListResources_NodesTTLVariant(t *testing.T) { StaticHostUsers: p.staticHostUsers, AutoUpdateService: p.autoUpdateService, ProvisioningStates: p.provisioningStates, + IdentityCenter: p.identityCenter, MaxRetryPeriod: 200 * time.Millisecond, EventsC: p.eventsC, neverOK: true, // ensure reads are never healthy @@ -1230,6 +1242,7 @@ func initStrategy(t *testing.T) { StaticHostUsers: p.staticHostUsers, AutoUpdateService: p.autoUpdateService, ProvisioningStates: p.provisioningStates, + IdentityCenter: p.identityCenter, MaxRetryPeriod: 200 * time.Millisecond, EventsC: p.eventsC, })) @@ -3002,7 +3015,7 @@ func testResources153[T types.Resource153](t *testing.T, p *testPack, funcs test } assert.Empty(collect, cmp.Diff(expected, out, cmpOpts...)) - }, 2*time.Second, 250*time.Millisecond) + }, 2*time.Second, 10*time.Millisecond) } // Check that the resource is now in the backend. @@ -3426,71 +3439,74 @@ func TestCacheWatchKindExistsInEvents(t *testing.T) { } events := map[string]types.Resource{ - types.KindCertAuthority: &types.CertAuthorityV2{}, - types.KindClusterName: &types.ClusterNameV2{}, - types.KindClusterAuditConfig: types.DefaultClusterAuditConfig(), - types.KindClusterNetworkingConfig: types.DefaultClusterNetworkingConfig(), - types.KindClusterAuthPreference: types.DefaultAuthPreference(), - types.KindSessionRecordingConfig: types.DefaultSessionRecordingConfig(), - types.KindUIConfig: &types.UIConfigV1{}, - types.KindStaticTokens: &types.StaticTokensV2{}, - types.KindToken: &types.ProvisionTokenV2{}, - types.KindUser: &types.UserV2{}, - types.KindRole: &types.RoleV6{Version: types.V4}, - types.KindNamespace: &types.Namespace{}, - types.KindNode: &types.ServerV2{}, - types.KindProxy: &types.ServerV2{}, - types.KindAuthServer: &types.ServerV2{}, - types.KindReverseTunnel: &types.ReverseTunnelV2{}, - types.KindTunnelConnection: &types.TunnelConnectionV2{}, - types.KindAccessRequest: &types.AccessRequestV3{}, - types.KindAppServer: &types.AppServerV3{}, - types.KindApp: &types.AppV3{}, - types.KindWebSession: &types.WebSessionV2{SubKind: types.KindWebSession}, - types.KindAppSession: &types.WebSessionV2{SubKind: types.KindAppSession}, - types.KindSnowflakeSession: &types.WebSessionV2{SubKind: types.KindSnowflakeSession}, - types.KindSAMLIdPSession: &types.WebSessionV2{SubKind: types.KindSAMLIdPServiceProvider}, - types.KindWebToken: &types.WebTokenV3{}, - types.KindRemoteCluster: &types.RemoteClusterV3{}, - types.KindKubeServer: &types.KubernetesServerV3{}, - types.KindDatabaseService: &types.DatabaseServiceV1{}, - types.KindDatabaseServer: &types.DatabaseServerV3{}, - types.KindDatabase: &types.DatabaseV3{}, - types.KindNetworkRestrictions: &types.NetworkRestrictionsV4{}, - types.KindLock: &types.LockV2{}, - types.KindWindowsDesktopService: &types.WindowsDesktopServiceV3{}, - types.KindWindowsDesktop: &types.WindowsDesktopV3{}, - types.KindDynamicWindowsDesktop: &types.DynamicWindowsDesktopV1{}, - types.KindInstaller: &types.InstallerV1{}, - types.KindKubernetesCluster: &types.KubernetesClusterV3{}, - types.KindSAMLIdPServiceProvider: &types.SAMLIdPServiceProviderV1{}, - types.KindUserGroup: &types.UserGroupV1{}, - types.KindOktaImportRule: &types.OktaImportRuleV1{}, - types.KindOktaAssignment: &types.OktaAssignmentV1{}, - types.KindIntegration: &types.IntegrationV1{}, - types.KindDiscoveryConfig: newDiscoveryConfig(t, "discovery-config"), - types.KindHeadlessAuthentication: &types.HeadlessAuthentication{}, - types.KindUserLoginState: newUserLoginState(t, "user-login-state"), - types.KindAuditQuery: newAuditQuery(t, "audit-query"), - types.KindSecurityReport: newSecurityReport(t, "security-report"), - types.KindSecurityReportState: newSecurityReport(t, "security-report-state"), - types.KindAccessList: newAccessList(t, "access-list", clock), - types.KindAccessListMember: newAccessListMember(t, "access-list", "member"), - types.KindAccessListReview: newAccessListReview(t, "access-list", "review"), - types.KindKubeWaitingContainer: newKubeWaitingContainer(t), - types.KindNotification: types.Resource153ToLegacy(newUserNotification(t, "test")), - types.KindGlobalNotification: types.Resource153ToLegacy(newGlobalNotification(t, "test")), - types.KindAccessMonitoringRule: types.Resource153ToLegacy(newAccessMonitoringRule(t)), - types.KindCrownJewel: types.Resource153ToLegacy(newCrownJewel(t, "test")), - types.KindDatabaseObject: types.Resource153ToLegacy(newDatabaseObject(t, "test")), - types.KindAccessGraphSettings: types.Resource153ToLegacy(newAccessGraphSettings(t)), - types.KindSPIFFEFederation: types.Resource153ToLegacy(newSPIFFEFederation("test")), - types.KindStaticHostUser: types.Resource153ToLegacy(newStaticHostUser(t, "test")), - types.KindAutoUpdateConfig: types.Resource153ToLegacy(newAutoUpdateConfig(t)), - types.KindAutoUpdateVersion: types.Resource153ToLegacy(newAutoUpdateVersion(t)), - types.KindAutoUpdateAgentRollout: types.Resource153ToLegacy(newAutoUpdateAgentRollout(t)), - types.KindUserTask: types.Resource153ToLegacy(newUserTasks(t)), - types.KindProvisioningPrincipalState: types.Resource153ToLegacy(newProvisioningPrincipalState("u-alice@example.com")), + types.KindCertAuthority: &types.CertAuthorityV2{}, + types.KindClusterName: &types.ClusterNameV2{}, + types.KindClusterAuditConfig: types.DefaultClusterAuditConfig(), + types.KindClusterNetworkingConfig: types.DefaultClusterNetworkingConfig(), + types.KindClusterAuthPreference: types.DefaultAuthPreference(), + types.KindSessionRecordingConfig: types.DefaultSessionRecordingConfig(), + types.KindUIConfig: &types.UIConfigV1{}, + types.KindStaticTokens: &types.StaticTokensV2{}, + types.KindToken: &types.ProvisionTokenV2{}, + types.KindUser: &types.UserV2{}, + types.KindRole: &types.RoleV6{Version: types.V4}, + types.KindNamespace: &types.Namespace{}, + types.KindNode: &types.ServerV2{}, + types.KindProxy: &types.ServerV2{}, + types.KindAuthServer: &types.ServerV2{}, + types.KindReverseTunnel: &types.ReverseTunnelV2{}, + types.KindTunnelConnection: &types.TunnelConnectionV2{}, + types.KindAccessRequest: &types.AccessRequestV3{}, + types.KindAppServer: &types.AppServerV3{}, + types.KindApp: &types.AppV3{}, + types.KindWebSession: &types.WebSessionV2{SubKind: types.KindWebSession}, + types.KindAppSession: &types.WebSessionV2{SubKind: types.KindAppSession}, + types.KindSnowflakeSession: &types.WebSessionV2{SubKind: types.KindSnowflakeSession}, + types.KindSAMLIdPSession: &types.WebSessionV2{SubKind: types.KindSAMLIdPServiceProvider}, + types.KindWebToken: &types.WebTokenV3{}, + types.KindRemoteCluster: &types.RemoteClusterV3{}, + types.KindKubeServer: &types.KubernetesServerV3{}, + types.KindDatabaseService: &types.DatabaseServiceV1{}, + types.KindDatabaseServer: &types.DatabaseServerV3{}, + types.KindDatabase: &types.DatabaseV3{}, + types.KindNetworkRestrictions: &types.NetworkRestrictionsV4{}, + types.KindLock: &types.LockV2{}, + types.KindWindowsDesktopService: &types.WindowsDesktopServiceV3{}, + types.KindWindowsDesktop: &types.WindowsDesktopV3{}, + types.KindDynamicWindowsDesktop: &types.DynamicWindowsDesktopV1{}, + types.KindInstaller: &types.InstallerV1{}, + types.KindKubernetesCluster: &types.KubernetesClusterV3{}, + types.KindSAMLIdPServiceProvider: &types.SAMLIdPServiceProviderV1{}, + types.KindUserGroup: &types.UserGroupV1{}, + types.KindOktaImportRule: &types.OktaImportRuleV1{}, + types.KindOktaAssignment: &types.OktaAssignmentV1{}, + types.KindIntegration: &types.IntegrationV1{}, + types.KindDiscoveryConfig: newDiscoveryConfig(t, "discovery-config"), + types.KindHeadlessAuthentication: &types.HeadlessAuthentication{}, + types.KindUserLoginState: newUserLoginState(t, "user-login-state"), + types.KindAuditQuery: newAuditQuery(t, "audit-query"), + types.KindSecurityReport: newSecurityReport(t, "security-report"), + types.KindSecurityReportState: newSecurityReport(t, "security-report-state"), + types.KindAccessList: newAccessList(t, "access-list", clock), + types.KindAccessListMember: newAccessListMember(t, "access-list", "member"), + types.KindAccessListReview: newAccessListReview(t, "access-list", "review"), + types.KindKubeWaitingContainer: newKubeWaitingContainer(t), + types.KindNotification: types.Resource153ToLegacy(newUserNotification(t, "test")), + types.KindGlobalNotification: types.Resource153ToLegacy(newGlobalNotification(t, "test")), + types.KindAccessMonitoringRule: types.Resource153ToLegacy(newAccessMonitoringRule(t)), + types.KindCrownJewel: types.Resource153ToLegacy(newCrownJewel(t, "test")), + types.KindDatabaseObject: types.Resource153ToLegacy(newDatabaseObject(t, "test")), + types.KindAccessGraphSettings: types.Resource153ToLegacy(newAccessGraphSettings(t)), + types.KindSPIFFEFederation: types.Resource153ToLegacy(newSPIFFEFederation("test")), + types.KindStaticHostUser: types.Resource153ToLegacy(newStaticHostUser(t, "test")), + types.KindAutoUpdateConfig: types.Resource153ToLegacy(newAutoUpdateConfig(t)), + types.KindAutoUpdateVersion: types.Resource153ToLegacy(newAutoUpdateVersion(t)), + types.KindAutoUpdateAgentRollout: types.Resource153ToLegacy(newAutoUpdateAgentRollout(t)), + types.KindUserTask: types.Resource153ToLegacy(newUserTasks(t)), + types.KindProvisioningPrincipalState: types.Resource153ToLegacy(newProvisioningPrincipalState("u-alice@example.com")), + types.KindIdentityCenterAccount: types.Resource153ToLegacy(newIdentityCenterAccount("some_account")), + types.KindIdentityCenterAccountAssignment: types.Resource153ToLegacy(newIdentityCenterAccountAssignment("some_account_assignment")), + types.KindIdentityCenterPrincipalAssignment: types.Resource153ToLegacy(newIdentityCenterPrincipalAssignment("some_principal_assignment")), } for name, cfg := range cases { diff --git a/lib/cache/collections.go b/lib/cache/collections.go index 130cfd303c23f..17c28934a32c3 100644 --- a/lib/cache/collections.go +++ b/lib/cache/collections.go @@ -33,6 +33,7 @@ import ( clusterconfigpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/clusterconfig/v1" crownjewelv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/crownjewel/v1" dbobjectv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/dbobject/v1" + identitycenterv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/identitycenter/v1" kubewaitingcontainerpb "github.com/gravitational/teleport/api/gen/proto/go/teleport/kubewaitingcontainer/v1" machineidv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/machineid/v1" notificationsv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/notifications/v1" @@ -94,104 +95,6 @@ type executor[T any, R any] interface { // noReader is returned by getReader for resources which aren't directly used by the cache, and therefore have no associated reader. type noReader struct{} -// genericCollection is a generic collection implementation for resource type T with collection-specific logic -// encapsulated in executor type E. Type R provides getter methods related to the collection, e.g. GetNodes(), -// GetRoles(). -type genericCollection[T any, R any, E executor[T, R]] struct { - cache *Cache - watch types.WatchKind - exec E -} - -// fetch implements collection -func (g *genericCollection[T, R, _]) fetch(ctx context.Context, cacheOK bool) (apply func(ctx context.Context) error, err error) { - // Singleton objects will only get deleted or updated, not both - deleteSingleton := false - - var resources []T - if cacheOK { - resources, err = g.exec.getAll(ctx, g.cache, g.watch.LoadSecrets) - if err != nil { - if !trace.IsNotFound(err) { - return nil, trace.Wrap(err) - } - deleteSingleton = true - } - } - - return func(ctx context.Context) error { - // Always perform the delete if this is not a singleton, otherwise - // only perform the delete if the singleton wasn't found - // or the resource kind isn't cached in the current generation. - if !g.exec.isSingleton() || deleteSingleton || !cacheOK { - if err := g.exec.deleteAll(ctx, g.cache); err != nil { - if !trace.IsNotFound(err) { - return trace.Wrap(err) - } - } - } - // If this is a singleton and we performed a deletion, return here - // because we only want to update or delete a singleton, not both. - // Also don't continue if the resource kind isn't cached in the current generation. - if g.exec.isSingleton() && deleteSingleton || !cacheOK { - return nil - } - for _, resource := range resources { - if err := g.exec.upsert(ctx, g.cache, resource); err != nil { - return trace.Wrap(err) - } - } - return nil - }, nil -} - -// processEvent implements collection -func (g *genericCollection[T, R, _]) processEvent(ctx context.Context, event types.Event) error { - switch event.Type { - case types.OpDelete: - if err := g.exec.delete(ctx, g.cache, event.Resource); err != nil { - if !trace.IsNotFound(err) { - g.cache.Logger.WithError(err).Warn("Failed to delete resource.") - return trace.Wrap(err) - } - } - case types.OpPut: - var resource T - var ok bool - switch r := event.Resource.(type) { - case types.Resource153Unwrapper: - resource, ok = r.Unwrap().(T) - default: - resource, ok = event.Resource.(T) - } - if !ok { - return trace.BadParameter("unexpected type %T", event.Resource) - } - - if err := g.exec.upsert(ctx, g.cache, resource); err != nil { - return trace.Wrap(err) - } - default: - g.cache.Logger.WithField("event", event.Type).Warn("Skipping unsupported event type.") - } - return nil -} - -// watchKind implements collection -func (g *genericCollection[T, R, _]) watchKind() types.WatchKind { - return g.watch -} - -var _ collection = (*genericCollection[types.Resource, any, executor[types.Resource, any]])(nil) - -// genericCollection obtains the reader object from the executor based on the provided health status of the cache. -// Note that cacheOK set to true means that cache is overall healthy and the collection was confirmed as supported. -func (c *genericCollection[T, R, _]) getReader(cacheOK bool) R { - return c.exec.getReader(c.cache, cacheOK) -} - -var _ collectionReader[any] = (*genericCollection[types.Resource, any, executor[types.Resource, any]])(nil) - type crownjewelsGetter interface { ListCrownJewels(ctx context.Context, pageSize int64, nextToken string) ([]*crownjewelv1.CrownJewel, string, error) GetCrownJewel(ctx context.Context, name string) (*crownjewelv1.CrownJewel, error) @@ -208,68 +111,71 @@ type cacheCollections struct { // byKind is a map of registered collections by resource Kind/SubKind byKind map[resourceKind]collection - auditQueries collectionReader[services.SecurityAuditQueryGetter] - secReports collectionReader[services.SecurityReportGetter] - secReportsStates collectionReader[services.SecurityReportStateGetter] - accessLists collectionReader[accessListsGetter] - accessListMembers collectionReader[accessListMembersGetter] - accessListReviews collectionReader[accessListReviewsGetter] - apps collectionReader[services.AppGetter] - nodes collectionReader[nodeGetter] - tunnelConnections collectionReader[tunnelConnectionGetter] - appSessions collectionReader[appSessionGetter] - appServers collectionReader[appServerGetter] - authPreferences collectionReader[authPreferenceGetter] - authServers collectionReader[authServerGetter] - certAuthorities collectionReader[services.AuthorityGetter] - clusterAuditConfigs collectionReader[clusterAuditConfigGetter] - clusterNames collectionReader[clusterNameGetter] - clusterNetworkingConfigs collectionReader[clusterNetworkingConfigGetter] - databases collectionReader[services.DatabaseGetter] - databaseObjects collectionReader[services.DatabaseObjectsGetter] - databaseServers collectionReader[databaseServerGetter] - discoveryConfigs collectionReader[services.DiscoveryConfigsGetter] - installers collectionReader[installerGetter] - integrations collectionReader[services.IntegrationsGetter] - userTasks collectionReader[userTasksGetter] - crownJewels collectionReader[crownjewelsGetter] - kubeClusters collectionReader[kubernetesClusterGetter] - kubeWaitingContainers collectionReader[kubernetesWaitingContainerGetter] - staticHostUsers collectionReader[staticHostUserGetter] - kubeServers collectionReader[kubeServerGetter] - locks collectionReader[services.LockGetter] - namespaces collectionReader[namespaceGetter] - networkRestrictions collectionReader[networkRestrictionGetter] - oktaAssignments collectionReader[oktaAssignmentGetter] - oktaImportRules collectionReader[oktaImportRuleGetter] - proxies collectionReader[services.ProxyGetter] - remoteClusters collectionReader[remoteClusterGetter] - reverseTunnels collectionReader[reverseTunnelGetter] - roles collectionReader[roleGetter] - samlIdPServiceProviders collectionReader[samlIdPServiceProviderGetter] - samlIdPSessions collectionReader[samlIdPSessionGetter] - sessionRecordingConfigs collectionReader[sessionRecordingConfigGetter] - snowflakeSessions collectionReader[snowflakeSessionGetter] - staticTokens collectionReader[staticTokensGetter] - tokens collectionReader[tokenGetter] - uiConfigs collectionReader[uiConfigGetter] - users collectionReader[userGetter] - userGroups collectionReader[userGroupGetter] - userLoginStates collectionReader[services.UserLoginStatesGetter] - webSessions collectionReader[webSessionGetter] - webTokens collectionReader[webTokenGetter] - windowsDesktops collectionReader[windowsDesktopsGetter] - dynamicWindowsDesktops collectionReader[dynamicWindowsDesktopsGetter] - windowsDesktopServices collectionReader[windowsDesktopServiceGetter] - userNotifications collectionReader[notificationGetter] - accessGraphSettings collectionReader[accessGraphSettingsGetter] - globalNotifications collectionReader[notificationGetter] - accessMonitoringRules collectionReader[accessMonitoringRuleGetter] - spiffeFederations collectionReader[SPIFFEFederationReader] - autoUpdateConfigs collectionReader[autoUpdateConfigGetter] - autoUpdateVersions collectionReader[autoUpdateVersionGetter] - autoUpdateAgentRollouts collectionReader[autoUpdateAgentRolloutGetter] - provisioningStates collectionReader[provisioningStateGetter] + auditQueries collectionReader[services.SecurityAuditQueryGetter] + secReports collectionReader[services.SecurityReportGetter] + secReportsStates collectionReader[services.SecurityReportStateGetter] + accessLists collectionReader[accessListsGetter] + accessListMembers collectionReader[accessListMembersGetter] + accessListReviews collectionReader[accessListReviewsGetter] + apps collectionReader[services.AppGetter] + nodes collectionReader[nodeGetter] + tunnelConnections collectionReader[tunnelConnectionGetter] + appSessions collectionReader[appSessionGetter] + appServers collectionReader[appServerGetter] + authPreferences collectionReader[authPreferenceGetter] + authServers collectionReader[authServerGetter] + certAuthorities collectionReader[services.AuthorityGetter] + clusterAuditConfigs collectionReader[clusterAuditConfigGetter] + clusterNames collectionReader[clusterNameGetter] + clusterNetworkingConfigs collectionReader[clusterNetworkingConfigGetter] + databases collectionReader[services.DatabaseGetter] + databaseObjects collectionReader[services.DatabaseObjectsGetter] + databaseServers collectionReader[databaseServerGetter] + discoveryConfigs collectionReader[services.DiscoveryConfigsGetter] + installers collectionReader[installerGetter] + integrations collectionReader[services.IntegrationsGetter] + userTasks collectionReader[userTasksGetter] + crownJewels collectionReader[crownjewelsGetter] + kubeClusters collectionReader[kubernetesClusterGetter] + kubeWaitingContainers collectionReader[kubernetesWaitingContainerGetter] + staticHostUsers collectionReader[staticHostUserGetter] + kubeServers collectionReader[kubeServerGetter] + locks collectionReader[services.LockGetter] + namespaces collectionReader[namespaceGetter] + networkRestrictions collectionReader[networkRestrictionGetter] + oktaAssignments collectionReader[oktaAssignmentGetter] + oktaImportRules collectionReader[oktaImportRuleGetter] + proxies collectionReader[services.ProxyGetter] + remoteClusters collectionReader[remoteClusterGetter] + reverseTunnels collectionReader[reverseTunnelGetter] + roles collectionReader[roleGetter] + samlIdPServiceProviders collectionReader[samlIdPServiceProviderGetter] + samlIdPSessions collectionReader[samlIdPSessionGetter] + sessionRecordingConfigs collectionReader[sessionRecordingConfigGetter] + snowflakeSessions collectionReader[snowflakeSessionGetter] + staticTokens collectionReader[staticTokensGetter] + tokens collectionReader[tokenGetter] + uiConfigs collectionReader[uiConfigGetter] + users collectionReader[userGetter] + userGroups collectionReader[userGroupGetter] + userLoginStates collectionReader[services.UserLoginStatesGetter] + webSessions collectionReader[webSessionGetter] + webTokens collectionReader[webTokenGetter] + windowsDesktops collectionReader[windowsDesktopsGetter] + dynamicWindowsDesktops collectionReader[dynamicWindowsDesktopsGetter] + windowsDesktopServices collectionReader[windowsDesktopServiceGetter] + userNotifications collectionReader[notificationGetter] + accessGraphSettings collectionReader[accessGraphSettingsGetter] + globalNotifications collectionReader[notificationGetter] + accessMonitoringRules collectionReader[accessMonitoringRuleGetter] + spiffeFederations collectionReader[SPIFFEFederationReader] + autoUpdateConfigs collectionReader[autoUpdateConfigGetter] + autoUpdateVersions collectionReader[autoUpdateVersionGetter] + autoUpdateAgentRollouts collectionReader[autoUpdateAgentRolloutGetter] + provisioningStates collectionReader[provisioningStateGetter] + identityCenterAccounts collectionReader[identityCenterAccountGetter] + identityCenterPrincipalAssignments collectionReader[identityCenterPrincipalAssignmentGetter] + identityCenterAccountAssignments collectionReader[identityCenterAccountAssignmentGetter] } // setupCollections returns a registry of collections. @@ -836,6 +742,48 @@ func setupCollections(c *Cache, watches []types.WatchKind) (*cacheCollections, e } collections.byKind[resourceKind] = collections.provisioningStates + case types.KindIdentityCenterAccount: + if c.IdentityCenter == nil { + return nil, trace.BadParameter("missing upstream IdentityCenter collection") + } + collections.identityCenterAccounts = &genericCollection[ + services.IdentityCenterAccount, + identityCenterAccountGetter, + identityCenterAccountExecutor, + ]{ + cache: c, + watch: watch, + } + collections.byKind[resourceKind] = collections.identityCenterAccounts + + case types.KindIdentityCenterPrincipalAssignment: + if c.IdentityCenter == nil { + return nil, trace.BadParameter("missing parameter IdentityCenter") + } + collections.identityCenterPrincipalAssignments = &genericCollection[ + *identitycenterv1.PrincipalAssignment, + identityCenterPrincipalAssignmentGetter, + identityCenterPrincipalAssignmentExecutor, + ]{ + cache: c, + watch: watch, + } + collections.byKind[resourceKind] = collections.identityCenterPrincipalAssignments + + case types.KindIdentityCenterAccountAssignment: + if c.IdentityCenter == nil { + return nil, trace.BadParameter("missing parameter IdentityCenter") + } + collections.identityCenterAccountAssignments = &genericCollection[ + services.IdentityCenterAccountAssignment, + identityCenterAccountAssignmentGetter, + identityCenterAccountAssignmentExecutor, + ]{ + cache: c, + watch: watch, + } + collections.byKind[resourceKind] = collections.identityCenterAccountAssignments + default: return nil, trace.BadParameter("resource %q is not supported", watch.Kind) } diff --git a/lib/cache/genericcollection.go b/lib/cache/genericcollection.go new file mode 100644 index 0000000000000..ac0260da844d9 --- /dev/null +++ b/lib/cache/genericcollection.go @@ -0,0 +1,128 @@ +// 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 cache + +import ( + "context" + + "github.com/gravitational/trace" + + "github.com/gravitational/teleport/api/types" +) + +// genericCollection is a generic collection implementation for resource type T with collection-specific logic +// encapsulated in executor type E. Type R provides getter methods related to the collection, e.g. GetNodes(), +// GetRoles(). +type genericCollection[T any, R any, E executor[T, R]] struct { + cache *Cache + watch types.WatchKind + exec E +} + +// fetch implements collection +func (g *genericCollection[T, R, _]) fetch(ctx context.Context, cacheOK bool) (apply func(ctx context.Context) error, err error) { + // Singleton objects will only get deleted or updated, not both + deleteSingleton := false + + var resources []T + if cacheOK { + resources, err = g.exec.getAll(ctx, g.cache, g.watch.LoadSecrets) + if err != nil { + if !trace.IsNotFound(err) { + return nil, trace.Wrap(err) + } + deleteSingleton = true + } + } + + return func(ctx context.Context) error { + // Always perform the delete if this is not a singleton, otherwise + // only perform the delete if the singleton wasn't found + // or the resource kind isn't cached in the current generation. + if !g.exec.isSingleton() || deleteSingleton || !cacheOK { + if err := g.exec.deleteAll(ctx, g.cache); err != nil { + if !trace.IsNotFound(err) { + return trace.Wrap(err) + } + } + } + // If this is a singleton and we performed a deletion, return here + // because we only want to update or delete a singleton, not both. + // Also don't continue if the resource kind isn't cached in the current generation. + if g.exec.isSingleton() && deleteSingleton || !cacheOK { + return nil + } + for _, resource := range resources { + if err := g.exec.upsert(ctx, g.cache, resource); err != nil { + return trace.Wrap(err) + } + } + return nil + }, nil +} + +// processEvent implements collection +func (g *genericCollection[T, R, _]) processEvent(ctx context.Context, event types.Event) error { + switch event.Type { + case types.OpDelete: + if err := g.exec.delete(ctx, g.cache, event.Resource); err != nil { + if !trace.IsNotFound(err) { + g.cache.Logger.WithError(err).Warn("Failed to delete resource.") + return trace.Wrap(err) + } + } + case types.OpPut: + var resource T + var ok bool + switch r := event.Resource.(type) { + case types.Resource153Unwrapper: + resource, ok = r.Unwrap().(T) + if !ok { + return trace.BadParameter("unexpected wrapped type %T (expected %T)", r.Unwrap(), resource) + } + + default: + resource, ok = event.Resource.(T) + } + + if !ok { + return trace.BadParameter("unexpected type %T (expected %T)", event.Resource, resource) + } + + if err := g.exec.upsert(ctx, g.cache, resource); err != nil { + return trace.Wrap(err) + } + default: + g.cache.Logger.WithField("event", event.Type).Warn("Skipping unsupported event type.") + } + return nil +} + +// watchKind implements collection +func (g *genericCollection[T, R, _]) watchKind() types.WatchKind { + return g.watch +} + +var _ collection = (*genericCollection[types.Resource, any, executor[types.Resource, any]])(nil) + +// genericCollection obtains the reader object from the executor based on the provided health status of the cache. +// Note that cacheOK set to true means that cache is overall healthy and the collection was confirmed as supported. +func (c *genericCollection[T, R, _]) getReader(cacheOK bool) R { + return c.exec.getReader(c.cache, cacheOK) +} + +var _ collectionReader[any] = (*genericCollection[types.Resource, any, executor[types.Resource, any]])(nil) diff --git a/lib/cache/identitycenter.go b/lib/cache/identitycenter.go new file mode 100644 index 0000000000000..1b431cba57da2 --- /dev/null +++ b/lib/cache/identitycenter.go @@ -0,0 +1,196 @@ +// 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 cache + +import ( + "context" + + "github.com/gravitational/trace" + + identitycenterv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/identitycenter/v1" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/utils/pagination" +) + +type identityCenterAccountGetter interface { + GetIdentityCenterAccount(context.Context, services.IdentityCenterAccountID) (services.IdentityCenterAccount, error) + ListIdentityCenterAccounts(context.Context, int, *pagination.PageRequestToken) ([]services.IdentityCenterAccount, pagination.NextPageToken, error) +} + +type identityCenterAccountExecutor struct{} + +func (identityCenterAccountExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]services.IdentityCenterAccount, error) { + var pageToken pagination.PageRequestToken + var resources []services.IdentityCenterAccount + for { + resourcesPage, nextPage, err := cache.IdentityCenter.ListIdentityCenterAccounts(ctx, 0, &pageToken) + if err != nil { + return nil, trace.Wrap(err) + } + + resources = append(resources, resourcesPage...) + + if nextPage == pagination.EndOfList { + break + } + pageToken.Update(nextPage) + } + return resources, nil +} + +func (identityCenterAccountExecutor) upsert(ctx context.Context, cache *Cache, resource services.IdentityCenterAccount) error { + _, err := cache.identityCenterCache.UpsertIdentityCenterAccount(ctx, resource) + return trace.Wrap(err) +} + +func (identityCenterAccountExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error { + return trace.Wrap(cache.identityCenterCache.DeleteIdentityCenterAccount(ctx, + services.IdentityCenterAccountID(resource.GetName()))) +} + +func (identityCenterAccountExecutor) deleteAll(ctx context.Context, cache *Cache) error { + return trace.Wrap(cache.identityCenterCache.DeleteAllIdentityCenterAccounts(ctx)) +} + +func (identityCenterAccountExecutor) getReader(cache *Cache, cacheOK bool) identityCenterAccountGetter { + if cacheOK { + return cache.identityCenterCache + } + return cache.Config.IdentityCenter +} + +func (identityCenterAccountExecutor) isSingleton() bool { + return false +} + +var _ executor[ + services.IdentityCenterAccount, + identityCenterAccountGetter, +] = identityCenterAccountExecutor{} + +type identityCenterPrincipalAssignmentGetter interface { + GetPrincipalAssignment(context.Context, services.PrincipalAssignmentID) (*identitycenterv1.PrincipalAssignment, error) + ListPrincipalAssignments(context.Context, int, *pagination.PageRequestToken) ([]*identitycenterv1.PrincipalAssignment, pagination.NextPageToken, error) +} + +type identityCenterPrincipalAssignmentExecutor struct{} + +var _ executor[ + *identitycenterv1.PrincipalAssignment, + identityCenterPrincipalAssignmentGetter, +] = identityCenterPrincipalAssignmentExecutor{} + +func (identityCenterPrincipalAssignmentExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]*identitycenterv1.PrincipalAssignment, error) { + var pageToken pagination.PageRequestToken + var resources []*identitycenterv1.PrincipalAssignment + for { + resourcesPage, nextPage, err := cache.IdentityCenter.ListPrincipalAssignments(ctx, 0, &pageToken) + if err != nil { + return nil, trace.Wrap(err) + } + + resources = append(resources, resourcesPage...) + + if nextPage == pagination.EndOfList { + break + } + pageToken.Update(nextPage) + } + return resources, nil +} + +func (identityCenterPrincipalAssignmentExecutor) upsert(ctx context.Context, cache *Cache, resource *identitycenterv1.PrincipalAssignment) error { + _, err := cache.identityCenterCache.UpsertPrincipalAssignment(ctx, resource) + return trace.Wrap(err) +} + +func (identityCenterPrincipalAssignmentExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error { + return trace.Wrap(cache.identityCenterCache.DeletePrincipalAssignment(ctx, + services.PrincipalAssignmentID(resource.GetName()))) +} + +func (identityCenterPrincipalAssignmentExecutor) deleteAll(ctx context.Context, cache *Cache) error { + return trace.Wrap(cache.identityCenterCache.DeleteAllPrincipalAssignments(ctx)) +} + +func (identityCenterPrincipalAssignmentExecutor) getReader(cache *Cache, cacheOK bool) identityCenterPrincipalAssignmentGetter { + if cacheOK { + return cache.identityCenterCache + } + return cache.Config.IdentityCenter +} + +func (identityCenterPrincipalAssignmentExecutor) isSingleton() bool { + return false +} + +type identityCenterAccountAssignmentGetter interface { + GetAccountAssignment(context.Context, services.IdentityCenterAccountAssignmentID) (services.IdentityCenterAccountAssignment, error) + ListAccountAssignments(context.Context, int, *pagination.PageRequestToken) ([]services.IdentityCenterAccountAssignment, pagination.NextPageToken, error) +} + +type identityCenterAccountAssignmentExecutor struct{} + +func (identityCenterAccountAssignmentExecutor) getAll(ctx context.Context, cache *Cache, loadSecrets bool) ([]services.IdentityCenterAccountAssignment, error) { + var pageToken pagination.PageRequestToken + var resources []services.IdentityCenterAccountAssignment + for { + resourcesPage, nextPage, err := cache.IdentityCenter.ListAccountAssignments(ctx, 0, &pageToken) + if err != nil { + return nil, trace.Wrap(err) + } + + resources = append(resources, resourcesPage...) + + if nextPage == pagination.EndOfList { + break + } + pageToken.Update(nextPage) + } + return resources, nil +} + +func (identityCenterAccountAssignmentExecutor) upsert(ctx context.Context, cache *Cache, resource services.IdentityCenterAccountAssignment) error { + _, err := cache.identityCenterCache.UpsertAccountAssignment(ctx, resource) + return trace.Wrap(err) +} + +func (identityCenterAccountAssignmentExecutor) delete(ctx context.Context, cache *Cache, resource types.Resource) error { + return trace.Wrap(cache.identityCenterCache.DeleteAccountAssignment(ctx, + services.IdentityCenterAccountAssignmentID(resource.GetName()))) +} + +func (identityCenterAccountAssignmentExecutor) deleteAll(ctx context.Context, cache *Cache) error { + return trace.Wrap(cache.identityCenterCache.DeleteAllIdentityCenterAccounts(ctx)) +} + +func (identityCenterAccountAssignmentExecutor) getReader(cache *Cache, cacheOK bool) identityCenterAccountAssignmentGetter { + if cacheOK { + return cache.identityCenterCache + } + return cache.Config.IdentityCenter +} + +func (identityCenterAccountAssignmentExecutor) isSingleton() bool { + return false +} + +var _ executor[ + services.IdentityCenterAccountAssignment, + identityCenterAccountAssignmentGetter, +] = identityCenterAccountAssignmentExecutor{} diff --git a/lib/cache/identitycenter_test.go b/lib/cache/identitycenter_test.go new file mode 100644 index 0000000000000..c312d778aeafa --- /dev/null +++ b/lib/cache/identitycenter_test.go @@ -0,0 +1,263 @@ +// 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 cache + +import ( + "context" + "log/slog" + "os" + "testing" + + "github.com/gravitational/trace" + + headerv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/header/v1" + identitycenterv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/identitycenter/v1" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/services" + logutils "github.com/gravitational/teleport/lib/utils/log" + "github.com/gravitational/teleport/lib/utils/pagination" +) + +func newIdentityCenterAccount(id string) *identitycenterv1.Account { + return &identitycenterv1.Account{ + Kind: types.KindIdentityCenterAccount, + SubKind: "", + Version: types.V1, + Metadata: &headerv1.Metadata{ + Name: id, + }, + Spec: &identitycenterv1.AccountSpec{ + Id: id, + Arn: "arn:aws:sso:::permissionSet/ssoins-722326ecc902a06a/" + id, + }, + Status: &identitycenterv1.AccountStatus{}, + } +} + +// TestIdentityCenterAccount asserts that an Identoty Ceneter Account can be cached +func TestIdentityCenterAccount(t *testing.T) { + slog.SetDefault( + slog.New(logutils.NewSlogTextHandler( + os.Stderr, logutils.SlogTextHandlerConfig{Level: slog.LevelDebug}))) + + t.Parallel() + + fixturePack := newTestPack(t, ForAuth) + t.Cleanup(fixturePack.Close) + + collect := func(ctx context.Context, src identityCenterAccountGetter) ([]services.IdentityCenterAccount, error) { + var result []services.IdentityCenterAccount + var pageToken pagination.PageRequestToken + for { + page, nextPage, err := src.ListIdentityCenterAccounts(ctx, 0, &pageToken) + if err != nil { + return nil, trace.Wrap(err) + } + result = append(result, page...) + + if nextPage == pagination.EndOfList { + break + } + + pageToken.Update(nextPage) + } + return result, nil + } + + testResources153(t, fixturePack, testFuncs153[services.IdentityCenterAccount]{ + newResource: func(s string) (services.IdentityCenterAccount, error) { + return services.IdentityCenterAccount{Account: newIdentityCenterAccount(s)}, nil + }, + create: func(ctx context.Context, item services.IdentityCenterAccount) error { + _, err := fixturePack.identityCenter.CreateIdentityCenterAccount(ctx, item) + return trace.Wrap(err) + }, + update: func(ctx context.Context, item services.IdentityCenterAccount) error { + _, err := fixturePack.identityCenter.UpdateIdentityCenterAccount(ctx, item) + return trace.Wrap(err) + }, + list: func(ctx context.Context) ([]services.IdentityCenterAccount, error) { + return collect(ctx, fixturePack.identityCenter) + }, + delete: func(ctx context.Context, id string) error { + return trace.Wrap(fixturePack.identityCenter.DeleteIdentityCenterAccount( + ctx, services.IdentityCenterAccountID(id))) + }, + deleteAll: func(ctx context.Context) error { + return trace.Wrap(fixturePack.identityCenter.DeleteAllIdentityCenterAccounts(ctx)) + }, + cacheList: func(ctx context.Context) ([]services.IdentityCenterAccount, error) { + return collect(ctx, fixturePack.cache.identityCenterCache) + }, + cacheGet: func(ctx context.Context, id string) (services.IdentityCenterAccount, error) { + r, err := fixturePack.cache.identityCenterCache.GetIdentityCenterAccount( + ctx, services.IdentityCenterAccountID(id)) + return r, trace.Wrap(err) + }, + }) +} + +func newIdentityCenterPrincipalAssignment(id string) *identitycenterv1.PrincipalAssignment { + return &identitycenterv1.PrincipalAssignment{ + Kind: types.KindIdentityCenterPrincipalAssignment, + SubKind: "", + Version: types.V1, + Metadata: &headerv1.Metadata{ + Name: id, + }, + Spec: &identitycenterv1.PrincipalAssignmentSpec{ + PrincipalType: identitycenterv1.PrincipalType_PRINCIPAL_TYPE_USER, + PrincipalId: id, + ExternalId: "ext_" + id, + }, + Status: &identitycenterv1.PrincipalAssignmentStatus{ + ProvisioningState: identitycenterv1.ProvisioningState_PROVISIONING_STATE_PROVISIONED, + }, + } +} + +// TestIdentityCenterPrincpialAssignment asserts that an Identity Center PrincipalAssignment can be cached +func TestIdentityCenterPrincipalAssignment(t *testing.T) { + fixturePack := newTestPack(t, ForAuth) + t.Cleanup(fixturePack.Close) + + collect := func(ctx context.Context, src identityCenterPrincipalAssignmentGetter) ([]*identitycenterv1.PrincipalAssignment, error) { + var result []*identitycenterv1.PrincipalAssignment + var pageToken pagination.PageRequestToken + for { + page, nextPage, err := src.ListPrincipalAssignments(ctx, 0, &pageToken) + if err != nil { + return nil, trace.Wrap(err) + } + result = append(result, page...) + + if nextPage == pagination.EndOfList { + break + } + + pageToken.Update(nextPage) + } + return result, nil + } + + testResources153(t, fixturePack, testFuncs153[*identitycenterv1.PrincipalAssignment]{ + newResource: func(s string) (*identitycenterv1.PrincipalAssignment, error) { + return newIdentityCenterPrincipalAssignment(s), nil + }, + create: func(ctx context.Context, item *identitycenterv1.PrincipalAssignment) error { + _, err := fixturePack.identityCenter.CreatePrincipalAssignment(ctx, item) + return trace.Wrap(err) + }, + update: func(ctx context.Context, item *identitycenterv1.PrincipalAssignment) error { + _, err := fixturePack.identityCenter.UpdatePrincipalAssignment(ctx, item) + return trace.Wrap(err) + }, + list: func(ctx context.Context) ([]*identitycenterv1.PrincipalAssignment, error) { + return collect(ctx, fixturePack.identityCenter) + }, + delete: func(ctx context.Context, id string) error { + return trace.Wrap(fixturePack.identityCenter.DeletePrincipalAssignment(ctx, services.PrincipalAssignmentID(id))) + }, + deleteAll: func(ctx context.Context) error { + return trace.Wrap(fixturePack.identityCenter.DeleteAllPrincipalAssignments(ctx)) + }, + cacheList: func(ctx context.Context) ([]*identitycenterv1.PrincipalAssignment, error) { + return collect(ctx, fixturePack.cache.identityCenterCache) + }, + cacheGet: func(ctx context.Context, id string) (*identitycenterv1.PrincipalAssignment, error) { + r, err := fixturePack.cache.identityCenterCache.GetPrincipalAssignment( + ctx, services.PrincipalAssignmentID(id)) + return r, trace.Wrap(err) + }, + }) +} + +func newIdentityCenterAccountAssignment(id string) *identitycenterv1.AccountAssignment { + return &identitycenterv1.AccountAssignment{ + Kind: types.KindIdentityCenterAccountAssignment, + SubKind: "", + Version: types.V1, + Metadata: &headerv1.Metadata{ + Name: id, + }, + Spec: &identitycenterv1.AccountAssignmentSpec{ + Display: "account " + id, + PermissionSet: &identitycenterv1.PermissionSetInfo{}, + AccountName: id, + AccountId: id, + }, + } +} + +// TestIdentityCenterAccountAssignment asserts that an Identity Center +// AccountAssignment can be cached +func TestIdentityCenterAccountAssignment(t *testing.T) { + fixturePack := newTestPack(t, ForAuth) + t.Cleanup(fixturePack.Close) + + collect := func(ctx context.Context, src identityCenterAccountAssignmentGetter) ([]services.IdentityCenterAccountAssignment, error) { + var result []services.IdentityCenterAccountAssignment + var pageToken pagination.PageRequestToken + for { + page, nextPage, err := src.ListAccountAssignments(ctx, 0, &pageToken) + if err != nil { + return nil, trace.Wrap(err) + } + result = append(result, page...) + + if nextPage == pagination.EndOfList { + break + } + + pageToken.Update(nextPage) + } + return result, nil + } + + testResources153(t, fixturePack, testFuncs153[services.IdentityCenterAccountAssignment]{ + newResource: func(s string) (services.IdentityCenterAccountAssignment, error) { + return services.IdentityCenterAccountAssignment{ + AccountAssignment: newIdentityCenterAccountAssignment(s), + }, nil + }, + create: func(ctx context.Context, item services.IdentityCenterAccountAssignment) error { + _, err := fixturePack.identityCenter.CreateAccountAssignment(ctx, item) + return trace.Wrap(err) + }, + update: func(ctx context.Context, item services.IdentityCenterAccountAssignment) error { + _, err := fixturePack.identityCenter.UpdateAccountAssignment(ctx, item) + return trace.Wrap(err) + }, + list: func(ctx context.Context) ([]services.IdentityCenterAccountAssignment, error) { + return collect(ctx, fixturePack.identityCenter) + }, + delete: func(ctx context.Context, id string) error { + return trace.Wrap(fixturePack.identityCenter.DeleteAccountAssignment(ctx, services.IdentityCenterAccountAssignmentID(id))) + }, + deleteAll: func(ctx context.Context) error { + return trace.Wrap(fixturePack.identityCenter.DeleteAllAccountAssignments(ctx)) + }, + cacheList: func(ctx context.Context) ([]services.IdentityCenterAccountAssignment, error) { + return collect(ctx, fixturePack.cache.identityCenterCache) + }, + cacheGet: func(ctx context.Context, id string) (services.IdentityCenterAccountAssignment, error) { + r, err := fixturePack.cache.identityCenterCache.GetAccountAssignment( + ctx, services.IdentityCenterAccountAssignmentID(id)) + return r, trace.Wrap(err) + }, + }) +} diff --git a/lib/client/mfa/prompt.go b/lib/client/mfa/prompt.go index cfbb6e1c2d1a6..c96935c897f18 100644 --- a/lib/client/mfa/prompt.go +++ b/lib/client/mfa/prompt.go @@ -51,17 +51,8 @@ type PromptConfig struct { ProxyAddress string // WebauthnLoginFunc performs client-side Webauthn login. WebauthnLoginFunc WebauthnLoginFunc - // AllowStdinHijack allows stdin hijack during MFA prompts. - // Stdin hijack provides a better login UX, but it can be difficult to reason - // about and is often a source of bugs. - // Do not set this options unless you deeply understand what you are doing. - // If false then only the strongest auth method is prompted. - AllowStdinHijack bool // AuthenticatorAttachment specifies the desired authenticator attachment. AuthenticatorAttachment wancli.AuthenticatorAttachment - // PreferOTP favors OTP challenges, if applicable. - // Takes precedence over AuthenticatorAttachment settings. - PreferOTP bool // WebauthnSupported indicates whether Webauthn is supported. WebauthnSupported bool } @@ -81,41 +72,6 @@ func NewPromptConfig(proxyAddr string, opts ...mfa.PromptOpt) *PromptConfig { return cfg } -// RunOpts are mfa prompt run options. -type RunOpts struct { - PromptTOTP bool - PromptWebauthn bool -} - -// GetRunOptions gets mfa prompt run options by cross referencing the mfa challenge with prompt configuration. -func (c PromptConfig) GetRunOptions(ctx context.Context, chal *proto.MFAAuthenticateChallenge) (RunOpts, error) { - promptTOTP := chal.TOTP != nil - promptWebauthn := chal.WebauthnChallenge != nil - - // Does the current platform support hardware MFA? Adjust accordingly. - switch { - case !promptTOTP && promptWebauthn && !c.WebauthnSupported: - return RunOpts{}, trace.BadParameter("hardware device MFA not supported by your platform, please register an OTP device") - case !c.WebauthnSupported: - // Do not prompt for hardware devices, it won't work. - promptWebauthn = false - } - - // Tweak enabled/disabled methods according to opts. - switch { - case promptTOTP && c.PreferOTP: - promptWebauthn = false - case promptWebauthn && c.AuthenticatorAttachment != wancli.AttachmentAuto: - // Prefer Webauthn if an specific attachment was requested. - promptTOTP = false - case promptWebauthn && !c.AllowStdinHijack: - // Use strongest auth if hijack is not allowed. - promptTOTP = false - } - - return RunOpts{promptTOTP, promptWebauthn}, nil -} - func (c PromptConfig) GetWebauthnOrigin() string { if !strings.HasPrefix(c.ProxyAddress, "https://") { return "https://" + c.ProxyAddress diff --git a/lib/config/configuration.go b/lib/config/configuration.go index 0f23047f64f74..5ef37af409f81 100644 --- a/lib/config/configuration.go +++ b/lib/config/configuration.go @@ -1169,6 +1169,7 @@ func applyAWSKMSConfig(kmsConfig *AWSKMS, cfg *servicecfg.Config) error { return trace.BadParameter("must set region in ca_key_params.aws_kms") } cfg.Auth.KeyStore.AWSKMS.AWSRegion = kmsConfig.Region + cfg.Auth.KeyStore.AWSKMS.MultiRegion = kmsConfig.MultiRegion return nil } diff --git a/lib/config/fileconf.go b/lib/config/fileconf.go index 34ea2a60f2607..8a666b8221803 100644 --- a/lib/config/fileconf.go +++ b/lib/config/fileconf.go @@ -919,6 +919,11 @@ type AWSKMS struct { Account string `yaml:"account"` // Region is the AWS region to use. Region string `yaml:"region"` + // MultiRegion contains configuration for multi-region AWS KMS. + MultiRegion struct { + // Enabled configures new keys to be multi-region. + Enabled bool + } `yaml:"multi_region,omitempty"` } // TrustedCluster struct holds configuration values under "trusted_clusters" key diff --git a/lib/integrations/awsoidc/clients.go b/lib/integrations/awsoidc/clients.go index 82c84136ecb58..52be22b0dabe8 100644 --- a/lib/integrations/awsoidc/clients.go +++ b/lib/integrations/awsoidc/clients.go @@ -37,9 +37,6 @@ import ( // AWSClientRequest contains the required fields to set up an AWS service client. type AWSClientRequest struct { - // IntegrationName is the integration name that is going to issue an API Call. - IntegrationName string - // Token is the token used to issue the API Call. Token string @@ -55,10 +52,6 @@ type AWSClientRequest struct { // CheckAndSetDefaults checks if the required fields are present. func (req *AWSClientRequest) CheckAndSetDefaults() error { - if req.IntegrationName == "" { - return trace.BadParameter("integration name is required") - } - if req.Token == "" { return trace.BadParameter("token is required") } diff --git a/lib/integrations/awsoidc/clients_test.go b/lib/integrations/awsoidc/clients_test.go index ade39eeecdfc8..05e894b2edd7a 100644 --- a/lib/integrations/awsoidc/clients_test.go +++ b/lib/integrations/awsoidc/clients_test.go @@ -29,30 +29,27 @@ import ( func TestCheckAndSetDefaults(t *testing.T) { t.Run("invalid regions must return an error", func(t *testing.T) { err := (&AWSClientRequest{ - IntegrationName: "my-integration", - Token: "token", - RoleARN: "some-arn", - Region: "?", + Token: "token", + RoleARN: "some-arn", + Region: "?", }).CheckAndSetDefaults() require.True(t, trace.IsBadParameter(err)) }) t.Run("valid region", func(t *testing.T) { err := (&AWSClientRequest{ - IntegrationName: "my-integration", - Token: "token", - RoleARN: "some-arn", - Region: "us-east-1", + Token: "token", + RoleARN: "some-arn", + Region: "us-east-1", }).CheckAndSetDefaults() require.NoError(t, err) }) t.Run("empty region", func(t *testing.T) { err := (&AWSClientRequest{ - IntegrationName: "my-integration", - Token: "token", - RoleARN: "some-arn", - Region: "", + Token: "token", + RoleARN: "some-arn", + Region: "", }).CheckAndSetDefaults() require.NoError(t, err) }) diff --git a/lib/integrations/awsoidc/deployservice_vcr_test.go b/lib/integrations/awsoidc/deployservice_vcr_test.go index 24c60c4ccdfa1..48c49a835ff69 100644 --- a/lib/integrations/awsoidc/deployservice_vcr_test.go +++ b/lib/integrations/awsoidc/deployservice_vcr_test.go @@ -69,11 +69,10 @@ func TestDeployDBService(t *testing.T) { return &AWSClientRequest{ // To record new fixtures you will need a valid token. // You can get one by getting the generated token in a real cluster. - Token: awsOIDCToken, - RoleARN: awsOIDCRoleARN, - Region: awsRegion, - IntegrationName: integrationName, - httpClient: httpClient, + Token: awsOIDCToken, + RoleARN: awsOIDCRoleARN, + Region: awsRegion, + httpClient: httpClient, } } diff --git a/lib/integrations/awsoidc/token_generator.go b/lib/integrations/awsoidc/token_generator.go index afcd807325f9b..0cb4e8d122172 100644 --- a/lib/integrations/awsoidc/token_generator.go +++ b/lib/integrations/awsoidc/token_generator.go @@ -59,6 +59,8 @@ type KeyStoreManager interface { // GenerateAWSOIDCTokenRequest contains the required elements to generate an AWS OIDC Token (JWT). type GenerateAWSOIDCTokenRequest struct { // Integration is the AWS OIDC Integration name. + // This field is only used to obtain custom Issuers (those stored at S3 buckets). + // If empty, the default issuer for the cluster (its public endpoint URL) will be used. Integration string // Username is the JWT Username (on behalf of claim) Username string @@ -70,9 +72,6 @@ type GenerateAWSOIDCTokenRequest struct { // CheckAndSetDefaults checks the request params. func (g *GenerateAWSOIDCTokenRequest) CheckAndSetDefaults() error { - if g.Integration == "" { - return trace.BadParameter("integration missing") - } if g.Username == "" { return trace.BadParameter("username missing") } @@ -86,7 +85,28 @@ func (g *GenerateAWSOIDCTokenRequest) CheckAndSetDefaults() error { return nil } -func issuerForIntegration(ctx context.Context, integration types.Integration, cacheClt Cache) (string, error) { +// IssuerForIntegration returns the issuer for a given integration. +// Returns the default Issuer (oidc.IssuerForCluster) if integrationName is empty. +// All calls should be replaced with oidc.IssuerForCluster when IssuerS3URI is removed (it is currently deprecated). +func issuerForIntegration(ctx context.Context, cacheClt Cache, integrationName string) (string, error) { + if integrationName == "" { + issuer, err := oidc.IssuerForCluster(ctx, cacheClt, "") + return issuer, trace.Wrap(err) + } + + integration, err := cacheClt.GetIntegration(ctx, integrationName) + if err != nil { + return "", trace.Wrap(err) + } + + if integration.GetSubKind() != types.IntegrationSubKindAWSOIDC { + return "", trace.BadParameter("integration subkind (%s) mismatch", integration.GetSubKind()) + } + + if integration.GetAWSOIDCIntegrationSpec() == nil { + return "", trace.BadParameter("missing spec fields for %q (%q) integration", integration.GetName(), integration.GetSubKind()) + } + issuerS3URI := integration.GetAWSOIDCIntegrationSpec().IssuerS3URI if issuerS3URI == "" { issuer, err := oidc.IssuerForCluster(ctx, cacheClt, "") @@ -107,20 +127,7 @@ func GenerateAWSOIDCToken(ctx context.Context, cacheClt Cache, keyStoreManager K return "", trace.Wrap(err) } - integration, err := cacheClt.GetIntegration(ctx, req.Integration) - if err != nil { - return "", trace.Wrap(err) - } - - if integration.GetSubKind() != types.IntegrationSubKindAWSOIDC { - return "", trace.BadParameter("integration subkind (%s) mismatch", integration.GetSubKind()) - } - - if integration.GetAWSOIDCIntegrationSpec() == nil { - return "", trace.BadParameter("missing spec fields for %q (%q) integration", integration.GetName(), integration.GetSubKind()) - } - - issuer, err := issuerForIntegration(ctx, integration, cacheClt) + issuer, err := issuerForIntegration(ctx, cacheClt, req.Integration) if err != nil { return "", trace.Wrap(err) } diff --git a/lib/kube/proxy/server.go b/lib/kube/proxy/server.go index 580abc957795b..8c770c16bbdb8 100644 --- a/lib/kube/proxy/server.go +++ b/lib/kube/proxy/server.go @@ -45,6 +45,7 @@ import ( "github.com/gravitational/teleport/lib/multiplexer" "github.com/gravitational/teleport/lib/reversetunnel" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/srv" "github.com/gravitational/teleport/lib/srv/ingress" ) @@ -98,7 +99,7 @@ type TLSServerConfig struct { // kubernetes cluster name. Proxy uses this map to route requests to the correct // kubernetes_service. The servers are kept in memory to avoid making unnecessary // unmarshal calls followed by filtering and to improve memory usage. - KubernetesServersWatcher *services.KubeServerWatcher + KubernetesServersWatcher *services.GenericWatcher[types.KubeServer, readonly.KubeServer] // PROXYProtocolMode controls behavior related to unsigned PROXY protocol headers. PROXYProtocolMode multiplexer.PROXYProtocolMode // InventoryHandle is used to send kube server heartbeats via the inventory control stream. @@ -170,7 +171,7 @@ type TLSServer struct { closeContext context.Context closeFunc context.CancelFunc // kubeClusterWatcher monitors changes to kube cluster resources. - kubeClusterWatcher *services.KubeClusterWatcher + kubeClusterWatcher *services.GenericWatcher[types.KubeCluster, readonly.KubeCluster] // reconciler reconciles proxied kube clusters with kube_clusters resources. reconciler *services.Reconciler[types.KubeCluster] // monitoredKubeClusters contains all kube clusters the proxied kube_clusters are @@ -620,7 +621,9 @@ func (t *TLSServer) getKubernetesServersForKubeClusterFunc() (getKubeServersByNa }, nil case ProxyService: return func(ctx context.Context, name string) ([]types.KubeServer, error) { - servers, err := t.KubernetesServersWatcher.GetKubeServersByClusterName(ctx, name) + servers, err := t.KubernetesServersWatcher.CurrentResourcesWithFilter(ctx, func(ks readonly.KubeServer) bool { + return ks.GetCluster().GetName() == name + }) return servers, trace.Wrap(err) }, nil case LegacyProxyService: @@ -630,7 +633,9 @@ func (t *TLSServer) getKubernetesServersForKubeClusterFunc() (getKubeServersByNa // and forward the request to the next proxy. kube, err := t.getKubeClusterWithServiceLabels(name) if err != nil { - servers, err := t.KubernetesServersWatcher.GetKubeServersByClusterName(ctx, name) + servers, err := t.KubernetesServersWatcher.CurrentResourcesWithFilter(ctx, func(ks readonly.KubeServer) bool { + return ks.GetCluster().GetName() == name + }) return servers, trace.Wrap(err) } srv, err := types.NewKubernetesServerV3FromCluster(kube, "", t.HostID) diff --git a/lib/kube/proxy/utils_testing.go b/lib/kube/proxy/utils_testing.go index 4621b7d51bec1..462638df203c4 100644 --- a/lib/kube/proxy/utils_testing.go +++ b/lib/kube/proxy/utils_testing.go @@ -294,6 +294,7 @@ func SetupTestContext(ctx context.Context, t *testing.T, cfg TestConfig) *TestCo Component: teleport.ComponentKube, Client: client, }, + KubernetesServerGetter: client, }, ) require.NoError(t, err) @@ -387,7 +388,7 @@ func SetupTestContext(ctx context.Context, t *testing.T, cfg TestConfig) *TestCo // Ensure watcher has the correct list of clusters. require.Eventually(t, func() bool { - kubeServers, err := kubeServersWatcher.GetKubernetesServers(ctx) + kubeServers, err := kubeServersWatcher.CurrentResources(ctx) return err == nil && len(kubeServers) == len(cfg.Clusters) }, 3*time.Second, time.Millisecond*100) diff --git a/lib/kube/proxy/watcher.go b/lib/kube/proxy/watcher.go index 047b0a4401f89..24e52e2d9c923 100644 --- a/lib/kube/proxy/watcher.go +++ b/lib/kube/proxy/watcher.go @@ -29,6 +29,7 @@ import ( "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/utils" ) @@ -89,7 +90,7 @@ func (s *TLSServer) startReconciler(ctx context.Context) (err error) { // startKubeClusterResourceWatcher starts watching changes to Kube Clusters resources and // registers/unregisters the proxied Kube Cluster accordingly. -func (s *TLSServer) startKubeClusterResourceWatcher(ctx context.Context) (*services.KubeClusterWatcher, error) { +func (s *TLSServer) startKubeClusterResourceWatcher(ctx context.Context) (*services.GenericWatcher[types.KubeCluster, readonly.KubeCluster], error) { if len(s.ResourceMatchers) == 0 || s.KubeServiceType != KubeService { s.log.Debug("Not initializing Kube Cluster resource watcher.") return nil, nil @@ -102,6 +103,7 @@ func (s *TLSServer) startKubeClusterResourceWatcher(ctx context.Context) (*servi // Logger: s.log, Client: s.AccessPoint, }, + KubernetesClusterGetter: s.AccessPoint, }) if err != nil { return nil, trace.Wrap(err) @@ -110,7 +112,7 @@ func (s *TLSServer) startKubeClusterResourceWatcher(ctx context.Context) (*servi defer watcher.Close() for { select { - case clusters := <-watcher.KubeClustersC: + case clusters := <-watcher.ResourcesC: s.monitoredKubeClusters.setResources(clusters) select { case s.reconcileCh <- struct{}{}: diff --git a/lib/proxy/peer/client.go b/lib/proxy/peer/client.go index c00b67006875f..fe3659a92bf4a 100644 --- a/lib/proxy/peer/client.go +++ b/lib/proxy/peer/client.go @@ -51,6 +51,7 @@ import ( // AccessPoint is the subset of the auth cache consumed by the [Client]. type AccessPoint interface { types.Events + services.ProxyGetter } // ClientConfig configures a Client instance. @@ -416,6 +417,7 @@ func (c *Client) sync() { Client: c.config.AccessPoint, Logger: c.config.Log, }, + ProxyGetter: c.config.AccessPoint, ProxyDiffer: func(old, new types.Server) bool { return old.GetPeerAddr() != new.GetPeerAddr() }, @@ -434,7 +436,7 @@ func (c *Client) sync() { case <-proxyWatcher.Done(): c.config.Log.DebugContext(c.ctx, "stopping peer proxy sync: proxy watcher done") return - case proxies := <-proxyWatcher.ProxiesC: + case proxies := <-proxyWatcher.ResourcesC: if err := c.updateConnections(proxies); err != nil { c.config.Log.ErrorContext(c.ctx, "error syncing peer proxies", "error", err) } diff --git a/lib/proxy/router.go b/lib/proxy/router.go index 18e22adc798ee..f54f9718af604 100644 --- a/lib/proxy/router.go +++ b/lib/proxy/router.go @@ -44,6 +44,7 @@ import ( "github.com/gravitational/teleport/lib/observability/metrics" "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/teleagent" "github.com/gravitational/teleport/lib/utils" ) @@ -383,7 +384,7 @@ func (r *Router) getRemoteCluster(ctx context.Context, clusterName string, check // site is the minimum interface needed to match servers // for a reversetunnelclient.RemoteSite. It makes testing easier. type site interface { - GetNodes(ctx context.Context, fn func(n services.Node) bool) ([]types.Server, error) + GetNodes(ctx context.Context, fn func(n readonly.Server) bool) ([]types.Server, error) GetClusterNetworkingConfig(ctx context.Context) (types.ClusterNetworkingConfig, error) } @@ -394,13 +395,13 @@ type remoteSite struct { } // GetNodes uses the wrapped sites NodeWatcher to filter nodes -func (r remoteSite) GetNodes(ctx context.Context, fn func(n services.Node) bool) ([]types.Server, error) { +func (r remoteSite) GetNodes(ctx context.Context, fn func(n readonly.Server) bool) ([]types.Server, error) { watcher, err := r.site.NodeWatcher() if err != nil { return nil, trace.Wrap(err) } - return watcher.GetNodes(ctx, fn), nil + return watcher.CurrentResourcesWithFilter(ctx, fn) } // GetClusterNetworkingConfig uses the wrapped sites cache to retrieve the ClusterNetworkingConfig @@ -450,7 +451,7 @@ func getServerWithResolver(ctx context.Context, host, port string, site site, re var maxScore int scores := make(map[string]int) - matches, err := site.GetNodes(ctx, func(server services.Node) bool { + matches, err := site.GetNodes(ctx, func(server readonly.Server) bool { score := routeMatcher.RouteToServerScore(server) if score < 1 { return false diff --git a/lib/proxy/router_test.go b/lib/proxy/router_test.go index 48268cf355961..177875fda2fd6 100644 --- a/lib/proxy/router_test.go +++ b/lib/proxy/router_test.go @@ -37,7 +37,7 @@ import ( "github.com/gravitational/teleport/lib/cryptosuites" "github.com/gravitational/teleport/lib/observability/tracing" "github.com/gravitational/teleport/lib/reversetunnelclient" - "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/teleagent" "github.com/gravitational/teleport/lib/utils" ) @@ -51,7 +51,7 @@ func (t testSite) GetClusterNetworkingConfig(ctx context.Context) (types.Cluster return t.cfg, nil } -func (t testSite) GetNodes(ctx context.Context, fn func(n services.Node) bool) ([]types.Server, error) { +func (t testSite) GetNodes(ctx context.Context, fn func(n readonly.Server) bool) ([]types.Server, error) { var out []types.Server for _, s := range t.nodes { if fn(s) { diff --git a/lib/reversetunnel/localsite.go b/lib/reversetunnel/localsite.go index 54e9d5db3a680..7c89ea25273b0 100644 --- a/lib/reversetunnel/localsite.go +++ b/lib/reversetunnel/localsite.go @@ -44,6 +44,7 @@ import ( "github.com/gravitational/teleport/lib/reversetunnel/track" "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/srv/forward" "github.com/gravitational/teleport/lib/teleagent" "github.com/gravitational/teleport/lib/utils" @@ -180,7 +181,7 @@ func (s *localSite) CachingAccessPoint() (authclient.RemoteProxyAccessPoint, err } // NodeWatcher returns a services.NodeWatcher for this cluster. -func (s *localSite) NodeWatcher() (*services.NodeWatcher, error) { +func (s *localSite) NodeWatcher() (*services.GenericWatcher[types.Server, readonly.Server], error) { return s.srv.NodeWatcher, nil } @@ -540,10 +541,9 @@ func (s *localSite) setupTunnelForOpenSSHEICENode(ctx context.Context, targetSer } openTunnelClt, err := awsoidc.NewOpenTunnelEC2Client(ctx, &awsoidc.AWSClientRequest{ - IntegrationName: integration.GetName(), - Token: token, - RoleARN: integration.GetAWSOIDCIntegrationSpec().RoleARN, - Region: awsInfo.Region, + Token: token, + RoleARN: integration.GetAWSOIDCIntegrationSpec().RoleARN, + Region: awsInfo.Region, }) if err != nil { return nil, trace.BadParameter("failed to create the ec2 open tunnel client: %v", err) @@ -739,7 +739,11 @@ func (s *localSite) handleHeartbeat(rconn *remoteConn, ch ssh.Channel, reqC <-ch return case <-proxyResyncTicker.Chan(): var req discoveryRequest - req.SetProxies(s.srv.proxyWatcher.GetCurrent()) + proxies, err := s.srv.proxyWatcher.CurrentResources(s.srv.ctx) + if err != nil { + logger.WithError(err).Warn("Failed to get proxy set") + } + req.SetProxies(proxies) if err := rconn.sendDiscoveryRequest(req); err != nil { logger.WithError(err).Debug("Marking connection invalid on error") @@ -764,9 +768,12 @@ func (s *localSite) handleHeartbeat(rconn *remoteConn, ch ssh.Channel, reqC <-ch if firstHeartbeat { // as soon as the agent connects and sends a first heartbeat // send it the list of current proxies back - current := s.srv.proxyWatcher.GetCurrent() - if len(current) > 0 { - rconn.updateProxies(current) + proxies, err := s.srv.proxyWatcher.CurrentResources(s.srv.ctx) + if err != nil { + logger.WithError(err).Warn("Failed to get proxy set") + } + if len(proxies) > 0 { + rconn.updateProxies(proxies) } reverseSSHTunnels.WithLabelValues(rconn.tunnelType).Inc() firstHeartbeat = false @@ -935,7 +942,7 @@ func (s *localSite) periodicFunctions() { // sshTunnelStats reports SSH tunnel statistics for the cluster. func (s *localSite) sshTunnelStats() error { - missing := s.srv.NodeWatcher.GetNodes(s.srv.ctx, func(server services.Node) bool { + missing, err := s.srv.NodeWatcher.CurrentResourcesWithFilter(s.srv.ctx, func(server readonly.Server) bool { // Skip over any servers that have a TTL larger than announce TTL (10 // minutes) and are non-IoT SSH servers (they won't have tunnels). // @@ -967,6 +974,9 @@ func (s *localSite) sshTunnelStats() error { return err != nil }) + if err != nil { + return trace.Wrap(err) + } // Update Prometheus metrics and also log if any tunnels are missing. missingSSHTunnels.Set(float64(len(missing))) diff --git a/lib/reversetunnel/localsite_test.go b/lib/reversetunnel/localsite_test.go index 3397aed763683..195a1e76510c2 100644 --- a/lib/reversetunnel/localsite_test.go +++ b/lib/reversetunnel/localsite_test.go @@ -58,14 +58,16 @@ func TestRemoteConnCleanup(t *testing.T) { clock := clockwork.NewFakeClock() + clt := &mockLocalSiteClient{} watcher, err := services.NewProxyWatcher(ctx, services.ProxyWatcherConfig{ ResourceWatcherConfig: services.ResourceWatcherConfig{ Component: "test", Logger: utils.NewSlogLoggerForTests(), Clock: clock, - Client: &mockLocalSiteClient{}, + Client: clt, }, - ProxiesC: make(chan []types.Server, 2), + ProxyGetter: clt, + ProxiesC: make(chan []types.Server, 2), }) require.NoError(t, err) require.NoError(t, watcher.WaitInitialization()) @@ -249,17 +251,19 @@ func TestProxyResync(t *testing.T) { proxy2, err := types.NewServer(uuid.NewString(), types.KindProxy, types.ServerSpecV2{}) require.NoError(t, err) + clt := &mockLocalSiteClient{ + proxies: []types.Server{proxy1, proxy2}, + } // set up the watcher and wait for it to be initialized watcher, err := services.NewProxyWatcher(ctx, services.ProxyWatcherConfig{ ResourceWatcherConfig: services.ResourceWatcherConfig{ Component: "test", Logger: utils.NewSlogLoggerForTests(), Clock: clock, - Client: &mockLocalSiteClient{ - proxies: []types.Server{proxy1, proxy2}, - }, + Client: clt, }, - ProxiesC: make(chan []types.Server, 2), + ProxyGetter: clt, + ProxiesC: make(chan []types.Server, 2), }) require.NoError(t, err) require.NoError(t, watcher.WaitInitialization()) diff --git a/lib/reversetunnel/peer.go b/lib/reversetunnel/peer.go index fc16cbe11cefa..570be5edf4bbe 100644 --- a/lib/reversetunnel/peer.go +++ b/lib/reversetunnel/peer.go @@ -33,6 +33,7 @@ import ( "github.com/gravitational/teleport/lib/auth/authclient" "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" ) func newClusterPeers(clusterName string) *clusterPeers { @@ -90,7 +91,7 @@ func (p *clusterPeers) CachingAccessPoint() (authclient.RemoteProxyAccessPoint, return peer.CachingAccessPoint() } -func (p *clusterPeers) NodeWatcher() (*services.NodeWatcher, error) { +func (p *clusterPeers) NodeWatcher() (*services.GenericWatcher[types.Server, readonly.Server], error) { peer, err := p.pickPeer() if err != nil { return nil, trace.Wrap(err) @@ -202,7 +203,7 @@ func (s *clusterPeer) CachingAccessPoint() (authclient.RemoteProxyAccessPoint, e return nil, trace.ConnectionProblem(nil, "unable to fetch access point, this proxy %v has not been discovered yet, try again later", s) } -func (s *clusterPeer) NodeWatcher() (*services.NodeWatcher, error) { +func (s *clusterPeer) NodeWatcher() (*services.GenericWatcher[types.Server, readonly.Server], error) { return nil, trace.ConnectionProblem(nil, "unable to fetch node watcher, this proxy %v has not been discovered yet, try again later", s) } diff --git a/lib/reversetunnel/remotesite.go b/lib/reversetunnel/remotesite.go index 8e8b7e4c3fe79..f9617f33b87d5 100644 --- a/lib/reversetunnel/remotesite.go +++ b/lib/reversetunnel/remotesite.go @@ -42,6 +42,7 @@ import ( "github.com/gravitational/teleport/lib/auth/authclient" "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/srv/forward" "github.com/gravitational/teleport/lib/teleagent" "github.com/gravitational/teleport/lib/utils" @@ -85,7 +86,7 @@ type remoteSite struct { remoteAccessPoint authclient.RemoteProxyAccessPoint // nodeWatcher provides access the node set for the remote site - nodeWatcher *services.NodeWatcher + nodeWatcher *services.GenericWatcher[types.Server, readonly.Server] // remoteCA is the last remote certificate authority recorded by the client. // It is used to detect CA rotation status changes. If the rotation @@ -164,7 +165,7 @@ func (s *remoteSite) CachingAccessPoint() (authclient.RemoteProxyAccessPoint, er } // NodeWatcher returns the services.NodeWatcher for the remote cluster. -func (s *remoteSite) NodeWatcher() (*services.NodeWatcher, error) { +func (s *remoteSite) NodeWatcher() (*services.GenericWatcher[types.Server, readonly.Server], error) { return s.nodeWatcher, nil } @@ -429,7 +430,11 @@ func (s *remoteSite) handleHeartbeat(conn *remoteConn, ch ssh.Channel, reqC <-ch return case <-proxyResyncTicker.Chan(): var req discoveryRequest - req.SetProxies(s.srv.proxyWatcher.GetCurrent()) + proxies, err := s.srv.proxyWatcher.CurrentResources(s.srv.ctx) + if err != nil { + logger.WithError(err).Warn("Failed to get proxy set") + } + req.SetProxies(proxies) if err := conn.sendDiscoveryRequest(req); err != nil { logger.WithError(err).Debug("Marking connection invalid on error") @@ -458,9 +463,12 @@ func (s *remoteSite) handleHeartbeat(conn *remoteConn, ch ssh.Channel, reqC <-ch if firstHeartbeat { // as soon as the agent connects and sends a first heartbeat // send it the list of current proxies back - current := s.srv.proxyWatcher.GetCurrent() - if len(current) > 0 { - conn.updateProxies(current) + proxies, err := s.srv.proxyWatcher.CurrentResources(s.srv.ctx) + if err != nil { + logger.WithError(err).Warn("Failed to get proxy set") + } + if len(proxies) > 0 { + conn.updateProxies(proxies) } firstHeartbeat = false } diff --git a/lib/reversetunnel/srv.go b/lib/reversetunnel/srv.go index 19dfd9e2d43ca..4cf45cf81a15f 100644 --- a/lib/reversetunnel/srv.go +++ b/lib/reversetunnel/srv.go @@ -49,6 +49,7 @@ import ( "github.com/gravitational/teleport/lib/proxy/peer" "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/srv/ingress" "github.com/gravitational/teleport/lib/sshca" "github.com/gravitational/teleport/lib/sshutils" @@ -114,7 +115,7 @@ type server struct { // proxyWatcher monitors changes to the proxies // and broadcasts updates - proxyWatcher *services.ProxyWatcher + proxyWatcher *services.GenericWatcher[types.Server, readonly.Server] // offlineThreshold is how long to wait for a keep alive message before // marking a reverse tunnel connection as invalid. @@ -201,7 +202,7 @@ type Config struct { LockWatcher *services.LockWatcher // NodeWatcher is a node watcher. - NodeWatcher *services.NodeWatcher + NodeWatcher *services.GenericWatcher[types.Server, readonly.Server] // CertAuthorityWatcher is a cert authority watcher. CertAuthorityWatcher *services.CertAuthorityWatcher @@ -307,9 +308,6 @@ func NewServer(cfg Config) (reversetunnelclient.Server, error) { }, ProxiesC: make(chan []types.Server, 10), ProxyGetter: cfg.LocalAccessPoint, - ProxyDiffer: func(_, _ types.Server) bool { - return true // we always want to store the most recently heartbeated proxy - }, }) if err != nil { cancel() @@ -401,7 +399,7 @@ func (s *server) periodicFunctions() { s.log.Debugf("Closing.") return // Proxies have been updated, notify connected agents about the update. - case proxies := <-s.proxyWatcher.ProxiesC: + case proxies := <-s.proxyWatcher.ResourcesC: s.fanOutProxies(proxies) case <-ticker.C: if err := s.fetchClusterPeers(); err != nil { diff --git a/lib/reversetunnelclient/api.go b/lib/reversetunnelclient/api.go index f7e8dfb47ef63..e044bf4beb012 100644 --- a/lib/reversetunnelclient/api.go +++ b/lib/reversetunnelclient/api.go @@ -31,6 +31,7 @@ import ( "github.com/gravitational/teleport/lib/auth/authclient" "github.com/gravitational/teleport/lib/proxy/peer" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/teleagent" ) @@ -123,7 +124,7 @@ type RemoteSite interface { // but is resilient to auth server crashes CachingAccessPoint() (authclient.RemoteProxyAccessPoint, error) // NodeWatcher returns the node watcher that maintains the node set for the site - NodeWatcher() (*services.NodeWatcher, error) + NodeWatcher() (*services.GenericWatcher[types.Server, readonly.Server], error) // GetTunnelsCount returns the amount of active inbound tunnels // from the remote cluster GetTunnelsCount() int diff --git a/lib/service/awsoidc.go b/lib/service/awsoidc.go index 7dfedcf62eba7..47baedcac25dd 100644 --- a/lib/service/awsoidc.go +++ b/lib/service/awsoidc.go @@ -265,10 +265,9 @@ func (updater *AWSOIDCDeployServiceUpdater) updateAWSOIDCDeployService(ctx conte } req := &awsoidc.AWSClientRequest{ - IntegrationName: integration.GetName(), - Token: token, - RoleARN: integration.GetAWSOIDCIntegrationSpec().RoleARN, - Region: awsRegion, + Token: token, + RoleARN: integration.GetAWSOIDCIntegrationSpec().RoleARN, + Region: awsRegion, } // The deploy service client is initialized using AWS OIDC integration. diff --git a/lib/service/service.go b/lib/service/service.go index 01e4fdad21224..215fdb0035f00 100644 --- a/lib/service/service.go +++ b/lib/service/service.go @@ -2531,6 +2531,7 @@ func (process *TeleportProcess) newAccessCacheForServices(cfg accesspoint.Config cfg.WindowsDesktops = services.WindowsDesktops cfg.AutoUpdateService = services.AutoUpdateService cfg.ProvisioningStates = services.ProvisioningStates + cfg.IdentityCenter = services.IdentityCenter return accesspoint.NewCache(cfg) } @@ -5025,6 +5026,7 @@ func (process *TeleportProcess) initProxyEndpoint(conn *Connector) error { Logger: process.logger.With(teleport.ComponentKey, teleport.Component(teleport.ComponentReverseTunnelServer, process.id)), Client: accessPoint, }, + KubernetesServerGetter: accessPoint, }) if err != nil { return trace.Wrap(err) diff --git a/lib/service/servicecfg/auth.go b/lib/service/servicecfg/auth.go index 5c56d18b117c1..3663ea25ae0ea 100644 --- a/lib/service/servicecfg/auth.go +++ b/lib/service/servicecfg/auth.go @@ -278,6 +278,11 @@ type AWSKMSConfig struct { AWSAccount string // AWSRegion is the AWS region where the keys will reside. AWSRegion string + // MultiRegion contains configuration for multi-region AWS KMS. + MultiRegion struct { + // Enabled configures new keys to be multi-region. + Enabled bool + } } // CheckAndSetDefaults checks that required parameters of the config are diff --git a/lib/services/identitycenter.go b/lib/services/identitycenter.go index d3fbf6aca9756..e256ab9941025 100644 --- a/lib/services/identitycenter.go +++ b/lib/services/identitycenter.go @@ -204,6 +204,10 @@ type IdentityCenterAccountAssignments interface { // Account Assignment, returning the updated record on success. UpdateAccountAssignment(context.Context, IdentityCenterAccountAssignment) (IdentityCenterAccountAssignment, error) + // UpsertAccountAssignment performs an unconditional update on the supplied + // Account Assignment, returning the updated record on success. + UpsertAccountAssignment(context.Context, IdentityCenterAccountAssignment) (IdentityCenterAccountAssignment, error) + // DeleteAccountAssignment deletes a specific account assignment DeleteAccountAssignment(context.Context, IdentityCenterAccountAssignmentID) error diff --git a/lib/services/local/events.go b/lib/services/local/events.go index 09084857dbf06..2f1c9854da9cd 100644 --- a/lib/services/local/events.go +++ b/lib/services/local/events.go @@ -242,6 +242,12 @@ func (e *EventsService) NewWatcher(ctx context.Context, watch types.Watch) (type parser = newStaticHostUserParser() case types.KindProvisioningPrincipalState: parser = newProvisioningStateParser() + case types.KindIdentityCenterAccount: + parser = newIdentityCenterAccountParser() + case types.KindIdentityCenterPrincipalAssignment: + parser = newIdentityCenterPrincipalAssignmentParser() + case types.KindIdentityCenterAccountAssignment: + parser = newIdentityCenterAccountAssignmentParser() default: if watch.AllowPartialSuccess { continue diff --git a/lib/services/local/identitycenter.go b/lib/services/local/identitycenter.go index a24e433ef3b84..10cdf7777e33b 100644 --- a/lib/services/local/identitycenter.go +++ b/lib/services/local/identitycenter.go @@ -388,6 +388,16 @@ func (svc *IdentityCenterService) UpdateAccountAssignment(ctx context.Context, a return services.IdentityCenterAccountAssignment{AccountAssignment: updated}, nil } +// UpsertAccountAssignment performs an unconditional upsert on the supplied +// Account Assignment, returning the updated record on success. +func (svc *IdentityCenterService) UpsertAccountAssignment(ctx context.Context, asmt services.IdentityCenterAccountAssignment) (services.IdentityCenterAccountAssignment, error) { + updated, err := svc.accountAssignments.UpsertResource(ctx, asmt.AccountAssignment) + if err != nil { + return services.IdentityCenterAccountAssignment{}, trace.Wrap(err, "upserting principal assignment record") + } + return services.IdentityCenterAccountAssignment{AccountAssignment: updated}, nil +} + // DeleteAccountAssignment deletes a specific account assignment func (svc *IdentityCenterService) DeleteAccountAssignment(ctx context.Context, name services.IdentityCenterAccountAssignmentID) error { return trace.Wrap(svc.accountAssignments.DeleteResource(ctx, string(name))) diff --git a/lib/services/local/identitycenter_events.go b/lib/services/local/identitycenter_events.go new file mode 100644 index 0000000000000..b8cc8933b200b --- /dev/null +++ b/lib/services/local/identitycenter_events.go @@ -0,0 +1,162 @@ +// 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 local + +import ( + "strings" + + "github.com/gravitational/trace" + + apidefaults "github.com/gravitational/teleport/api/defaults" + identitycenterv1 "github.com/gravitational/teleport/api/gen/proto/go/teleport/identitycenter/v1" + "github.com/gravitational/teleport/api/types" + "github.com/gravitational/teleport/lib/backend" + "github.com/gravitational/teleport/lib/services" +) + +type identityCenterAccountParser struct { + baseParser + prefix backend.Key +} + +func newIdentityCenterAccountParser() *identityCenterAccountParser { + prefix := backend.NewKey(awsResourcePrefix, awsAccountPrefix) + return &identityCenterAccountParser{ + baseParser: newBaseParser(prefix), + prefix: prefix, + } +} + +func (p *identityCenterAccountParser) parse(event backend.Event) (types.Resource, error) { + switch event.Type { + case types.OpDelete: + name := event.Item.Key.TrimPrefix(p.prefix).String() + if name == "" { + return nil, trace.NotFound("failed parsing %v", event.Item.Key.String()) + } + return &types.ResourceHeader{ + Kind: types.KindIdentityCenterAccount, + Version: types.V1, + Metadata: types.Metadata{ + Name: strings.TrimPrefix(name, backend.SeparatorString), + Namespace: apidefaults.Namespace, + }, + }, nil + case types.OpPut: + r, err := services.UnmarshalProtoResource[*identitycenterv1.Account]( + event.Item.Value, + services.WithExpires(event.Item.Expires), + services.WithRevision(event.Item.Revision), + ) + if err != nil { + return nil, trace.Wrap(err) + } + return types.Resource153ToLegacy(services.IdentityCenterAccount{Account: r}), nil + default: + return nil, trace.BadParameter("event %v is not supported", event.Type) + } +} + +type identityCenterPrincipalAssignmentParser struct { + baseParser + prefix backend.Key +} + +func newIdentityCenterPrincipalAssignmentParser() *identityCenterPrincipalAssignmentParser { + prefix := backend.NewKey(awsResourcePrefix, awsPrincipalAssignmentPrefix) + return &identityCenterPrincipalAssignmentParser{ + baseParser: newBaseParser(prefix), + prefix: prefix, + } +} + +func (p *identityCenterPrincipalAssignmentParser) parse(event backend.Event) (types.Resource, error) { + switch event.Type { + case types.OpDelete: + name := event.Item.Key.TrimPrefix(p.prefix).String() + if name == "" { + return nil, trace.NotFound("failed parsing %v", event.Item.Key.String()) + } + return &types.ResourceHeader{ + Kind: types.KindIdentityCenterPrincipalAssignment, + Version: types.V1, + Metadata: types.Metadata{ + Name: strings.TrimPrefix(name, backend.SeparatorString), + Namespace: apidefaults.Namespace, + }, + }, nil + + case types.OpPut: + r, err := services.UnmarshalProtoResource[*identitycenterv1.PrincipalAssignment]( + event.Item.Value, + services.WithExpires(event.Item.Expires), + services.WithRevision(event.Item.Revision), + ) + if err != nil { + return nil, trace.Wrap(err) + } + return types.Resource153ToLegacy(r), nil + + default: + return nil, trace.BadParameter("event %v is not supported", event.Type) + } +} + +type identityCenterAccountAssignmentParser struct { + baseParser + prefix backend.Key +} + +func newIdentityCenterAccountAssignmentParser() *identityCenterAccountAssignmentParser { + prefix := backend.NewKey(awsResourcePrefix, awsAccountAssignmentPrefix) + return &identityCenterAccountAssignmentParser{ + baseParser: newBaseParser(prefix), + prefix: prefix, + } +} + +func (p *identityCenterAccountAssignmentParser) parse(event backend.Event) (types.Resource, error) { + switch event.Type { + case types.OpDelete: + name := event.Item.Key.TrimPrefix(p.prefix).String() + if name == "" { + return nil, trace.NotFound("failed parsing %v", event.Item.Key.String()) + } + return &types.ResourceHeader{ + Kind: types.KindIdentityCenterAccountAssignment, + Version: types.V1, + Metadata: types.Metadata{ + Name: strings.TrimPrefix(name, backend.SeparatorString), + Namespace: apidefaults.Namespace, + }, + }, nil + case types.OpPut: + r, err := services.UnmarshalProtoResource[*identitycenterv1.AccountAssignment]( + event.Item.Value, + services.WithExpires(event.Item.Expires), + services.WithRevision(event.Item.Revision), + ) + if err != nil { + return nil, trace.Wrap(err) + } + return types.Resource153ToLegacy( + services.IdentityCenterAccountAssignment{AccountAssignment: r}), + nil + default: + return nil, trace.BadParameter("event %v is not supported", event.Type) + } +} diff --git a/lib/services/local/identitycenter_test.go b/lib/services/local/identitycenter_test.go index a15c2a51f323b..b64a98eda5df6 100644 --- a/lib/services/local/identitycenter_test.go +++ b/lib/services/local/identitycenter_test.go @@ -100,6 +100,10 @@ func TestIdentityCenterResourceCRUD(t *testing.T) { asmt := r.(services.IdentityCenterAccountAssignment) return svc.UpdateAccountAssignment(subtestCtx, asmt) }, + upsertResource: func(subtestCtx context.Context, svc services.IdentityCenter, r types.Resource153) (types.Resource153, error) { + asmt := r.(services.IdentityCenterAccountAssignment) + return svc.UpsertAccountAssignment(subtestCtx, asmt) + }, }, { name: "PrincipalAssignment", diff --git a/lib/services/readonly/readonly.go b/lib/services/readonly/readonly.go index db65197a4338a..c4ed3185ace66 100644 --- a/lib/services/readonly/readonly.go +++ b/lib/services/readonly/readonly.go @@ -137,3 +137,317 @@ func (a sealedAccessGraphSettings) SecretsScanConfig() clusterconfigpb.AccessGra func (a sealedAccessGraphSettings) Clone() *clusterconfigpb.AccessGraphSettings { return protobuf.Clone(a.AccessGraphSettings).(*clusterconfigpb.AccessGraphSettings) } + +// Resource is a read only variant of [types.Resource]. +type Resource interface { + // GetKind returns resource kind + GetKind() string + // GetSubKind returns resource subkind + GetSubKind() string + // GetVersion returns resource version + GetVersion() string + // GetName returns the name of the resource + GetName() string + // Expiry returns object expiry setting + Expiry() time.Time + // GetMetadata returns object metadata + GetMetadata() types.Metadata + // GetRevision returns the revision + GetRevision() string +} + +// ResourceWithOrigin is a read only variant of [types.ResourceWithOrigin]. +type ResourceWithOrigin interface { + Resource + // Origin returns the origin value of the resource. + Origin() string +} + +// ResourceWithLabels is a read only variant of [types.ResourceWithLabels]. +type ResourceWithLabels interface { + ResourceWithOrigin + // GetLabel retrieves the label with the provided key. + GetLabel(key string) (value string, ok bool) + // GetAllLabels returns all resource's labels. + GetAllLabels() map[string]string + // GetStaticLabels returns the resource's static labels. + GetStaticLabels() map[string]string + // MatchSearch goes through select field values of a resource + // and tries to match against the list of search values. + MatchSearch(searchValues []string) bool +} + +// Application is a read only variant of [types.Application]. +type Application interface { + // ResourceWithLabels provides common resource methods. + ResourceWithLabels + // GetNamespace returns the app namespace. + GetNamespace() string + // GetStaticLabels returns the app static labels. + GetStaticLabels() map[string]string + // GetDynamicLabels returns the app dynamic labels. + GetDynamicLabels() map[string]types.CommandLabel + // String returns string representation of the app. + String() string + // GetDescription returns the app description. + GetDescription() string + // GetURI returns the app connection endpoint. + GetURI() string + // GetPublicAddr returns the app public address. + GetPublicAddr() string + // GetInsecureSkipVerify returns the app insecure setting. + GetInsecureSkipVerify() bool + // GetRewrite returns the app rewrite configuration. + GetRewrite() *types.Rewrite + // IsAWSConsole returns true if this app is AWS management console. + IsAWSConsole() bool + // IsAzureCloud returns true if this app represents Azure Cloud instance. + IsAzureCloud() bool + // IsGCP returns true if this app represents GCP instance. + IsGCP() bool + // IsTCP returns true if this app represents a TCP endpoint. + IsTCP() bool + // GetProtocol returns the application protocol. + GetProtocol() string + // GetAWSAccountID returns value of label containing AWS account ID on this app. + GetAWSAccountID() string + // GetAWSExternalID returns the AWS External ID configured for this app. + GetAWSExternalID() string + // GetUserGroups will get the list of user group IDs associated with the application. + GetUserGroups() []string + // Copy returns a copy of this app resource. + Copy() *types.AppV3 + // GetIntegration will return the Integration. + // If present, the Application must use the Integration's credentials instead of ambient credentials to access Cloud APIs. + GetIntegration() string + // GetRequiredAppNames will return a list of required apps names that should be authenticated during this apps authentication process. + GetRequiredAppNames() []string + // GetCORS returns the CORS configuration for the app. + GetCORS() *types.CORSPolicy +} + +// KubeServer is a read only variant of [types.KubeServer]. +type KubeServer interface { + // ResourceWithLabels provides common resource methods. + ResourceWithLabels + // GetNamespace returns server namespace. + GetNamespace() string + // GetTeleportVersion returns the teleport version the server is running on. + GetTeleportVersion() string + // GetHostname returns the server hostname. + GetHostname() string + // GetHostID returns ID of the host the server is running on. + GetHostID() string + // GetRotation gets the state of certificate authority rotation. + GetRotation() types.Rotation + // String returns string representation of the server. + String() string + // Copy returns a copy of this kube server object. + Copy() types.KubeServer + // CloneResource returns a copy of the KubeServer as a ResourceWithLabels + CloneResource() types.ResourceWithLabels + // GetCluster returns the Kubernetes Cluster this kube server proxies. + GetCluster() types.KubeCluster + // GetProxyIDs returns a list of proxy ids this service is connected to. + GetProxyIDs() []string +} + +// KubeCluster is a read only variant of [types.KubeCluster]. +type KubeCluster interface { + // ResourceWithLabels provides common resource methods. + ResourceWithLabels + // GetNamespace returns the kube cluster namespace. + GetNamespace() string + // GetStaticLabels returns the kube cluster static labels. + GetStaticLabels() map[string]string + // GetDynamicLabels returns the kube cluster dynamic labels. + GetDynamicLabels() map[string]types.CommandLabel + // GetKubeconfig returns the kubeconfig payload. + GetKubeconfig() []byte + // String returns string representation of the kube cluster. + String() string + // GetDescription returns the kube cluster description. + GetDescription() string + // GetAzureConfig gets the Azure config. + GetAzureConfig() types.KubeAzure + // GetAWSConfig gets the AWS config. + GetAWSConfig() types.KubeAWS + // GetGCPConfig gets the GCP config. + GetGCPConfig() types.KubeGCP + // IsAzure indentifies if the KubeCluster contains Azure details. + IsAzure() bool + // IsAWS indentifies if the KubeCluster contains AWS details. + IsAWS() bool + // IsGCP indentifies if the KubeCluster contains GCP details. + IsGCP() bool + // IsKubeconfig identifies if the KubeCluster contains kubeconfig data. + IsKubeconfig() bool + // Copy returns a copy of this kube cluster resource. + Copy() *types.KubernetesClusterV3 + // GetCloud gets the cloud this kube cluster is running on, or an empty string if it + // isn't running on a cloud provider. + GetCloud() string +} + +// Database is a read only variant of [types.Database]. +type Database interface { + // ResourceWithLabels provides common resource methods. + ResourceWithLabels + // GetNamespace returns the database namespace. + GetNamespace() string + // GetStaticLabels returns the database static labels. + GetStaticLabels() map[string]string + // GetDynamicLabels returns the database dynamic labels. + GetDynamicLabels() map[string]types.CommandLabel + // String returns string representation of the database. + String() string + // GetDescription returns the database description. + GetDescription() string + // GetProtocol returns the database protocol. + GetProtocol() string + // GetURI returns the database connection endpoint. + GetURI() string + // GetCA returns the database CA certificate. + GetCA() string + // GetTLS returns the database TLS configuration. + GetTLS() types.DatabaseTLS + // GetStatusCA gets the database CA certificate in the status field. + GetStatusCA() string + // GetMySQL returns the database options from spec. + GetMySQL() types.MySQLOptions + // GetOracle returns the database options from spec. + GetOracle() types.OracleOptions + // GetMySQLServerVersion returns the MySQL server version either from configuration or + // reported by the database. + GetMySQLServerVersion() string + // GetAWS returns the database AWS metadata. + GetAWS() types.AWS + // GetGCP returns GCP information for Cloud SQL databases. + GetGCP() types.GCPCloudSQL + // GetAzure returns Azure database server metadata. + GetAzure() types.Azure + // GetAD returns Active Directory database configuration. + GetAD() types.AD + // GetType returns the database authentication type: self-hosted, RDS, Redshift or Cloud SQL. + GetType() string + // GetSecretStore returns secret store configurations. + GetSecretStore() types.SecretStore + // GetManagedUsers returns a list of database users that are managed by Teleport. + GetManagedUsers() []string + // GetMongoAtlas returns Mongo Atlas database metadata. + GetMongoAtlas() types.MongoAtlas + // IsRDS returns true if this is an RDS/Aurora database. + IsRDS() bool + // IsRDSProxy returns true if this is an RDS Proxy database. + IsRDSProxy() bool + // IsRedshift returns true if this is a Redshift database. + IsRedshift() bool + // IsCloudSQL returns true if this is a Cloud SQL database. + IsCloudSQL() bool + // IsAzure returns true if this is an Azure database. + IsAzure() bool + // IsElastiCache returns true if this is an AWS ElastiCache database. + IsElastiCache() bool + // IsMemoryDB returns true if this is an AWS MemoryDB database. + IsMemoryDB() bool + // IsAWSHosted returns true if database is hosted by AWS. + IsAWSHosted() bool + // IsCloudHosted returns true if database is hosted in the cloud (AWS, Azure or Cloud SQL). + IsCloudHosted() bool + // RequireAWSIAMRolesAsUsers returns true for database types that require + // AWS IAM roles as database users. + RequireAWSIAMRolesAsUsers() bool + // SupportAWSIAMRoleARNAsUsers returns true for database types that support + // AWS IAM roles as database users. + SupportAWSIAMRoleARNAsUsers() bool + // Copy returns a copy of this database resource. + Copy() *types.DatabaseV3 + // GetAdminUser returns database privileged user information. + GetAdminUser() types.DatabaseAdminUser + // SupportsAutoUsers returns true if this database supports automatic + // user provisioning. + SupportsAutoUsers() bool + // GetEndpointType returns the endpoint type of the database, if available. + GetEndpointType() string + // GetCloud gets the cloud this database is running on, or an empty string if it + // isn't running on a cloud provider. + GetCloud() string + // IsUsernameCaseInsensitive returns true if the database username is case + // insensitive. + IsUsernameCaseInsensitive() bool +} + +// Server is a read only variant of [types.Server]. +type Server interface { + // ResourceWithLabels provides common resource headers + ResourceWithLabels + // GetTeleportVersion returns the teleport version the server is running on + GetTeleportVersion() string + // GetAddr return server address + GetAddr() string + // GetHostname returns server hostname + GetHostname() string + // GetNamespace returns server namespace + GetNamespace() string + // GetLabels returns server's static label key pairs + GetLabels() map[string]string + // GetCmdLabels gets command labels + GetCmdLabels() map[string]types.CommandLabel + // GetPublicAddr returns a public address where this server can be reached. + GetPublicAddr() string + // GetPublicAddrs returns a list of public addresses where this server can be reached. + GetPublicAddrs() []string + // GetRotation gets the state of certificate authority rotation. + GetRotation() types.Rotation + // GetUseTunnel gets if a reverse tunnel should be used to connect to this node. + GetUseTunnel() bool + // String returns string representation of the server + String() string + // GetPeerAddr returns the peer address of the server. + GetPeerAddr() string + // GetProxyIDs returns a list of proxy ids this service is connected to. + GetProxyIDs() []string + // DeepCopy creates a clone of this server value + DeepCopy() types.Server + + // CloneResource is used to return a clone of the Server and match the CloneAny interface + // This is helpful when interfacing with multiple types at the same time in unified resources + CloneResource() types.ResourceWithLabels + + // GetCloudMetadata gets the cloud metadata for the server. + GetCloudMetadata() *types.CloudMetadata + // GetAWSInfo returns the AWSInfo for the server. + GetAWSInfo() *types.AWSInfo + + // IsOpenSSHNode returns whether the connection to this Server must use OpenSSH. + // This returns true for SubKindOpenSSHNode and SubKindOpenSSHEICENode. + IsOpenSSHNode() bool + + // IsEICE returns whether the Node is an EICE instance. + // Must be `openssh-ec2-ice` subkind and have the AccountID and InstanceID information (AWS Metadata or Labels). + IsEICE() bool + + // GetAWSInstanceID returns the AWS Instance ID if this node comes from an EC2 instance. + GetAWSInstanceID() string + // GetAWSAccountID returns the AWS Account ID if this node comes from an EC2 instance. + GetAWSAccountID() string +} + +// DynamicWindowsDesktop represents a Windows desktop host that is automatically discovered by Windows Desktop Service. +type DynamicWindowsDesktop interface { + // ResourceWithLabels provides common resource methods. + ResourceWithLabels + // GetAddr returns the network address of this host. + GetAddr() string + // GetDomain returns the ActiveDirectory domain of this host. + GetDomain() string + // NonAD checks whether this is a standalone host that + // is not joined to an Active Directory domain. + NonAD() bool + // GetScreenSize returns the desired size of the screen to use for sessions + // to this host. Returns (0, 0) if no screen size is set, which means to + // use the size passed by the client over TDP. + GetScreenSize() (width, height uint32) + // Copy returns a copy of this dynamic Windows desktop + Copy() *types.DynamicWindowsDesktopV1 +} diff --git a/lib/services/watcher.go b/lib/services/watcher.go index 93daf0aee5cd6..7699f5459b070 100644 --- a/lib/services/watcher.go +++ b/lib/services/watcher.go @@ -34,6 +34,7 @@ import ( "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/api/utils/retryutils" "github.com/gravitational/teleport/lib/defaults" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/utils" logutils "github.com/gravitational/teleport/lib/utils/log" ) @@ -87,21 +88,21 @@ func watchKindsString(kinds []types.WatchKind) string { // ResourceWatcherConfig configures resource watcher. type ResourceWatcherConfig struct { - // Component is a component used in logs. - Component string + // Clock is used to control time. + Clock clockwork.Clock + // Client is used to create new watchers + Client types.Events // Logger emits log messages. Logger *slog.Logger + // ResetC is a channel to notify of internal watcher reset (used in tests). + ResetC chan time.Duration + // Component is a component used in logs. + Component string // MaxRetryPeriod is the maximum retry period on failed watchers. MaxRetryPeriod time.Duration - // Clock is used to control time. - Clock clockwork.Clock - // Client is used to create new watchers. - Client types.Events // MaxStaleness is a maximum acceptable staleness for the locally maintained // resources, zero implies no staleness detection. MaxStaleness time.Duration - // ResetC is a channel to notify of internal watcher reset (used in tests). - ResetC chan time.Duration // QueueSize is an optional queue size QueueSize int } @@ -165,28 +166,23 @@ func newResourceWatcher(ctx context.Context, collector resourceCollector, cfg Re // resourceWatcher monitors additions, updates and deletions // to a set of resources. type resourceWatcher struct { - ResourceWatcherConfig - collector resourceCollector - - // ctx is a context controlling the lifetime of this resourceWatcher - // instance. - ctx context.Context - cancel context.CancelFunc - - // retry is used to manage backoff logic for watchers. - retry retryutils.Retry - // failureStartedAt records when the current sync failures were first // detected, zero if there are no failures present. failureStartedAt time.Time - + collector resourceCollector + // ctx is a context controlling the lifetime of this resourceWatcher + // instance. + ctx context.Context + // retry is used to manage backoff logic for watchers. + retry retryutils.Retry + cancel context.CancelFunc // LoopC is a channel to check whether the watch loop is running // (used in tests). LoopC chan struct{} - // StaleC is a channel that can trigger the condition of resource staleness // (used in tests). StaleC chan struct{} + ResourceWatcherConfig } // Done returns a channel that signals resource watcher closure. @@ -380,195 +376,523 @@ func (p *resourceWatcher) watch() error { // ProxyWatcherConfig is a ProxyWatcher configuration. type ProxyWatcherConfig struct { - ResourceWatcherConfig // ProxyGetter is used to directly fetch the list of active proxies. ProxyGetter // ProxyDiffer is used to decide whether a put operation on an existing proxy should // trigger a event. ProxyDiffer func(old, new types.Server) bool // ProxiesC is a channel used to report the current proxy set. It receives - // a fresh list at startup and subsequently a list of all known proxies + // a fresh list at startup and subsequently a list of all known proxy // whenever an addition or deletion is detected. ProxiesC chan []types.Server + ResourceWatcherConfig +} + +// NewProxyWatcher returns a new instance of GenericWatcher that is configured +// to watch for changes. +func NewProxyWatcher(ctx context.Context, cfg ProxyWatcherConfig) (*GenericWatcher[types.Server, readonly.Server], error) { + if cfg.ProxyGetter == nil { + return nil, trace.BadParameter("ProxyGetter must be provided") + } + + if cfg.ProxyDiffer == nil { + cfg.ProxyDiffer = func(old, new types.Server) bool { return true } + } + + w, err := NewGenericResourceWatcher(ctx, GenericWatcherConfig[types.Server, readonly.Server]{ + ResourceWatcherConfig: cfg.ResourceWatcherConfig, + ResourceKind: types.KindProxy, + ResourceKey: types.Server.GetName, + ResourceGetter: func(ctx context.Context) ([]types.Server, error) { + return cfg.ProxyGetter.GetProxies() + }, + ResourcesC: cfg.ProxiesC, + ResourceDiffer: cfg.ProxyDiffer, + RequireResourcesForInitialBroadcast: true, + CloneFunc: types.Server.DeepCopy, + }) + return w, trace.Wrap(err) +} + +// DatabaseWatcherConfig is a DatabaseWatcher configuration. +type DatabaseWatcherConfig struct { + // DatabaseGetter is responsible for fetching database resources. + DatabaseGetter + // DatabasesC receives up-to-date list of all database resources. + DatabasesC chan []types.Database + // ResourceWatcherConfig is the resource watcher configuration. + ResourceWatcherConfig +} + +// NewDatabaseWatcher returns a new instance of DatabaseWatcher. +func NewDatabaseWatcher(ctx context.Context, cfg DatabaseWatcherConfig) (*GenericWatcher[types.Database, readonly.Database], error) { + if cfg.DatabaseGetter == nil { + return nil, trace.BadParameter("DatabaseGetter must be provided") + } + + w, err := NewGenericResourceWatcher(ctx, GenericWatcherConfig[types.Database, readonly.Database]{ + ResourceWatcherConfig: cfg.ResourceWatcherConfig, + ResourceKind: types.KindDatabase, + ResourceKey: types.Database.GetName, + ResourceGetter: func(ctx context.Context) ([]types.Database, error) { + return cfg.DatabaseGetter.GetDatabases(ctx) + }, + ResourcesC: cfg.DatabasesC, + CloneFunc: func(resource types.Database) types.Database { + return resource.Copy() + }, + }) + return w, trace.Wrap(err) +} + +// AppWatcherConfig is an AppWatcher configuration. +type AppWatcherConfig struct { + // AppGetter is responsible for fetching application resources. + AppGetter + // AppsC receives up-to-date list of all application resources. + AppsC chan []types.Application + // ResourceWatcherConfig is the resource watcher configuration. + ResourceWatcherConfig +} + +// NewAppWatcher returns a new instance of AppWatcher. +func NewAppWatcher(ctx context.Context, cfg AppWatcherConfig) (*GenericWatcher[types.Application, readonly.Application], error) { + if cfg.AppGetter == nil { + return nil, trace.BadParameter("AppGetter must be provided") + } + + w, err := NewGenericResourceWatcher(ctx, GenericWatcherConfig[types.Application, readonly.Application]{ + ResourceWatcherConfig: cfg.ResourceWatcherConfig, + ResourceKind: types.KindApp, + ResourceKey: types.Application.GetName, + ResourceGetter: func(ctx context.Context) ([]types.Application, error) { + return cfg.AppGetter.GetApps(ctx) + }, + ResourcesC: cfg.AppsC, + CloneFunc: func(resource types.Application) types.Application { + return resource.Copy() + }, + }) + + return w, trace.Wrap(err) +} + +// KubeServerWatcherConfig is an KubeServerWatcher configuration. +type KubeServerWatcherConfig struct { + // KubernetesServerGetter is responsible for fetching kube_server resources. + KubernetesServerGetter + // ResourceWatcherConfig is the resource watcher configuration. + ResourceWatcherConfig +} + +// NewKubeServerWatcher returns a new instance of KubeServerWatcher. +func NewKubeServerWatcher(ctx context.Context, cfg KubeServerWatcherConfig) (*GenericWatcher[types.KubeServer, readonly.KubeServer], error) { + if cfg.KubernetesServerGetter == nil { + return nil, trace.BadParameter("KubernetesServerGetter must be provided") + } + + w, err := NewGenericResourceWatcher(ctx, GenericWatcherConfig[types.KubeServer, readonly.KubeServer]{ + ResourceWatcherConfig: cfg.ResourceWatcherConfig, + ResourceKind: types.KindKubeServer, + ResourceGetter: func(ctx context.Context) ([]types.KubeServer, error) { + return cfg.KubernetesServerGetter.GetKubernetesServers(ctx) + }, + ResourceKey: func(resource types.KubeServer) string { + return resource.GetHostID() + resource.GetName() + }, + DisableUpdateBroadcast: true, + CloneFunc: types.KubeServer.Copy, + }) + return w, trace.Wrap(err) +} + +// KubeClusterWatcherConfig is an KubeClusterWatcher configuration. +type KubeClusterWatcherConfig struct { + // KubernetesGetter is responsible for fetching kube_cluster resources. + KubernetesClusterGetter + // KubeClustersC receives up-to-date list of all kube_cluster resources. + KubeClustersC chan []types.KubeCluster + // ResourceWatcherConfig is the resource watcher configuration. + ResourceWatcherConfig +} + +// NewKubeClusterWatcher returns a new instance of KubeClusterWatcher. +func NewKubeClusterWatcher(ctx context.Context, cfg KubeClusterWatcherConfig) (*GenericWatcher[types.KubeCluster, readonly.KubeCluster], error) { + if cfg.KubernetesClusterGetter == nil { + return nil, trace.BadParameter("KubernetesClusterGetter must be provided") + } + + w, err := NewGenericResourceWatcher(ctx, GenericWatcherConfig[types.KubeCluster, readonly.KubeCluster]{ + ResourceWatcherConfig: cfg.ResourceWatcherConfig, + ResourceKind: types.KindKubernetesCluster, + ResourceGetter: func(ctx context.Context) ([]types.KubeCluster, error) { + return cfg.KubernetesClusterGetter.GetKubernetesClusters(ctx) + }, + ResourceKey: types.KubeCluster.GetName, + ResourcesC: cfg.KubeClustersC, + CloneFunc: func(resource types.KubeCluster) types.KubeCluster { + return resource.Copy() + }, + }) + return w, trace.Wrap(err) +} + +type DynamicWindowsDesktopGetter interface { + ListDynamicWindowsDesktops(ctx context.Context, pageSize int, pageToken string) ([]types.DynamicWindowsDesktop, string, error) +} + +// DynamicWindowsDesktopWatcherConfig is a DynamicWindowsDesktopWatcher configuration. +type DynamicWindowsDesktopWatcherConfig struct { + // DynamicWindowsDesktopGetter is responsible for fetching DynamicWindowsDesktop resources. + DynamicWindowsDesktopGetter + // DynamicWindowsDesktopsC receives up-to-date list of all DynamicWindowsDesktop resources. + DynamicWindowsDesktopsC chan []types.DynamicWindowsDesktop + // ResourceWatcherConfig is the resource watcher configuration. + ResourceWatcherConfig +} + +// NewDynamicWindowsDesktopWatcher returns a new instance of DynamicWindowsDesktopWatcher. +func NewDynamicWindowsDesktopWatcher(ctx context.Context, cfg DynamicWindowsDesktopWatcherConfig) (*GenericWatcher[types.DynamicWindowsDesktop, readonly.DynamicWindowsDesktop], error) { + if cfg.DynamicWindowsDesktopGetter == nil { + return nil, trace.BadParameter("KubernetesClusterGetter must be provided") + } + + w, err := NewGenericResourceWatcher(ctx, GenericWatcherConfig[types.DynamicWindowsDesktop, readonly.DynamicWindowsDesktop]{ + ResourceWatcherConfig: cfg.ResourceWatcherConfig, + ResourceKind: types.KindDynamicWindowsDesktop, + ResourceGetter: func(ctx context.Context) ([]types.DynamicWindowsDesktop, error) { + var desktops []types.DynamicWindowsDesktop + next := "" + for { + d, token, err := cfg.DynamicWindowsDesktopGetter.ListDynamicWindowsDesktops(ctx, defaults.MaxIterationLimit, next) + if err != nil { + return nil, err + } + desktops = append(desktops, d...) + if token == "" { + break + } + next = token + } + return desktops, nil + }, + ResourceKey: types.DynamicWindowsDesktop.GetName, + ResourcesC: cfg.DynamicWindowsDesktopsC, + CloneFunc: func(resource types.DynamicWindowsDesktop) types.DynamicWindowsDesktop { + return resource.Copy() + }, + }) + return w, trace.Wrap(err) +} + +// GenericWatcherConfig is a generic resource watcher configuration. +type GenericWatcherConfig[T any, R any] struct { + // ResourceGetter is used to directly fetch the current set of resources. + ResourceGetter func(context.Context) ([]T, error) + // ResourceDiffer is used to decide whether a put operation on an existing ResourceGetter should + // trigger an event. + ResourceDiffer func(old, new T) bool + // ResourceKey defines how the resources should be keyed. + ResourceKey func(resource T) string + // ResourcesC is a channel used to report the current resourxe set. It receives + // a fresh list at startup and subsequently a list of all known resourxes + // whenever an addition or deletion is detected. + ResourcesC chan []T + // CloneFunc defines how a resource is cloned. All resources provided via + // the broadcast mechanism, or retrieved via [GenericWatcer.CurrentResources] + // or [GenericWatcher.CurrentResourcesWithFilter] will be cloned by this + // mechanism before being provided to callers. + CloneFunc func(resource T) T + ResourceWatcherConfig + // ResourceKind specifies the kind of resource the watcher is monitoring. + ResourceKind string + // RequireResourcesForInitialBroadcast indicates whether an update should be + // performed if the initial set of resources is empty. + RequireResourcesForInitialBroadcast bool + // DisableUpdateBroadcast turns off emitting updates on changes. When this + // mode is opted into, users must invoke [GenericWatcher.CurrentResources] or + // [GenericWatcher.CurrentResourcesWithFilter] manually to retrieve the active + // resource set. + DisableUpdateBroadcast bool } // CheckAndSetDefaults checks parameters and sets default values. -func (cfg *ProxyWatcherConfig) CheckAndSetDefaults() error { +func (cfg *GenericWatcherConfig[T, R]) CheckAndSetDefaults() error { if err := cfg.ResourceWatcherConfig.CheckAndSetDefaults(); err != nil { return trace.Wrap(err) } - if cfg.ProxyGetter == nil { - getter, ok := cfg.Client.(ProxyGetter) - if !ok { - return trace.BadParameter("missing parameter ProxyGetter and Client not usable as ProxyGetter") - } - cfg.ProxyGetter = getter + + if cfg.ResourceGetter == nil { + return trace.BadParameter("ResourceGetter not provided to generic resource watcher") + } + + if cfg.ResourceKind == "" { + return trace.BadParameter("ResourceKind not provided to generic resource watcher") + } + + if cfg.ResourceKey == nil { + return trace.BadParameter("ResourceKey not provided to generic resource watcher") + } + + if cfg.ResourceDiffer == nil { + cfg.ResourceDiffer = func(T, T) bool { return true } } - if cfg.ProxiesC == nil { - cfg.ProxiesC = make(chan []types.Server) + + if cfg.ResourcesC == nil { + cfg.ResourcesC = make(chan []T) } return nil } -// NewProxyWatcher returns a new instance of ProxyWatcher. -func NewProxyWatcher(ctx context.Context, cfg ProxyWatcherConfig) (*ProxyWatcher, error) { +// NewGenericResourceWatcher returns a new instance of resource watcher. +func NewGenericResourceWatcher[T any, R any](ctx context.Context, cfg GenericWatcherConfig[T, R]) (*GenericWatcher[T, R], error) { if err := cfg.CheckAndSetDefaults(); err != nil { return nil, trace.Wrap(err) } - collector := &proxyCollector{ - ProxyWatcherConfig: cfg, - initializationC: make(chan struct{}), + + cache, err := utils.NewFnCache(utils.FnCacheConfig{ + Context: ctx, + TTL: 3 * time.Second, + Clock: cfg.Clock, + }) + if err != nil { + return nil, trace.Wrap(err) + } + + collector := &genericCollector[T, R]{ + GenericWatcherConfig: cfg, + initializationC: make(chan struct{}), + cache: cache, } + collector.stale.Store(true) watcher, err := newResourceWatcher(ctx, collector, cfg.ResourceWatcherConfig) if err != nil { return nil, trace.Wrap(err) } - return &ProxyWatcher{watcher, collector}, nil + return &GenericWatcher[T, R]{watcher, collector}, nil } -// ProxyWatcher is built on top of resourceWatcher to monitor additions -// and deletions to the set of proxies. -type ProxyWatcher struct { +// GenericWatcher is built on top of resourceWatcher to monitor additions +// and deletions to the set of resources. +type GenericWatcher[T any, R any] struct { *resourceWatcher - *proxyCollector + *genericCollector[T, R] +} + +// ResourceCount returns the current number of resources known to the watcher. +func (g *GenericWatcher[T, R]) ResourceCount() int { + g.rw.RLock() + defer g.rw.RUnlock() + return len(g.current) +} + +// CurrentResources returns a copy of the resources known to the watcher. +func (g *GenericWatcher[T, R]) CurrentResources(ctx context.Context) ([]T, error) { + if err := g.refreshStaleResources(ctx); err != nil { + return nil, trace.Wrap(err) + } + + g.rw.RLock() + defer g.rw.RUnlock() + + return resourcesToSlice(g.current, g.CloneFunc), nil +} + +// CurrentResourcesWithFilter returns a copy of the resources known to the watcher +// that match the provided filter. +func (g *GenericWatcher[T, R]) CurrentResourcesWithFilter(ctx context.Context, filter func(R) bool) ([]T, error) { + if err := g.refreshStaleResources(ctx); err != nil { + return nil, trace.Wrap(err) + } + + g.rw.RLock() + defer g.rw.RUnlock() + + r := func(a any) R { + return a.(R) + } + + var out []T + for _, resource := range g.current { + if filter(r(resource)) { + out = append(out, g.CloneFunc(resource)) + } + } + + return out, nil } -// proxyCollector accompanies resourceWatcher when monitoring proxies. -type proxyCollector struct { - ProxyWatcherConfig - // current holds a map of the currently known proxies (keyed by server name, +// genericCollector accompanies resourceWatcher when monitoring proxies. +type genericCollector[T any, R any] struct { + GenericWatcherConfig[T, R] + // current holds a map of the currently known resources (keyed by server name, // RWMutex protected). - current map[string]types.Server - rw sync.RWMutex + current map[string]T initializationC chan struct{} - once sync.Once + // cache is a helper for temporarily storing the results of CurrentResources. + // It's used to limit the number of calls to the backend. + cache *utils.FnCache + rw sync.RWMutex + once sync.Once + // stale is used to indicate that the watcher is stale and needs to be + // refreshed. + stale atomic.Bool } -// GetCurrent returns the currently stored proxies. -func (p *proxyCollector) GetCurrent() []types.Server { - p.rw.RLock() - defer p.rw.RUnlock() - return serverMapValues(p.current) +// resourceKinds specifies the resource kind to watch. +func (g *genericCollector[T, R]) resourceKinds() []types.WatchKind { + return []types.WatchKind{{Kind: g.ResourceKind}} } -// resourceKinds specifies the resource kind to watch. -func (p *proxyCollector) resourceKinds() []types.WatchKind { - return []types.WatchKind{{Kind: types.KindProxy}} +// getResources gets the list of current resources. +func (g *genericCollector[T, R]) getResources(ctx context.Context) (map[string]T, error) { + resources, err := g.GenericWatcherConfig.ResourceGetter(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + current := make(map[string]T, len(resources)) + for _, resource := range resources { + current[g.GenericWatcherConfig.ResourceKey(resource)] = resource + } + return current, nil +} + +func (g *genericCollector[T, R]) refreshStaleResources(ctx context.Context) error { + if !g.stale.Load() { + return nil + } + + _, err := utils.FnCacheGet(ctx, g.cache, g.GenericWatcherConfig.ResourceKind, func(ctx context.Context) (any, error) { + current, err := g.getResources(ctx) + if err != nil { + return nil, trace.Wrap(err) + } + + // There is a chance that the watcher reinitialized while + // getting resources happened above. Check if we are still stale + if g.stale.CompareAndSwap(true, false) { + g.rw.Lock() + g.current = current + g.rw.Unlock() + } + + return nil, nil + }) + + return trace.Wrap(err) } // getResourcesAndUpdateCurrent is called when the resources should be // (re-)fetched directly. -func (p *proxyCollector) getResourcesAndUpdateCurrent(ctx context.Context) error { - proxies, err := p.ProxyGetter.GetProxies() +func (g *genericCollector[T, R]) getResourcesAndUpdateCurrent(ctx context.Context) error { + newCurrent, err := g.getResources(ctx) if err != nil { return trace.Wrap(err) } - newCurrent := make(map[string]types.Server, len(proxies)) - for _, proxy := range proxies { - newCurrent[proxy.GetName()] = proxy - } - p.rw.Lock() - defer p.rw.Unlock() - p.current = newCurrent - // only emit an empty proxy list if the collector has already been initialized - // to prevent an empty slice being sent out on creation of the watcher - if len(proxies) > 0 || (len(proxies) == 0 && p.isInitialized()) { - p.broadcastUpdate(ctx) + g.rw.Lock() + defer g.rw.Unlock() + g.current = newCurrent + g.stale.Store(false) + // Only emit an empty set of resources if the watcher is already initialized, + // or if explicitly opted into by for the watcher. + if len(newCurrent) > 0 || g.isInitialized() || + (!g.RequireResourcesForInitialBroadcast && len(newCurrent) == 0) { + g.broadcastUpdate(ctx) } - p.defineCollectorAsInitialized() + g.defineCollectorAsInitialized() return nil } -func (p *proxyCollector) defineCollectorAsInitialized() { - p.once.Do(func() { +func (g *genericCollector[T, R]) defineCollectorAsInitialized() { + g.once.Do(func() { // mark watcher as initialized. - close(p.initializationC) + close(g.initializationC) }) } // processEventsAndUpdateCurrent is called when a watcher event is received. -func (p *proxyCollector) processEventsAndUpdateCurrent(ctx context.Context, events []types.Event) { - p.rw.Lock() - defer p.rw.Unlock() +func (g *genericCollector[T, R]) processEventsAndUpdateCurrent(ctx context.Context, events []types.Event) { + g.rw.Lock() + defer g.rw.Unlock() var updated bool for _, event := range events { - if event.Resource == nil || event.Resource.GetKind() != types.KindProxy { - p.Logger.WarnContext(ctx, "Received unexpected event", "event", logutils.StringerAttr(event)) + if event.Resource == nil || event.Resource.GetKind() != g.ResourceKind { + g.Logger.WarnContext(ctx, "Received unexpected event", "event", logutils.StringerAttr(event)) continue } switch event.Type { case types.OpDelete: - delete(p.current, event.Resource.GetName()) - // Always broadcast when a proxy is deleted. + // On delete events, the server description is populated with the host ID. + delete(g.current, event.Resource.GetMetadata().Description+event.Resource.GetName()) + // Always broadcast when a resource is deleted. updated = true case types.OpPut: - server, ok := event.Resource.(types.Server) + resource, ok := event.Resource.(T) if !ok { - p.Logger.WarnContext(ctx, "Received unexpected type", "resource", event.Resource.GetKind()) + g.Logger.WarnContext(ctx, "Received unexpected type", "resource", event.Resource.GetKind()) continue } - current, exists := p.current[server.GetName()] - p.current[server.GetName()] = server - if !exists || (p.ProxyDiffer != nil && p.ProxyDiffer(current, server)) { - updated = true - } + + key := g.ResourceKey(resource) + current := g.current[key] + g.current[key] = resource + updated = g.ResourceDiffer(current, resource) default: - p.Logger.WarnContext(ctx, "Skipping unsupported event type", "event_type", event.Type) + g.Logger.WarnContext(ctx, "Skipping unsupported event type", "event_type", event.Type) } } if updated { - p.broadcastUpdate(ctx) + g.broadcastUpdate(ctx) } } -// broadcastUpdate broadcasts information about updating the proxy set. -func (p *proxyCollector) broadcastUpdate(ctx context.Context) { - names := make([]string, 0, len(p.current)) - for k := range p.current { +// broadcastUpdate broadcasts information about updating the resource set. +func (g *genericCollector[T, R]) broadcastUpdate(ctx context.Context) { + if g.DisableUpdateBroadcast { + return + } + + names := make([]string, 0, len(g.current)) + for k := range g.current { names = append(names, k) } - p.Logger.DebugContext(ctx, "List of known proxies updated", "proxies", names) + g.Logger.DebugContext(ctx, "List of known resources updated", "resources", names) select { - case p.ProxiesC <- serverMapValues(p.current): + case g.ResourcesC <- resourcesToSlice(g.current, g.CloneFunc): case <-ctx.Done(): } } // isInitialized is used to check that the cache has done its initial // sync -func (p *proxyCollector) initializationChan() <-chan struct{} { - return p.initializationC +func (g *genericCollector[T, R]) initializationChan() <-chan struct{} { + return g.initializationC } -func (p *proxyCollector) isInitialized() bool { +func (g *genericCollector[T, R]) isInitialized() bool { select { - case <-p.initializationC: + case <-g.initializationC: return true default: return false } } -func (p *proxyCollector) notifyStale() {} - -func serverMapValues(serverMap map[string]types.Server) []types.Server { - servers := make([]types.Server, 0, len(serverMap)) - for _, server := range serverMap { - servers = append(servers, server) - } - return servers +func (g *genericCollector[T, R]) notifyStale() { + g.stale.Store(true) } // LockWatcherConfig is a LockWatcher configuration. type LockWatcherConfig struct { - ResourceWatcherConfig LockGetter + ResourceWatcherConfig } // CheckAndSetDefaults checks parameters and sets default values. @@ -622,15 +946,15 @@ type lockCollector struct { LockWatcherConfig // current holds a map of the currently known locks (keyed by lock name). current map[string]types.Lock - // isStale indicates whether the local lock view (current) is stale. - isStale bool - // currentRW is a mutex protecting both current and isStale. - currentRW sync.RWMutex // fanout provides support for multiple subscribers to the lock updates. fanout *FanoutV2 // initializationC is used to check whether the initial sync has completed initializationC chan struct{} - once sync.Once + // currentRW is a mutex protecting both current and isStale. + currentRW sync.RWMutex + once sync.Once + // isStale indicates whether the local lock view (current) is stale. + isStale bool } // IsStale is used to check whether the lock watcher is stale. @@ -817,858 +1141,37 @@ func lockMapValues(lockMap map[string]types.Lock) []types.Lock { return locks } -// DatabaseWatcherConfig is a DatabaseWatcher configuration. -type DatabaseWatcherConfig struct { +func resourcesToSlice[T any](resources map[string]T, cloneFunc func(T) T) (slice []T) { + for _, resource := range resources { + slice = append(slice, cloneFunc(resource)) + } + return slice +} + +// CertAuthorityWatcherConfig is a CertAuthorityWatcher configuration. +type CertAuthorityWatcherConfig struct { // ResourceWatcherConfig is the resource watcher configuration. ResourceWatcherConfig - // DatabaseGetter is responsible for fetching database resources. - DatabaseGetter - // DatabasesC receives up-to-date list of all database resources. - DatabasesC chan types.Databases + // AuthorityGetter is responsible for fetching cert authority resources. + AuthorityGetter + // Types restricts which cert authority types are retrieved via the AuthorityGetter. + Types []types.CertAuthType } // CheckAndSetDefaults checks parameters and sets default values. -func (cfg *DatabaseWatcherConfig) CheckAndSetDefaults() error { +func (cfg *CertAuthorityWatcherConfig) CheckAndSetDefaults() error { if err := cfg.ResourceWatcherConfig.CheckAndSetDefaults(); err != nil { return trace.Wrap(err) } - if cfg.DatabaseGetter == nil { - getter, ok := cfg.Client.(DatabaseGetter) + if cfg.AuthorityGetter == nil { + getter, ok := cfg.Client.(AuthorityGetter) if !ok { - return trace.BadParameter("missing parameter DatabaseGetter and Client not usable as DatabaseGetter") + return trace.BadParameter("missing parameter AuthorityGetter and Client not usable as AuthorityGetter") } - cfg.DatabaseGetter = getter + cfg.AuthorityGetter = getter } - if cfg.DatabasesC == nil { - cfg.DatabasesC = make(chan types.Databases) - } - return nil -} - -// NewDatabaseWatcher returns a new instance of DatabaseWatcher. -func NewDatabaseWatcher(ctx context.Context, cfg DatabaseWatcherConfig) (*DatabaseWatcher, error) { - if err := cfg.CheckAndSetDefaults(); err != nil { - return nil, trace.Wrap(err) - } - collector := &databaseCollector{ - DatabaseWatcherConfig: cfg, - initializationC: make(chan struct{}), - } - watcher, err := newResourceWatcher(ctx, collector, cfg.ResourceWatcherConfig) - if err != nil { - return nil, trace.Wrap(err) - } - return &DatabaseWatcher{watcher, collector}, nil -} - -// DatabaseWatcher is built on top of resourceWatcher to monitor database resources. -type DatabaseWatcher struct { - *resourceWatcher - *databaseCollector -} - -// databaseCollector accompanies resourceWatcher when monitoring database resources. -type databaseCollector struct { - // DatabaseWatcherConfig is the watcher configuration. - DatabaseWatcherConfig - // current holds a map of the currently known database resources. - current map[string]types.Database - // lock protects the "current" map. - lock sync.RWMutex - // initializationC is used to check that the - initializationC chan struct{} - once sync.Once -} - -// resourceKinds specifies the resource kind to watch. -func (p *databaseCollector) resourceKinds() []types.WatchKind { - return []types.WatchKind{{Kind: types.KindDatabase}} -} - -// isInitialized is used to check that the cache has done its initial -// sync -func (p *databaseCollector) initializationChan() <-chan struct{} { - return p.initializationC -} - -// getResourcesAndUpdateCurrent refreshes the list of current resources. -func (p *databaseCollector) getResourcesAndUpdateCurrent(ctx context.Context) error { - databases, err := p.DatabaseGetter.GetDatabases(ctx) - if err != nil { - return trace.Wrap(err) - } - newCurrent := make(map[string]types.Database, len(databases)) - for _, database := range databases { - newCurrent[database.GetName()] = database - } - p.lock.Lock() - defer p.lock.Unlock() - p.current = newCurrent - p.defineCollectorAsInitialized() - - select { - case <-ctx.Done(): - return trace.Wrap(ctx.Err()) - case p.DatabasesC <- databases: - } - - return nil -} - -func (p *databaseCollector) defineCollectorAsInitialized() { - p.once.Do(func() { - // mark watcher as initialized. - close(p.initializationC) - }) -} - -// processEventsAndUpdateCurrent is called when a watcher event is received. -func (p *databaseCollector) processEventsAndUpdateCurrent(ctx context.Context, events []types.Event) { - p.lock.Lock() - defer p.lock.Unlock() - - var updated bool - for _, event := range events { - if event.Resource == nil || event.Resource.GetKind() != types.KindDatabase { - p.Logger.WarnContext(ctx, "Received unexpected event", "event", logutils.StringerAttr(event)) - continue - } - switch event.Type { - case types.OpDelete: - delete(p.current, event.Resource.GetName()) - updated = true - case types.OpPut: - database, ok := event.Resource.(types.Database) - if !ok { - p.Logger.WarnContext(ctx, "Received unexpected resource type", "resource", event.Resource.GetKind()) - continue - } - p.current[database.GetName()] = database - updated = true - default: - p.Logger.WarnContext(ctx, "Received unsupported event type", "event_type", event.Type) - } - } - - if updated { - select { - case <-ctx.Done(): - case p.DatabasesC <- resourcesToSlice(p.current): - } - } -} - -func (*databaseCollector) notifyStale() {} - -type DynamicWindowsDesktopGetter interface { - ListDynamicWindowsDesktops(ctx context.Context, pageSize int, pageToken string) ([]types.DynamicWindowsDesktop, string, error) -} - -// DynamicWindowsDesktopWatcherConfig is a DynamicWindowsDesktopWatcher configuration. -type DynamicWindowsDesktopWatcherConfig struct { - // ResourceWatcherConfig is the resource watcher configuration. - ResourceWatcherConfig - // DynamicWindowsDesktopGetter is responsible for fetching DynamicWindowsDesktop resources. - DynamicWindowsDesktopGetter - // DynamicWindowsDesktopsC receives up-to-date list of all DynamicWindowsDesktop resources. - DynamicWindowsDesktopsC chan types.DynamicWindowsDesktops -} - -// CheckAndSetDefaults checks parameters and sets default values. -func (cfg *DynamicWindowsDesktopWatcherConfig) CheckAndSetDefaults() error { - if err := cfg.ResourceWatcherConfig.CheckAndSetDefaults(); err != nil { - return trace.Wrap(err) - } - if cfg.DynamicWindowsDesktopGetter == nil { - getter, ok := cfg.Client.(DynamicWindowsDesktopGetter) - if !ok { - return trace.BadParameter("missing parameter DynamicWindowsDesktopGetter and Client %T not usable as DynamicWindowsDesktopGetter", cfg.Client) - } - cfg.DynamicWindowsDesktopGetter = getter - } - if cfg.DynamicWindowsDesktopsC == nil { - cfg.DynamicWindowsDesktopsC = make(chan types.DynamicWindowsDesktops) - } - return nil -} - -// NewDynamicWindowsDesktopWatcher returns a new instance of DynamicWindowsDesktopWatcher. -func NewDynamicWindowsDesktopWatcher(ctx context.Context, cfg DynamicWindowsDesktopWatcherConfig) (*DynamicWindowsDesktopWatcher, error) { - if err := cfg.CheckAndSetDefaults(); err != nil { - return nil, trace.Wrap(err) - } - collector := &dynamicWindowsDesktopCollector{ - DynamicWindowsDesktopWatcherConfig: cfg, - initializationC: make(chan struct{}), - } - watcher, err := newResourceWatcher(ctx, collector, cfg.ResourceWatcherConfig) - if err != nil { - return nil, trace.Wrap(err) - } - return &DynamicWindowsDesktopWatcher{watcher, collector}, nil -} - -// DynamicWindowsDesktopWatcher is built on top of resourceWatcher to monitor DynamicWindowsDesktop resources. -type DynamicWindowsDesktopWatcher struct { - *resourceWatcher - *dynamicWindowsDesktopCollector -} - -// dynamicWindowsDesktopCollector accompanies resourceWatcher when monitoring DynamicWindowsDesktop resources. -type dynamicWindowsDesktopCollector struct { - // DynamicWindowsDesktopWatcherConfig is the watcher configuration. - DynamicWindowsDesktopWatcherConfig - // current holds a map of the currently known DynamicWindowsDesktop resources. - current map[string]types.DynamicWindowsDesktop - // lock protects the "current" map. - lock sync.RWMutex - // initializationC is used to check that the - initializationC chan struct{} - once sync.Once -} - -// resourceKinds specifies the resource kind to watch. -func (p *dynamicWindowsDesktopCollector) resourceKinds() []types.WatchKind { - return []types.WatchKind{{Kind: types.KindDynamicWindowsDesktop}} -} - -// isInitialized is used to check that the cache has done its initial -// sync -func (p *dynamicWindowsDesktopCollector) initializationChan() <-chan struct{} { - return p.initializationC -} - -// getResourcesAndUpdateCurrent refreshes the list of current resources. -func (p *dynamicWindowsDesktopCollector) getResourcesAndUpdateCurrent(ctx context.Context) error { - var dynamicWindowsDesktops []types.DynamicWindowsDesktop - next := "" - for { - desktops, token, err := p.DynamicWindowsDesktopGetter.ListDynamicWindowsDesktops(ctx, defaults.MaxIterationLimit, next) - if err != nil { - return trace.Wrap(err) - } - dynamicWindowsDesktops = append(dynamicWindowsDesktops, desktops...) - if token == "" { - break - } - next = token - } - newCurrent := make(map[string]types.DynamicWindowsDesktop, len(dynamicWindowsDesktops)) - for _, dynamicWindowsDesktop := range dynamicWindowsDesktops { - newCurrent[dynamicWindowsDesktop.GetName()] = dynamicWindowsDesktop - } - p.lock.Lock() - defer p.lock.Unlock() - p.current = newCurrent - p.defineCollectorAsInitialized() - - select { - case <-ctx.Done(): - return trace.Wrap(ctx.Err()) - case p.DynamicWindowsDesktopsC <- dynamicWindowsDesktops: - } - - return nil -} - -func (p *dynamicWindowsDesktopCollector) defineCollectorAsInitialized() { - p.once.Do(func() { - // mark watcher as initialized. - close(p.initializationC) - }) -} - -// processEventsAndUpdateCurrent is called when a watcher event is received. -func (p *dynamicWindowsDesktopCollector) processEventsAndUpdateCurrent(ctx context.Context, events []types.Event) { - p.lock.Lock() - defer p.lock.Unlock() - - var updated bool - for _, event := range events { - if event.Resource == nil || event.Resource.GetKind() != types.KindDynamicWindowsDesktop { - p.Logger.WarnContext(ctx, "Received unexpected event", "event", logutils.StringerAttr(event)) - continue - } - switch event.Type { - case types.OpDelete: - delete(p.current, event.Resource.GetName()) - updated = true - case types.OpPut: - dynamicWindowsDesktop, ok := event.Resource.(types.DynamicWindowsDesktop) - if !ok { - p.Logger.WarnContext(ctx, "Received unexpected resource type", "resource", event.Resource.GetKind()) - continue - } - p.current[dynamicWindowsDesktop.GetName()] = dynamicWindowsDesktop - updated = true - default: - p.Logger.WarnContext(ctx, "Received unsupported event type", "event_type", event.Type) - } - } - - if updated { - select { - case <-ctx.Done(): - case p.DynamicWindowsDesktopsC <- resourcesToSlice(p.current): - } - } -} - -func (*dynamicWindowsDesktopCollector) notifyStale() {} - -// AppWatcherConfig is an AppWatcher configuration. -type AppWatcherConfig struct { - // ResourceWatcherConfig is the resource watcher configuration. - ResourceWatcherConfig - // AppGetter is responsible for fetching application resources. - AppGetter - // AppsC receives up-to-date list of all application resources. - AppsC chan types.Apps -} - -// CheckAndSetDefaults checks parameters and sets default values. -func (cfg *AppWatcherConfig) CheckAndSetDefaults() error { - if err := cfg.ResourceWatcherConfig.CheckAndSetDefaults(); err != nil { - return trace.Wrap(err) - } - if cfg.AppGetter == nil { - getter, ok := cfg.Client.(AppGetter) - if !ok { - return trace.BadParameter("missing parameter AppGetter and Client not usable as AppGetter") - } - cfg.AppGetter = getter - } - if cfg.AppsC == nil { - cfg.AppsC = make(chan types.Apps) - } - return nil -} - -// NewAppWatcher returns a new instance of AppWatcher. -func NewAppWatcher(ctx context.Context, cfg AppWatcherConfig) (*AppWatcher, error) { - if err := cfg.CheckAndSetDefaults(); err != nil { - return nil, trace.Wrap(err) - } - collector := &appCollector{ - AppWatcherConfig: cfg, - initializationC: make(chan struct{}), - } - watcher, err := newResourceWatcher(ctx, collector, cfg.ResourceWatcherConfig) - if err != nil { - return nil, trace.Wrap(err) - } - return &AppWatcher{watcher, collector}, nil -} - -// AppWatcher is built on top of resourceWatcher to monitor application resources. -type AppWatcher struct { - *resourceWatcher - *appCollector -} - -// appCollector accompanies resourceWatcher when monitoring application resources. -type appCollector struct { - // AppWatcherConfig is the watcher configuration. - AppWatcherConfig - // current holds a map of the currently known application resources. - current map[string]types.Application - // lock protects the "current" map. - lock sync.RWMutex - // initializationC is used to check whether the initial sync has completed - initializationC chan struct{} - once sync.Once -} - -// resourceKinds specifies the resource kind to watch. -func (p *appCollector) resourceKinds() []types.WatchKind { - return []types.WatchKind{{Kind: types.KindApp}} -} - -// isInitialized is used to check that the cache has done its initial -// sync -func (p *appCollector) initializationChan() <-chan struct{} { - return p.initializationC -} - -// getResourcesAndUpdateCurrent refreshes the list of current resources. -func (p *appCollector) getResourcesAndUpdateCurrent(ctx context.Context) error { - apps, err := p.AppGetter.GetApps(ctx) - if err != nil { - return trace.Wrap(err) - } - newCurrent := make(map[string]types.Application, len(apps)) - for _, app := range apps { - newCurrent[app.GetName()] = app - } - p.lock.Lock() - defer p.lock.Unlock() - p.current = newCurrent - p.defineCollectorAsInitialized() - select { - case <-ctx.Done(): - return trace.Wrap(ctx.Err()) - case p.AppsC <- apps: - } - return nil -} - -func (p *appCollector) defineCollectorAsInitialized() { - p.once.Do(func() { - // mark watcher as initialized. - close(p.initializationC) - }) -} - -// processEventsAndUpdateCurrent is called when a watcher event is received. -func (p *appCollector) processEventsAndUpdateCurrent(ctx context.Context, events []types.Event) { - p.lock.Lock() - defer p.lock.Unlock() - for _, event := range events { - if event.Resource == nil || event.Resource.GetKind() != types.KindApp { - p.Logger.WarnContext(ctx, "Received unexpected event", "event", logutils.StringerAttr(event)) - continue - } - switch event.Type { - case types.OpDelete: - delete(p.current, event.Resource.GetName()) - p.AppsC <- resourcesToSlice(p.current) - - select { - case <-ctx.Done(): - case p.AppsC <- resourcesToSlice(p.current): - } - - case types.OpPut: - app, ok := event.Resource.(types.Application) - if !ok { - p.Logger.WarnContext(ctx, "Received unexpected resource type", "resource", event.Resource.GetKind()) - continue - } - p.current[app.GetName()] = app - - select { - case <-ctx.Done(): - case p.AppsC <- resourcesToSlice(p.current): - } - default: - p.Logger.WarnContext(ctx, "Received unsupported event type", "event_type", event.Type) - } - } -} - -func (*appCollector) notifyStale() {} - -func resourcesToSlice[T any](resources map[string]T) (slice []T) { - for _, resource := range resources { - slice = append(slice, resource) - } - return slice -} - -// KubeClusterWatcherConfig is an KubeClusterWatcher configuration. -type KubeClusterWatcherConfig struct { - // ResourceWatcherConfig is the resource watcher configuration. - ResourceWatcherConfig - // KubernetesGetter is responsible for fetching kube_cluster resources. - KubernetesClusterGetter - // KubeClustersC receives up-to-date list of all kube_cluster resources. - KubeClustersC chan types.KubeClusters -} - -// CheckAndSetDefaults checks parameters and sets default values. -func (cfg *KubeClusterWatcherConfig) CheckAndSetDefaults() error { - if err := cfg.ResourceWatcherConfig.CheckAndSetDefaults(); err != nil { - return trace.Wrap(err) - } - if cfg.KubernetesClusterGetter == nil { - getter, ok := cfg.Client.(KubernetesClusterGetter) - if !ok { - return trace.BadParameter("missing parameter KubernetesGetter and Client not usable as KubernetesGetter") - } - cfg.KubernetesClusterGetter = getter - } - if cfg.KubeClustersC == nil { - cfg.KubeClustersC = make(chan types.KubeClusters) - } - return nil -} - -// NewKubeClusterWatcher returns a new instance of KubeClusterWatcher. -func NewKubeClusterWatcher(ctx context.Context, cfg KubeClusterWatcherConfig) (*KubeClusterWatcher, error) { - if err := cfg.CheckAndSetDefaults(); err != nil { - return nil, trace.Wrap(err) - } - collector := &kubeCollector{ - KubeClusterWatcherConfig: cfg, - initializationC: make(chan struct{}), - } - watcher, err := newResourceWatcher(ctx, collector, cfg.ResourceWatcherConfig) - if err != nil { - return nil, trace.Wrap(err) - } - return &KubeClusterWatcher{watcher, collector}, nil -} - -// KubeClusterWatcher is built on top of resourceWatcher to monitor kube_cluster resources. -type KubeClusterWatcher struct { - *resourceWatcher - *kubeCollector -} - -// kubeCollector accompanies resourceWatcher when monitoring kube_cluster resources. -type kubeCollector struct { - // KubeClusterWatcherConfig is the watcher configuration. - KubeClusterWatcherConfig - // current holds a map of the currently known kube_cluster resources. - current map[string]types.KubeCluster - // lock protects the "current" map. - lock sync.RWMutex - // initializationC is used to check whether the initial sync has completed - initializationC chan struct{} - once sync.Once -} - -// isInitialized is used to check that the cache has done its initial -// sync -func (k *kubeCollector) initializationChan() <-chan struct{} { - return k.initializationC -} - -// resourceKinds specifies the resource kind to watch. -func (k *kubeCollector) resourceKinds() []types.WatchKind { - return []types.WatchKind{{Kind: types.KindKubernetesCluster}} -} - -// getResourcesAndUpdateCurrent refreshes the list of current resources. -func (k *kubeCollector) getResourcesAndUpdateCurrent(ctx context.Context) error { - clusters, err := k.KubernetesClusterGetter.GetKubernetesClusters(ctx) - if err != nil { - return trace.Wrap(err) - } - newCurrent := make(map[string]types.KubeCluster, len(clusters)) - for _, cluster := range clusters { - newCurrent[cluster.GetName()] = cluster - } - k.lock.Lock() - defer k.lock.Unlock() - k.current = newCurrent - - select { - case <-ctx.Done(): - return trace.Wrap(ctx.Err()) - case k.KubeClustersC <- clusters: - } - - k.defineCollectorAsInitialized() - - return nil -} - -func (k *kubeCollector) defineCollectorAsInitialized() { - k.once.Do(func() { - // mark watcher as initialized. - close(k.initializationC) - }) -} - -// processEventsAndUpdateCurrent is called when a watcher event is received. -func (k *kubeCollector) processEventsAndUpdateCurrent(ctx context.Context, events []types.Event) { - k.lock.Lock() - defer k.lock.Unlock() - for _, event := range events { - if event.Resource == nil || event.Resource.GetKind() != types.KindKubernetesCluster { - k.Logger.WarnContext(ctx, "Received unexpected event", "event", logutils.StringerAttr(event)) - continue - } - switch event.Type { - case types.OpDelete: - delete(k.current, event.Resource.GetName()) - k.KubeClustersC <- resourcesToSlice(k.current) - - select { - case <-ctx.Done(): - case k.KubeClustersC <- resourcesToSlice(k.current): - } - - case types.OpPut: - cluster, ok := event.Resource.(types.KubeCluster) - if !ok { - k.Logger.WarnContext(ctx, "Received unexpected resource type", "resource", event.Resource.GetKind()) - continue - } - k.current[cluster.GetName()] = cluster - - select { - case <-ctx.Done(): - case k.KubeClustersC <- resourcesToSlice(k.current): - } - default: - k.Logger.WarnContext(ctx, "Received unsupported event type", "event_type", event.Type) - } - } -} - -func (*kubeCollector) notifyStale() {} - -// KubeServerWatcherConfig is an KubeServerWatcher configuration. -type KubeServerWatcherConfig struct { - // ResourceWatcherConfig is the resource watcher configuration. - ResourceWatcherConfig - // KubernetesServerGetter is responsible for fetching kube_server resources. - KubernetesServerGetter -} - -// CheckAndSetDefaults checks parameters and sets default values. -func (cfg *KubeServerWatcherConfig) CheckAndSetDefaults() error { - if err := cfg.ResourceWatcherConfig.CheckAndSetDefaults(); err != nil { - return trace.Wrap(err) - } - if cfg.KubernetesServerGetter == nil { - getter, ok := cfg.Client.(KubernetesServerGetter) - if !ok { - return trace.BadParameter("missing parameter KubernetesServerGetter and Client not usable as KubernetesServerGetter") - } - cfg.KubernetesServerGetter = getter - } - return nil -} - -// NewKubeServerWatcher returns a new instance of KubeServerWatcher. -func NewKubeServerWatcher(ctx context.Context, cfg KubeServerWatcherConfig) (*KubeServerWatcher, error) { - if err := cfg.CheckAndSetDefaults(); err != nil { - return nil, trace.Wrap(err) - } - cache, err := utils.NewFnCache(utils.FnCacheConfig{ - Context: ctx, - TTL: 3 * time.Second, - Clock: cfg.Clock, - }) - if err != nil { - return nil, trace.Wrap(err) - } - collector := &kubeServerCollector{ - KubeServerWatcherConfig: cfg, - initializationC: make(chan struct{}), - cache: cache, - } - // start the collector as staled. - collector.stale.Store(true) - watcher, err := newResourceWatcher(ctx, collector, cfg.ResourceWatcherConfig) - if err != nil { - return nil, trace.Wrap(err) - } - return &KubeServerWatcher{watcher, collector}, nil -} - -// KubeServerWatcher is built on top of resourceWatcher to monitor kube_server resources. -type KubeServerWatcher struct { - *resourceWatcher - *kubeServerCollector -} - -// GetKubeServersByClusterName returns a list of kubernetes servers for the specified cluster. -func (k *KubeServerWatcher) GetKubeServersByClusterName(ctx context.Context, clusterName string) ([]types.KubeServer, error) { - k.refreshStaleKubeServers(ctx) - - k.lock.RLock() - defer k.lock.RUnlock() - var servers []types.KubeServer - for _, server := range k.current { - if server.GetCluster().GetName() == clusterName { - servers = append(servers, server.Copy()) - } - } - if len(servers) == 0 { - return nil, trace.NotFound("no kubernetes servers found for cluster %q", clusterName) - } - - return servers, nil -} - -// GetKubernetesServers returns a list of kubernetes servers for all clusters. -func (k *KubeServerWatcher) GetKubernetesServers(ctx context.Context) ([]types.KubeServer, error) { - k.refreshStaleKubeServers(ctx) - - k.lock.RLock() - defer k.lock.RUnlock() - servers := make([]types.KubeServer, 0, len(k.current)) - for _, server := range k.current { - servers = append(servers, server.Copy()) - } - return servers, nil -} - -// kubeServerCollector accompanies resourceWatcher when monitoring kube_server resources. -type kubeServerCollector struct { - // KubeServerWatcherConfig is the watcher configuration. - KubeServerWatcherConfig - // current holds a map of the currently known kube_server resources. - current map[kubeServersKey]types.KubeServer - // lock protects the "current" map. - lock sync.RWMutex - // initializationC is used to check whether the initial sync has completed - initializationC chan struct{} - once sync.Once - // stale is used to indicate that the watcher is stale and needs to be - // refreshed. - stale atomic.Bool - // cache is a helper for temporarily storing the results of GetKubernetesServers. - // It's used to limit the amount of calls to the backend. - cache *utils.FnCache -} - -// kubeServersKey is used to uniquely identify a kube_server resource. -type kubeServersKey struct { - hostID string - resourceName string -} - -// isInitialized is used to check that the cache has done its initial -// sync -func (k *kubeServerCollector) initializationChan() <-chan struct{} { - return k.initializationC -} - -// resourceKinds specifies the resource kind to watch. -func (k *kubeServerCollector) resourceKinds() []types.WatchKind { - return []types.WatchKind{{Kind: types.KindKubeServer}} -} - -// getResourcesAndUpdateCurrent refreshes the list of current resources. -func (k *kubeServerCollector) getResourcesAndUpdateCurrent(ctx context.Context) error { - newCurrent, err := k.getResources(ctx) - if err != nil { - return trace.Wrap(err) - } - - k.lock.Lock() - k.current = newCurrent - k.lock.Unlock() - - k.stale.Store(false) - - k.defineCollectorAsInitialized() - return nil -} - -// getResourcesAndUpdateCurrent gets the list of current resources. -func (k *kubeServerCollector) getResources(ctx context.Context) (map[kubeServersKey]types.KubeServer, error) { - servers, err := k.KubernetesServerGetter.GetKubernetesServers(ctx) - if err != nil { - return nil, trace.Wrap(err) - } - current := make(map[kubeServersKey]types.KubeServer, len(servers)) - for _, server := range servers { - key := kubeServersKey{ - hostID: server.GetHostID(), - resourceName: server.GetName(), - } - current[key] = server - } - return current, nil -} - -func (k *kubeServerCollector) defineCollectorAsInitialized() { - k.once.Do(func() { - // mark watcher as initialized. - close(k.initializationC) - }) -} - -// processEventsAndUpdateCurrent is called when a watcher event is received. -func (k *kubeServerCollector) processEventsAndUpdateCurrent(ctx context.Context, events []types.Event) { - k.lock.Lock() - defer k.lock.Unlock() - - for _, event := range events { - if event.Resource == nil || event.Resource.GetKind() != types.KindKubeServer { - k.Logger.WarnContext(ctx, "Received unexpected event", "event", logutils.StringerAttr(event)) - continue - } - - switch event.Type { - case types.OpDelete: - key := kubeServersKey{ - // On delete events, the server description is populated with the host ID. - hostID: event.Resource.GetMetadata().Description, - resourceName: event.Resource.GetName(), - } - delete(k.current, key) - case types.OpPut: - server, ok := event.Resource.(types.KubeServer) - if !ok { - k.Logger.WarnContext(ctx, "Received unexpected resource type", "resource", event.Resource.GetKind()) - continue - } - - key := kubeServersKey{ - hostID: server.GetHostID(), - resourceName: server.GetName(), - } - k.current[key] = server - default: - k.Logger.WarnContext(ctx, "Received unsupported event type", "event_type", event.Type) - } - } -} - -func (k *kubeServerCollector) notifyStale() { - k.stale.Store(true) -} - -// refreshStaleKubeServers attempts to reload kube servers from the cache if -// the collector is stale. This ensures that no matter the health of -// the collector callers will be returned the most up to date node -// set as possible. -func (k *kubeServerCollector) refreshStaleKubeServers(ctx context.Context) error { - if !k.stale.Load() { - return nil - } - - _, err := utils.FnCacheGet(ctx, k.cache, "kube_servers", func(ctx context.Context) (any, error) { - current, err := k.getResources(ctx) - if err != nil { - return nil, trace.Wrap(err) - } - - // There is a chance that the watcher reinitialized while - // getting kube servers happened above. Check if we are still stale - if k.stale.CompareAndSwap(true, false) { - k.lock.Lock() - k.current = current - k.lock.Unlock() - } - - return nil, nil - }) - - return trace.Wrap(err) -} - -// CertAuthorityWatcherConfig is a CertAuthorityWatcher configuration. -type CertAuthorityWatcherConfig struct { - // ResourceWatcherConfig is the resource watcher configuration. - ResourceWatcherConfig - // AuthorityGetter is responsible for fetching cert authority resources. - AuthorityGetter - // Types restricts which cert authority types are retrieved via the AuthorityGetter. - Types []types.CertAuthType -} - -// CheckAndSetDefaults checks parameters and sets default values. -func (cfg *CertAuthorityWatcherConfig) CheckAndSetDefaults() error { - if err := cfg.ResourceWatcherConfig.CheckAndSetDefaults(); err != nil { - return trace.Wrap(err) - } - if cfg.AuthorityGetter == nil { - getter, ok := cfg.Client.(AuthorityGetter) - if !ok { - return trace.BadParameter("missing parameter AuthorityGetter and Client not usable as AuthorityGetter") - } - cfg.AuthorityGetter = getter - } - if len(cfg.Types) == 0 { - return trace.BadParameter("missing parameter Types") + if len(cfg.Types) == 0 { + return trace.BadParameter("missing parameter Types") } return nil } @@ -1712,17 +1215,15 @@ type CertAuthorityWatcher struct { // caCollector accompanies resourceWatcher when monitoring cert authority resources. type caCollector struct { - CertAuthorityWatcherConfig fanout *FanoutV2 - - // lock protects concurrent access to cas - lock sync.RWMutex - // cas maps ca type -> cluster -> ca - cas map[types.CertAuthType]map[string]types.CertAuthority + cas map[types.CertAuthType]map[string]types.CertAuthority // initializationC is used to check whether the initial sync has completed initializationC chan struct{} - once sync.Once filter types.CertAuthorityFilter + CertAuthorityWatcherConfig + // lock protects concurrent access to cas + lock sync.RWMutex + once sync.Once } // Subscribe is used to subscribe to the lock updates. @@ -1859,285 +1360,40 @@ func (c *caCollector) notifyStale() {} // NodeWatcherConfig is a NodeWatcher configuration. type NodeWatcherConfig struct { - ResourceWatcherConfig // NodesGetter is used to directly fetch the list of active nodes. NodesGetter -} - -// CheckAndSetDefaults checks parameters and sets default values. -func (cfg *NodeWatcherConfig) CheckAndSetDefaults() error { - if err := cfg.ResourceWatcherConfig.CheckAndSetDefaults(); err != nil { - return trace.Wrap(err) - } - if cfg.NodesGetter == nil { - getter, ok := cfg.Client.(NodesGetter) - if !ok { - return trace.BadParameter("missing parameter NodesGetter and Client not usable as NodesGetter") - } - cfg.NodesGetter = getter - } - return nil + ResourceWatcherConfig } // NewNodeWatcher returns a new instance of NodeWatcher. -func NewNodeWatcher(ctx context.Context, cfg NodeWatcherConfig) (*NodeWatcher, error) { - if err := cfg.CheckAndSetDefaults(); err != nil { - return nil, trace.Wrap(err) - } - - cache, err := utils.NewFnCache(utils.FnCacheConfig{ - Context: ctx, - TTL: 3 * time.Second, - Clock: cfg.Clock, - }) - if err != nil { - return nil, trace.Wrap(err) - } - - collector := &nodeCollector{ - NodeWatcherConfig: cfg, - current: map[string]types.Server{}, - initializationC: make(chan struct{}), - cache: cache, - stale: true, - } - - watcher, err := newResourceWatcher(ctx, collector, cfg.ResourceWatcherConfig) - if err != nil { - return nil, trace.Wrap(err) - } - - return &NodeWatcher{resourceWatcher: watcher, nodeCollector: collector}, nil -} - -// NodeWatcher is built on top of resourceWatcher to monitor additions -// and deletions to the set of nodes. -type NodeWatcher struct { - *resourceWatcher - *nodeCollector -} - -// nodeCollector accompanies resourceWatcher when monitoring nodes. -type nodeCollector struct { - NodeWatcherConfig - - // initializationC is used to check whether the initial sync has completed - initializationC chan struct{} - once sync.Once - - cache *utils.FnCache - - rw sync.RWMutex - // current holds a map of the currently known nodes keyed by server name - current map[string]types.Server - stale bool -} - -// Node is a readonly subset of the types.Server interface which -// users may filter by in GetNodes. -type Node interface { - // ResourceWithLabels provides common resource headers - types.ResourceWithLabels - // GetTeleportVersion returns the teleport version the server is running on - GetTeleportVersion() string - // GetAddr return server address - GetAddr() string - // GetPublicAddrs returns all public addresses where this server can be reached. - GetPublicAddrs() []string - // GetHostname returns server hostname - GetHostname() string - // GetNamespace returns server namespace - GetNamespace() string - // GetCmdLabels gets command labels - GetCmdLabels() map[string]types.CommandLabel - // GetRotation gets the state of certificate authority rotation. - GetRotation() types.Rotation - // GetUseTunnel gets if a reverse tunnel should be used to connect to this node. - GetUseTunnel() bool - // GetProxyIDs returns a list of proxy ids this server is connected to. - GetProxyIDs() []string - // IsEICE returns whether the Node is an EICE instance. - // Must be `openssh-ec2-ice` subkind and have the AccountID and InstanceID information (AWS Metadata or Labels). - IsEICE() bool -} - -// GetNodes allows callers to retrieve a subset of nodes that match the filter provided. The -// returned servers are a copy and can be safely modified. It is intentionally hard to retrieve -// the full set of nodes to reduce the number of copies needed since the number of nodes can get -// quite large and doing so can be expensive. -func (n *nodeCollector) GetNodes(ctx context.Context, fn func(n Node) bool) []types.Server { - // Attempt to freshen our data first. - n.refreshStaleNodes(ctx) - - n.rw.RLock() - defer n.rw.RUnlock() - - var matched []types.Server - for _, server := range n.current { - if fn(server) { - matched = append(matched, server.DeepCopy()) - } - } - - return matched -} - -// GetNode allows callers to retrieve a node based on its name. The -// returned server are a copy and can be safely modified. -func (n *nodeCollector) GetNode(ctx context.Context, name string) (types.Server, error) { - // Attempt to freshen our data first. - n.refreshStaleNodes(ctx) - - n.rw.RLock() - defer n.rw.RUnlock() - - server, found := n.current[name] - if !found { - return nil, trace.NotFound("server does not exist") - } - return server.DeepCopy(), nil -} - -// refreshStaleNodes attempts to reload nodes from the NodeGetter if -// the collecter is stale. This ensures that no matter the health of -// the collecter callers will be returned the most up to date node -// set as possible. -func (n *nodeCollector) refreshStaleNodes(ctx context.Context) error { - n.rw.RLock() - if !n.stale { - n.rw.RUnlock() - return nil - } - n.rw.RUnlock() - - _, err := utils.FnCacheGet(ctx, n.cache, "nodes", func(ctx context.Context) (any, error) { - current, err := n.getNodes(ctx) - if err != nil { - return nil, trace.Wrap(err) - } - - n.rw.Lock() - defer n.rw.Unlock() - - // There is a chance that the watcher reinitialized while - // getting nodes happened above. Check if we are still stale - // now that the lock is held to ensure that the refresh is - // still necessary. - if !n.stale { - return nil, nil - } - - n.current = current - return nil, trace.Wrap(err) - }) - - return trace.Wrap(err) -} - -func (n *nodeCollector) NodeCount() int { - n.rw.RLock() - defer n.rw.RUnlock() - return len(n.current) -} - -// resourceKinds specifies the resource kind to watch. -func (n *nodeCollector) resourceKinds() []types.WatchKind { - return []types.WatchKind{{Kind: types.KindNode}} -} - -// getResourcesAndUpdateCurrent is called when the resources should be -// (re-)fetched directly. -func (n *nodeCollector) getResourcesAndUpdateCurrent(ctx context.Context) error { - newCurrent, err := n.getNodes(ctx) - if err != nil { - return trace.Wrap(err) - } - defer n.defineCollectorAsInitialized() - - if len(newCurrent) == 0 { - return nil - } - - n.rw.Lock() - defer n.rw.Unlock() - n.current = newCurrent - n.stale = false - return nil -} - -func (n *nodeCollector) getNodes(ctx context.Context) (map[string]types.Server, error) { - nodes, err := n.NodesGetter.GetNodes(ctx, apidefaults.Namespace) - if err != nil { - return nil, trace.Wrap(err) - } - - if len(nodes) == 0 { - return map[string]types.Server{}, nil - } - - current := make(map[string]types.Server, len(nodes)) - for _, node := range nodes { - current[node.GetName()] = node +func NewNodeWatcher(ctx context.Context, cfg NodeWatcherConfig) (*GenericWatcher[types.Server, readonly.Server], error) { + if cfg.NodesGetter == nil { + return nil, trace.BadParameter("NodesGetter must be provided") } - return current, nil -} - -func (n *nodeCollector) defineCollectorAsInitialized() { - n.once.Do(func() { - // mark watcher as initialized. - close(n.initializationC) + w, err := NewGenericResourceWatcher(ctx, GenericWatcherConfig[types.Server, readonly.Server]{ + ResourceWatcherConfig: cfg.ResourceWatcherConfig, + ResourceKind: types.KindNode, + ResourceGetter: func(ctx context.Context) ([]types.Server, error) { + return cfg.NodesGetter.GetNodes(ctx, apidefaults.Namespace) + }, + ResourceKey: types.Server.GetName, + DisableUpdateBroadcast: true, + CloneFunc: types.Server.DeepCopy, }) -} - -// processEventsAndUpdateCurrent is called when a watcher event is received. -func (n *nodeCollector) processEventsAndUpdateCurrent(ctx context.Context, events []types.Event) { - n.rw.Lock() - defer n.rw.Unlock() - - for _, event := range events { - if event.Resource == nil || event.Resource.GetKind() != types.KindNode { - n.Logger.WarnContext(ctx, "Received unexpected event", "event", logutils.StringerAttr(event)) - continue - } - - switch event.Type { - case types.OpDelete: - delete(n.current, event.Resource.GetName()) - case types.OpPut: - server, ok := event.Resource.(types.Server) - if !ok { - n.Logger.WarnContext(ctx, "Received unexpected type", "resource", event.Resource.GetKind()) - continue - } - - n.current[server.GetName()] = server - default: - n.Logger.WarnContext(ctx, "Skipping unsupported event type", "event_type", event.Type) - } - } -} - -func (n *nodeCollector) initializationChan() <-chan struct{} { - return n.initializationC -} - -func (n *nodeCollector) notifyStale() { - n.rw.Lock() - defer n.rw.Unlock() - n.stale = true + return w, trace.Wrap(err) } // AccessRequestWatcherConfig is a AccessRequestWatcher configuration. type AccessRequestWatcherConfig struct { - // ResourceWatcherConfig is the resource watcher configuration. - ResourceWatcherConfig // AccessRequestGetter is responsible for fetching access request resources. AccessRequestGetter - // Filter is the filter to use to monitor access requests. - Filter types.AccessRequestFilter // AccessRequestsC receives up-to-date list of all access request resources. AccessRequestsC chan types.AccessRequests + // ResourceWatcherConfig is the resource watcher configuration. + ResourceWatcherConfig + // Filter is the filter to use to monitor access requests. + Filter types.AccessRequestFilter } // CheckAndSetDefaults checks parameters and sets default values. @@ -2186,11 +1442,11 @@ type accessRequestCollector struct { AccessRequestWatcherConfig // current holds a map of the currently known access request resources. current map[string]types.AccessRequest - // lock protects the "current" map. - lock sync.RWMutex // initializationC is used to check that the watcher has been initialized properly. initializationC chan struct{} - once sync.Once + // lock protects the "current" map. + lock sync.RWMutex + once sync.Once } // resourceKinds specifies the resource kind to watch. @@ -2250,7 +1506,7 @@ func (p *accessRequestCollector) processEventsAndUpdateCurrent(ctx context.Conte delete(p.current, event.Resource.GetName()) select { case <-ctx.Done(): - case p.AccessRequestsC <- resourcesToSlice(p.current): + case p.AccessRequestsC <- resourcesToSlice(p.current, types.AccessRequest.Copy): } case types.OpPut: accessRequest, ok := event.Resource.(types.AccessRequest) @@ -2261,7 +1517,7 @@ func (p *accessRequestCollector) processEventsAndUpdateCurrent(ctx context.Conte p.current[accessRequest.GetName()] = accessRequest select { case <-ctx.Done(): - case p.AccessRequestsC <- resourcesToSlice(p.current): + case p.AccessRequestsC <- resourcesToSlice(p.current, types.AccessRequest.Copy): } default: @@ -2274,14 +1530,14 @@ func (*accessRequestCollector) notifyStale() {} // OktaAssignmentWatcherConfig is a OktaAssignmentWatcher configuration. type OktaAssignmentWatcherConfig struct { - // RWCfg is the resource watcher configuration. - RWCfg ResourceWatcherConfig // OktaAssignments is responsible for fetching Okta assignments. OktaAssignments OktaAssignmentsGetter - // PageSize is the number of Okta assignments to list at a time. - PageSize int // OktaAssignmentsC receives up-to-date list of all Okta assignment resources. OktaAssignmentsC chan types.OktaAssignments + // RWCfg is the resource watcher configuration. + RWCfg ResourceWatcherConfig + // PageSize is the number of Okta assignments to list at a time. + PageSize int } // CheckAndSetDefaults checks parameters and sets default values. @@ -2346,16 +1602,16 @@ func (o *OktaAssignmentWatcher) Done() <-chan struct{} { // oktaAssignmentCollector accompanies resourceWatcher when monitoring Okta assignment resources. type oktaAssignmentCollector struct { - logger *slog.Logger // OktaAssignmentWatcherConfig is the watcher configuration. - cfg OktaAssignmentWatcherConfig - // mu guards "current" - mu sync.RWMutex + cfg OktaAssignmentWatcherConfig + logger *slog.Logger // current holds a map of the currently known Okta assignment resources. current map[string]types.OktaAssignment // initializationC is used to check that the watcher has been initialized properly. initializationC chan struct{} - once sync.Once + // mu guards "current" + mu sync.RWMutex + once sync.Once } // resourceKinds specifies the resource kind to watch. @@ -2423,7 +1679,7 @@ func (c *oktaAssignmentCollector) processEventsAndUpdateCurrent(ctx context.Cont switch event.Type { case types.OpDelete: delete(c.current, event.Resource.GetName()) - resources := resourcesToSlice(c.current) + resources := resourcesToSlice(c.current, types.OktaAssignment.Copy) select { case <-ctx.Done(): case c.cfg.OktaAssignmentsC <- resources: @@ -2435,7 +1691,7 @@ func (c *oktaAssignmentCollector) processEventsAndUpdateCurrent(ctx context.Cont continue } c.current[oktaAssignment.GetName()] = oktaAssignment - resources := resourcesToSlice(c.current) + resources := resourcesToSlice(c.current, types.OktaAssignment.Copy) select { case <-ctx.Done(): diff --git a/lib/services/watcher_test.go b/lib/services/watcher_test.go index 3ffe202bb7087..730c7430696a4 100644 --- a/lib/services/watcher_test.go +++ b/lib/services/watcher_test.go @@ -45,6 +45,7 @@ import ( "github.com/gravitational/teleport/lib/fixtures" "github.com/gravitational/teleport/lib/services" "github.com/gravitational/teleport/lib/services/local" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/tlsca" ) @@ -131,7 +132,8 @@ func TestProxyWatcher(t *testing.T) { Events: local.NewEventsService(bk), }, }, - ProxiesC: make(chan []types.Server, 10), + ProxyGetter: presence, + ProxiesC: make(chan []types.Server, 10), }) require.NoError(t, err) t.Cleanup(w.Close) @@ -143,7 +145,7 @@ func TestProxyWatcher(t *testing.T) { // The first event is always the current list of proxies. select { - case changeset := <-w.ProxiesC: + case changeset := <-w.ResourcesC: require.Len(t, changeset, 1) require.Empty(t, resourceDiff(changeset[0], proxy)) case <-w.Done(): @@ -158,7 +160,7 @@ func TestProxyWatcher(t *testing.T) { // Watcher should detect the proxy list change. select { - case changeset := <-w.ProxiesC: + case changeset := <-w.ResourcesC: require.Len(t, changeset, 2) case <-w.Done(): t.Fatal("Watcher has unexpectedly exited.") @@ -171,7 +173,7 @@ func TestProxyWatcher(t *testing.T) { // Watcher should detect the proxy list change. select { - case changeset := <-w.ProxiesC: + case changeset := <-w.ResourcesC: require.Len(t, changeset, 1) require.Empty(t, resourceDiff(changeset[0], proxy2)) case <-w.Done(): @@ -185,7 +187,7 @@ func TestProxyWatcher(t *testing.T) { // Watcher should detect the proxy list change. select { - case changeset := <-w.ProxiesC: + case changeset := <-w.ResourcesC: require.Empty(t, changeset) case <-w.Done(): t.Fatal("Watcher has unexpectedly exited.") @@ -562,14 +564,15 @@ func TestDatabaseWatcher(t *testing.T) { Events: local.NewEventsService(bk), }, }, - DatabasesC: make(chan types.Databases, 10), + DatabaseGetter: databasesService, + DatabasesC: make(chan []types.Database, 10), }) require.NoError(t, err) t.Cleanup(w.Close) // Initially there are no databases so watcher should send an empty list. select { - case changeset := <-w.DatabasesC: + case changeset := <-w.ResourcesC: require.Empty(t, changeset) case <-w.Done(): t.Fatal("Watcher has unexpectedly exited.") @@ -583,7 +586,7 @@ func TestDatabaseWatcher(t *testing.T) { // The first event is always the current list of databases. select { - case changeset := <-w.DatabasesC: + case changeset := <-w.ResourcesC: require.Len(t, changeset, 1) require.Empty(t, resourceDiff(changeset[0], database1)) case <-w.Done(): @@ -598,7 +601,7 @@ func TestDatabaseWatcher(t *testing.T) { // Watcher should detect the database list change. select { - case changeset := <-w.DatabasesC: + case changeset := <-w.ResourcesC: require.Len(t, changeset, 2) case <-w.Done(): t.Fatal("Watcher has unexpectedly exited.") @@ -611,7 +614,7 @@ func TestDatabaseWatcher(t *testing.T) { // Watcher should detect the database list change. select { - case changeset := <-w.DatabasesC: + case changeset := <-w.ResourcesC: require.Len(t, changeset, 1) require.Empty(t, resourceDiff(changeset[0], database2)) case <-w.Done(): @@ -661,14 +664,15 @@ func TestAppWatcher(t *testing.T) { Events: local.NewEventsService(bk), }, }, - AppsC: make(chan types.Apps, 10), + AppGetter: appService, + AppsC: make(chan []types.Application, 10), }) require.NoError(t, err) t.Cleanup(w.Close) // Initially there are no apps so watcher should send an empty list. select { - case changeset := <-w.AppsC: + case changeset := <-w.ResourcesC: require.Empty(t, changeset) case <-w.Done(): t.Fatal("Watcher has unexpectedly exited.") @@ -682,7 +686,7 @@ func TestAppWatcher(t *testing.T) { // The first event is always the current list of apps. select { - case changeset := <-w.AppsC: + case changeset := <-w.ResourcesC: require.Len(t, changeset, 1) require.Empty(t, resourceDiff(changeset[0], app1)) case <-w.Done(): @@ -697,7 +701,7 @@ func TestAppWatcher(t *testing.T) { // Watcher should detect the app list change. select { - case changeset := <-w.AppsC: + case changeset := <-w.ResourcesC: require.Len(t, changeset, 2) case <-w.Done(): t.Fatal("Watcher has unexpectedly exited.") @@ -710,7 +714,7 @@ func TestAppWatcher(t *testing.T) { // Watcher should detect the database list change. select { - case changeset := <-w.AppsC: + case changeset := <-w.ResourcesC: require.Len(t, changeset, 1) require.Empty(t, resourceDiff(changeset[0], app2)) case <-w.Done(): @@ -909,6 +913,7 @@ func TestNodeWatcherFallback(t *testing.T) { }, MaxStaleness: time.Minute, }, + NodesGetter: presence, }) require.NoError(t, err) t.Cleanup(w.Close) @@ -922,15 +927,14 @@ func TestNodeWatcherFallback(t *testing.T) { nodes = append(nodes, node) } - require.Empty(t, w.NodeCount()) + require.Empty(t, w.ResourceCount()) require.False(t, w.IsInitialized()) - got := w.GetNodes(ctx, func(n services.Node) bool { - return true - }) + got, err := w.CurrentResources(ctx) + require.NoError(t, err) require.Len(t, nodes, len(got)) - require.Len(t, nodes, w.NodeCount()) + require.Len(t, nodes, w.ResourceCount()) require.False(t, w.IsInitialized()) } @@ -961,6 +965,7 @@ func TestNodeWatcher(t *testing.T) { }, MaxStaleness: time.Minute, }, + NodesGetter: presence, }) require.NoError(t, err) t.Cleanup(w.Close) @@ -974,25 +979,27 @@ func TestNodeWatcher(t *testing.T) { nodes = append(nodes, node) } - require.Eventually(t, func() bool { - filtered := w.GetNodes(ctx, func(n services.Node) bool { - return true - }) - return len(filtered) == len(nodes) + require.EventuallyWithT(t, func(t *assert.CollectT) { + filtered, err := w.CurrentResources(ctx) + assert.NoError(t, err) + assert.Len(t, filtered, len(nodes)) }, time.Second, time.Millisecond, "Timeout waiting for watcher to receive nodes.") - require.Len(t, w.GetNodes(ctx, func(n services.Node) bool { return n.GetUseTunnel() }), 3) + filtered, err := w.CurrentResourcesWithFilter(ctx, func(n readonly.Server) bool { return n.GetUseTunnel() }) + require.NoError(t, err) + require.Len(t, filtered, 3) require.NoError(t, presence.DeleteNode(ctx, apidefaults.Namespace, nodes[0].GetName())) - require.Eventually(t, func() bool { - filtered := w.GetNodes(ctx, func(n services.Node) bool { - return true - }) - return len(filtered) == len(nodes)-1 + require.EventuallyWithT(t, func(t *assert.CollectT) { + filtered, err := w.CurrentResources(ctx) + assert.NoError(t, err) + assert.Len(t, filtered, len(nodes)-1) }, time.Second, time.Millisecond, "Timeout waiting for watcher to receive nodes.") - require.Empty(t, w.GetNodes(ctx, func(n services.Node) bool { return n.GetName() == nodes[0].GetName() })) + filtered, err = w.CurrentResourcesWithFilter(ctx, func(n readonly.Server) bool { return n.GetName() == nodes[0].GetName() }) + require.NoError(t, err) + require.Empty(t, filtered) } func newNodeServer(t *testing.T, name, hostname, addr string, tunnel bool) types.Server { @@ -1032,6 +1039,7 @@ func TestKubeServerWatcher(t *testing.T) { }, MaxStaleness: time.Minute, }, + KubernetesServerGetter: presence, }) require.NoError(t, err) t.Cleanup(w.Close) @@ -1057,55 +1065,66 @@ func TestKubeServerWatcher(t *testing.T) { kubeServers = append(kubeServers, kubeServer) } - require.Eventually(t, func() bool { - filtered, err := w.GetKubernetesServers(context.Background()) + require.EventuallyWithT(t, func(t *assert.CollectT) { + filtered, err := w.CurrentResources(context.Background()) assert.NoError(t, err) - return len(filtered) == len(kubeServers) + assert.Len(t, filtered, len(kubeServers)) }, time.Second, time.Millisecond, "Timeout waiting for watcher to receive kube servers.") // Test filtering by cluster name. - filtered, err := w.GetKubeServersByClusterName(context.Background(), kubeServers[0].GetName()) + filtered, err := w.CurrentResourcesWithFilter(context.Background(), func(ks readonly.KubeServer) bool { + return ks.GetName() == kubeServers[0].GetName() + }) require.NoError(t, err) require.Len(t, filtered, 1) // Test Deleting a kube server. require.NoError(t, presence.DeleteKubernetesServer(ctx, kubeServers[0].GetHostID(), kubeServers[0].GetName())) - require.Eventually(t, func() bool { - kube, err := w.GetKubernetesServers(context.Background()) + require.EventuallyWithT(t, func(t *assert.CollectT) { + kube, err := w.CurrentResources(context.Background()) assert.NoError(t, err) - return len(kube) == len(kubeServers)-1 + assert.Len(t, kube, len(kubeServers)-1) }, time.Second, time.Millisecond, "Timeout waiting for watcher to receive the delete event.") - filtered, err = w.GetKubeServersByClusterName(context.Background(), kubeServers[0].GetName()) - require.Error(t, err) + filtered, err = w.CurrentResourcesWithFilter(context.Background(), func(ks readonly.KubeServer) bool { + return ks.GetName() == kubeServers[0].GetName() + }) + require.NoError(t, err) require.Empty(t, filtered) // Test adding a kube server with the same name as an existing one. kubeServer := newKubeServer(t, kubeServers[1].GetName(), "addr", uuid.NewString()) _, err = presence.UpsertKubernetesServer(ctx, kubeServer) require.NoError(t, err) - require.Eventually(t, func() bool { - filtered, err := w.GetKubeServersByClusterName(context.Background(), kubeServers[1].GetName()) + require.EventuallyWithT(t, func(t *assert.CollectT) { + filtered, err := w.CurrentResourcesWithFilter(context.Background(), func(ks readonly.KubeServer) bool { + return ks.GetName() == kubeServers[1].GetName() + }) assert.NoError(t, err) - return len(filtered) == 2 - }, time.Second, time.Millisecond, "Timeout waiting for watcher to the new registered kube server.") + assert.Len(t, filtered, 2) + }, 1000*time.Second, time.Millisecond, "Timeout waiting for watcher to the new registered kube server.") // Test deleting all kube servers with the same name. - filtered, err = w.GetKubeServersByClusterName(context.Background(), kubeServers[1].GetName()) + filtered, err = w.CurrentResourcesWithFilter(context.Background(), func(ks readonly.KubeServer) bool { + return ks.GetName() == kubeServers[1].GetName() + }) assert.NoError(t, err) for _, server := range filtered { require.NoError(t, presence.DeleteKubernetesServer(ctx, server.GetHostID(), server.GetName())) } - require.Eventually(t, func() bool { - filtered, err := w.GetKubeServersByClusterName(context.Background(), kubeServers[1].GetName()) - return len(filtered) == 0 && err != nil + require.EventuallyWithT(t, func(t *assert.CollectT) { + filtered, err := w.CurrentResourcesWithFilter(context.Background(), func(ks readonly.KubeServer) bool { + return ks.GetName() == kubeServers[1].GetName() + }) + assert.NoError(t, err) + assert.Empty(t, filtered) }, time.Second, time.Millisecond, "Timeout waiting for watcher to receive the two delete events.") require.NoError(t, presence.DeleteAllKubernetesServers(ctx)) - require.Eventually(t, func() bool { - filtered, err := w.GetKubernetesServers(context.Background()) + require.EventuallyWithT(t, func(t *assert.CollectT) { + filtered, err := w.CurrentResources(context.Background()) assert.NoError(t, err) - return len(filtered) == 0 + assert.Empty(t, filtered) }, time.Second, time.Millisecond, "Timeout waiting for watcher to receive all delete events.") } diff --git a/lib/srv/app/server.go b/lib/srv/app/server.go index 83684289cdb3b..393086b69c1c2 100644 --- a/lib/srv/app/server.go +++ b/lib/srv/app/server.go @@ -40,6 +40,7 @@ import ( "github.com/gravitational/teleport/lib/labels" "github.com/gravitational/teleport/lib/reversetunnel" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/srv" "github.com/gravitational/teleport/lib/utils" ) @@ -153,7 +154,7 @@ type Server struct { reconcileCh chan struct{} // watcher monitors changes to application resources. - watcher *services.AppWatcher + watcher *services.GenericWatcher[types.Application, readonly.Application] } // monitoredApps is a collection of applications from different sources diff --git a/lib/srv/app/watcher.go b/lib/srv/app/watcher.go index ac355fd6b9fd2..c88e73dd7f5ab 100644 --- a/lib/srv/app/watcher.go +++ b/lib/srv/app/watcher.go @@ -28,6 +28,7 @@ import ( "github.com/gravitational/teleport" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/utils" ) @@ -67,7 +68,7 @@ func (s *Server) startReconciler(ctx context.Context) error { // startResourceWatcher starts watching changes to application resources and // registers/unregisters the proxied applications accordingly. -func (s *Server) startResourceWatcher(ctx context.Context) (*services.AppWatcher, error) { +func (s *Server) startResourceWatcher(ctx context.Context) (*services.GenericWatcher[types.Application, readonly.Application], error) { if len(s.c.ResourceMatchers) == 0 { s.log.DebugContext(ctx, "Not initializing application resource watcher.") return nil, nil @@ -80,6 +81,7 @@ func (s *Server) startResourceWatcher(ctx context.Context) (*services.AppWatcher // Log: s.log, Client: s.c.AccessPoint, }, + AppGetter: s.c.AccessPoint, }) if err != nil { return nil, trace.Wrap(err) @@ -88,7 +90,7 @@ func (s *Server) startResourceWatcher(ctx context.Context) (*services.AppWatcher defer watcher.Close() for { select { - case apps := <-watcher.AppsC: + case apps := <-watcher.ResourcesC: appsWithAddr := make(types.Apps, 0, len(apps)) for _, app := range apps { appsWithAddr = append(appsWithAddr, s.guessPublicAddr(app)) diff --git a/lib/srv/db/server.go b/lib/srv/db/server.go index 292615fe9f46e..10f54db7343f8 100644 --- a/lib/srv/db/server.go +++ b/lib/srv/db/server.go @@ -49,6 +49,7 @@ import ( "github.com/gravitational/teleport/lib/limiter" "github.com/gravitational/teleport/lib/reversetunnel" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/srv" "github.com/gravitational/teleport/lib/srv/db/cassandra" "github.com/gravitational/teleport/lib/srv/db/clickhouse" @@ -313,7 +314,7 @@ type Server struct { // heartbeats holds heartbeats for database servers. heartbeats map[string]srv.HeartbeatI // watcher monitors changes to database resources. - watcher *services.DatabaseWatcher + watcher *services.GenericWatcher[types.Database, readonly.Database] // proxiedDatabases contains databases this server currently is proxying. // Proxied databases are reconciled against monitoredDatabases below. proxiedDatabases map[string]types.Database diff --git a/lib/srv/db/watcher.go b/lib/srv/db/watcher.go index 58010eb6ad8d9..b65386a981247 100644 --- a/lib/srv/db/watcher.go +++ b/lib/srv/db/watcher.go @@ -27,6 +27,7 @@ import ( "github.com/gravitational/teleport" "github.com/gravitational/teleport/api/types" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" discovery "github.com/gravitational/teleport/lib/srv/discovery/common" dbfetchers "github.com/gravitational/teleport/lib/srv/discovery/fetchers/db" "github.com/gravitational/teleport/lib/utils" @@ -69,7 +70,7 @@ func (s *Server) startReconciler(ctx context.Context) error { // startResourceWatcher starts watching changes to database resources and // registers/unregisters the proxied databases accordingly. -func (s *Server) startResourceWatcher(ctx context.Context) (*services.DatabaseWatcher, error) { +func (s *Server) startResourceWatcher(ctx context.Context) (*services.GenericWatcher[types.Database, readonly.Database], error) { if len(s.cfg.ResourceMatchers) == 0 { s.log.DebugContext(ctx, "Not starting database resource watcher.") return nil, nil @@ -81,6 +82,7 @@ func (s *Server) startResourceWatcher(ctx context.Context) (*services.DatabaseWa Logger: s.log, Client: s.cfg.AccessPoint, }, + DatabaseGetter: s.cfg.AccessPoint, }) if err != nil { return nil, trace.Wrap(err) @@ -90,7 +92,7 @@ func (s *Server) startResourceWatcher(ctx context.Context) (*services.DatabaseWa defer watcher.Close() for { select { - case databases := <-watcher.DatabasesC: + case databases := <-watcher.ResourcesC: s.monitoredDatabases.setResources(databases) select { case s.reconcileCh <- struct{}{}: diff --git a/lib/srv/desktop/discovery.go b/lib/srv/desktop/discovery.go index c44bcc0a9cabb..0e22d2487a802 100644 --- a/lib/srv/desktop/discovery.go +++ b/lib/srv/desktop/discovery.go @@ -39,6 +39,7 @@ import ( "github.com/gravitational/teleport/lib/auth/windows" "github.com/gravitational/teleport/lib/defaults" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/utils" ) @@ -99,10 +100,15 @@ func (s *WindowsService) ldapSearchFilter() string { // getDesktopsFromLDAP discovers Windows hosts via LDAP func (s *WindowsService) getDesktopsFromLDAP() map[string]types.WindowsDesktop { - if !s.ldapReady() { - s.cfg.Logger.WarnContext(context.Background(), "skipping desktop discovery: LDAP not yet initialized") + // Check whether we've ever successfully initialized our LDAP client. + s.mu.Lock() + if !s.ldapInitialized { + s.cfg.Logger.DebugContext(context.Background(), "LDAP not ready, skipping discovery and attempting to reconnect") + s.mu.Unlock() + s.initializeLDAP() return nil } + s.mu.Unlock() filter := s.ldapSearchFilter() s.cfg.Logger.DebugContext(context.Background(), "searching for desktops", "filter", filter) @@ -250,7 +256,11 @@ func (s *WindowsService) lookupDesktop(ctx context.Context, hostname string) ([] // ldapEntryToWindowsDesktop generates the Windows Desktop resource // from an LDAP search result -func (s *WindowsService) ldapEntryToWindowsDesktop(ctx context.Context, entry *ldap.Entry, getHostLabels func(string) map[string]string) (types.WindowsDesktop, error) { +func (s *WindowsService) ldapEntryToWindowsDesktop( + ctx context.Context, + entry *ldap.Entry, + getHostLabels func(string) map[string]string, +) (types.WindowsDesktop, error) { hostname := entry.GetAttributeValue(windows.AttrDNSHostName) if hostname == "" { attrs := make([]string, len(entry.Attributes)) @@ -311,7 +321,7 @@ func (s *WindowsService) ldapEntryToWindowsDesktop(ctx context.Context, entry *l // startDynamicReconciler starts resource watcher and reconciler that registers/unregisters Windows desktops // according to the up-to-date list of dynamic Windows desktops resources. -func (s *WindowsService) startDynamicReconciler(ctx context.Context) (*services.DynamicWindowsDesktopWatcher, error) { +func (s *WindowsService) startDynamicReconciler(ctx context.Context) (*services.GenericWatcher[types.DynamicWindowsDesktop, readonly.DynamicWindowsDesktop], error) { if len(s.cfg.ResourceMatchers) == 0 { s.cfg.Logger.DebugContext(ctx, "Not starting dynamic desktop resource watcher.") return nil, nil @@ -354,7 +364,7 @@ func (s *WindowsService) startDynamicReconciler(ctx context.Context) (*services. defer watcher.Close() for { select { - case desktops := <-watcher.DynamicWindowsDesktopsC: + case desktops := <-watcher.ResourcesC: newResources = make(map[string]types.WindowsDesktop) for _, dynamicDesktop := range desktops { desktop, err := s.toWindowsDesktop(dynamicDesktop) diff --git a/lib/srv/desktop/windows_server.go b/lib/srv/desktop/windows_server.go index 791f477861666..fd75cbc89bd04 100644 --- a/lib/srv/desktop/windows_server.go +++ b/lib/srv/desktop/windows_server.go @@ -425,10 +425,60 @@ func NewWindowsService(cfg WindowsServiceConfig) (*WindowsService, error) { s.cfg.Logger.InfoContext(ctx, "desktop discovery via LDAP is disabled, set 'base_dn' to enable") } + // if LDAP-based discovery is not enabled, but we have configured LDAP + // then it's important that we periodically try to use the LDAP connection + // to detect connection closure + if s.ldapConfigured && len(s.cfg.DiscoveryBaseDN) == 0 { + s.startLDAPConnectionCheck(ctx) + } + ok = true return s, nil } +// startLDAPConnectionCheck starts a background process that +// periodically reads from the LDAP connection in order to detect +// connection closure, and reconnects if necessary. +// This is useful when LDAP-based discovery is disabled, because without +// discovery the connection goes idle and may be closed by the server. +func (s *WindowsService) startLDAPConnectionCheck(ctx context.Context) { + s.cfg.Logger.DebugContext(ctx, "starting LDAP connection checker") + go func() { + t := s.cfg.Clock.NewTicker(5 * time.Minute) + defer t.Stop() + + for { + select { + case <-t.Chan(): + // First check if we have successfully initialized the LDAP client. + // If not, then do that now and return. + // (This mimics the check that is performed when LDAP discovery is enabled.) + s.mu.Lock() + if !s.ldapInitialized { + s.cfg.Logger.DebugContext(context.Background(), "LDAP not ready, attempting to reconnect") + s.mu.Unlock() + s.initializeLDAP() + return + } + s.mu.Unlock() + + // If we have initizlied the LDAP client, then try to use it to make sure we're still connected + // by attempting to read CAs in the NTAuth store (we know we have permissions to do so). + ntAuthDN := "CN=NTAuthCertificates,CN=Public Key Services,CN=Services,CN=Configuration," + s.cfg.LDAPConfig.DomainDN() + _, err := s.lc.Read(ntAuthDN, "certificationAuthority", []string{"cACertificate"}) + if trace.IsConnectionProblem(err) { + s.cfg.Logger.DebugContext(ctx, "detected broken LDAP connection, will reconnect") + if err := s.initializeLDAP(); err != nil { + s.cfg.Logger.WarnContext(ctx, "failed to reconnect to LDAP", "error", err) + } + } + case <-ctx.Done(): + return + } + } + }() +} + func (s *WindowsService) newSessionRecorder(recConfig types.SessionRecordingConfig, sessionID string) (libevents.SessionPreparerRecorder, error) { return recorder.New(recorder.Config{ SessionID: session.ID(sessionID), @@ -693,12 +743,6 @@ func (s *WindowsService) readyForConnections() bool { return s.ldapInitialized } -func (s *WindowsService) ldapReady() bool { - s.mu.Lock() - defer s.mu.Unlock() - return s.ldapInitialized -} - // handleConnection handles TLS connections from a Teleport proxy. // It authenticates and authorizes the connection, and then begins // translating the TDP messages from the proxy into native RDP. diff --git a/lib/srv/discovery/discovery.go b/lib/srv/discovery/discovery.go index 6e93a8a8eddc6..095da62b6475f 100644 --- a/lib/srv/discovery/discovery.go +++ b/lib/srv/discovery/discovery.go @@ -55,6 +55,7 @@ import ( "github.com/gravitational/teleport/lib/cryptosuites" "github.com/gravitational/teleport/lib/integrations/awsoidc" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/srv/discovery/common" "github.com/gravitational/teleport/lib/srv/discovery/fetchers" aws_sync "github.com/gravitational/teleport/lib/srv/discovery/fetchers/aws-sync" @@ -267,7 +268,7 @@ type Server struct { // cancelfn is used with ctx when stopping the discovery server cancelfn context.CancelFunc // nodeWatcher is a node watcher. - nodeWatcher *services.NodeWatcher + nodeWatcher *services.GenericWatcher[types.Server, readonly.Server] // ec2Watcher periodically retrieves EC2 instances. ec2Watcher *server.Watcher @@ -777,13 +778,16 @@ func (s *Server) initGCPWatchers(ctx context.Context, matchers []types.GCPMatche return nil } -func (s *Server) filterExistingEC2Nodes(instances *server.EC2Instances) { - nodes := s.nodeWatcher.GetNodes(s.ctx, func(n services.Node) bool { +func (s *Server) filterExistingEC2Nodes(instances *server.EC2Instances) error { + nodes, err := s.nodeWatcher.CurrentResourcesWithFilter(s.ctx, func(n readonly.Server) bool { labels := n.GetAllLabels() _, accountOK := labels[types.AWSAccountIDLabel] _, instanceOK := labels[types.AWSInstanceIDLabel] return accountOK && instanceOK }) + if err != nil { + return trace.Wrap(err) + } var filtered []server.EC2Instance outer: @@ -800,6 +804,7 @@ outer: filtered = append(filtered, inst) } instances.Instances = filtered + return nil } func genEC2InstancesLogStr(instances []server.EC2Instance) string { @@ -850,7 +855,9 @@ func (s *Server) handleEC2Instances(instances *server.EC2Instances) error { // EICE Nodes must never be filtered, so that we can extend their expiration and sync labels. totalInstancesFound := len(instances.Instances) if !instances.Rotation && instances.EnrollMode != types.InstallParamEnrollMode_INSTALL_PARAM_ENROLL_MODE_EICE { - s.filterExistingEC2Nodes(instances) + if err := s.filterExistingEC2Nodes(instances); err != nil { + return trace.Wrap(err) + } } instancesAlreadyEnrolled := totalInstancesFound - len(instances.Instances) @@ -904,12 +911,24 @@ func (s *Server) heartbeatEICEInstance(instances *server.EC2Instances) { continue } - existingNode, err := s.nodeWatcher.GetNode(s.ctx, eiceNode.GetName()) + existingNodes, err := s.nodeWatcher.CurrentResourcesWithFilter(s.ctx, func(s readonly.Server) bool { + return s.GetName() == eiceNode.GetName() + }) if err != nil && !trace.IsNotFound(err) { s.Log.Warnf("Error finding the existing node with name %q: %v", eiceNode.GetName(), err) continue } + var existingNode types.Server + switch len(existingNodes) { + case 0: + case 1: + existingNode = existingNodes[0] + default: + s.Log.Warnf("Found multiple matching nodes with name %q", eiceNode.GetName()) + continue + } + // EICE Node's Name are deterministic (based on the Account and Instance ID). // // To reduce load, nodes are skipped if @@ -1064,7 +1083,7 @@ func (s *Server) findUnrotatedEC2Nodes(ctx context.Context) ([]types.Server, err if err != nil { return nil, trace.Wrap(err) } - found := s.nodeWatcher.GetNodes(ctx, func(n services.Node) bool { + found, err := s.nodeWatcher.CurrentResourcesWithFilter(ctx, func(n readonly.Server) bool { if n.GetSubKind() != types.SubKindOpenSSHNode { return false } @@ -1077,6 +1096,9 @@ func (s *Server) findUnrotatedEC2Nodes(ctx context.Context) ([]types.Server, err return mostRecentCertRotation.After(n.GetRotation().LastRotated) }) + if err != nil { + return nil, trace.Wrap(err) + } if len(found) == 0 { return nil, trace.NotFound("no unrotated nodes found") @@ -1118,13 +1140,18 @@ func (s *Server) handleEC2Discovery() { } } -func (s *Server) filterExistingAzureNodes(instances *server.AzureInstances) { - nodes := s.nodeWatcher.GetNodes(s.ctx, func(n services.Node) bool { +func (s *Server) filterExistingAzureNodes(instances *server.AzureInstances) error { + nodes, err := s.nodeWatcher.CurrentResourcesWithFilter(s.ctx, func(n readonly.Server) bool { labels := n.GetAllLabels() _, subscriptionOK := labels[types.SubscriptionIDLabel] _, vmOK := labels[types.VMIDLabel] return subscriptionOK && vmOK }) + + if err != nil { + return trace.Wrap(err) + } + var filtered []*armcompute.VirtualMachine outer: for _, inst := range instances.Instances { @@ -1144,6 +1171,7 @@ outer: filtered = append(filtered, inst) } instances.Instances = filtered + return nil } func (s *Server) handleAzureInstances(instances *server.AzureInstances) error { @@ -1151,7 +1179,9 @@ func (s *Server) handleAzureInstances(instances *server.AzureInstances) error { if err != nil { return trace.Wrap(err) } - s.filterExistingAzureNodes(instances) + if err := s.filterExistingAzureNodes(instances); err != nil { + return trace.Wrap(err) + } if len(instances.Instances) == 0 { return trace.Wrap(errNoInstances) } @@ -1206,14 +1236,19 @@ func (s *Server) handleAzureDiscovery() { } } -func (s *Server) filterExistingGCPNodes(instances *server.GCPInstances) { - nodes := s.nodeWatcher.GetNodes(s.ctx, func(n services.Node) bool { +func (s *Server) filterExistingGCPNodes(instances *server.GCPInstances) error { + nodes, err := s.nodeWatcher.CurrentResourcesWithFilter(s.ctx, func(n readonly.Server) bool { labels := n.GetAllLabels() _, projectIDOK := labels[types.ProjectIDLabelDiscovery] _, zoneOK := labels[types.ZoneLabelDiscovery] _, nameOK := labels[types.NameLabelDiscovery] return projectIDOK && zoneOK && nameOK }) + + if err != nil { + return trace.Wrap(err) + } + var filtered []*gcpimds.Instance outer: for _, inst := range instances.Instances { @@ -1230,6 +1265,7 @@ outer: filtered = append(filtered, inst) } instances.Instances = filtered + return nil } func (s *Server) handleGCPInstances(instances *server.GCPInstances) error { @@ -1237,7 +1273,9 @@ func (s *Server) handleGCPInstances(instances *server.GCPInstances) error { if err != nil { return trace.Wrap(err) } - s.filterExistingGCPNodes(instances) + if err := s.filterExistingGCPNodes(instances); err != nil { + return trace.Wrap(err) + } if len(instances.Instances) == 0 { return trace.Wrap(errNoInstances) } @@ -1730,6 +1768,7 @@ func (s *Server) initTeleportNodeWatcher() (err error) { Client: s.AccessPoint, MaxStaleness: time.Minute, }, + NodesGetter: s.AccessPoint, }) return trace.Wrap(err) diff --git a/lib/srv/discovery/discovery_test.go b/lib/srv/discovery/discovery_test.go index 974dd1bfcdad1..ab384e65d74f5 100644 --- a/lib/srv/discovery/discovery_test.go +++ b/lib/srv/discovery/discovery_test.go @@ -852,11 +852,10 @@ func TestDiscoveryServerConcurrency(t *testing.T) { // We must get only one EC2 EICE Node. // Even when two servers are discovering the same EC2 Instance, they will use the same name when converting to EICE Node. - require.Eventually(t, func() bool { + require.EventuallyWithT(t, func(t *assert.CollectT) { allNodes, err := tlsServer.Auth().GetNodes(ctx, "default") - require.NoError(t, err) - - return len(allNodes) == 1 + assert.NoError(t, err) + assert.Len(t, allNodes, 1) }, 1*time.Second, 50*time.Millisecond) // We should never get a duplicate instance. diff --git a/lib/srv/forward/sshserver.go b/lib/srv/forward/sshserver.go index 7b2cf1b83fd3b..0e20e9d8434d6 100644 --- a/lib/srv/forward/sshserver.go +++ b/lib/srv/forward/sshserver.go @@ -690,10 +690,9 @@ func (s *Server) sendSSHPublicKeyToTarget(ctx context.Context) (ssh.Signer, erro } sendSSHClient, err := awsoidc.NewEICESendSSHPublicKeyClient(ctx, &awsoidc.AWSClientRequest{ - IntegrationName: integration.GetName(), - Token: token, - RoleARN: integration.GetAWSOIDCIntegrationSpec().RoleARN, - Region: awsInfo.Region, + Token: token, + RoleARN: integration.GetAWSOIDCIntegrationSpec().RoleARN, + Region: awsInfo.Region, }) if err != nil { return nil, trace.BadParameter("failed to create an aws client to send ssh public key: %v", err) diff --git a/lib/srv/regular/sshserver_test.go b/lib/srv/regular/sshserver_test.go index 42df4c9d4017c..8d6a64154ee9b 100644 --- a/lib/srv/regular/sshserver_test.go +++ b/lib/srv/regular/sshserver_test.go @@ -70,6 +70,7 @@ import ( "github.com/gravitational/teleport/lib/reversetunnel" "github.com/gravitational/teleport/lib/service/servicecfg" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" sess "github.com/gravitational/teleport/lib/session" "github.com/gravitational/teleport/lib/srv" "github.com/gravitational/teleport/lib/sshutils" @@ -2865,12 +2866,13 @@ func newLockWatcher(ctx context.Context, t testing.TB, client types.Events) *ser return lockWatcher } -func newNodeWatcher(ctx context.Context, t *testing.T, client types.Events) *services.NodeWatcher { +func newNodeWatcher(ctx context.Context, t *testing.T, client *authclient.Client) *services.GenericWatcher[types.Server, readonly.Server] { nodeWatcher, err := services.NewNodeWatcher(ctx, services.NodeWatcherConfig{ ResourceWatcherConfig: services.ResourceWatcherConfig{ Component: "test", Client: client, }, + NodesGetter: client, }) require.NoError(t, err) t.Cleanup(nodeWatcher.Close) diff --git a/lib/teleterm/clusters/storage.go b/lib/teleterm/clusters/storage.go index 2be5817012fcf..79e6f63f57a0d 100644 --- a/lib/teleterm/clusters/storage.go +++ b/lib/teleterm/clusters/storage.go @@ -285,17 +285,6 @@ func (s *Storage) makeDefaultClientConfig(rootClusterURI uri.ResourceURI) *clien cfg.InsecureSkipVerify = s.InsecureSkipVerify cfg.AddKeysToAgent = s.AddKeysToAgent cfg.WebauthnLogin = s.WebauthnLogin - // Set AllowStdinHijack to true to enable daemon.mfaPrompt to ask for both TOTP and Webauthn at - // the same time if available. - // - // tsh sets AllowStdinHijack to true only during tsh login to avoid input swallowing bugs where - // calling a command would prompt for MFA and then expect some further data through stdin. tsh - // login does not ask for any further input after the MFA prompt. - // - // Since tsh daemon ran by Connect never expects data over stdin, it can always set this flag to - // true. - cfg.AllowStdinHijack = true - cfg.CustomHardwareKeyPrompt = s.HardwareKeyPromptConstructor(rootClusterURI) cfg.DTAuthnRunCeremony = dtauthn.NewCeremony().Run cfg.DTAutoEnroll = dtenroll.AutoEnroll diff --git a/lib/teleterm/daemon/mfaprompt.go b/lib/teleterm/daemon/mfaprompt.go index 81f53b9ab8004..a40d02130033b 100644 --- a/lib/teleterm/daemon/mfaprompt.go +++ b/lib/teleterm/daemon/mfaprompt.go @@ -73,13 +73,11 @@ func (s *Service) promptAppMFA(ctx context.Context, in *api.PromptMFARequest) (* // Run prompts the user to complete an MFA authentication challenge. func (p *mfaPrompt) Run(ctx context.Context, chal *proto.MFAAuthenticateChallenge) (*proto.MFAAuthenticateResponse, error) { - runOpts, err := p.cfg.GetRunOptions(ctx, chal) - if err != nil { - return nil, trace.Wrap(err) - } + promptOTP := chal.TOTP != nil + promptWebauthn := chal.WebauthnChallenge != nil && p.cfg.WebauthnSupported // No prompt to run, no-op. - if !runOpts.PromptTOTP && !runOpts.PromptWebauthn { + if !promptOTP && !promptWebauthn { return &proto.MFAAuthenticateResponse{}, nil } @@ -92,7 +90,7 @@ func (p *mfaPrompt) Run(ctx context.Context, chal *proto.MFAAuthenticateChalleng go func() { defer wg.Done() - resp, err := p.promptMFA(ctx, runOpts) + resp, err := p.promptMFA(ctx, promptOTP, promptWebauthn) respC <- libmfa.MFAGoroutineResponse{Resp: resp, Err: err} // If the user closes the modal in the Electron app, we need to be able to cancel the other @@ -103,7 +101,7 @@ func (p *mfaPrompt) Run(ctx context.Context, chal *proto.MFAAuthenticateChalleng }() // Fire Webauthn goroutine. - if runOpts.PromptWebauthn { + if promptWebauthn { wg.Add(1) go func() { defer wg.Done() @@ -128,12 +126,12 @@ func (p *mfaPrompt) promptWebauthn(ctx context.Context, chal *proto.MFAAuthentic return resp, nil } -func (p *mfaPrompt) promptMFA(ctx context.Context, runOpts libmfa.RunOpts) (*proto.MFAAuthenticateResponse, error) { +func (p *mfaPrompt) promptMFA(ctx context.Context, promptOTP, promptWebauthn bool) (*proto.MFAAuthenticateResponse, error) { resp, err := p.promptAppMFA(ctx, &api.PromptMFARequest{ ClusterUri: p.resourceURI.GetClusterURI().String(), Reason: p.cfg.PromptReason, - Totp: runOpts.PromptTOTP, - Webauthn: runOpts.PromptWebauthn, + Totp: promptOTP, + Webauthn: promptWebauthn, }) if err != nil { return nil, trail.FromGRPC(err) diff --git a/lib/utils/fncache.go b/lib/utils/fncache.go index e45a8b3a2d821..84f5be17478bb 100644 --- a/lib/utils/fncache.go +++ b/lib/utils/fncache.go @@ -245,6 +245,8 @@ func FnCacheGetWithTTL[T any](ctx context.Context, cache *FnCache, key any, ttl switch { case err != nil: return ret, err + case t == nil: + return ret, nil case !ok: return ret, trace.BadParameter("value retrieved was %T, expected %T", t, ret) } diff --git a/lib/utils/unpack.go b/lib/utils/unpack.go index a32cff6ef76b9..78b111daf8992 100644 --- a/lib/utils/unpack.go +++ b/lib/utils/unpack.go @@ -23,6 +23,7 @@ import ( "errors" "io" "os" + "path" "path/filepath" "strings" @@ -36,7 +37,10 @@ import ( // resulting files and directories are created using the current user context. // Extract will only unarchive files into dir, and will fail if the tarball // tries to write files outside of dir. -func Extract(r io.Reader, dir string) error { +// +// If any paths are specified, only the specified paths are extracted. +// The destination specified in the first matching path is selected. +func Extract(r io.Reader, dir string, paths ...ExtractPath) error { tarball := tar.NewReader(r) for { @@ -46,7 +50,9 @@ func Extract(r io.Reader, dir string) error { } else if err != nil { return trace.Wrap(err) } - + if ok := filterHeader(header, paths); !ok { + continue + } err = sanitizeTarPath(header, dir) if err != nil { return trace.Wrap(err) @@ -59,6 +65,62 @@ func Extract(r io.Reader, dir string) error { return nil } +// ExtractPath specifies a path to be extracted. +type ExtractPath struct { + // Src path and Dst path within the archive to extract files to. + // Directories in the Src path are not included in the extraction dir. + // For example, given foo/bar/file.txt with Src=foo/bar Dst=baz, baz/file.txt results. + // Trailing slashes are always ignored. + Src, Dst string + // Skip extracting the Src path and ignore Dst. + Skip bool +} + +// filterHeader modifies the tar header by filtering it through the ExtractPaths. +// filterHeader returns false if the tar header should be skipped. +func filterHeader(hdr *tar.Header, paths []ExtractPath) (include bool) { + name := path.Clean(hdr.Name) + for _, p := range paths { + src := path.Clean(p.Src) + switch hdr.Typeflag { + case tar.TypeDir: + // If name is a directory, then + // assume src is a directory prefix, or the directory itself, + // and replace that prefix with dst. + if src != "/" { + src += "/" // ensure HasPrefix does not match partial names + } + if !strings.HasPrefix(name, src) { + continue + } + dst := path.Join(p.Dst, strings.TrimPrefix(name, src)) + if dst != "/" { + dst += "/" // tar directory headers end in / + } + hdr.Name = dst + return !p.Skip + default: + // If name is a file, then + // if src is an exact match to the file name, assume src is a file and write directly to dst, + // otherwise, assume src is a directory prefix, and replace that prefix with dst. + if src == name { + hdr.Name = path.Clean(p.Dst) + return !p.Skip + } + if src != "/" { + src += "/" // ensure HasPrefix does not match partial names + } + if !strings.HasPrefix(name, src) { + continue + } + hdr.Name = path.Join(p.Dst, strings.TrimPrefix(name, src)) + return !p.Skip + + } + } + return len(paths) == 0 +} + // extractFile extracts a single file or directory from tarball into dir. // Uses header to determine the type of item to create // Based on https://github.com/mholt/archiver diff --git a/lib/web/apiserver.go b/lib/web/apiserver.go index faaffa2ff3e1e..de4d085377c3c 100644 --- a/lib/web/apiserver.go +++ b/lib/web/apiserver.go @@ -98,6 +98,7 @@ import ( "github.com/gravitational/teleport/lib/reversetunnelclient" "github.com/gravitational/teleport/lib/secret" "github.com/gravitational/teleport/lib/services" + "github.com/gravitational/teleport/lib/services/readonly" "github.com/gravitational/teleport/lib/session" "github.com/gravitational/teleport/lib/tlsca" "github.com/gravitational/teleport/lib/utils" @@ -130,6 +131,10 @@ const ( // DefaultFeatureWatchInterval is the default time in which the feature watcher // should ping the auth server to check for updated features DefaultFeatureWatchInterval = time.Minute * 5 + // findEndpointCacheTTL is the cache TTL for the find endpoint generic answer. + // This cache is here to protect against accidental or intentional DDoS, the TTL must be low to quickly reflect + // cluster configuration changes. + findEndpointCacheTTL = 10 * time.Second ) // healthCheckAppServerFunc defines a function used to perform a health check @@ -164,7 +169,7 @@ type Handler struct { // nodeWatcher is a services.NodeWatcher used by Assist to lookup nodes from // the proxy's cache and get nodes in real time. - nodeWatcher *services.NodeWatcher + nodeWatcher *services.GenericWatcher[types.Server, readonly.Server] // tracer is used to create spans. tracer oteltrace.Tracer @@ -173,6 +178,11 @@ type Handler struct { // an authenticated websocket so unauthenticated sockets dont get left // open. wsIODeadline time.Duration + + // findEndpointCache is used to cache the find endpoint answer. As this endpoint is unprotected and has high + // rate-limits, each call must cause minimal work. The cached answer can be modulated after, for example if the + // caller specified its Automatic Updates UUID or group. + findEndpointCache *utils.FnCache } // HandlerOption is a functional argument - an option that can be passed @@ -300,7 +310,7 @@ type Config struct { // NodeWatcher is a services.NodeWatcher used by Assist to lookup nodes from // the proxy's cache and get nodes in real time. - NodeWatcher *services.NodeWatcher + NodeWatcher *services.GenericWatcher[types.Server, readonly.Server] // PresenceChecker periodically runs the mfa ceremony for moderated // sessions. @@ -477,6 +487,18 @@ func NewHandler(cfg Config, opts ...HandlerOption) (*APIHandler, error) { } } + // We create the cache after applying the options to make sure we use the fake clock if it was passed. + findCache, err := utils.NewFnCache(utils.FnCacheConfig{ + TTL: findEndpointCacheTTL, + Clock: h.clock, + Context: cfg.Context, + ReloadOnErr: false, + }) + if err != nil { + return nil, trace.Wrap(err, "creating /find cache") + } + h.findEndpointCache = findCache + sessionLingeringThreshold := cachedSessionLingeringThreshold if cfg.CachedSessionLingeringThreshold != nil { sessionLingeringThreshold = *cfg.CachedSessionLingeringThreshold @@ -1521,56 +1543,63 @@ func (h *Handler) ping(w http.ResponseWriter, r *http.Request, p httprouter.Para } func (h *Handler) find(w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) { - // TODO(jent,espadolini): add a time-based cache to further reduce load on this endpoint - proxyConfig, err := h.cfg.ProxySettings.GetProxySettings(r.Context()) - if err != nil { - return nil, trace.Wrap(err) - } - authPref, err := h.cfg.AccessPoint.GetAuthPreference(r.Context()) - if err != nil { - return nil, trace.Wrap(err) - } - response := webclient.PingResponse{ - Auth: webclient.AuthenticationSettings{ - // Nodes need the signature algorithm suite when joining to generate - // keys with the correct algorithm. - SignatureAlgorithmSuite: authPref.GetSignatureAlgorithmSuite(), - }, - Proxy: *proxyConfig, - ServerVersion: teleport.Version, - MinClientVersion: teleport.MinClientVersion, - ClusterName: h.auth.clusterName, - } + // cache the generic answer to avoid doing work for each request + resp, err := utils.FnCacheGet[*webclient.PingResponse](r.Context(), h.findEndpointCache, "find", func(ctx context.Context) (*webclient.PingResponse, error) { + response := webclient.PingResponse{ + ServerVersion: teleport.Version, + MinClientVersion: teleport.MinClientVersion, + ClusterName: h.auth.clusterName, + } - autoUpdateConfig, err := h.cfg.AccessPoint.GetAutoUpdateConfig(r.Context()) - // TODO(vapopov) DELETE IN v18.0.0 check of IsNotImplemented, must be backported to all latest supported versions. - if err != nil && !trace.IsNotFound(err) && !trace.IsNotImplemented(err) { - h.logger.ErrorContext(r.Context(), "failed to receive AutoUpdateConfig", "error", err) - } - // If we can't get the AU config or tools AU are not configured, we default to "disabled". - // This ensures we fail open and don't accidentally update agents if something is going wrong. - // If we want to enable AUs by default, it would be better to create a default "autoupdate_config" resource - // than changing this logic. - if autoUpdateConfig.GetSpec().GetTools() == nil { - response.AutoUpdate.ToolsMode = autoupdate.ToolsUpdateModeDisabled - } else { - response.AutoUpdate.ToolsMode = autoUpdateConfig.GetSpec().GetTools().GetMode() - } + proxyConfig, err := h.cfg.ProxySettings.GetProxySettings(r.Context()) + if err != nil { + return nil, trace.Wrap(err) + } + response.Proxy = *proxyConfig - autoUpdateVersion, err := h.cfg.AccessPoint.GetAutoUpdateVersion(r.Context()) - // TODO(vapopov) DELETE IN v18.0.0 check of IsNotImplemented, must be backported to all latest supported versions. - if err != nil && !trace.IsNotFound(err) && !trace.IsNotImplemented(err) { - h.logger.ErrorContext(r.Context(), "failed to receive AutoUpdateVersion", "error", err) - } - // If we can't get the AU version or tools AU version is not specified, we default to the current proxy version. - // This ensures we always advertise a version compatible with the cluster. - if autoUpdateVersion.GetSpec().GetTools() == nil { - response.AutoUpdate.ToolsVersion = api.Version - } else { - response.AutoUpdate.ToolsVersion = autoUpdateVersion.GetSpec().GetTools().GetTargetVersion() + authPref, err := h.cfg.AccessPoint.GetAuthPreference(r.Context()) + if err != nil { + return nil, trace.Wrap(err) + } + response.Auth = webclient.AuthenticationSettings{SignatureAlgorithmSuite: authPref.GetSignatureAlgorithmSuite()} + + autoUpdateConfig, err := h.cfg.AccessPoint.GetAutoUpdateConfig(r.Context()) + // TODO(vapopov) DELETE IN v18.0.0 check of IsNotImplemented, must be backported to all latest supported versions. + if err != nil && !trace.IsNotFound(err) && !trace.IsNotImplemented(err) { + h.logger.ErrorContext(r.Context(), "failed to receive AutoUpdateConfig", "error", err) + } + // If we can't get the AU config or tools AU are not configured, we default to "disabled". + // This ensures we fail open and don't accidentally update agents if something is going wrong. + // If we want to enable AUs by default, it would be better to create a default "autoupdate_config" resource + // than changing this logic. + if autoUpdateConfig.GetSpec().GetTools() == nil { + response.AutoUpdate.ToolsMode = autoupdate.ToolsUpdateModeDisabled + } else { + response.AutoUpdate.ToolsMode = autoUpdateConfig.GetSpec().GetTools().GetMode() + } + + autoUpdateVersion, err := h.cfg.AccessPoint.GetAutoUpdateVersion(r.Context()) + // TODO(vapopov) DELETE IN v18.0.0 check of IsNotImplemented, must be backported to all latest supported versions. + if err != nil && !trace.IsNotFound(err) && !trace.IsNotImplemented(err) { + h.logger.ErrorContext(r.Context(), "failed to receive AutoUpdateVersion", "error", err) + } + // If we can't get the AU version or tools AU version is not specified, we default to the current proxy version. + // This ensures we always advertise a version compatible with the cluster. + if autoUpdateVersion.GetSpec().GetTools() == nil { + response.AutoUpdate.ToolsVersion = api.Version + } else { + response.AutoUpdate.ToolsVersion = autoUpdateVersion.GetSpec().GetTools().GetTargetVersion() + } + + return &response, nil + }) + if err != nil { + return nil, trace.Wrap(err) } - return response, nil + // If you need to modulate the response based on the request params (will need to do this for automatic updates) + // Do it here. + return resp, nil } func (h *Handler) pingWithConnector(w http.ResponseWriter, r *http.Request, p httprouter.Params) (interface{}, error) { @@ -3544,9 +3573,12 @@ func (h *Handler) siteNodeConnect( WebsocketConn: ws, SSHDialTimeout: dialTimeout, HostNameResolver: func(serverID string) (string, error) { - matches := nw.GetNodes(r.Context(), func(n services.Node) bool { + matches, err := nw.CurrentResourcesWithFilter(r.Context(), func(n readonly.Server) bool { return n.GetName() == serverID }) + if err != nil { + return "", trace.Wrap(err) + } if len(matches) != 1 { return "", trace.NotFound("unable to resolve hostname for server %s", serverID) diff --git a/lib/web/apiserver_ping_test.go b/lib/web/apiserver_ping_test.go index 903a204fe2228..231c8625ffacd 100644 --- a/lib/web/apiserver_ping_test.go +++ b/lib/web/apiserver_ping_test.go @@ -395,6 +395,11 @@ func TestPing_autoUpdateResources(t *testing.T) { require.NoError(t, err) } + // expire the fn cache to force the next answer to be fresh + for _, proxy := range env.proxies { + proxy.clock.Advance(2 * findEndpointCacheTTL) + } + resp, err := client.NewInsecureWebClient().Do(req) require.NoError(t, err) diff --git a/lib/web/apiserver_test.go b/lib/web/apiserver_test.go index 5e3fea922d245..a585579f7ddda 100644 --- a/lib/web/apiserver_test.go +++ b/lib/web/apiserver_test.go @@ -381,6 +381,7 @@ func newWebSuiteWithConfig(t *testing.T, cfg webSuiteConfig) *WebSuite { Component: teleport.ComponentProxy, Client: s.proxyClient, }, + NodesGetter: s.proxyClient, }) require.NoError(t, err) @@ -8185,6 +8186,7 @@ func createProxy(ctx context.Context, t *testing.T, proxyID string, node *regula Component: teleport.ComponentProxy, Client: client, }, + NodesGetter: client, }) require.NoError(t, err) t.Cleanup(proxyNodeWatcher.Close) @@ -9075,6 +9077,7 @@ func startKubeWithoutCleanup(ctx context.Context, t *testing.T, cfg startKubeOpt Client: client, Clock: clock, }, + KubernetesServerGetter: client, }) require.NoError(t, err) diff --git a/lib/web/integrations_awsoidc.go b/lib/web/integrations_awsoidc.go index 8a28e2582e9c2..52d7d1710809b 100644 --- a/lib/web/integrations_awsoidc.go +++ b/lib/web/integrations_awsoidc.go @@ -1434,6 +1434,7 @@ func getServiceURLs(dbServices []types.DatabaseService, accountID, region, telep } // awsOIDCPing performs an health check for the integration. +// If ARN is present in the request body, that's the ARN that will be used instead of using the one stored in the integration. // Returns meta information: account id and assumed the ARN for the IAM Role. func (h *Handler) awsOIDCPing(w http.ResponseWriter, r *http.Request, p httprouter.Params, sctx *SessionContext, site reversetunnelclient.RemoteSite) (any, error) { ctx := r.Context() @@ -1443,6 +1444,11 @@ func (h *Handler) awsOIDCPing(w http.ResponseWriter, r *http.Request, p httprout return nil, trace.BadParameter("an integration name is required") } + var req ui.AWSOIDCPingRequest + if err := httplib.ReadJSON(r, &req); err != nil { + return nil, trace.Wrap(err) + } + clt, err := sctx.GetUserClient(ctx, site) if err != nil { return nil, trace.Wrap(err) @@ -1450,6 +1456,7 @@ func (h *Handler) awsOIDCPing(w http.ResponseWriter, r *http.Request, p httprout pingResp, err := clt.IntegrationAWSOIDCClient().Ping(ctx, &integrationv1.PingRequest{ Integration: integrationName, + RoleArn: req.RoleARN, }) if err != nil { return nil, trace.Wrap(err) diff --git a/lib/web/ui/integration.go b/lib/web/ui/integration.go index 2db7010c4f450..f1eaf46188164 100644 --- a/lib/web/ui/integration.go +++ b/lib/web/ui/integration.go @@ -525,3 +525,11 @@ type AWSOIDCPingResponse struct { // UserID is the unique identifier of the calling entity. UserID string `json:"userId"` } + +// AWSOIDCPingRequest contains ping request fields. +type AWSOIDCPingRequest struct { + // RoleARN is optional, and used for cases such as + // pinging to check validity before upserting an + // AWS OIDC integration. + RoleARN string `json:"roleArn,omitempty"` +} diff --git a/proto/prehog/v1alpha/teleport.proto b/proto/prehog/v1alpha/teleport.proto index 0e1e08833dad9..aee8d81b6cfc0 100644 --- a/proto/prehog/v1alpha/teleport.proto +++ b/proto/prehog/v1alpha/teleport.proto @@ -778,6 +778,7 @@ enum CTA { CTA_EXTERNAL_AUDIT_STORAGE = 10; CTA_OKTA_USER_SYNC = 11; CTA_ENTRA_ID = 12; + CTA_OKTA_SCIM = 13; } // a request forwarded to a kube cluster's API server (other than exec and @@ -1008,10 +1009,6 @@ message AccessListReviewComplianceEvent { // IntegrationEnrollKind represents the types of integration that // can be enrolled. -// -// Note: IntegrationEnrollKind enum must be kept in sync with the values defined -// in api/proto/teleport/usageevents/v1/usageevents.proto. Values 18-25 have -// become out of sync and are manually mapped to each other. enum IntegrationEnrollKind { INTEGRATION_ENROLL_KIND_UNSPECIFIED = 0; INTEGRATION_ENROLL_KIND_SLACK = 1; @@ -1403,6 +1400,31 @@ message DatabaseUserPermissionsUpdateEvent { int32 num_tables_permissions = 4; } +// SessionRecordingAccessEvent is emitted when the user accesses a session +// recording. +// +// PostHog event: tp.recording.access +message SessionRecordingAccessEvent { + // session_type is type of the session, should be + // "ssh"/"k8s"/"db"/"app"/"desktop" (matching the values for + // api/types.SessionKind). + // + // PostHog property: tp.session_type + string session_type = 1; + + // user_name is the anonymized Teleport username, 32 bytes (HMAC-SHA-256) + // encoded in base64. + // + // PostHog property: tp.user_name + string user_name = 2; + + // format is the format the session recording was accessed. + // One of text/json/yaml/pty. pty being the interactive session player. + // + // PostHog property: tp.recording.format + string format = 3; +} + // UserTaskStateEvent is emitted when a UserTask state changes. // This can happen when the Task is created, when it's manually // resolved by the user or when it changes back to being open @@ -1588,6 +1610,8 @@ message SubmitEventRequest { UIAccessGraphCrownJewelDiffViewEvent ui_access_graph_crown_jewel_diff_view = 92; + SessionRecordingAccessEvent session_recording_access = 93; + UserTaskStateEvent user_task_state = 94; } diff --git a/tool/teleport-update/main.go b/tool/teleport-update/main.go index 11aee2aae3906..300da6736471a 100644 --- a/tool/teleport-update/main.go +++ b/tool/teleport-update/main.go @@ -81,16 +81,8 @@ type cliConfig struct { LogFormat string // DataDir for Teleport (usually /var/lib/teleport) DataDir string -} - -func (c *cliConfig) CheckAndSetDefaults() error { - if c.DataDir == "" { - c.DataDir = libdefaults.DataDir - } - if c.LogFormat == "" { - c.LogFormat = libutils.LogFormatText - } - return nil + // LinkDir for linking binaries and systemd services + LinkDir string } func Run(args []string) error { @@ -105,6 +97,8 @@ func Run(args []string) error { Default(libdefaults.DataDir).StringVar(&ccfg.DataDir) app.Flag("log-format", "Controls the format of output logs. Can be `json` or `text`. Defaults to `text`."). Default(libutils.LogFormatText).EnumVar(&ccfg.LogFormat, libutils.LogFormatJSON, libutils.LogFormatText) + app.Flag("link-dir", "Directory to create system symlinks to binaries and services."). + Default(filepath.Join("usr", "local")).Hidden().StringVar(&ccfg.LinkDir) app.HelpFlag.Short('h') @@ -138,10 +132,6 @@ func Run(args []string) error { return trace.Errorf("failed to set up logger") } - if err := ccfg.CheckAndSetDefaults(); err != nil { - return trace.Wrap(err) - } - switch command { case enableCmd.FullCommand(): err = cmdEnable(ctx, &ccfg) @@ -194,6 +184,7 @@ func cmdDisable(ctx context.Context, ccfg *cliConfig) error { }() updater, err := autoupdate.NewLocalUpdater(autoupdate.LocalUpdaterConfig{ VersionsDir: versionsDir, + LinkDir: ccfg.LinkDir, Log: plog, }) if err != nil { @@ -225,6 +216,7 @@ func cmdEnable(ctx context.Context, ccfg *cliConfig) error { updater, err := autoupdate.NewLocalUpdater(autoupdate.LocalUpdaterConfig{ VersionsDir: versionsDir, + LinkDir: ccfg.LinkDir, Log: plog, }) if err != nil { diff --git a/web/packages/design/src/Alert/Alert.tsx b/web/packages/design/src/Alert/Alert.tsx index 5e471280ffe24..c674aff2b1b79 100644 --- a/web/packages/design/src/Alert/Alert.tsx +++ b/web/packages/design/src/Alert/Alert.tsx @@ -20,6 +20,8 @@ import React, { useState } from 'react'; import styled, { useTheme } from 'styled-components'; import { style, color, ColorProps } from 'styled-system'; +import { IconProps } from 'design/Icon/Icon'; + import { space, SpaceProps, width, WidthProps } from '../system'; import { Theme } from '../theme'; import * as Icon from '../Icon'; @@ -111,7 +113,7 @@ interface Props { /** Additional description to be displayed below the main content. */ details?: React.ReactNode; /** Overrides the icon specified by {@link AlertProps.kind}. */ - icon?: React.ComponentType; + icon?: React.ComponentType; /** If specified, causes the alert to display a primary action button. */ primaryAction?: Action; /** If specified, causes the alert to display a secondary action button. */ @@ -253,8 +255,8 @@ const AlertIcon = ({ ...otherProps }: { kind: AlertKind | BannerKind; - customIcon?: React.ComponentType; -} & Icon.IconProps) => { + customIcon?: React.ComponentType; +} & IconProps) => { const commonProps = { role: 'graphics-symbol', ...otherProps }; if (CustomIcon) { return ; diff --git a/web/packages/design/src/DataTable/Table.test.tsx b/web/packages/design/src/DataTable/Table.test.tsx index f53522f924c57..77ee038dbfb9d 100644 --- a/web/packages/design/src/DataTable/Table.test.tsx +++ b/web/packages/design/src/DataTable/Table.test.tsx @@ -18,6 +18,7 @@ import React from 'react'; import { within } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; import { render, fireEvent, screen } from 'design/utils/testing'; @@ -366,3 +367,36 @@ describe('sorting by iso date string', () => { expect(rows[2]).toHaveTextContent('a3'); }); }); + +test('navigate to next and previous pages', async () => { + render( + + ); + + let { rows } = getTableRows(); + expect(rows).toHaveLength(2); + expect(rows[0]).toHaveTextContent(data[0].hostname); + expect(rows[1]).toHaveTextContent(data[1].hostname); + + await userEvent.click(screen.getByTitle('Next page')); + rows = getTableRows().rows; + expect(rows).toHaveLength(2); + expect(rows[0]).toHaveTextContent(data[2].hostname); + expect(rows[1]).toHaveTextContent(data[3].hostname); + + await userEvent.click(screen.getByTitle('Previous page')); + rows = getTableRows().rows; + expect(rows).toHaveLength(2); + expect(rows[0]).toHaveTextContent(data[0].hostname); + expect(rows[1]).toHaveTextContent(data[1].hostname); +}); diff --git a/web/packages/design/src/DataTable/Table.tsx b/web/packages/design/src/DataTable/Table.tsx index 8f3b9bc8bcaa5..d028e1b18a844 100644 --- a/web/packages/design/src/DataTable/Table.tsx +++ b/web/packages/design/src/DataTable/Table.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import React, { ReactNode } from 'react'; +import React, { ReactNode, PropsWithChildren } from 'react'; import { Box, Flex, Indicator, P1, Text } from 'design'; import * as Icons from 'design/Icon'; @@ -108,6 +108,22 @@ export default function Table(props: TableProps) { return ; } data.map((item, rowIdx) => { + const TableRow: React.FC = ({ children }) => ( + row?.onClick?.(item)} + style={row?.getStyle?.(item)} + > + {children} + + ); + + const customRow = row?.customRow?.(item); + if (customRow) { + rows.push({customRow}); + return; + } + const cells = columns.flatMap((column, columnIdx) => { if (column.isNonRender) { return []; // does not include this column. @@ -125,15 +141,7 @@ export default function Table(props: TableProps) { ); }); - rows.push( - row?.onClick?.(item)} - style={row?.getStyle?.(item)} - > - {cells} - - ); + rows.push({cells}); }); if (rows.length) { diff --git a/web/packages/design/src/DataTable/types.ts b/web/packages/design/src/DataTable/types.ts index afe803116613a..9f5ec0490653c 100644 --- a/web/packages/design/src/DataTable/types.ts +++ b/web/packages/design/src/DataTable/types.ts @@ -79,6 +79,14 @@ export type TableProps = { * conditionally style a row (eg: cursor: pointer, disabled) */ getStyle?(row: T): React.CSSProperties; + /** + * conditionally render a custom row + * use case: by default all columns are represented by cells + * but certain rows you need all the columns to be merged + * into one cell to render other related elements like a + * dropdown selector. + */ + customRow?(row: T): JSX.Element; }; }; diff --git a/web/packages/design/src/DataTable/useTable.ts b/web/packages/design/src/DataTable/useTable.ts index 7b7deda0af0e3..e8c70f3bd2dd0 100644 --- a/web/packages/design/src/DataTable/useTable.ts +++ b/web/packages/design/src/DataTable/useTable.ts @@ -185,30 +185,30 @@ export default function useTable({ if (serversideProps) { fetching?.onFetchNext?.(); } - setState({ - ...state, - pagination: state.pagination + setState(prevState => ({ + ...prevState, + pagination: prevState.pagination ? { - ...state.pagination, - currentPage: state.pagination.currentPage + 1, + ...prevState.pagination, + currentPage: prevState.pagination.currentPage + 1, } : undefined, - }); + })); } function prevPage() { if (serversideProps) { fetching?.onFetchPrev?.(); } - setState({ - ...state, - pagination: state.pagination + setState(prevState => ({ + ...prevState, + pagination: prevState.pagination ? { - ...state.pagination, - currentPage: state.pagination.currentPage + 1, + ...prevState.pagination, + currentPage: prevState.pagination.currentPage - 1, } : undefined, - }); + })); } useEffect(() => { diff --git a/web/packages/design/src/Icon/Icons.story.tsx b/web/packages/design/src/Icon/Icons.story.tsx index a511f5692b4ca..4a792aeec912c 100644 --- a/web/packages/design/src/Icon/Icons.story.tsx +++ b/web/packages/design/src/Icon/Icons.story.tsx @@ -135,6 +135,7 @@ export const Icons = () => ( + @@ -152,6 +153,7 @@ export const Icons = () => ( + @@ -170,6 +172,7 @@ export const Icons = () => ( + diff --git a/web/packages/design/src/Icon/Icons/KeyHole.tsx b/web/packages/design/src/Icon/Icons/KeyHole.tsx new file mode 100644 index 0000000000000..afc86a7543647 --- /dev/null +++ b/web/packages/design/src/Icon/Icons/KeyHole.tsx @@ -0,0 +1,73 @@ +/** + * Teleport + * Copyright (C) 2023 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 . + */ + +/* MIT License + +Copyright (c) 2020 Phosphor Icons + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +import React from 'react'; + +import { Icon, IconProps } from '../Icon'; + +/* + +THIS FILE IS GENERATED. DO NOT EDIT. + +*/ + +export function KeyHole({ size = 24, color, ...otherProps }: IconProps) { + return ( + + + + + ); +} diff --git a/web/packages/design/src/Icon/Icons/LockKey.tsx b/web/packages/design/src/Icon/Icons/LockKey.tsx new file mode 100644 index 0000000000000..65a953566d71d --- /dev/null +++ b/web/packages/design/src/Icon/Icons/LockKey.tsx @@ -0,0 +1,73 @@ +/** + * Teleport + * Copyright (C) 2023 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 . + */ + +/* MIT License + +Copyright (c) 2020 Phosphor Icons + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +import React from 'react'; + +import { Icon, IconProps } from '../Icon'; + +/* + +THIS FILE IS GENERATED. DO NOT EDIT. + +*/ + +export function LockKey({ size = 24, color, ...otherProps }: IconProps) { + return ( + + + + + ); +} diff --git a/web/packages/design/src/Icon/Icons/PlugsConnected.tsx b/web/packages/design/src/Icon/Icons/PlugsConnected.tsx new file mode 100644 index 0000000000000..ec991cd95b2ee --- /dev/null +++ b/web/packages/design/src/Icon/Icons/PlugsConnected.tsx @@ -0,0 +1,72 @@ +/** + * Teleport + * Copyright (C) 2023 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 . + */ + +/* MIT License + +Copyright (c) 2020 Phosphor Icons + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +import React from 'react'; + +import { Icon, IconProps } from '../Icon'; + +/* + +THIS FILE IS GENERATED. DO NOT EDIT. + +*/ + +export function PlugsConnected({ size = 24, color, ...otherProps }: IconProps) { + return ( + + + + + + + + ); +} diff --git a/web/packages/design/src/Icon/assets/KeyHole.svg b/web/packages/design/src/Icon/assets/KeyHole.svg new file mode 100644 index 0000000000000..c4c69dfaf4c8e --- /dev/null +++ b/web/packages/design/src/Icon/assets/KeyHole.svg @@ -0,0 +1,4 @@ + + + + diff --git a/web/packages/design/src/Icon/assets/LockKey.svg b/web/packages/design/src/Icon/assets/LockKey.svg new file mode 100644 index 0000000000000..554f55b8d71d4 --- /dev/null +++ b/web/packages/design/src/Icon/assets/LockKey.svg @@ -0,0 +1,4 @@ + + + + diff --git a/web/packages/design/src/Icon/assets/PlugsConnected.svg b/web/packages/design/src/Icon/assets/PlugsConnected.svg new file mode 100644 index 0000000000000..2ce54755155bf --- /dev/null +++ b/web/packages/design/src/Icon/assets/PlugsConnected.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/web/packages/design/src/Icon/index.ts b/web/packages/design/src/Icon/index.ts index 57f2fa84d3a11..6e24c134497db 100644 --- a/web/packages/design/src/Icon/index.ts +++ b/web/packages/design/src/Icon/index.ts @@ -22,7 +22,7 @@ THIS FILE IS GENERATED. DO NOT EDIT. */ -export { Icon, type IconProps } from './Icon'; +export { Icon } from './Icon'; export { Add } from './Icons/Add'; export { AddCircle } from './Icons/AddCircle'; @@ -121,6 +121,7 @@ export { Info } from './Icons/Info'; export { Integrations } from './Icons/Integrations'; export { Invoices } from './Icons/Invoices'; export { Key } from './Icons/Key'; +export { KeyHole } from './Icons/KeyHole'; export { Keyboard } from './Icons/Keyboard'; export { Keypair } from './Icons/Keypair'; export { Kubernetes } from './Icons/Kubernetes'; @@ -138,6 +139,7 @@ export { ListMagnifyingGlass } from './Icons/ListMagnifyingGlass'; export { ListThin } from './Icons/ListThin'; export { ListView } from './Icons/ListView'; export { Lock } from './Icons/Lock'; +export { LockKey } from './Icons/LockKey'; export { Logout } from './Icons/Logout'; export { Magnifier } from './Icons/Magnifier'; export { MagnifyingMinus } from './Icons/MagnifyingMinus'; @@ -156,6 +158,7 @@ export { PaperPlane } from './Icons/PaperPlane'; export { Password } from './Icons/Password'; export { Pencil } from './Icons/Pencil'; export { Planet } from './Icons/Planet'; +export { PlugsConnected } from './Icons/PlugsConnected'; export { Plus } from './Icons/Plus'; export { PowerSwitch } from './Icons/PowerSwitch'; export { Printer } from './Icons/Printer'; diff --git a/web/packages/design/src/Link/Link.jsx b/web/packages/design/src/Link/Link.jsx index 957be80a5f7be..260c31f85094b 100644 --- a/web/packages/design/src/Link/Link.jsx +++ b/web/packages/design/src/Link/Link.jsx @@ -31,7 +31,6 @@ const StyledButtonLink = styled.a.attrs({ rel: 'noreferrer', })` color: ${({ theme }) => theme.colors.buttons.link.default}; - font-weight: normal; background: none; text-decoration: underline; text-transform: none; diff --git a/web/packages/shared/components/AccessRequests/NewRequest/CheckableOption.tsx b/web/packages/shared/components/AccessRequests/NewRequest/CheckableOption.tsx new file mode 100644 index 0000000000000..f10b940050628 --- /dev/null +++ b/web/packages/shared/components/AccessRequests/NewRequest/CheckableOption.tsx @@ -0,0 +1,48 @@ +/** + * 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 . + */ + +import React from 'react'; +import { Flex, Text } from 'design'; +import { components, OptionProps } from 'react-select'; + +import { Option as BaseOption } from 'shared/components/Select'; + +export type Option = BaseOption & { + isAdded?: boolean; + kind: 'app' | 'user_group' | 'namespace'; +}; + +export const CheckableOptionComponent = ( + props: OptionProps + ); + } + } + + return ( + + {({ validator }) => ( + <> + {showRequestRoleErrBanner && + fetchResourceRequestRolesAttempt.status === 'failed' && ( + + )} + {hasUnsupportedKubeRequestModes && ( + + + You can only request Kubernetes resource{' '} + {pluralize(unsupportedKubeRequestModes.length, 'kind')}{' '} + {listToSentence(unsupportedKubeRequestModes)} for + cluster {affectedKubeClusterName}. Requesting those + resource kinds is currently only supported through the{' '} + + tsh CLI tool + + . Use the{' '} + + tsh request search + {' '} + command that will help you construct the request. + + + Example: + - - {({ validator }) => ( + + )} + {fetchStatus === 'loading' && ( + + + + )} + + {fetchStatus === 'loaded' && ( +
+ {createAttempt.status === 'success' ? ( + <> + + +

Resources Requested Successfully

+ + You've successfully requested {numRequestedResources}{' '} + {pluralize(numRequestedResources, 'resource')} + +
+ + + +
+ + + ) : ( + <> + {Header?.() || DefaultHeader()} + {createAttempt.status === 'failed' && ( + + )} + d.kind !== 'namespace' + )} + row={{ + customRow, + }} + columns={[ + { + key: 'clusterName', + headerText: 'Cluster Name', + isNonRender: !showClusterNameColumn, + }, + { + key: 'kind', + headerText: 'Type', + render: item => ( + {getPrettyResourceKind(item.kind)} + ), + }, + { + key: 'name', + headerText: 'Name', + }, + { + altKey: 'delete-btn', + render: resource => ( + + + + ), + }, + ]} + emptyText="No resources are selected" + /> + {userGroupFetchAttempt?.status === 'processing' && ( + + + + )} + {userGroupFetchAttempt?.status === 'failed' && ( + {userGroupFetchAttempt.statusText} + )} + {userGroupFetchAttempt?.status === 'success' && + appsGrantedByUserGroup.length > 0 && ( + + )} + {isResourceRequest && ( + + )} + + r.name) ?? [] + } + selectedReviewers={selectedReviewers} + setSelectedReviewers={setSelectedReviewers} + /> + {dryRunResponse && ( @@ -394,19 +487,19 @@ export function RequestCheckout({ reset(); onClose(); }} - disabled={submitBtnDisabled} + disabled={cancelBtnDisabled} > Cancel - )} - - + + )} +
)} - + )} - +
); } @@ -549,7 +642,7 @@ function ResourceRequestRoles({ {roles.map((roleName, index) => { const checked = selectedRoles.includes(roleName); return ( - + ; export interface PendingListItem { - kind: ResourceKind; + kind: RequestableResourceKind; /** Name of the resource, for presentation purposes only. */ name: string; /** Identifier of the resource. Should be sent in requests. */ id: string; clusterName?: string; + /** + * This field must be defined if a user is requesting subresources. + * + * Example: + * "kube_cluster" resource can have subresources such as "namespace". + * Example PendingListItem values if user is requesting a kubes namespace: + * - kind: const "namespace" + * - id: name of the kube_cluster + * - subResourceName: name of the kube_cluster's namespace + * - clusterName: name of teleport cluster where kube_cluster is located + * - name: same as subResourceName as this is what we want to display to user + * */ + subResourceName?: string; } +export type PendingKubeResourceItem = Omit & { + kind: Extract; +}; + export type RequestCheckoutProps = { onClose(): void; @@ -816,6 +928,11 @@ export type RequestCheckoutProps = Header?: () => JSX.Element; startTime: Date; onStartTimeChange(t?: Date): void; + fetchKubeNamespaces(p: KubeNamespaceRequest): Promise; + bulkToggleKubeResources( + kubeResources: PendingKubeResourceItem[], + kubeCluster: T + ): void; }; type SuccessComponentParams = { diff --git a/web/packages/shared/components/AccessRequests/NewRequest/RequestCheckout/index.ts b/web/packages/shared/components/AccessRequests/NewRequest/RequestCheckout/index.ts index 95712e2755a15..9e727450cd3e1 100644 --- a/web/packages/shared/components/AccessRequests/NewRequest/RequestCheckout/index.ts +++ b/web/packages/shared/components/AccessRequests/NewRequest/RequestCheckout/index.ts @@ -17,7 +17,11 @@ */ export { RequestCheckoutWithSlider, RequestCheckout } from './RequestCheckout'; -export type { RequestCheckoutProps, PendingListItem } from './RequestCheckout'; +export type { + RequestCheckoutProps, + PendingListItem, + PendingKubeResourceItem, +} from './RequestCheckout'; export * from './utils'; export type { ReviewerOption } from './types'; diff --git a/web/packages/shared/components/AccessRequests/NewRequest/ResourceList/Apps.tsx b/web/packages/shared/components/AccessRequests/NewRequest/ResourceList/Apps.tsx index 33e01c9fa7675..5488ceeedaefd 100644 --- a/web/packages/shared/components/AccessRequests/NewRequest/ResourceList/Apps.tsx +++ b/web/packages/shared/components/AccessRequests/NewRequest/ResourceList/Apps.tsx @@ -30,7 +30,7 @@ import Select, { } from 'shared/components/Select'; import { ToolTipInfo } from 'shared/components/ToolTip'; -import { ResourceMap, ResourceKind } from '../resource'; +import { ResourceMap, RequestableResourceKind } from '../resource'; import { ListProps, StyledTable } from './ResourceList'; @@ -125,7 +125,7 @@ function ActionCell({ agent: App; addedResources: ResourceMap; addOrRemoveResource: ( - kind: ResourceKind, + kind: RequestableResourceKind, resourceId: string, resourceName?: string ) => void; diff --git a/web/packages/shared/components/AccessRequests/NewRequest/ResourceList/ResourceList.tsx b/web/packages/shared/components/AccessRequests/NewRequest/ResourceList/ResourceList.tsx index 1828fce8d7298..2981f1175ebd3 100644 --- a/web/packages/shared/components/AccessRequests/NewRequest/ResourceList/ResourceList.tsx +++ b/web/packages/shared/components/AccessRequests/NewRequest/ResourceList/ResourceList.tsx @@ -30,7 +30,7 @@ import { CustomSort } from 'design/DataTable/types'; import { ResourceLabel, UnifiedResource } from 'teleport/services/agents'; -import { ResourceMap, ResourceKind } from '../resource'; +import { ResourceMap, RequestableResourceKind } from '../resource'; import { Apps } from './Apps'; import { Databases } from './Databases'; @@ -126,7 +126,7 @@ export type ListProps = { onLabelClick: (label: ResourceLabel) => void; addedResources: ResourceMap; addOrRemoveResource: ( - kind: ResourceKind, + kind: RequestableResourceKind, resourceId: string, resourceName?: string ) => void; @@ -135,7 +135,7 @@ export type ListProps = { export type ResourceListProps = { agents: UnifiedResource[]; - selectedResource: ResourceKind; + selectedResource: RequestableResourceKind; // disableRows disable clicking on any buttons (when fetching). disableRows: boolean; } & ListProps; diff --git a/web/packages/shared/components/AccessRequests/NewRequest/index.ts b/web/packages/shared/components/AccessRequests/NewRequest/index.ts index 46181260d19f7..9074113221b16 100644 --- a/web/packages/shared/components/AccessRequests/NewRequest/index.ts +++ b/web/packages/shared/components/AccessRequests/NewRequest/index.ts @@ -18,5 +18,7 @@ export * from './RequestCheckout'; export * from './ResourceList'; -export type { ResourceMap, ResourceKind } from './resource'; +export type { ResourceMap, RequestableResourceKind } from './resource'; export { getEmptyResourceState } from './resource'; +export type { KubeNamespaceRequest } from './kube'; +export { isKubeClusterWithNamespaces } from './kube'; diff --git a/web/packages/shared/components/AccessRequests/NewRequest/kube.test.ts b/web/packages/shared/components/AccessRequests/NewRequest/kube.test.ts new file mode 100644 index 0000000000000..33e136e0dc038 --- /dev/null +++ b/web/packages/shared/components/AccessRequests/NewRequest/kube.test.ts @@ -0,0 +1,61 @@ +/** + * 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 . + */ + +import { checkForUnsupportedKubeRequestModes } from './kube'; + +test('checkForUnsupportedKubeRequestModes: non failed status', () => { + const { + affectedKubeClusterName, + unsupportedKubeRequestModes, + requiresNamespaceSelect, + } = checkForUnsupportedKubeRequestModes({ status: '' }); + + expect(affectedKubeClusterName).toBeFalsy(); + expect(unsupportedKubeRequestModes).toBeFalsy(); + expect(requiresNamespaceSelect).toBeFalsy(); +}); + +test('checkForUnsupportedKubeRequestModes: failed status with unsupported kinds', () => { + const { + affectedKubeClusterName, + unsupportedKubeRequestModes, + requiresNamespaceSelect, + } = checkForUnsupportedKubeRequestModes({ + status: 'failed', + statusText: `Your Teleport roles request_mode field restricts you from requesting kinds [kube_cluster] for Kubernetes cluster "pumpkin-kube-cluster". Allowed kinds: [pod secret]`, + }); + + expect(affectedKubeClusterName).toEqual(`pumpkin-kube-cluster`); + expect(unsupportedKubeRequestModes).toEqual(['pod', 'secret']); + expect(requiresNamespaceSelect).toBeFalsy(); +}); + +test('checkForUnsupportedKubeRequestModes: failed status with supported namespace', () => { + const { + affectedKubeClusterName, + unsupportedKubeRequestModes, + requiresNamespaceSelect, + } = checkForUnsupportedKubeRequestModes({ + status: 'failed', + statusText: `Your Teleport roles request_mode field restricts you from requesting kinds [kube_cluster] for Kubernetes cluster "pumpkin-kube-cluster". Allowed kinds: [pod secret namespace]`, + }); + + expect(affectedKubeClusterName).toEqual(`pumpkin-kube-cluster`); + expect(unsupportedKubeRequestModes).toBeFalsy(); + expect(requiresNamespaceSelect).toBeTruthy(); +}); diff --git a/web/packages/shared/components/AccessRequests/NewRequest/kube.ts b/web/packages/shared/components/AccessRequests/NewRequest/kube.ts new file mode 100644 index 0000000000000..e84ed46c972b4 --- /dev/null +++ b/web/packages/shared/components/AccessRequests/NewRequest/kube.ts @@ -0,0 +1,94 @@ +/** + * 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 . + */ + +import { Attempt } from 'shared/hooks/useAttemptNext'; + +import { PendingListItem } from './RequestCheckout'; + +export type KubeNamespaceRequest = { + kubeCluster: string; + search: string; +}; + +/** + * Returns true if the item is a kube cluster or is a namespace + * of the item. + * + * Technically you can request for both a kube_cluster and its subresources + * but it's probably not what a user would expect from the web UI because + * requesting for subresources means narrowing access versus requesting + * access to the whole kube_cluster. + */ +export function isKubeClusterWithNamespaces( + item: PendingListItem, + allItems: PendingListItem[] +) { + return ( + item.kind === 'kube_cluster' && + allItems.find(a => a.kind === 'namespace' && a.id == item.id) + ); +} + +/** + * Checks each data for kube_cluster or namespace + */ +export function checkForUnsupportedKubeRequestModes( + requestRoleAttempt: Attempt +) { + let unsupportedKubeRequestModes: string[]; + let affectedKubeClusterName = ''; + let requiresNamespaceSelect = false; + + if (requestRoleAttempt.status === 'failed') { + const errMsg = requestRoleAttempt.statusText.toLowerCase(); + + if (errMsg.includes('request_mode') && errMsg.includes('allowed kinds: ')) { + let allowedKinds = errMsg.split('allowed kinds: ')[1]; + + // Web UI supports selecting namespace and wildcard + // which basically means requiring namespace. + if (allowedKinds.includes('*') || allowedKinds.includes('namespace')) { + requiresNamespaceSelect = true; + } else { + if (allowedKinds.startsWith('[')) { + allowedKinds = allowedKinds.slice(1, -1); + } + unsupportedKubeRequestModes = allowedKinds.split(' '); + } + + const initialSplit = errMsg.split('for kubernetes cluster "'); + if (initialSplit.length > 1) { + affectedKubeClusterName = initialSplit[1] + .split('". allowed kinds')[0] + .trim(); + } + + return { + affectedKubeClusterName, + requiresNamespaceSelect, + unsupportedKubeRequestModes, + }; + } + } + + return { + affectedKubeClusterName, + unsupportedKubeRequestModes, + requiresNamespaceSelect, + }; +} diff --git a/web/packages/shared/components/AccessRequests/NewRequest/resource.ts b/web/packages/shared/components/AccessRequests/NewRequest/resource.ts index 42070e9448283..f56ad58110d25 100644 --- a/web/packages/shared/components/AccessRequests/NewRequest/resource.ts +++ b/web/packages/shared/components/AccessRequests/NewRequest/resource.ts @@ -17,16 +17,21 @@ */ import { ResourceIdKind } from 'teleport/services/agents'; +import { KubeResourceKind } from 'teleport/services/kube'; /** Available request kinds for resource-based and role-based access requests. */ -export type ResourceKind = ResourceIdKind | 'role' | 'resource'; +export type RequestableResourceKind = + | ResourceIdKind + | 'role' + | 'resource' + | Exclude; /** * Maps a resource ID (usually agent name) to resource description (usually the * same, but not necessarily). */ export type ResourceMap = { - [K in ResourceIdKind | 'role']: Record; + [K in Exclude]: Record; }; export function getEmptyResourceState(): ResourceMap { @@ -39,5 +44,6 @@ export function getEmptyResourceState(): ResourceMap { windows_desktop: {}, role: {}, saml_idp_service_provider: {}, + namespace: {}, }; } diff --git a/web/packages/shared/components/AccessRequests/Shared/utils.ts b/web/packages/shared/components/AccessRequests/Shared/utils.ts index 1ac9a291328bf..6185e568c4c21 100644 --- a/web/packages/shared/components/AccessRequests/Shared/utils.ts +++ b/web/packages/shared/components/AccessRequests/Shared/utils.ts @@ -40,6 +40,7 @@ export function getNumAddedResources(addedResources: ResourceMap) { Object.keys(addedResources.kube_cluster).length + Object.keys(addedResources.user_group).length + Object.keys(addedResources.windows_desktop).length + - Object.keys(addedResources.saml_idp_service_provider).length + Object.keys(addedResources.saml_idp_service_provider).length + + Object.keys(addedResources.namespace).length ); } diff --git a/web/packages/shared/components/FieldSelect/FieldSelect.tsx b/web/packages/shared/components/FieldSelect/FieldSelect.tsx index 90e875ee9868c..66007b24f18fc 100644 --- a/web/packages/shared/components/FieldSelect/FieldSelect.tsx +++ b/web/packages/shared/components/FieldSelect/FieldSelect.tsx @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { GroupBase } from 'react-select'; +import { GroupBase, OptionsOrGroups } from 'react-select'; import { useAsync } from 'shared/hooks/useAsync'; @@ -69,7 +69,28 @@ export function FieldSelectAsync< Opt = Option, IsMulti extends boolean = false, Group extends GroupBase = GroupBase, ->(props: AsyncSelectProps & FieldProps) { +>( + props: AsyncSelectProps & + FieldProps & { + /** + * A function that sets the initial options, after the initial options are + * finished fetching (triggered by when user clicks on the select component + * that renders the dropdown menu). + * + * Select async doesn't provide an option for "on menu open, load options". + * There is only "on render load, or provide default array of options". + * There are some cases where there can be many select async components rendered + * (eg: bulk adding kube clusters to an access request) and users may not be + * required to select anything from the select async dropdown, so this provides + * a way to load options only on need (menu open) and save wasteful api calls. + * + * Requires: + * - base.onMenuOpen to be defined + * - defaultOptions to be an array + */ + initOptionsOnMenuOpen?(options: OptionsOrGroups): void; + } +) { const { base, wrapper, others } = splitSelectProps< Opt, IsMulti, @@ -78,15 +99,35 @@ export function FieldSelectAsync< >(props, { defaultOptions: true, }); - const { defaultOptions, loadOptions, ...styles } = others; + const { defaultOptions, loadOptions, initOptionsOnMenuOpen, ...styles } = + others; const [attempt, runAttempt] = useAsync(resolveUndefinedOptions(loadOptions)); + + async function onMenuOpen() { + if (!base.onMenuOpen) return; + + base.onMenuOpen(); + + if ( + initOptionsOnMenuOpen && + defaultOptions && + Array.isArray(defaultOptions) && + defaultOptions.length == 0 + ) { + const [options, error] = await runAttempt('', null); + if (!error) { + return others.initOptionsOnMenuOpen(options); + } + } + } + return ( {...base} + onMenuOpen={onMenuOpen} defaultOptions={defaultOptions} loadOptions={async (value, callback) => { - console.log('loading'); const [options, error] = await runAttempt(value, callback); if (error) { return []; @@ -97,6 +138,9 @@ export function FieldSelectAsync< if (attempt.status === 'error') { return `Could not load options: ${attempt.statusText}`; } + if (attempt.status === 'processing') { + return 'Loading...'; + } return base.noOptionsMessage?.(obj) ?? 'No options'; }} /> diff --git a/web/packages/shared/components/FieldSelect/shared.tsx b/web/packages/shared/components/FieldSelect/shared.tsx index a25768f5c2df1..03857ea3ac2ee 100644 --- a/web/packages/shared/components/FieldSelect/shared.tsx +++ b/web/packages/shared/components/FieldSelect/shared.tsx @@ -191,6 +191,10 @@ export function splitSelectProps< markAsError, maxMenuHeight, menuIsOpen, + onMenuOpen, + onMenuClose, + closeMenuOnSelect, + hideSelectedOptions, menuPosition, name, noOptionsMessage, @@ -222,8 +226,12 @@ export function splitSelectProps< isMulti, isSearchable, maxMenuHeight, - menuIsOpen, menuPosition, + menuIsOpen, + onMenuOpen, + onMenuClose, + closeMenuOnSelect, + hideSelectedOptions, name, noOptionsMessage, onBlur, @@ -267,6 +275,10 @@ type KeysRemovedFromOthers = | 'maxMenuHeight' | 'menuIsOpen' | 'menuPosition' + | 'onMenuOpen' + | 'onMenuClose' + | 'closeMenuOnSelect' + | 'hideSelectedOptions' | 'name' | 'noOptionsMessage' | 'onBlur' diff --git a/web/packages/shared/services/accessRequests/accessRequests.ts b/web/packages/shared/services/accessRequests/accessRequests.ts index 3b5517c393b4b..855e71e777ca3 100644 --- a/web/packages/shared/services/accessRequests/accessRequests.ts +++ b/web/packages/shared/services/accessRequests/accessRequests.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { ResourceIdKind } from 'teleport/services/agents'; +import { RequestableResourceKind } from 'shared/components/AccessRequests/NewRequest/resource'; export type RequestState = | 'NONE' @@ -76,7 +76,7 @@ export type Resource = { // ResourceID is a unique identifier for a teleport resource. export type ResourceId = { // kind is the resource (agent) kind. - kind: ResourceIdKind; + kind: RequestableResourceKind; // name is the name of the specific resource. name: string; // clusterName is the name of cluster. diff --git a/web/packages/shared/utils/text.test.ts b/web/packages/shared/utils/text.test.ts index 0cd297f7b20d5..a76bb90fbb594 100644 --- a/web/packages/shared/utils/text.test.ts +++ b/web/packages/shared/utils/text.test.ts @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -import { pluralize, capitalizeFirstLetter } from './text'; +import { pluralize, capitalizeFirstLetter, listToSentence } from './text'; test('pluralize', () => { expect(pluralize(0, 'apple')).toBe('apples'); @@ -30,3 +30,39 @@ test('capitalizeFirstLetter', () => { expect(capitalizeFirstLetter('hello')).toBe('Hello'); expect(capitalizeFirstLetter('')).toBe(''); }); + +describe('listToSentence()', () => { + const testCases = [ + { + name: 'no words', + list: [], + expected: '', + }, + { + name: 'one word', + list: ['a'], + expected: 'a', + }, + { + name: 'two words', + list: ['a', 'b'], + expected: 'a and b', + }, + { + name: 'three words', + list: ['a', 'b', 'c'], + expected: 'a, b and c', + }, + { + name: 'lost of words', + list: ['a', 'b', 'c', 'd', 'e', 'f', 'g'], + expected: 'a, b, c, d, e, f and g', + }, + ]; + + test.each(testCases)('$name', ({ list, expected }) => { + const originalList = [...list]; + expect(listToSentence(list)).toEqual(expected); + expect(list).toEqual(originalList); + }); +}); diff --git a/web/packages/shared/utils/text.ts b/web/packages/shared/utils/text.ts index a424ea5bd9b14..37635c4c0bad2 100644 --- a/web/packages/shared/utils/text.ts +++ b/web/packages/shared/utils/text.ts @@ -39,3 +39,28 @@ export function capitalizeFirstLetter(str: string) { } return str[0].toUpperCase() + str.slice(1); } + +/** + * Takes a list of words and converts it into a sentence. + * eg: given list ["apple", "banana", "carrot"], converts + * to string "apple, banana and carrot" + * + * Does not modify original list. + */ +export function listToSentence(listOfWords: string[]) { + if (!listOfWords || !listOfWords.length) { + return ''; + } + + if (listOfWords.length == 1) { + return listOfWords[0]; + } + + if (listOfWords.length == 2) { + return `${listOfWords[0]} and ${listOfWords[1]}`; + } + + const copiedList = [...listOfWords]; + const lastWord = copiedList.pop(); + return `${copiedList.join(', ')} and ${lastWord}`; +} diff --git a/web/packages/teleport/src/AccessRequests/service.ts b/web/packages/teleport/src/AccessRequests/service.ts index 20637193ef24a..03b7e158d3f3b 100644 --- a/web/packages/teleport/src/AccessRequests/service.ts +++ b/web/packages/teleport/src/AccessRequests/service.ts @@ -18,7 +18,8 @@ import { formatDuration } from 'date-fns'; -import { ResourceIdKind } from 'teleport/services/agents'; +import { RequestableResourceKind } from 'shared/components/AccessRequests/NewRequest/resource'; + import api from 'teleport/services/api'; import cfg from 'teleport/config'; import { @@ -41,7 +42,7 @@ export async function createAccessRequest( reason, roles, resourceIds: resources.map(item => ({ - kind: item.type as ResourceIdKind, + kind: item.type as RequestableResourceKind, name: item.id, clusterName: clusterId, })), diff --git a/web/packages/teleport/src/AccessRequests/types.ts b/web/packages/teleport/src/AccessRequests/types.ts index 38fa71386729e..de08d61605961 100644 --- a/web/packages/teleport/src/AccessRequests/types.ts +++ b/web/packages/teleport/src/AccessRequests/types.ts @@ -16,15 +16,15 @@ * along with this program. If not, see . */ -import type { Option } from 'shared/components/Select'; +import { RequestableResourceKind } from 'shared/components/AccessRequests/NewRequest/resource'; -import type { ResourceIdKind } from 'teleport/services/agents'; +import type { Option } from 'shared/components/Select'; export type DurationOption = Option; export interface Resource { id: { - kind: ResourceIdKind; + kind: RequestableResourceKind; name: string; clusterName: string; subResourceName?: string; @@ -38,7 +38,7 @@ export interface Resource { type RequestState = 'NONE' | 'PENDING' | 'APPROVED' | 'DENIED' | 'APPLIED' | ''; export interface ResourceId { - kind: ResourceIdKind; + kind: RequestableResourceKind; name: string; clusterName: string; subResourceName?: string; diff --git a/web/packages/teleport/src/Main/MainContainer.tsx b/web/packages/teleport/src/Main/MainContainer.tsx index 4f7910b80e5dd..75a4109c32d15 100644 --- a/web/packages/teleport/src/Main/MainContainer.tsx +++ b/web/packages/teleport/src/Main/MainContainer.tsx @@ -29,11 +29,9 @@ export const MainContainer = styled.div` --sidebar-width: 256px; --sidenav-width: 76px; --sidenav-panel-width: 224px; + overflow: hidden; margin-top: ${p => p.theme.topBarHeight[0]}px; @media screen and (min-width: ${p => p.theme.breakpoints.small}px) { margin-top: ${p => p.theme.topBarHeight[1]}px; } - @media screen and (min-width: ${p => p.theme.breakpoints.large}px) { - margin-top: ${p => p.theme.topBarHeight[2]}px; - } `; diff --git a/web/packages/teleport/src/Navigation/SideNavigation/CategoryIcon.tsx b/web/packages/teleport/src/Navigation/SideNavigation/CategoryIcon.tsx index feb2135801050..944b53c218b2e 100644 --- a/web/packages/teleport/src/Navigation/SideNavigation/CategoryIcon.tsx +++ b/web/packages/teleport/src/Navigation/SideNavigation/CategoryIcon.tsx @@ -41,7 +41,7 @@ export function CategoryIcon({ Icon = Icons.Server; break; case NavigationCategory.Access: - Icon = Icons.Lock; + Icon = Icons.KeyHole; break; case NavigationCategory.Identity: Icon = Icons.FingerprintSimple; diff --git a/web/packages/teleport/src/Navigation/SideNavigation/Navigation.tsx b/web/packages/teleport/src/Navigation/SideNavigation/Navigation.tsx index 9d39688b52156..2099a09abd61f 100644 --- a/web/packages/teleport/src/Navigation/SideNavigation/Navigation.tsx +++ b/web/packages/teleport/src/Navigation/SideNavigation/Navigation.tsx @@ -16,10 +16,10 @@ * along with this program. If not, see . */ -import React, { useState, useCallback } from 'react'; +import React, { useState, useCallback, useEffect, useRef } from 'react'; import styled, { useTheme } from 'styled-components'; import { matchPath, useHistory } from 'react-router'; -import { Text, Flex, Box } from 'design'; +import { Text, Flex, Box, P2 } from 'design'; import { ToolTipInfo } from 'shared/components/ToolTip'; @@ -36,11 +36,12 @@ import { import { zIndexMap } from './zIndexMap'; import { + CustomNavigationSubcategory, NAVIGATION_CATEGORIES, - STANDALONE_CATEGORIES, SidenavCategory, } from './categories'; import { SearchSection } from './Search'; +import { ResourcesSection } from './ResourcesSection'; import type * as history from 'history'; import type { TeleportFeature } from 'teleport/types'; @@ -86,6 +87,20 @@ export type NavigationSubsection = { icon: (props) => JSX.Element; parent?: TeleportFeature; searchableTags?: string[]; + /** + * customRouteMatchFn is a custom function for determining whether this subsection is currently active, + * this is useful in cases where a simple base route match isn't sufficient. + */ + customRouteMatchFn?: (currentViewRoute: string) => boolean; + /** + * subCategory is the subcategory (ie. subsection grouping) this subsection should be under, if applicable. + * */ + subCategory?: CustomNavigationSubcategory; + /** + * onClick is custom code that can be run when clicking on the subsection. + * Note that this is merely extra logic, and does not replace the default routing behaviour of a subsection which will navigate the user to the route. + */ + onClick?: () => void; }; function getNavigationSections( @@ -94,7 +109,6 @@ function getNavigationSections( const navigationSections = NAVIGATION_CATEGORIES.map(category => ({ category, subsections: getSubsectionsForCategory(category, features), - standalone: STANDALONE_CATEGORIES.indexOf(category) !== -1, })); return navigationSections; @@ -123,6 +137,8 @@ function getSubsectionsForCategory( }); } +// getNavSubsectionForRoute returns the sidenav subsection that the user is correctly on (based on route). +// Note that it is possible for this not to return anything, such as in the case where the user is on a page that isn't in the sidenav (eg. Account Settings). function getNavSubsectionForRoute( features: TeleportFeature[], route: history.Location | Location @@ -150,14 +166,64 @@ function getNavSubsectionForRoute( }; } +/** + * useDebounceClose adds a debounce to closing drawers, this is to prevent the drawer closing if the user overshoots it, giving them a slight delay to re-enter the drawer. + */ +function useDebounceClose( + value: T | null, + delay: number, + isClosing: boolean +): T | null { + const [debouncedValue, setDebouncedValue] = useState(value); + const timeoutRef = useRef(); + + useEffect(() => { + // Clear any existing timeout + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + + // If we're closing the drarwer as opposed to switching to a different section (value is null and isClosing is true), apply debounce. + if (value === null && isClosing) { + timeoutRef.current = setTimeout(() => { + setDebouncedValue(null); + }, delay); + } else { + // For opening or any other change, update immediately. + setDebouncedValue(value); + } + + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current); + } + }; + }, [value, delay, isClosing]); + + return debouncedValue; +} + export function Navigation() { const features = useFeatures(); const history = useHistory(); - const [expandedSection, setExpandedSection] = - useState(null); - const currentView = getNavSubsectionForRoute(features, history.location); + const [targetSection, setTargetSection] = useState( + null + ); + const [isClosing, setIsClosing] = useState(false); + const debouncedSection = useDebounceClose(targetSection, 200, isClosing); const [previousExpandedSection, setPreviousExpandedSection] = useState(); + const navigationTimeoutRef = useRef(); + + // Clear navigation timeout on unmount. + useEffect(() => { + return () => { + if (navigationTimeoutRef.current) { + clearTimeout(navigationTimeoutRef.current); + } + }; + }, []); + const currentView = getNavSubsectionForRoute(features, history.location); const navSections = getNavigationSections(features).filter( section => section.subsections.length @@ -165,24 +231,59 @@ export function Navigation() { const handleSetExpandedSection = useCallback( (section: NavigationSection) => { + setIsClosing(false); if (!section.standalone) { - setPreviousExpandedSection(expandedSection); - setExpandedSection(section); + setPreviousExpandedSection(debouncedSection); + setTargetSection(section); } else { setPreviousExpandedSection(null); - setExpandedSection(null); + setTargetSection(null); } }, - [expandedSection] + [debouncedSection] ); - const resetExpandedSection = useCallback(() => { + const resetExpandedSection = useCallback((closeAfterDelay = true) => { + setIsClosing(closeAfterDelay); setPreviousExpandedSection(null); - setExpandedSection(null); + setTargetSection(null); }, []); + // Handler for navigation actions + const handleNavigation = useCallback( + (route: string) => { + history.push(route); + + // Clear any existing timeout + if (navigationTimeoutRef.current) { + clearTimeout(navigationTimeoutRef.current); + } + + // Add a small delay to the close to allow the user to see some feedback (see the section they clicked become active). + navigationTimeoutRef.current = setTimeout(() => { + resetExpandedSection(false); + }, 150); + }, + [resetExpandedSection, history] + ); + + // Hide the nav if the current feature has hideNavigation set to true. + const hideNav = features.find( + f => + f.route && + matchPath(history.location.pathname, { + path: f.route.path, + exact: f.route.exact ?? false, + }) + )?.hideNavigation; + + if (hideNav) { + return null; + } + return ( resetExpandedSection()} onKeyUp={e => e.key === 'Escape' && resetExpandedSection()} onBlur={(event: React.FocusEvent) => { @@ -200,73 +301,87 @@ export function Navigation() { + {navSections.map(section => ( -
handleSetExpandedSection(section)} - aria-controls={`panel-${expandedSection?.category}`} - onClick={() => { - if (section.standalone) { - history.push(section.subsections[0].route); + + {section.category === 'Add New' && } +
handleSetExpandedSection(section)} + aria-controls={`panel-${debouncedSection?.category}`} + onClick={() => { + if (section.standalone) { + handleNavigation(section.subsections[0].route); + } + }} + isExpanded={ + !!debouncedSection && + !debouncedSection.standalone && + section.category === debouncedSection?.category } - }} - isExpanded={ - !!expandedSection && - !expandedSection.standalone && - section.category === expandedSection?.category - } - > - handleSetExpandedSection(section)} > - handleSetExpandedSection(section)} + onMouseEnter={() => handleSetExpandedSection(section)} > - - - - {section.category} - - - {!section.standalone && - section.subsections.map(section => ( - - - {section.title} - - ))} - - {cfg.edition === 'oss' && } - {cfg.edition === 'community' && } - - -
+ + + + {section.category} + + + {!section.standalone && + section.subsections.map(subsection => ( + { + e.preventDefault(); + handleNavigation(subsection.route); + }} + > + + {subsection.title} + + ))} + + {cfg.edition === 'oss' && } + {cfg.edition === 'community' && } + + +
+ ))}
@@ -356,3 +471,10 @@ const SubText = styled(Text)` color: ${props => props.theme.colors.text.disabled}; font-size: ${props => props.theme.fontSizes[1]}px; `; + +const Divider = styled.div` + z-index: ${zIndexMap.sideNavButtons}; + height: 1px; + background: ${props => props.theme.colors.interactive.tonal.neutral[1]}; + width: 60px; +`; diff --git a/web/packages/teleport/src/Navigation/SideNavigation/ResourcesSection.tsx b/web/packages/teleport/src/Navigation/SideNavigation/ResourcesSection.tsx new file mode 100644 index 0000000000000..dbcfbdc903195 --- /dev/null +++ b/web/packages/teleport/src/Navigation/SideNavigation/ResourcesSection.tsx @@ -0,0 +1,349 @@ +/** + * 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 . + */ + +import React from 'react'; +import styled from 'styled-components'; +import { matchPath } from 'react-router'; + +import { Box, Flex, Text } from 'design'; +import * as Icons from 'design/Icon'; + +import { DefaultTab } from 'gen-proto-ts/teleport/userpreferences/v1/unified_resource_preferences_pb'; +import { UserPreferences } from 'gen-proto-ts/teleport/userpreferences/v1/userpreferences_pb'; + +import cfg from 'teleport/config'; +import useStickyClusterId from 'teleport/useStickyClusterId'; +import { encodeUrlQueryParams } from 'teleport/components/hooks/useUrlFiltering'; +import { EncodeUrlQueryParamsProps } from 'teleport/components/hooks/useUrlFiltering/encodeUrlQueryParams'; +import { ResourceIdKind } from 'teleport/services/agents'; +import { useUser } from 'teleport/User/UserContext'; + +import { NavigationSubsection, NavigationSection } from './Navigation'; +import { + Section, + RightPanel, + verticalPadding, + SubsectionItem, +} from './Section'; +import { CustomNavigationSubcategory, NavigationCategory } from './categories'; + +/** + * getResourcesSectionForSearch returns a NavigationSection for resources, + * this is only used for the sake of indexing these subsections in the sidenav search. + */ +export function getResourcesSectionForSearch( + subsectionProps: GetSubsectionProps +): NavigationSection { + return { + category: NavigationCategory.Resources, + subsections: getResourcesSubsections(subsectionProps), + }; +} + +type GetSubsectionProps = { + clusterId: string; + preferences: UserPreferences; + updatePreferences: (preferences: Partial) => Promise; + searchParams: URLSearchParams; +}; + +function encodeUrlQueryParamsWithTypedKinds( + params: Omit & { + kinds?: ResourceIdKind[]; + } +) { + return encodeUrlQueryParams(params); +} + +function getResourcesSubsections({ + clusterId, + preferences, + updatePreferences, + searchParams, +}: GetSubsectionProps): NavigationSubsection[] { + const baseRoute = cfg.getUnifiedResourcesRoute(clusterId); + + const setPinnedUserPreference = (pinnedOnly: boolean) => { + // Return early if the current user preference already matches the pinnedOnly param provided, since nothing needs to be done. + if ( + (pinnedOnly && + preferences?.unifiedResourcePreferences?.defaultTab === + DefaultTab.PINNED) || + (!pinnedOnly && + (preferences?.unifiedResourcePreferences?.defaultTab === + DefaultTab.ALL || + preferences?.unifiedResourcePreferences?.defaultTab === + DefaultTab.UNSPECIFIED)) + ) { + return; + } + + updatePreferences({ + ...preferences, + unifiedResourcePreferences: { + ...preferences?.unifiedResourcePreferences, + defaultTab: pinnedOnly ? DefaultTab.PINNED : DefaultTab.ALL, + }, + }); + }; + + const currentKinds = searchParams + .getAll('kinds') + .flatMap(k => k.split(',')) + .filter(Boolean); + const isPinnedOnly = + preferences?.unifiedResourcePreferences?.defaultTab === DefaultTab.PINNED; + + // isKindActive returns true if we are currently filtering for only the provided kind of resource. + const isKindActive = (kind: ResourceIdKind) => { + // This subsection for this kind should only be marked active when it is the only kind being filtered for, + // if there are multiple kinds then the "All Resources" button should be active. + return currentKinds.length === 1 && currentKinds[0] === kind; + }; + + const allResourcesRoute = encodeUrlQueryParamsWithTypedKinds({ + pathname: baseRoute, + pinnedOnly: false, + }); + const pinnedOnlyRoute = encodeUrlQueryParamsWithTypedKinds({ + pathname: baseRoute, + pinnedOnly: true, + }); + const applicationsOnlyRoute = encodeUrlQueryParamsWithTypedKinds({ + pathname: baseRoute, + kinds: ['app'], + pinnedOnly: false, + }); + const databasesOnlyRoute = encodeUrlQueryParamsWithTypedKinds({ + pathname: baseRoute, + kinds: ['db'], + pinnedOnly: false, + }); + const desktopsOnlyRoute = encodeUrlQueryParamsWithTypedKinds({ + pathname: baseRoute, + kinds: ['windows_desktop'], + pinnedOnly: false, + }); + const kubesOnlyRoute = encodeUrlQueryParamsWithTypedKinds({ + pathname: baseRoute, + kinds: ['kube_cluster'], + pinnedOnly: false, + }); + const nodesOnlyRoute = encodeUrlQueryParamsWithTypedKinds({ + pathname: baseRoute, + kinds: ['node'], + pinnedOnly: false, + }); + + return [ + { + title: 'All Resources', + icon: Icons.Server, + route: allResourcesRoute, + searchableTags: ['resources', 'resources', 'all resources'], + category: NavigationCategory.Resources, + exact: false, + customRouteMatchFn: currentViewRoute => + !!matchPath(currentViewRoute, { + path: cfg.routes.unifiedResources, + exact: false, + }) && + !isPinnedOnly && + currentKinds.length !== 1, + onClick: () => setPinnedUserPreference(false), + }, + { + title: 'Pinned Resources', + icon: Icons.PushPin, + route: pinnedOnlyRoute, + searchableTags: ['resources', 'resources', 'pinned resources'], + category: NavigationCategory.Resources, + exact: false, + customRouteMatchFn: () => isPinnedOnly && currentKinds.length !== 1, + onClick: () => setPinnedUserPreference(true), + }, + { + title: 'Applications', + icon: Icons.Application, + route: applicationsOnlyRoute, + searchableTags: ['resources', 'apps', 'applications'], + category: NavigationCategory.Resources, + exact: false, + customRouteMatchFn: () => isKindActive('app'), + onClick: () => setPinnedUserPreference(false), + subCategory: CustomNavigationSubcategory.FilteredViews, + }, + { + title: 'Databases', + icon: Icons.Database, + route: databasesOnlyRoute, + searchableTags: ['resources', 'dbs', 'databases'], + category: NavigationCategory.Resources, + exact: false, + customRouteMatchFn: () => isKindActive('db'), + onClick: () => setPinnedUserPreference(false), + subCategory: CustomNavigationSubcategory.FilteredViews, + }, + { + title: 'Desktops', + icon: Icons.Database, + route: desktopsOnlyRoute, + searchableTags: ['resources', 'desktops', 'rdp', 'windows'], + category: NavigationCategory.Resources, + exact: false, + customRouteMatchFn: () => isKindActive('windows_desktop'), + onClick: () => setPinnedUserPreference(false), + subCategory: CustomNavigationSubcategory.FilteredViews, + }, + { + title: 'Kubernetes', + icon: Icons.Kubernetes, + route: kubesOnlyRoute, + searchableTags: ['resources', 'k8s', 'kubes', 'kubernetes'], + category: NavigationCategory.Resources, + exact: false, + customRouteMatchFn: () => isKindActive('kube_cluster'), + onClick: () => setPinnedUserPreference(false), + subCategory: CustomNavigationSubcategory.FilteredViews, + }, + { + title: 'SSH Resources', + icon: Icons.Server, + route: nodesOnlyRoute, + searchableTags: ['resources', 'servers', 'nodes', 'ssh resources'], + category: NavigationCategory.Resources, + exact: false, + customRouteMatchFn: () => isKindActive('node'), + onClick: () => setPinnedUserPreference(false), + subCategory: CustomNavigationSubcategory.FilteredViews, + }, + ]; +} + +export function ResourcesSection({ + expandedSection, + previousExpandedSection, + handleSetExpandedSection, + currentView, +}: { + expandedSection: NavigationSection; + previousExpandedSection: NavigationSection; + currentView: NavigationSubsection; + handleSetExpandedSection: (section: NavigationSection) => void; +}) { + const { clusterId } = useStickyClusterId(); + const { preferences, updatePreferences } = useUser(); + const section: NavigationSection = { + category: NavigationCategory.Resources, + subsections: [], + }; + const baseRoute = cfg.getUnifiedResourcesRoute(clusterId); + + const searchParams = new URLSearchParams(location.search); + + const isExpanded = expandedSection?.category === NavigationCategory.Resources; + + const subsections = getResourcesSubsections({ + clusterId, + preferences, + updatePreferences, + searchParams, + }); + + const currentViewRoute = currentView?.route; + + return ( +
null} + setExpandedSection={() => handleSetExpandedSection(section)} + aria-controls={`panel-${expandedSection?.category}`} + isExpanded={isExpanded} + > + handleSetExpandedSection(section)} + > + + + + Resources + + + {subsections + .filter(section => !section.subCategory) + .map(section => ( + + + {section.title} + + ))} + + + + + Filtered Views + + + + {subsections + .filter( + section => + section.subCategory === + CustomNavigationSubcategory.FilteredViews + ) + .map(section => ( + + + {section.title} + + ))} + + +
+ ); +} + +export const Divider = styled.div` + height: 1px; + width: 100%; + background: ${props => props.theme.colors.interactive.tonal.neutral[1]}; + margin: ${props => props.theme.space[1]}px 0px + ${props => props.theme.space[1]}px 0px; +`; diff --git a/web/packages/teleport/src/Navigation/SideNavigation/Search.tsx b/web/packages/teleport/src/Navigation/SideNavigation/Search.tsx index 9ca0c39aab873..118fc905f7f79 100644 --- a/web/packages/teleport/src/Navigation/SideNavigation/Search.tsx +++ b/web/packages/teleport/src/Navigation/SideNavigation/Search.tsx @@ -23,6 +23,9 @@ import styled from 'styled-components'; import { Box, Flex, Text } from 'design'; import { height, space, color } from 'design/system'; +import useStickyClusterId from 'teleport/useStickyClusterId'; +import { useUser } from 'teleport/User/UserContext'; + import { NavigationSection, NavigationSubsection } from './Navigation'; import { Section, @@ -32,6 +35,7 @@ import { } from './Section'; import { CategoryIcon } from './CategoryIcon'; import { CustomNavigationCategory } from './categories'; +import { getResourcesSectionForSearch } from './ResourcesSection'; export function SearchSection({ navigationSections, @@ -50,6 +54,20 @@ export function SearchSection({ category: CustomNavigationCategory.Search, subsections: [], }; + const { clusterId } = useStickyClusterId(); + const { preferences, updatePreferences } = useUser(); + + const searchParams = new URLSearchParams(location.search); + + const searchableNavSections: NavigationSection[] = [ + getResourcesSectionForSearch({ + clusterId, + preferences, + updatePreferences, + searchParams, + }), + ...navigationSections, + ]; const isExpanded = expandedSection?.category === CustomNavigationCategory.Search; @@ -70,7 +88,7 @@ export function SearchSection({ onFocus={() => handleSetExpandedSection(section)} > @@ -123,7 +141,11 @@ function SearchContent({ ))} @@ -141,7 +163,12 @@ function SearchResult({ $active: boolean; }) { return ( - + ` position: fixed; left: var(--sidenav-width); height: 100%; - scrollbar-gutter: auto; scrollbar-color: ${p => p.theme.colors.spotBackground[2]} transparent; - overflow: visible; width: ${rightPanelWidth}; background: ${p => p.theme.colors.levels.surface}; z-index: ${zIndexMap.sideNavExpandedPanel}; @@ -94,18 +92,14 @@ export const RightPanel = styled(Box).attrs({ pt: 2, px: 2 })<{ top: ${p => p.theme.topBarHeight[1]}px; padding-bottom: ${p => p.theme.topBarHeight[1] + p.theme.space[2]}px; } - @media screen and (min-width: ${p => p.theme.breakpoints.large}px) { - top: ${p => p.theme.topBarHeight[2]}px; - padding-bottom: ${p => p.theme.topBarHeight[3] + p.theme.space[2]}px; - } `; export const CategoryButton = styled.button<{ $active: boolean; isExpanded: boolean; }>` - height: 60px; - width: 60px; + min-height: 60px; + min-width: 60px; cursor: pointer; outline: hidden; border: none; @@ -115,6 +109,11 @@ export const CategoryButton = styled.button<{ justify-content: center; border-radius: ${props => props.theme.radii[2]}px; z-index: ${zIndexMap.sideNavButtons}; + display: flex; + align-items: center; + justify-content: center; + gap: ${props => props.theme.space[1]}px; + font-family: ${props => props.theme.font}; font-size: ${props => props.theme.typography.body4.fontSize}; font-weight: ${props => props.theme.typography.body4.fontWeight}; @@ -164,7 +163,7 @@ export function getCategoryStyles( } ${isExpanded && ` - background: ${theme.colors.interactive.tonal.neutral[0]}; + background: ${theme.colors.interactive.tonal.neutral[0]}; color: ${theme.colors.text.main}; `} `; @@ -177,20 +176,28 @@ export function SubsectionItem({ to, exact, children, + onClick, }: { $active: boolean; to: string; exact: boolean; children: React.ReactNode; + onClick?: (event: React.MouseEvent) => void; }) { return ( - + {children} ); } -const StyledSubsectionItem = styled(NavLink)<{ +export const StyledSubsectionItem = styled(NavLink)<{ $active: boolean; }>` display: flex; @@ -214,6 +221,9 @@ export function getSubsectionStyles(theme: Theme, active: boolean) { return css` color: ${theme.colors.brand}; background: ${theme.colors.interactive.tonal.primary[0]}; + p { + font-weight: 500; + } &:focus-visible { outline: 2px solid ${theme.colors.interactive.solid.primary.default}; } diff --git a/web/packages/teleport/src/Navigation/SideNavigation/categories.ts b/web/packages/teleport/src/Navigation/SideNavigation/categories.ts index 33d6cf290e40a..6bc60bd20f818 100644 --- a/web/packages/teleport/src/Navigation/SideNavigation/categories.ts +++ b/web/packages/teleport/src/Navigation/SideNavigation/categories.ts @@ -25,24 +25,27 @@ export enum NavigationCategory { AddNew = 'Add New', } -/* CustomNavigationCategory are pseudo-categories which exist only in the nav menu, eg. Search. */ +/** + * CustomNavigationCategory are pseudo-categories which exist only in the nav menu, eg. Search. + */ export enum CustomNavigationCategory { Search = 'Search', } +/** + * CustomNavigationSubcategory are subcategories within a navigation category which can be used to + * create groupings of subsections, eg. Filtered Views. + */ +export enum CustomNavigationSubcategory { + FilteredViews = 'Filtered Views', +} + export type SidenavCategory = NavigationCategory | CustomNavigationCategory; export const NAVIGATION_CATEGORIES = [ - NavigationCategory.Resources, NavigationCategory.Access, NavigationCategory.Identity, NavigationCategory.Policy, NavigationCategory.Audit, NavigationCategory.AddNew, ]; - -export const STANDALONE_CATEGORIES = [ - NavigationCategory.AddNew, - // TODO(rudream): Remove this once shortcuts to pinned/nodes/apps/dbs/desktops/kubes are implemented. - NavigationCategory.Resources, -]; diff --git a/web/packages/teleport/src/Navigation/SideNavigation/zIndexMap.ts b/web/packages/teleport/src/Navigation/SideNavigation/zIndexMap.ts index a876bddbe8d37..745f119349d4c 100644 --- a/web/packages/teleport/src/Navigation/SideNavigation/zIndexMap.ts +++ b/web/packages/teleport/src/Navigation/SideNavigation/zIndexMap.ts @@ -17,8 +17,8 @@ */ export const zIndexMap = { - topBar: 23, - sideNavButtons: 22, - sideNavContainer: 21, - sideNavExpandedPanel: 20, + topBar: 9, + sideNavButtons: 8, + sideNavContainer: 7, + sideNavExpandedPanel: 6, }; diff --git a/web/packages/teleport/src/Notifications/Notification.story.tsx b/web/packages/teleport/src/Notifications/Notification.story.tsx index 05b76bfae920b..d8619f66a8227 100644 --- a/web/packages/teleport/src/Notifications/Notification.story.tsx +++ b/web/packages/teleport/src/Notifications/Notification.story.tsx @@ -220,7 +220,7 @@ const ListComponent = () => { css={` width: 100%; justify-content: center; - height: ${p => p.theme.topBarHeight[2]}px; + height: ${p => p.theme.topBarHeight[1]}px; `} > diff --git a/web/packages/teleport/src/TopBar/TopBarSideNav.tsx b/web/packages/teleport/src/TopBar/TopBarSideNav.tsx index a3a5d966ce2b6..c787f984fa763 100644 --- a/web/packages/teleport/src/TopBar/TopBarSideNav.tsx +++ b/web/packages/teleport/src/TopBar/TopBarSideNav.tsx @@ -85,9 +85,6 @@ export const TopBarContainer = styled(TopNav)` @media screen and (min-width: ${p => p.theme.breakpoints.small}px) { height: ${p => p.theme.topBarHeight[1]}px; } - @media screen and (min-width: ${p => p.theme.breakpoints.large}px) { - height: ${p => p.theme.topBarHeight[2]}px; - } `; const TeleportLogo = ({ CustomLogo }: TopBarProps) => { diff --git a/web/packages/teleport/src/components/Dropdown/Dropdown.tsx b/web/packages/teleport/src/components/Dropdown/Dropdown.tsx index 546dccd7c8dcc..36e47071dcfe7 100644 --- a/web/packages/teleport/src/components/Dropdown/Dropdown.tsx +++ b/web/packages/teleport/src/components/Dropdown/Dropdown.tsx @@ -50,9 +50,6 @@ export const Dropdown = styled.div` @media screen and (min-width: ${p => p.theme.breakpoints.small}px) { top: ${p => p.theme.topBarHeight[1]}px; } - @media screen and (min-width: ${p => p.theme.breakpoints.large}px) { - top: ${p => p.theme.topBarHeight[2]}px; - } `; export const DropdownItem = styled.div<{ diff --git a/web/packages/teleport/src/components/hooks/useUrlFiltering/encodeUrlQueryParams.test.ts b/web/packages/teleport/src/components/hooks/useUrlFiltering/encodeUrlQueryParams.test.ts index f68e5a0ca5733..56ac3f40c6358 100644 --- a/web/packages/teleport/src/components/hooks/useUrlFiltering/encodeUrlQueryParams.test.ts +++ b/web/packages/teleport/src/components/hooks/useUrlFiltering/encodeUrlQueryParams.test.ts @@ -29,17 +29,17 @@ const testCases: { { title: 'No query params', args: { pathname: '/foo' }, - expected: '/foo', + expected: '/foo?pinnedOnly=false', }, { title: 'Search string', args: { pathname: '/test', searchString: 'something' }, - expected: '/test?search=something', + expected: '/test?search=something&pinnedOnly=false', }, { title: 'Search string, encoded', args: { pathname: '/test', searchString: 'a$b$c' }, - expected: '/test?search=a%24b%24c', + expected: '/test?search=a%24b%24c&pinnedOnly=false', }, { title: 'Advanced search', @@ -48,7 +48,7 @@ const testCases: { searchString: 'foo=="bar"', isAdvancedSearch: true, }, - expected: '/test?query=foo%3D%3D%22bar%22', + expected: '/test?query=foo%3D%3D%22bar%22&pinnedOnly=false', }, { title: 'Search and sort', @@ -57,7 +57,7 @@ const testCases: { searchString: 'foobar', sort: { fieldName: 'name', dir: 'ASC' }, }, - expected: '/test?search=foobar&sort=name%3Aasc', + expected: '/test?search=foobar&sort=name%3Aasc&pinnedOnly=false', }, { title: 'Sort only', @@ -65,7 +65,7 @@ const testCases: { pathname: '/test', sort: { fieldName: 'name', dir: 'ASC' }, }, - expected: '/test?sort=name%3Aasc', + expected: '/test?sort=name%3Aasc&pinnedOnly=false', }, { title: 'Search, sort, and filter by kind', @@ -75,7 +75,8 @@ const testCases: { sort: { fieldName: 'name', dir: 'DESC' }, kinds: ['db', 'node'], }, - expected: '/test?search=foo&sort=name%3Adesc&kinds=db&kinds=node', + expected: + '/test?search=foo&sort=name%3Adesc&pinnedOnly=false&kinds=db&kinds=node', }, ]; diff --git a/web/packages/teleport/src/components/hooks/useUrlFiltering/encodeUrlQueryParams.ts b/web/packages/teleport/src/components/hooks/useUrlFiltering/encodeUrlQueryParams.ts index a00b57dc47695..fbcbf0217f917 100644 --- a/web/packages/teleport/src/components/hooks/useUrlFiltering/encodeUrlQueryParams.ts +++ b/web/packages/teleport/src/components/hooks/useUrlFiltering/encodeUrlQueryParams.ts @@ -45,7 +45,7 @@ export function encodeUrlQueryParams({ urlParams.append('sort', `${sort.fieldName}:${sort.dir.toLowerCase()}`); } - if (pinnedOnly) { + if (pinnedOnly !== undefined) { urlParams.append('pinnedOnly', `${pinnedOnly}`); } diff --git a/web/packages/teleport/src/components/hooks/useUrlFiltering/useUrlFiltering.ts b/web/packages/teleport/src/components/hooks/useUrlFiltering/useUrlFiltering.ts index 37652913fcb21..fa2bc1ce175a1 100644 --- a/web/packages/teleport/src/components/hooks/useUrlFiltering/useUrlFiltering.ts +++ b/web/packages/teleport/src/components/hooks/useUrlFiltering/useUrlFiltering.ts @@ -62,8 +62,16 @@ export function useUrlFiltering( const [initialParamsState] = useState(initialParams); const params = useMemo(() => { - return { ...initialParamsState, ...getResourceUrlQueryParams(search) }; - }, [initialParamsState, search]); + const urlParams = getResourceUrlQueryParams(search); + return { + ...initialParamsState, + ...urlParams, + pinnedOnly: + urlParams.pinnedOnly !== undefined + ? urlParams.pinnedOnly + : initialParamsState.pinnedOnly, + }; + }, [search]); function setParams(newParams: ResourceFilter) { replaceHistory( @@ -134,6 +142,7 @@ export default function getResourceUrlQueryParams( // Conditionally adds the sort field based on whether it exists or not ...(!!processedSortParam && { sort: processedSortParam }), // Conditionally adds the pinnedResources field based on whether its true or not - ...(pinnedOnly === 'true' && { pinnedOnly: true }), + pinnedOnly: + pinnedOnly === 'true' ? true : pinnedOnly === 'false' ? false : undefined, }; } diff --git a/web/packages/teleport/src/config.ts b/web/packages/teleport/src/config.ts index b1e184d7d821d..a429bc7f60ef0 100644 --- a/web/packages/teleport/src/config.ts +++ b/web/packages/teleport/src/config.ts @@ -1270,7 +1270,7 @@ export interface UrlKubeResourcesParams { searchAsRoles?: 'yes' | ''; kubeNamespace?: string; kubeCluster: string; - kind: KubeResourceKind; + kind: Omit; } export interface UrlDeployServiceIamConfigureScriptParams { diff --git a/web/packages/teleport/src/features.tsx b/web/packages/teleport/src/features.tsx index 0ea8bd7b9d3c1..f1aab44471ad5 100644 --- a/web/packages/teleport/src/features.tsx +++ b/web/packages/teleport/src/features.tsx @@ -19,7 +19,6 @@ import React from 'react'; import { - AddCircle, Bots as BotsIcon, CirclePlay, ClipboardUser, @@ -29,14 +28,14 @@ import { Laptop, ListAddCheck, ListThin, - Lock, + LockKey, + PlugsConnected, Question, Server, - ShieldCheck, SlidersVertical, Terminal, UserCircleGear, - Users as UsersIcon, + User as UserIcon, } from 'design/Icon'; import cfg from 'teleport/config'; @@ -221,7 +220,7 @@ export class FeatureUsers implements TeleportFeature { navigationItem = { title: NavTitle.Users, - icon: UsersIcon, + icon: UserIcon, exact: true, getLink() { return cfg.getUsersRoute(); @@ -268,13 +267,12 @@ export class FeatureBots implements TeleportFeature { export class FeatureAddBots implements TeleportFeature { category = NavigationCategory.Management; section = ManagementSection.Access; - sideNavCategory = SideNavigationCategory.Access; - hideFromNavigation = true; + sideNavCategory = SideNavigationCategory.AddNew; route = { - title: 'New Bot', + title: 'Bot', path: cfg.routes.botsNew, - exact: false, + exact: true, component: () => , }; @@ -285,6 +283,16 @@ export class FeatureAddBots implements TeleportFeature { getRoute() { return this.route; } + + navigationItem = { + title: NavTitle.NewBot, + icon: BotsIcon, + exact: true, + getLink() { + return cfg.getBotsNewRoute(); + }, + searchableTags: ['add bot', 'new bot', 'bots'], + }; } export class FeatureRoles implements TeleportFeature { @@ -332,7 +340,7 @@ export class FeatureAuthConnectors implements TeleportFeature { navigationItem = { title: NavTitle.AuthConnectors, - icon: ShieldCheck, + icon: PlugsConnected, exact: false, getLink() { return cfg.routes.sso; @@ -359,7 +367,7 @@ export class FeatureLocks implements TeleportFeature { navigationItem = { title: NavTitle.SessionAndIdentityLocks, - icon: Lock, + icon: LockKey, exact: false, getLink() { return cfg.getLocksRoute(); @@ -394,7 +402,7 @@ export class FeatureDiscover implements TeleportFeature { standalone = true; route = { - title: 'Enroll New Resource', + title: 'Resource', path: cfg.routes.discover, exact: true, component: Discover, @@ -402,12 +410,12 @@ export class FeatureDiscover implements TeleportFeature { navigationItem = { title: NavTitle.EnrollNewResource, - icon: AddCircle, + icon: Server, exact: true, getLink() { return cfg.routes.discover; }, - searchableTags: ['new resource', 'add'], + searchableTags: ['new', 'add', 'enroll', 'resources'], }; hasAccess(flags: FeatureFlags) { @@ -453,11 +461,10 @@ export class FeatureIntegrations implements TeleportFeature { export class FeatureIntegrationEnroll implements TeleportFeature { category = NavigationCategory.Management; section = ManagementSection.Access; - sideNavCategory = SideNavigationCategory.Access; - parent = FeatureIntegrations; + sideNavCategory = SideNavigationCategory.AddNew; route = { - title: 'Enroll New Integration', + title: 'Integration', path: cfg.routes.integrationEnroll, exact: false, component: () => , @@ -469,10 +476,11 @@ export class FeatureIntegrationEnroll implements TeleportFeature { navigationItem = { title: NavTitle.EnrollNewIntegration, - icon: AddCircle, + icon: IntegrationsIcon, getLink() { return cfg.getIntegrationEnrollRoute(null); }, + searchableTags: ['new', 'add', 'enroll', 'integration'], }; // getRoute allows child class extending this @@ -586,7 +594,7 @@ export class FeatureTrust implements TeleportFeature { getLink() { return cfg.routes.trustedClusters; }, - searchableTags: ['clusters', 'trusted clusters'], + searchableTags: ['clusters', 'trusted clusters', 'root clusters'], }; } @@ -668,17 +676,18 @@ export function getOSSFeatures(): TeleportFeature[] { // TODO(rudream): Implement shortcuts to pinned/nodes/apps/dbs/desktops/kubes. new FeatureUnifiedResources(), - // Management + // AddNew + new FeatureDiscover(), + new FeatureIntegrationEnroll(), + new FeatureAddBots(), // - Access new FeatureUsers(), - new FeatureRoles(), new FeatureBots(), - new FeatureAddBots(), new FeatureJoinTokens(), + new FeatureRoles(), new FeatureAuthConnectors(), new FeatureIntegrations(), - new FeatureIntegrationEnroll(), new FeatureClusters(), new FeatureTrust(), @@ -693,8 +702,6 @@ export function getOSSFeatures(): TeleportFeature[] { new FeatureRecordings(), new FeatureSessions(), - new FeatureDiscover(), - // Other new FeatureAccount(), new FeatureHelpAndSupport(), diff --git a/web/packages/teleport/src/services/userEvent/types.ts b/web/packages/teleport/src/services/userEvent/types.ts index abe0cfd317bd8..16e927986df65 100644 --- a/web/packages/teleport/src/services/userEvent/types.ts +++ b/web/packages/teleport/src/services/userEvent/types.ts @@ -260,6 +260,7 @@ export enum CtaEvent { CTA_EXTERNAL_AUDIT_STORAGE = 10, CTA_OKTA_USER_SYNC = 11, CTA_ENTRA_ID = 12, + CTA_OKTA_SCIM = 13, } export enum Feature { diff --git a/web/packages/teleport/src/types.ts b/web/packages/teleport/src/types.ts index 2644288375b82..2c3620e6d86b7 100644 --- a/web/packages/teleport/src/types.ts +++ b/web/packages/teleport/src/types.ts @@ -63,12 +63,14 @@ export enum NavTitle { // Access Management Users = 'Users', Bots = 'Bots', - Roles = 'User Roles', + Roles = 'Roles', JoinTokens = 'Join Tokens', AuthConnectors = 'Auth Connectors', Integrations = 'Integrations', - EnrollNewResource = 'Enroll New Resource', - EnrollNewIntegration = 'Enroll New Integration', + EnrollNewResource = 'Resource', + EnrollNewIntegration = 'Integration', + NewAccessList = 'Access List', + NewBot = 'Bot', // Identity Governance & Security AccessLists = 'Access Lists', diff --git a/web/packages/teleterm/src/ui/AccessRequestCheckout/AccessRequestCheckout.tsx b/web/packages/teleterm/src/ui/AccessRequestCheckout/AccessRequestCheckout.tsx index 44e81b59b3822..dbcc521911839 100644 --- a/web/packages/teleterm/src/ui/AccessRequestCheckout/AccessRequestCheckout.tsx +++ b/web/packages/teleterm/src/ui/AccessRequestCheckout/AccessRequestCheckout.tsx @@ -32,6 +32,7 @@ import * as Icon from 'design/Icon'; import { pluralize } from 'shared/utils/text'; import { RequestCheckoutWithSlider } from 'shared/components/AccessRequests/NewRequest'; +import { isKubeClusterWithNamespaces } from 'shared/components/AccessRequests/NewRequest/kube'; import useAccessRequestCheckout from './useAccessRequestCheckout'; import { AssumedRolesBar } from './AssumedRolesBar'; @@ -102,6 +103,8 @@ export function AccessRequestCheckout() { pendingRequestTtlOptions, startTime, onStartTimeChange, + fetchKubeNamespaces, + bulkToggleKubeResources, } = useAccessRequestCheckout(); const isRoleRequest = pendingAccessRequests[0]?.kind === 'role'; @@ -111,116 +114,126 @@ export function AccessRequestCheckout() { setShowCheckout(false); } + const pendingAccessRequestsWithoutParentResource = + pendingAccessRequests.filter( + d => !isKubeClusterWithNamespaces(d, pendingAccessRequests) + ); + + const numAddedResources = pendingAccessRequestsWithoutParentResource.length; + // We should rather detect how much space we have, // but for simplicity we only count items. const moreToShow = Math.max( - pendingAccessRequests.length - MAX_RESOURCES_IN_BAR_TO_SHOW, + pendingAccessRequestsWithoutParentResource.length - + MAX_RESOURCES_IN_BAR_TO_SHOW, 0 ); - const numPendingAccessRequests = pendingAccessRequests.length; - return ( <> - {pendingAccessRequests.length > 0 && !isCollapsed() && ( - props.theme.colors.spotBackground[1]}; - `} - > - 0 && + !isCollapsed() && ( + props.theme.space[1]}px; + border-top: 1px solid + ${props => props.theme.colors.spotBackground[1]}; `} > - - - {numPendingAccessRequests}{' '} - {pluralize( - numPendingAccessRequests, - isRoleRequest ? 'role' : 'resource' - )}{' '} - added to access request: - - - {pendingAccessRequests - .slice(0, MAX_RESOURCES_IN_BAR_TO_SHOW) - .map(c => { - let resource = { - name: c.name, - key: `${c.clusterName}-${c.kind}-${c.id}`, - Icon: undefined, - }; - switch (c.kind) { - case 'app': - case 'saml_idp_service_provider': - resource.Icon = Icon.Application; - break; - case 'node': - resource.Icon = Icon.Server; - break; - case 'db': - resource.Icon = Icon.Database; - break; - case 'kube_cluster': - resource.Icon = Icon.Kubernetes; - break; - case 'role': - break; - default: - c satisfies never; - } - return resource; - }) - .map(c => ( - - ))} - {!!moreToShow && ( - - )} + {c.Icon && } + + {c.name} + + + ))} + {!!moreToShow && ( + + )} + + + + setShowCheckout(!showCheckout)} + textTransform="none" + css={` + white-space: nowrap; + `} + > + Proceed to request + + + + - - setShowCheckout(!showCheckout)} - textTransform="none" - css={` - white-space: nowrap; - `} - > - Proceed to request - - - - - - - - )} + + )} {assumedRequests.map(request => ( ))} @@ -270,6 +283,8 @@ export function AccessRequestCheckout() { setPendingRequestTtl={setPendingRequestTtl} startTime={startTime} onStartTimeChange={onStartTimeChange} + fetchKubeNamespaces={fetchKubeNamespaces} + bulkToggleKubeResources={bulkToggleKubeResources} /> )} diff --git a/web/packages/teleterm/src/ui/AccessRequestCheckout/useAccessRequestCheckout.test.tsx b/web/packages/teleterm/src/ui/AccessRequestCheckout/useAccessRequestCheckout.test.tsx index 11e5c955f2fc8..a4dc881042005 100644 --- a/web/packages/teleterm/src/ui/AccessRequestCheckout/useAccessRequestCheckout.test.tsx +++ b/web/packages/teleterm/src/ui/AccessRequestCheckout/useAccessRequestCheckout.test.tsx @@ -21,11 +21,14 @@ import { renderHook, waitFor } from '@testing-library/react'; import { makeRootCluster, makeServer, + makeKube, rootClusterUri, } from 'teleterm/services/tshd/testHelpers'; import { MockAppContext } from 'teleterm/ui/fixtures/mocks'; import { MockAppContextProvider } from 'teleterm/ui/fixtures/MockAppContextProvider'; +import { mapRequestToKubeNamespaceUri } from '../services/workspacesService/accessRequestsService'; + import useAccessRequestCheckout from './useAccessRequestCheckout'; test('fetching requestable roles for servers uses UUID, not hostname', async () => { @@ -64,3 +67,120 @@ test('fetching requestable roles for servers uses UUID, not hostname', async () }) ); }); + +test('fetching requestable roles for a kube_cluster resource without specifying a namespace', async () => { + const kube = makeKube(); + const cluster = makeRootCluster(); + const appContext = new MockAppContext(); + appContext.clustersService.setState(draftState => { + draftState.clusters.set(rootClusterUri, cluster); + }); + await appContext.workspacesService.setActiveWorkspace(rootClusterUri); + await appContext.workspacesService + .getWorkspaceAccessRequestsService(rootClusterUri) + .addOrRemoveResource({ + kind: 'kube', + resource: kube, + }); + + jest.spyOn(appContext.tshd, 'getRequestableRoles'); + + const wrapper = ({ children }) => ( + + {children} + + ); + + renderHook(useAccessRequestCheckout, { wrapper }); + + await waitFor(() => + expect(appContext.tshd.getRequestableRoles).toHaveBeenCalledWith({ + clusterUri: rootClusterUri, + resourceIds: [ + { + clusterName: 'teleport-local', + kind: 'kube_cluster', + name: kube.name, + subResourceName: '', + }, + ], + }) + ); +}); + +test(`fetching requestable roles for a kube cluster's namespaces only creates resource IDs for its namespaces`, async () => { + const kube1 = makeKube(); + const kube2 = makeKube({ + name: 'kube2', + uri: `${rootClusterUri}/kubes/kube2`, + }); + const cluster = makeRootCluster(); + const appContext = new MockAppContext(); + appContext.clustersService.setState(draftState => { + draftState.clusters.set(rootClusterUri, cluster); + }); + await appContext.workspacesService.setActiveWorkspace(rootClusterUri); + await appContext.workspacesService + .getWorkspaceAccessRequestsService(rootClusterUri) + .addOrRemoveResource({ + kind: 'kube', + resource: kube1, + }); + await appContext.workspacesService + .getWorkspaceAccessRequestsService(rootClusterUri) + .addOrRemoveResource({ + kind: 'kube', + resource: kube2, + }); + + await appContext.workspacesService + .getWorkspaceAccessRequestsService(rootClusterUri) + .addOrRemoveKubeNamespaces([ + mapRequestToKubeNamespaceUri({ + clusterUri: rootClusterUri, + id: kube1.name, + name: 'namespace1', + }), + mapRequestToKubeNamespaceUri({ + clusterUri: rootClusterUri, + id: kube1.name, + name: 'namespace2', + }), + ]); + + jest.spyOn(appContext.tshd, 'getRequestableRoles'); + + const wrapper = ({ children }) => ( + + {children} + + ); + + renderHook(useAccessRequestCheckout, { wrapper }); + + await waitFor(() => + expect(appContext.tshd.getRequestableRoles).toHaveBeenCalledWith({ + clusterUri: rootClusterUri, + resourceIds: [ + { + clusterName: 'teleport-local', + kind: 'namespace', + name: kube1.name, + subResourceName: 'namespace1', + }, + { + clusterName: 'teleport-local', + kind: 'namespace', + name: kube1.name, + subResourceName: 'namespace2', + }, + { + clusterName: 'teleport-local', + kind: 'kube_cluster', + name: kube2.name, + subResourceName: '', + }, + ], + }) + ); +}); diff --git a/web/packages/teleterm/src/ui/AccessRequestCheckout/useAccessRequestCheckout.ts b/web/packages/teleterm/src/ui/AccessRequestCheckout/useAccessRequestCheckout.ts index 4ad261cf61b3c..7f8095a019828 100644 --- a/web/packages/teleterm/src/ui/AccessRequestCheckout/useAccessRequestCheckout.ts +++ b/web/packages/teleterm/src/ui/AccessRequestCheckout/useAccessRequestCheckout.ts @@ -24,6 +24,9 @@ import useAttempt from 'shared/hooks/useAttemptNext'; import { getDryRunMaxDuration, PendingListItem, + PendingKubeResourceItem, + isKubeClusterWithNamespaces, + KubeNamespaceRequest, } from 'shared/components/AccessRequests/NewRequest'; import { useSpecifiableFields } from 'shared/components/AccessRequests/NewRequest/useSpecifiableFields'; @@ -34,6 +37,8 @@ import { PendingAccessRequest, extractResourceRequestProperties, ResourceRequest, + mapRequestToKubeNamespaceUri, + mapKubeNamespaceUriToRequest, } from 'teleterm/ui/services/workspacesService/accessRequestsService'; import { retryWithRelogin } from 'teleterm/ui/utils'; import { @@ -87,9 +92,18 @@ export default function useAccessRequestCheckout() { const workspaceAccessRequest = ctx.workspacesService.getActiveWorkspaceAccessRequestsService(); const docService = ctx.workspacesService.getActiveWorkspaceDocumentService(); - const pendingAccessRequest = + const pendingAccessRequestRequest = workspaceAccessRequest?.getPendingAccessRequest(); + const pendingAccessRequests = getPendingAccessRequestsPerResource( + pendingAccessRequestRequest + ); + + const pendingAccessRequestsWithoutParentResource = + pendingAccessRequests.filter( + p => !isKubeClusterWithNamespaces(p, pendingAccessRequests) + ); + useEffect(() => { // Do a new dry run per changes to pending access requests // to get the latest time options and latest calculated @@ -99,20 +113,18 @@ export default function useAccessRequestCheckout() { if (showCheckout && requestedCount == 0) { performDryRun(); } - }, [showCheckout, pendingAccessRequest]); + }, [showCheckout, pendingAccessRequestRequest]); useEffect(() => { - if (!pendingAccessRequest || requestedCount > 0) { + if (!pendingAccessRequestRequest || requestedCount > 0) { return; } - const pendingAccessRequests = - getPendingAccessRequestsPerResource(pendingAccessRequest); runFetchResourceRoles(() => retryWithRelogin(ctx, clusterUri, async () => { const { response } = await ctx.tshd.getRequestableRoles({ clusterUri: rootClusterUri, - resourceIds: pendingAccessRequests + resourceIds: pendingAccessRequestsWithoutParentResource .filter(d => d.kind !== 'role') .map(d => ({ // We have to use id, not name. @@ -121,14 +133,14 @@ export default function useAccessRequestCheckout() { name: d.id, kind: d.kind, clusterName: d.clusterName, - subResourceName: '', + subResourceName: d.subResourceName || '', })), }); setResourceRequestRoles(response.applicableRoles); setSelectedResourceRequestRoles(response.applicableRoles); }) ); - }, [pendingAccessRequest]); + }, [pendingAccessRequestRequest]); useEffect(() => { clearCreateAttempt(); @@ -146,6 +158,9 @@ export default function useAccessRequestCheckout() { } }, [showCheckout, hasExited, createRequestAttempt.status]); + /** + * @param pendingRequest holds a list or map of resources to process + */ function getPendingAccessRequestsPerResource( pendingRequest: PendingAccessRequest ): PendingListItemWithOriginalItem[] { @@ -170,9 +185,34 @@ export default function useAccessRequestCheckout() { } case 'resource': { pendingRequest.resources.forEach(resourceRequest => { + // If this request is a kube cluster and has namespaces + // extract each as own request. + if ( + resourceRequest.kind === 'kube' && + resourceRequest.resource.namespaces?.size > 0 + ) { + // Process each namespace. + resourceRequest.resource.namespaces.forEach(namespaceRequestUri => { + const { kind, id, name } = + mapKubeNamespaceUriToRequest(namespaceRequestUri); + + const item = { + kind, + id, + name, + subResourceName: name, + originalItem: resourceRequest, + clusterName: + ctx.clustersService.findClusterByResource(namespaceRequestUri) + ?.name, + }; + pendingAccessRequests.push(item); + }); + } + const { kind, id, name } = extractResourceRequestProperties(resourceRequest); - pendingAccessRequests.push({ + const item: PendingListItemWithOriginalItem = { kind, id, name, @@ -180,7 +220,8 @@ export default function useAccessRequestCheckout() { clusterName: ctx.clustersService.findClusterByResource( resourceRequest.resource.uri )?.name, - }); + }; + pendingAccessRequests.push(item); }); } } @@ -207,6 +248,21 @@ export default function useAccessRequestCheckout() { ); } + async function bulkToggleKubeResources( + items: PendingKubeResourceItem[], + kubeCluster: PendingListKubeClusterWithOriginalItem + ) { + await workspaceAccessRequest.addOrRemoveKubeNamespaces( + items.map(item => + mapRequestToKubeNamespaceUri({ + id: item.id, + name: item.subResourceName, + clusterUri: kubeCluster.originalItem.resource.uri, + }) + ) + ); + } + function getAssumedRequests() { if (!clusterUri) { return []; @@ -222,22 +278,22 @@ export default function useAccessRequestCheckout() { * Shared logic used both during dry runs and regular access request creation. */ function prepareAndCreateRequest(req: CreateRequest) { - const pendingAccessRequests = - getPendingAccessRequestsPerResource(pendingAccessRequest); const params: CreateAccessRequestRequest = { rootClusterUri, reason: req.reason, suggestedReviewers: req.suggestedReviewers || [], dryRun: req.dryRun, - resourceIds: pendingAccessRequests + resourceIds: pendingAccessRequestsWithoutParentResource .filter(d => d.kind !== 'role') - .map(d => ({ - name: d.id, - clusterName: d.clusterName, - kind: d.kind, - subResourceName: '', - })), - roles: pendingAccessRequests + .map(d => { + return { + name: d.id, + clusterName: d.clusterName, + kind: d.kind, + subResourceName: d.subResourceName || '', + }; + }), + roles: pendingAccessRequestsWithoutParentResource .filter(d => d.kind === 'role') .map(d => d.name), assumeStartTime: req.start && Timestamp.fromDate(req.start), @@ -245,6 +301,11 @@ export default function useAccessRequestCheckout() { requestTtl: req.requestTTL && Timestamp.fromDate(req.requestTTL), }; + // Don't attempt creating anything if there are no resources selected. + if (!params.resourceIds.length && !params.roles.length) { + return; + } + // if we have a resource access request, we pass along the selected roles from the checkout if (params.resourceIds.length > 0) { params.roles = selectedResourceRequestRoles; @@ -256,7 +317,8 @@ export default function useAccessRequestCheckout() { ctx.clustersService.createAccessRequest(params).then(({ response }) => { return { accessRequest: response.request, - requestedCount: pendingAccessRequests.length, + requestedCount: + pendingAccessRequestsWithoutParentResource.filter.length, }; }) ).catch(e => { @@ -275,9 +337,9 @@ export default function useAccessRequestCheckout() { }); teletermAccessRequest = accessRequest; } catch { + setCreateRequestAttempt({ status: '' }); return; } - setCreateRequestAttempt({ status: '' }); const accessRequest = makeUiAccessRequest(teletermAccessRequest); @@ -333,9 +395,27 @@ export default function useAccessRequestCheckout() { } } + async function fetchKubeNamespaces({ + kubeCluster, + search, + }: KubeNamespaceRequest): Promise { + const { response } = await ctx.tshd.listKubernetesResources({ + searchKeywords: search, + limit: 50, + useSearchAsRoles: true, + nextKey: '', + resourceType: 'namespace', + clusterUri, + predicateExpression: '', + kubernetesCluster: kubeCluster, + kubernetesNamespace: '', + }); + return response.resources.map(i => i.name); + } + const shouldShowClusterNameColumn = - pendingAccessRequest?.kind === 'resource' && - Array.from(pendingAccessRequest.resources.values()).some(a => + pendingAccessRequestRequest?.kind === 'resource' && + Array.from(pendingAccessRequestRequest.resources.values()).some(a => routing.isLeafCluster(a.resource.uri) ); @@ -344,8 +424,7 @@ export default function useAccessRequestCheckout() { isCollapsed, assumedRequests: getAssumedRequests(), toggleResource, - pendingAccessRequests: - getPendingAccessRequestsPerResource(pendingAccessRequest), + pendingAccessRequests, shouldShowClusterNameColumn, createRequest, reset, @@ -373,6 +452,8 @@ export default function useAccessRequestCheckout() { pendingRequestTtlOptions, startTime, onStartTimeChange, + fetchKubeNamespaces, + bulkToggleKubeResources, }; } @@ -386,3 +467,8 @@ type PendingListItemWithOriginalItem = Omit & kind: 'role'; } ); + +type PendingListKubeClusterWithOriginalItem = Omit & { + kind: Extract; + originalItem: Extract; +}; diff --git a/web/packages/teleterm/src/ui/DocumentAccessRequests/NewRequest/NewRequest.tsx b/web/packages/teleterm/src/ui/DocumentAccessRequests/NewRequest/NewRequest.tsx index ba0b18fe7ad42..64bf86013b3b7 100644 --- a/web/packages/teleterm/src/ui/DocumentAccessRequests/NewRequest/NewRequest.tsx +++ b/web/packages/teleterm/src/ui/DocumentAccessRequests/NewRequest/NewRequest.tsx @@ -258,6 +258,7 @@ function toResourceMap(request: PendingAccessRequest): ResourceMap { db: {}, app: {}, saml_idp_service_provider: {}, + namespace: {}, }; if (request.kind === 'role') { request.roles.forEach(role => { diff --git a/web/packages/teleterm/src/ui/DocumentAccessRequests/NewRequest/useNewRequest.ts b/web/packages/teleterm/src/ui/DocumentAccessRequests/NewRequest/useNewRequest.ts index fefd237f739f0..bcc9d7b04f3e0 100644 --- a/web/packages/teleterm/src/ui/DocumentAccessRequests/NewRequest/useNewRequest.ts +++ b/web/packages/teleterm/src/ui/DocumentAccessRequests/NewRequest/useNewRequest.ts @@ -22,6 +22,7 @@ import { FetchStatus, SortType } from 'design/DataTable/types'; import useAttempt from 'shared/hooks/useAttemptNext'; import { makeAdvancedSearchQueryForLabel } from 'shared/utils/advancedSearchLabelQuery'; +import { RequestableResourceKind } from 'shared/components/AccessRequests/NewRequest/resource'; import { ShowResources, @@ -49,7 +50,6 @@ import type { ResourceLabel, ResourceFilter as WeakAgentFilter, ResourcesResponse, - ResourceIdKind, UnifiedResource, } from 'teleport/services/agents'; import type * as teleportApps from 'teleport/services/apps'; @@ -211,6 +211,17 @@ export default function useNewRequest(rootCluster: Cluster) { return; } + /** + * This should never happen but just a safeguard. + * This function is used in the "unified resources" view, + * where a user can click on a "request access" button. + * Selecting kube_cluster's namespace is not available in this view + * (instead it is rendered in the "request checkout" view). + */ + if (kind === 'namespace') { + return; + } + accessRequestsService.addOrRemoveResource( toResourceRequest({ kind, @@ -348,8 +359,13 @@ function getDefaultSort(kind: ResourceKind): SortType { export type ResourceKind = | Extract< - ResourceIdKind, - 'node' | 'app' | 'db' | 'kube_cluster' | 'saml_idp_service_provider' + RequestableResourceKind, + | 'node' + | 'app' + | 'db' + | 'kube_cluster' + | 'saml_idp_service_provider' + | 'namespace' > | 'role'; diff --git a/web/packages/teleterm/src/ui/DocumentCluster/UnifiedResources.tsx b/web/packages/teleterm/src/ui/DocumentCluster/UnifiedResources.tsx index 03da9da97f998..1d2f6e7613701 100644 --- a/web/packages/teleterm/src/ui/DocumentCluster/UnifiedResources.tsx +++ b/web/packages/teleterm/src/ui/DocumentCluster/UnifiedResources.tsx @@ -223,7 +223,7 @@ export function UnifiedResources(props: { const bulkAddResources = useCallback( (resources: UnifiedResourceResponse[]) => { - accessRequestsService.addOrRemoveResources(resources); + accessRequestsService.addAllOrRemoveAllResources(resources); }, [accessRequestsService] ); diff --git a/web/packages/teleterm/src/ui/ModalsHost/modals/ReAuthenticate/ReAuthenticate.tsx b/web/packages/teleterm/src/ui/ModalsHost/modals/ReAuthenticate/ReAuthenticate.tsx index aa8386031fed7..456b5a2bd494a 100644 --- a/web/packages/teleterm/src/ui/ModalsHost/modals/ReAuthenticate/ReAuthenticate.tsx +++ b/web/packages/teleterm/src/ui/ModalsHost/modals/ReAuthenticate/ReAuthenticate.tsx @@ -61,14 +61,6 @@ export const ReAuthenticate: FC<{ const logger = useLogger('ReAuthenticate'); const { promptMfaRequest: req } = props; - // TODO(ravicious): At the moment it doesn't seem like it's possible for both Webauthn and TOTP to - // be available at the same time (see lib/client/mfa.PromptConfig/GetRunOptions). Whenever both - // Webauthn and TOTP are supported, Webauthn is preferred. Well, unless AllowStdinHijack is - // specified, but lib/teleterm doesn't do this and AllowStdinHijack has a scary comment next to it - // telling you not to use it. - // - // Alas, the data structure certainly allows for this so the modal was designed with supporting - // such scenario in mind. const availableMfaTypes: MfaType[] = []; // Add Webauthn first to prioritize it if both Webauthn and TOTP are available. if (req.webauthn) { diff --git a/web/packages/teleterm/src/ui/services/workspacesService/accessRequestsService.test.ts b/web/packages/teleterm/src/ui/services/workspacesService/accessRequestsService.test.ts index 751cab9849052..c0b2f46f99217 100644 --- a/web/packages/teleterm/src/ui/services/workspacesService/accessRequestsService.test.ts +++ b/web/packages/teleterm/src/ui/services/workspacesService/accessRequestsService.test.ts @@ -124,7 +124,7 @@ test('getAddedItemsCount() returns added resource count for pending request', () expect(service.getAddedItemsCount()).toBe(0); }); -test('addOrRemoveResources() adds all resources to pending request', async () => { +test('addAllOrRemoveAllResources() adds all resources to pending request', async () => { const { accessRequestsService: service } = getTestSetup( getMockPendingResourceAccessRequest() ); @@ -138,7 +138,9 @@ test('addOrRemoveResources() adds all resources to pending request', async () => }); // add a single resource that isn't added should add to the request - await service.addOrRemoveResources([{ kind: 'server', resource: server }]); + await service.addAllOrRemoveAllResources([ + { kind: 'server', resource: server }, + ]); let pendingAccessRequest = service.getPendingAccessRequest(); expect( pendingAccessRequest.kind === 'resource' && @@ -149,7 +151,7 @@ test('addOrRemoveResources() adds all resources to pending request', async () => }); // padding an array that contains some resources already added and some that aren't should add them all - await service.addOrRemoveResources([ + await service.addAllOrRemoveAllResources([ { kind: 'server', resource: server }, { kind: 'server', resource: server2 }, ]); @@ -170,7 +172,7 @@ test('addOrRemoveResources() adds all resources to pending request', async () => }); // passing an array of resources that are all already added should remove all the passed resources - await service.addOrRemoveResources([ + await service.addAllOrRemoveAllResources([ { kind: 'server', resource: server }, { kind: 'server', resource: server2 }, ]); diff --git a/web/packages/teleterm/src/ui/services/workspacesService/accessRequestsService.ts b/web/packages/teleterm/src/ui/services/workspacesService/accessRequestsService.ts index f8ff36b9c2491..e408e8244de68 100644 --- a/web/packages/teleterm/src/ui/services/workspacesService/accessRequestsService.ts +++ b/web/packages/teleterm/src/ui/services/workspacesService/accessRequestsService.ts @@ -24,6 +24,7 @@ import { DatabaseUri, KubeUri, AppUri, + KubeResourceNamespaceUri, } from 'teleterm/ui/uri'; import { ModalsService } from 'teleterm/ui/services/modals'; @@ -98,7 +99,44 @@ export class AccessRequestsService { }); } - async addOrRemoveResources(requestedResources: ResourceRequest[]) { + async addOrRemoveKubeNamespaces(namespaceUris: KubeResourceNamespaceUri[]) { + this.setState(draftState => { + if (draftState.pending.kind !== 'resource') { + throw new Error('Cannot add a kube namespace to a role access request'); + } + + const { resources } = draftState.pending; + + namespaceUris.forEach(resourceUri => { + const requestedResource = resources.get( + routing.getKubeUri( + routing.parseKubeResourceNamespaceUri(resourceUri).params + ) + ); + if (!requestedResource || requestedResource.kind !== 'kube') { + throw new Error('Cannot add a kube namespace to a non-kube resource'); + } + const kubeResource = requestedResource.resource; + + if (!kubeResource.namespaces) { + kubeResource.namespaces = new Set(); + } + if (kubeResource.namespaces.has(resourceUri)) { + kubeResource.namespaces.delete(resourceUri); + } else { + kubeResource.namespaces.add(resourceUri); + } + }); + }); + } + + /** + * Removes all requested resources, if all the requested resources were already added + * or adds all requested resources, if not all requested resources were added. + * + * Typically used when user "selects all or deselects all" + */ + async addAllOrRemoveAllResources(requestedResources: ResourceRequest[]) { if (!(await this.canUpdateRequest('resource'))) { return; } @@ -258,6 +296,7 @@ export type ResourceRequest = kind: 'kube'; resource: { uri: KubeUri; + namespaces?: Set; }; } | { @@ -287,8 +326,7 @@ export function extractResourceRequestProperties({ kind: SharedResourceAccessRequestKind; id: string; /** - * Pretty name of the resource (can be the same as `id`). - * For example, for nodes, we want to show hostname instead of its id. + * Can refer to a pretty name of the resource (can be the same as `id`) */ name: string; } { @@ -317,6 +355,42 @@ export function extractResourceRequestProperties({ } } +export function mapRequestToKubeNamespaceUri({ + clusterUri, + id, + name, +}: { + clusterUri: ClusterUri; + /** kubeId */ + id: string; + /** kubeNamespaceId */ + name: string; +}) { + const { + params: { rootClusterId, leafClusterId }, + } = routing.parseClusterUri(clusterUri); + return routing.getKubeResourceNamespaceUri({ + rootClusterId, + leafClusterId, + kubeId: id, + kubeNamespaceId: name, + }); +} + +export function mapKubeNamespaceUriToRequest( + kubeNamespaceUri: KubeResourceNamespaceUri +): { + kind: 'namespace'; + /** kubeId */ + id: string; + /** kubeNamespaceId */ + name: string; +} { + const { kubeNamespaceId, kubeId } = + routing.parseKubeResourceNamespaceUri(kubeNamespaceUri).params; + return { kind: 'namespace', id: kubeId, name: kubeNamespaceId }; +} + /** * Maps the type used by the shared access requests to the type * required by the access requests service.
+ + + + + {getPrettyResourceKind(item.kind)} + {item.name} - )} - {userGroupFetchAttempt?.status === 'failed' && ( - {userGroupFetchAttempt.statusText} - )} - {userGroupFetchAttempt?.status === 'success' && - appsGrantedByUserGroup.length > 0 && ( - - )} - {isResourceRequest && ( - - )} - - r.name) ?? []} - selectedReviewers={selectedReviewers} - setSelectedReviewers={setSelectedReviewers} + + + + +