Remove JSON schema validation (#6685)

* Remove JSON schema validation

Removing JSON schema validation from all resource unmarshalers.

--- what JSON schema gets us

Looking at the JSON schema spec and our usage, here are the supposed benefits:
- type validation - make sure incoming data uses the right types for the right fields
- required fields - make sure that mandatory fields are set
- defaulting - set defaults for fields
- documentation - schema definition for our API objects

Note that it does _not_ do:
- fail on unknown fields in data
- fail on a required field with an empty value

--- what replaces it

Based on the above, it may seem like JSON schema provides value.
But it's not the case, let's break it down one by one:
- type validation - unmarshaling JSON into a typed Go struct does this
- required fields - only checks that the field was provided, doesn't actually check that a value is set (e.g. `"name": ""` will pass the `required` check)
  - so it's pretty useless for any real validation
  - and we already have a separate place for proper validation - `CheckAndSetDefaults` methods
- defaulting - done in `CheckAndSetDefaults` methods
  - `Version` is the only annoying field, had to add it in a bunch of objects
- documentation - protobuf definitions are the source of truth for our API schema

--- the benefits

- performance - schema validation does a few rounds of `json.Marshal/Unmarshal` in addition to actual validation; now we simply skip all that
- maintenance - no need to keep protobuf and JSON schema definitions in sync anymore
- creating new API objects - one error-prone step removed
- (future) fewer dependencies - we can _almost_ remove the Go libraries for schema validation (one transient dependency keeping them around)

* Remove services.SkipValidation

No more JSON schema validation so this option is a noop.
This commit is contained in:
Andrew Lytvynov 2021-06-01 22:27:20 +00:00 committed by GitHub
parent 4ac06ba1b7
commit cd2f4fceb7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
89 changed files with 692 additions and 2361 deletions

View file

@ -699,10 +699,9 @@ func (c *Client) GetKubeServices(ctx context.Context) ([]types.Server, error) {
}
// GetAppServers gets all application servers.
func (c *Client) GetAppServers(ctx context.Context, namespace string, skipValidation bool) ([]types.Server, error) {
func (c *Client) GetAppServers(ctx context.Context, namespace string) ([]types.Server, error) {
resp, err := c.grpc.GetAppServers(ctx, &proto.GetAppServersRequest{
Namespace: namespace,
SkipValidation: skipValidation,
Namespace: namespace,
}, c.callOpts...)
if err != nil {
return nil, trail.FromGRPC(err)
@ -834,10 +833,9 @@ func (c *Client) DeleteAllKubeServices(ctx context.Context) error {
}
// GetDatabaseServers returns all registered database proxy servers.
func (c *Client) GetDatabaseServers(ctx context.Context, namespace string, skipValidation bool) ([]types.DatabaseServer, error) {
func (c *Client) GetDatabaseServers(ctx context.Context, namespace string) ([]types.DatabaseServer, error) {
resp, err := c.grpc.GetDatabaseServers(ctx, &proto.GetDatabaseServersRequest{
Namespace: namespace,
SkipValidation: skipValidation,
Namespace: namespace,
}, c.callOpts...)
if err != nil {
return nil, trail.FromGRPC(err)

View file

@ -2179,8 +2179,8 @@ var xxx_messageInfo_FlushAndCloseStream proto.InternalMessageInfo
type GetAppServersRequest struct {
// Namespace is the namespace for application.
Namespace string `protobuf:"bytes,1,opt,name=Namespace,proto3" json:"namespace"`
// SkipValidation is used to skip JSON schema validation.
SkipValidation bool `protobuf:"varint,2,opt,name=SkipValidation,proto3" json:"skip_validation"`
// DEPRECATED: SkipValidation is used to skip JSON schema validation.
SkipValidation bool `protobuf:"varint,2,opt,name=SkipValidation,proto3" json:"skip_validation"` // Deprecated: Do not use.
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -2226,6 +2226,7 @@ func (m *GetAppServersRequest) GetNamespace() string {
return ""
}
// Deprecated: Do not use.
func (m *GetAppServersRequest) GetSkipValidation() bool {
if m != nil {
return m.SkipValidation
@ -3301,8 +3302,8 @@ var xxx_messageInfo_DeleteAllKubeServicesRequest proto.InternalMessageInfo
type GetDatabaseServersRequest struct {
// Namespace is the database server namespace.
Namespace string `protobuf:"bytes,1,opt,name=Namespace,proto3" json:"namespace"`
// SkipValidation allows to turn off JSON schema validation.
SkipValidation bool `protobuf:"varint,2,opt,name=SkipValidation,proto3" json:"skip_validation"`
// DEPRECATED: SkipValidation allows to turn off JSON schema validation.
SkipValidation bool `protobuf:"varint,2,opt,name=SkipValidation,proto3" json:"skip_validation"` // Deprecated: Do not use.
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -3348,6 +3349,7 @@ func (m *GetDatabaseServersRequest) GetNamespace() string {
return ""
}
// Deprecated: Do not use.
func (m *GetDatabaseServersRequest) GetSkipValidation() bool {
if m != nil {
return m.SkipValidation
@ -6250,355 +6252,355 @@ func init() {
func init() { proto.RegisterFile("authservice.proto", fileDescriptor_ce8bd90b12161215) }
var fileDescriptor_ce8bd90b12161215 = []byte{
// 5560 bytes of a gzipped FileDescriptorProto
// 5561 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x3c, 0x4d, 0x6f, 0x1b, 0x59,
0x72, 0x6a, 0xea, 0x8b, 0x2c, 0x7d, 0x51, 0x4f, 0x5f, 0x14, 0x2d, 0x8b, 0xde, 0xf6, 0xae, 0xd7,
0x3b, 0x3b, 0x2b, 0xcd, 0x52, 0x3b, 0xf1, 0xec, 0x78, 0x66, 0x1c, 0x92, 0xfa, 0x20, 0xc7, 0xb2,
0xad, 0x69, 0x52, 0x74, 0x76, 0x33, 0x80, 0xd2, 0x22, 0x9f, 0xa9, 0x86, 0x28, 0x36, 0xa7, 0xbb,
0x29, 0x8f, 0x72, 0xda, 0x00, 0xbb, 0x8b, 0x20, 0x41, 0x80, 0x5c, 0x72, 0xc8, 0x29, 0x01, 0x72,
0xdf, 0x53, 0xae, 0x0b, 0xe4, 0x38, 0x08, 0x10, 0x6c, 0x90, 0x4b, 0x80, 0x1c, 0x98, 0xcd, 0x1c,
0xf9, 0x13, 0x72, 0x0a, 0xde, 0x57, 0xf7, 0x7b, 0xcd, 0x6e, 0x4a, 0xb2, 0x9d, 0xe4, 0x62, 0xab,
0xeb, 0x55, 0xd5, 0xab, 0xaa, 0x57, 0xaf, 0xaa, 0xde, 0x7b, 0x25, 0xc1, 0xa2, 0xd9, 0xf3, 0xce,
0x5c, 0xec, 0x5c, 0x5a, 0x0d, 0xbc, 0xd5, 0x75, 0x6c, 0xcf, 0x46, 0x93, 0xf4, 0xbf, 0xec, 0x72,
0xcb, 0x6e, 0xd9, 0xf4, 0xc7, 0x6d, 0xf2, 0x13, 0x1b, 0xcc, 0xde, 0x69, 0xd9, 0x76, 0xab, 0x8d,
0xb7, 0xe9, 0xd7, 0x69, 0xef, 0xd5, 0x36, 0xbe, 0xe8, 0x7a, 0x57, 0x7c, 0x30, 0x17, 0x1e, 0xf4,
0xac, 0x0b, 0xec, 0x7a, 0xe6, 0x45, 0x97, 0x23, 0x3c, 0x6a, 0x59, 0xde, 0x59, 0xef, 0x74, 0xab,
0x61, 0x5f, 0x6c, 0xb7, 0x1c, 0xf3, 0xd2, 0xf2, 0x4c, 0xcf, 0xb2, 0x3b, 0x66, 0x7b, 0xdb, 0xc3,
0x6d, 0xdc, 0xb5, 0x1d, 0x6f, 0xdb, 0xec, 0x5a, 0xdb, 0xde, 0x55, 0x17, 0xbb, 0xec, 0x5f, 0x4e,
0x58, 0xba, 0x0d, 0xe1, 0x6b, 0xc7, 0xec, 0x76, 0xb1, 0x13, 0xfc, 0xc0, 0x99, 0x3c, 0xb9, 0x0d,
0x13, 0x7c, 0x89, 0x3b, 0x9e, 0xf8, 0x8f, 0x31, 0xd0, 0xff, 0x6d, 0x1e, 0x26, 0xf7, 0x08, 0x00,
0x7d, 0x04, 0x13, 0xb5, 0xab, 0x2e, 0xce, 0x68, 0xf7, 0xb4, 0x87, 0xf3, 0xf9, 0x34, 0x1b, 0xdf,
0x7a, 0xd1, 0xc5, 0x0e, 0x65, 0x59, 0x44, 0x83, 0x7e, 0x6e, 0x9e, 0x30, 0x7a, 0xdf, 0xbe, 0xb0,
0x3c, 0x6a, 0x23, 0x83, 0x52, 0xa0, 0x97, 0x30, 0x6f, 0x60, 0xd7, 0xee, 0x39, 0x0d, 0x5c, 0xc6,
0x66, 0x13, 0x3b, 0x99, 0xc4, 0x3d, 0xed, 0xe1, 0x4c, 0x7e, 0x65, 0x8b, 0xe9, 0xab, 0x0e, 0x16,
0x57, 0x07, 0xfd, 0x1c, 0x72, 0x38, 0x2c, 0x60, 0x56, 0x1e, 0x33, 0x42, 0x6c, 0xd0, 0x97, 0x30,
0x57, 0xc2, 0x8e, 0x57, 0xe8, 0x79, 0x67, 0xb6, 0x63, 0x79, 0x57, 0x99, 0x71, 0xca, 0x77, 0x95,
0xf3, 0x55, 0xc6, 0xea, 0xf9, 0xe2, 0xc6, 0xa0, 0x9f, 0xcb, 0x34, 0xb0, 0xe3, 0x9d, 0x98, 0x02,
0xaa, 0xb0, 0x57, 0x99, 0xa1, 0x3f, 0x82, 0xd9, 0x2a, 0x31, 0x57, 0xa3, 0x66, 0x9f, 0xe3, 0x8e,
0x9b, 0x99, 0x50, 0x84, 0x96, 0x87, 0xea, 0xf9, 0xe2, 0x9d, 0x41, 0x3f, 0xb7, 0xe6, 0x52, 0xd8,
0x89, 0x47, 0x81, 0x0a, 0x6b, 0x85, 0x13, 0xfa, 0x13, 0x98, 0x3f, 0x72, 0xec, 0x4b, 0xcb, 0xb5,
0xec, 0x0e, 0x05, 0x65, 0x26, 0x29, 0xef, 0x35, 0xce, 0x5b, 0x1d, 0xac, 0xe7, 0x8b, 0x77, 0x07,
0xfd, 0xdc, 0x7a, 0x57, 0x40, 0xd9, 0x04, 0xaa, 0x65, 0x54, 0x12, 0x54, 0x83, 0x99, 0x52, 0xbb,
0xe7, 0x7a, 0xd8, 0x79, 0x6e, 0x5e, 0xe0, 0xcc, 0x14, 0x65, 0xbf, 0x2c, 0xec, 0x12, 0x8c, 0xd4,
0xf3, 0xc5, 0xec, 0xa0, 0x9f, 0x5b, 0x6d, 0x30, 0xd0, 0x49, 0xc7, 0xbc, 0x50, 0x4d, 0x2e, 0xb3,
0xa1, 0xf6, 0x66, 0x9f, 0x25, 0xbb, 0xf3, 0xca, 0x6a, 0x65, 0xa6, 0x55, 0x7b, 0xcb, 0x63, 0xf5,
0x1d, 0x6e, 0x6f, 0xce, 0xb9, 0x41, 0xa1, 0x21, 0x7b, 0xcb, 0x04, 0xe8, 0x11, 0x4c, 0x1c, 0xbb,
0xd8, 0xc9, 0x24, 0x29, 0xd3, 0x39, 0xce, 0x94, 0x80, 0xea, 0x79, 0xe6, 0x5d, 0x3d, 0x17, 0x3b,
0x0a, 0x07, 0x4a, 0x40, 0x08, 0x0d, 0xbb, 0x8d, 0x33, 0x29, 0x85, 0x90, 0x80, 0xea, 0x3b, 0x8c,
0xd0, 0xb1, 0xdb, 0xaa, 0x5a, 0x94, 0x00, 0x55, 0x20, 0x45, 0xf4, 0x72, 0xbb, 0x66, 0x03, 0x67,
0x80, 0x52, 0xa7, 0x39, 0xb5, 0x0f, 0x2f, 0xae, 0x0d, 0xfa, 0xb9, 0xa5, 0x8e, 0xf8, 0x54, 0xb8,
0x04, 0xd4, 0xe8, 0x09, 0x4c, 0x55, 0xb1, 0x73, 0x89, 0x9d, 0xcc, 0x0c, 0xe5, 0xb3, 0x20, 0xdc,
0x84, 0x02, 0xeb, 0xf9, 0xe2, 0xf2, 0xa0, 0x9f, 0x4b, 0xbb, 0xf4, 0x4b, 0xe1, 0xc1, 0xc9, 0x88,
0x6d, 0x0d, 0x7c, 0x89, 0x1d, 0x17, 0xd7, 0x7a, 0x9d, 0x0e, 0x6e, 0x67, 0x66, 0x15, 0xdb, 0x2a,
0x63, 0xc2, 0x97, 0x1d, 0x06, 0x3c, 0xf1, 0x28, 0x54, 0xb5, 0xad, 0x42, 0x80, 0xce, 0x20, 0xcd,
0x7e, 0x2a, 0xd9, 0x9d, 0x0e, 0x6e, 0x90, 0x0d, 0x9b, 0x99, 0xa3, 0x13, 0xac, 0xf3, 0x09, 0xc2,
0xc3, 0xf5, 0x7c, 0x31, 0x37, 0xe8, 0xe7, 0xee, 0x30, 0xde, 0x64, 0xf9, 0xf8, 0x80, 0x32, 0xcd,
0x10, 0x57, 0xa2, 0x47, 0xa1, 0xd1, 0xc0, 0xae, 0x6b, 0xe0, 0xaf, 0x7a, 0xd8, 0xf5, 0x32, 0xf3,
0x8a, 0x1e, 0xca, 0x98, 0xf0, 0x11, 0x93, 0x02, 0x4f, 0x1c, 0x06, 0x55, 0xf5, 0x50, 0x08, 0xd0,
0x11, 0x40, 0xa1, 0xdb, 0xad, 0x62, 0x97, 0xb8, 0x7a, 0x66, 0x81, 0xb2, 0x5e, 0xe2, 0xac, 0x5f,
0xe2, 0x53, 0x3e, 0x50, 0xcf, 0x17, 0xd7, 0x07, 0xfd, 0xdc, 0x8a, 0xd9, 0xed, 0x9e, 0xb8, 0x0c,
0xa4, 0x30, 0x95, 0x78, 0x30, 0xbb, 0x5f, 0xd8, 0x1e, 0xe6, 0xce, 0x98, 0x49, 0x87, 0xec, 0x2e,
0x8d, 0x09, 0x79, 0x1d, 0x0a, 0x3c, 0xe1, 0xae, 0x1d, 0xb6, 0xbb, 0x44, 0x40, 0x76, 0xfa, 0xae,
0xe9, 0x99, 0xa7, 0xa6, 0x8b, 0xb9, 0x7b, 0x2c, 0x2a, 0x3b, 0x5d, 0x1d, 0xac, 0xef, 0xb0, 0x9d,
0xde, 0xe4, 0xd0, 0x93, 0x08, 0x7f, 0x09, 0xf1, 0x23, 0x16, 0x09, 0x14, 0xcf, 0xa0, 0x6b, 0x2c,
0xf2, 0x1a, 0x9f, 0x46, 0x5b, 0x24, 0x40, 0x45, 0x65, 0x48, 0xbe, 0xc4, 0xa7, 0x2c, 0x2e, 0x2d,
0x51, 0x7e, 0x8b, 0x01, 0x3f, 0x16, 0x91, 0x76, 0xd8, 0xae, 0x20, 0xdc, 0x86, 0x63, 0x91, 0x4f,
0x8d, 0x7e, 0xa5, 0xc1, 0x9a, 0x88, 0x1f, 0xd8, 0x7b, 0x6d, 0x3b, 0xe7, 0x56, 0xa7, 0xc5, 0x43,
0xc7, 0x32, 0xe5, 0x7c, 0x2f, 0x14, 0x92, 0x42, 0x58, 0xf5, 0x7c, 0xf1, 0xfb, 0x83, 0x7e, 0xee,
0xbe, 0x1f, 0x9e, 0xfc, 0xf1, 0xa8, 0x78, 0x12, 0x37, 0x17, 0xfa, 0x33, 0x0d, 0x56, 0xb9, 0x76,
0x06, 0x6e, 0xd8, 0x4e, 0x33, 0x10, 0x63, 0x85, 0x8a, 0x91, 0xf3, 0x77, 0x6b, 0x14, 0x52, 0x3d,
0x5f, 0x7c, 0x30, 0xe8, 0xe7, 0x74, 0x6e, 0xb8, 0x13, 0x47, 0x0c, 0x47, 0x09, 0x11, 0x33, 0x51,
0x11, 0x20, 0x29, 0xb2, 0x97, 0x5e, 0x86, 0xc9, 0x97, 0xa6, 0xd7, 0x38, 0x43, 0x4f, 0x60, 0xf2,
0xa9, 0xd5, 0x69, 0xba, 0x19, 0xed, 0xde, 0x38, 0x0d, 0x3e, 0x2c, 0xa9, 0xd2, 0x41, 0x32, 0x50,
0x5c, 0xfb, 0xa6, 0x9f, 0x1b, 0x1b, 0xf4, 0x73, 0x0b, 0xe7, 0x04, 0x4d, 0xca, 0xac, 0x8c, 0x4e,
0xff, 0xc7, 0x04, 0xa4, 0x7c, 0x6c, 0xb4, 0x01, 0x13, 0xe4, 0x7f, 0x9a, 0xa2, 0x53, 0xc5, 0xe4,
0xa0, 0x9f, 0x9b, 0x20, 0x74, 0x06, 0x85, 0xa2, 0x3c, 0xcc, 0x1c, 0xda, 0x66, 0xb3, 0x8a, 0x1b,
0x0e, 0xf6, 0x5c, 0x9a, 0x83, 0x93, 0xc5, 0xf4, 0xa0, 0x9f, 0x9b, 0x6d, 0xdb, 0x66, 0xf3, 0xc4,
0x65, 0x70, 0x43, 0x46, 0x22, 0x1c, 0x69, 0x02, 0x19, 0x0f, 0x38, 0x92, 0x50, 0x68, 0x50, 0x28,
0xfa, 0x1c, 0xa6, 0xf6, 0xad, 0x36, 0xd9, 0x34, 0x13, 0x54, 0xfe, 0x8d, 0xb0, 0xfc, 0x5b, 0x6c,
0x78, 0xaf, 0xe3, 0x39, 0x57, 0x2c, 0x02, 0xbe, 0xa2, 0x00, 0x49, 0x11, 0xce, 0x01, 0x7d, 0x00,
0xd3, 0xd5, 0xde, 0x29, 0x15, 0x7f, 0x92, 0x4e, 0x46, 0xcb, 0x00, 0xb7, 0x77, 0x7a, 0x42, 0x54,
0x90, 0x08, 0x04, 0x5a, 0xf6, 0xa7, 0x30, 0x23, 0xb1, 0x47, 0x69, 0x18, 0x3f, 0xc7, 0x57, 0x4c,
0x77, 0x83, 0xfc, 0x88, 0x96, 0x61, 0xf2, 0xd2, 0x6c, 0xf7, 0x30, 0x55, 0x35, 0x65, 0xb0, 0x8f,
0x8f, 0x13, 0x1f, 0x69, 0xfa, 0x17, 0x30, 0x49, 0x72, 0xbd, 0x8b, 0xee, 0xc3, 0x78, 0xb5, 0x5a,
0xa6, 0x44, 0xb3, 0xc5, 0xc5, 0x41, 0x3f, 0x37, 0xe7, 0xba, 0x67, 0xd2, 0x64, 0x64, 0x94, 0x20,
0xd5, 0x0e, 0xab, 0x94, 0x0b, 0x47, 0xf2, 0xda, 0xf2, 0x5a, 0x90, 0x51, 0xfd, 0x77, 0x53, 0x90,
0x26, 0xd9, 0x88, 0xf2, 0x15, 0xe1, 0xea, 0x7d, 0x48, 0x1d, 0xf5, 0x4e, 0xdb, 0x56, 0xe3, 0x29,
0x97, 0x6c, 0xb6, 0x38, 0x3f, 0xe8, 0xe7, 0xa0, 0x4b, 0x81, 0x27, 0xe7, 0xf8, 0xca, 0x08, 0x10,
0xd0, 0x43, 0x48, 0x12, 0x0e, 0xc4, 0xc0, 0x4c, 0xe4, 0xe2, 0xec, 0xa0, 0x9f, 0x4b, 0xf6, 0x38,
0xcc, 0xf0, 0x47, 0x51, 0x15, 0xa6, 0xf7, 0xbe, 0xee, 0x5a, 0x0e, 0x76, 0x79, 0xc9, 0x93, 0xdd,
0x62, 0x75, 0xe8, 0x96, 0xa8, 0x43, 0xb7, 0x6a, 0xa2, 0x0e, 0x2d, 0xde, 0xe5, 0x3e, 0xb4, 0x88,
0x19, 0x49, 0x20, 0xf9, 0x5f, 0xff, 0x67, 0x4e, 0x33, 0x04, 0x27, 0xf4, 0x3e, 0x4c, 0xed, 0xdb,
0xce, 0x85, 0xe9, 0xd1, 0x4a, 0x27, 0xc5, 0xd7, 0x8b, 0x42, 0x94, 0xf5, 0xa2, 0x10, 0xb4, 0x0f,
0xf3, 0x86, 0xdd, 0xf3, 0x70, 0xcd, 0x16, 0x81, 0x93, 0x2d, 0xdb, 0xe6, 0xa0, 0x9f, 0xcb, 0x3a,
0x64, 0xe4, 0xc4, 0xb3, 0x87, 0x43, 0xa4, 0x11, 0xa2, 0x42, 0x7b, 0x30, 0xaf, 0x84, 0x78, 0x37,
0x33, 0x75, 0x6f, 0xfc, 0x61, 0x8a, 0x05, 0x42, 0x35, 0x31, 0xc8, 0x36, 0x0f, 0x11, 0xa1, 0xe7,
0xb0, 0xf8, 0xb4, 0x77, 0x8a, 0x9d, 0x0e, 0xf6, 0xb0, 0x2b, 0x24, 0x9a, 0xa6, 0x12, 0xdd, 0x1b,
0xf4, 0x73, 0x1b, 0xe7, 0xfe, 0x60, 0x84, 0x4c, 0xc3, 0xa4, 0x08, 0xc3, 0x02, 0x17, 0x54, 0xc4,
0x5b, 0x5e, 0x97, 0xac, 0x72, 0x1f, 0x0f, 0x8d, 0x16, 0xef, 0x73, 0x2b, 0xdf, 0xf1, 0x75, 0x17,
0x51, 0x5c, 0x9a, 0x28, 0xcc, 0x13, 0xed, 0x40, 0xf2, 0xb9, 0xdd, 0xc4, 0x74, 0x8f, 0xa5, 0xa8,
0xb4, 0xac, 0xdc, 0xb0, 0x9b, 0x38, 0x54, 0x8b, 0x19, 0x3e, 0x22, 0x3a, 0x84, 0xc9, 0x63, 0xd7,
0x6c, 0xb1, 0x92, 0x65, 0x3e, 0xff, 0x1d, 0x2e, 0x51, 0xd8, 0xfb, 0x68, 0xfd, 0x4b, 0x11, 0x8b,
0x4b, 0x24, 0x84, 0xf4, 0xc8, 0x8f, 0x72, 0x08, 0xa1, 0x63, 0xe8, 0x0b, 0x00, 0x2e, 0x55, 0xa1,
0xdb, 0xe5, 0xd5, 0xcb, 0xa2, 0xaa, 0x64, 0xa1, 0xdb, 0x2d, 0x6e, 0x72, 0xfd, 0x56, 0x7d, 0xfd,
0xcc, 0x6e, 0x57, 0xe2, 0x26, 0x31, 0xd1, 0x77, 0x21, 0xe5, 0xcf, 0x8d, 0xa6, 0x61, 0xbc, 0xd0,
0x6e, 0xa7, 0xc7, 0xc8, 0x0f, 0xd5, 0x6a, 0x39, 0xad, 0xa1, 0x79, 0x80, 0xc0, 0xe0, 0xe9, 0x04,
0x9a, 0x85, 0xa4, 0x30, 0x48, 0x7a, 0x9c, 0xe2, 0x77, 0xbb, 0xe9, 0x09, 0xfd, 0xdf, 0xb5, 0xa1,
0x35, 0x20, 0x31, 0xac, 0xca, 0x4e, 0x6e, 0xd4, 0x64, 0x2c, 0xd0, 0xd1, 0x18, 0xc6, 0x0f, 0x74,
0xd4, 0x6a, 0x86, 0x8c, 0x44, 0xb6, 0xd5, 0x11, 0xd1, 0xa6, 0x61, 0xb7, 0xe5, 0x6d, 0xd5, 0xe5,
0x30, 0xc3, 0x1f, 0x45, 0x79, 0x69, 0x03, 0x8e, 0x07, 0x41, 0x48, 0x6c, 0x40, 0x79, 0x31, 0xfc,
0xad, 0x98, 0x0f, 0x84, 0xe7, 0xfb, 0x86, 0xd2, 0x44, 0x2c, 0xbe, 0x8f, 0xa7, 0xff, 0x56, 0x93,
0x6d, 0xee, 0x07, 0x59, 0x2d, 0x32, 0xc8, 0xbe, 0x0f, 0x29, 0x9e, 0x52, 0x2a, 0xbb, 0x5c, 0x7e,
0x1a, 0x43, 0x44, 0x36, 0xb2, 0x9a, 0x46, 0x80, 0x80, 0xb6, 0x01, 0x58, 0x40, 0x29, 0x34, 0x9b,
0x0e, 0x57, 0x62, 0x61, 0xd0, 0xcf, 0xcd, 0xf0, 0x90, 0x63, 0x36, 0x9b, 0x8e, 0x21, 0xa1, 0x10,
0x8b, 0xca, 0x27, 0x85, 0x89, 0xc0, 0xa2, 0xf2, 0x99, 0x40, 0x39, 0x07, 0xe8, 0x6d, 0x98, 0x3f,
0xc0, 0x1e, 0x31, 0x81, 0x08, 0x74, 0xa3, 0x55, 0xf8, 0x04, 0x66, 0x5e, 0x5a, 0xde, 0x99, 0x9a,
0x79, 0xe8, 0xb9, 0xe3, 0xb5, 0xe5, 0x9d, 0x89, 0xcc, 0x23, 0x99, 0x4a, 0x46, 0xd7, 0xf7, 0x60,
0x81, 0xcf, 0xe6, 0xc7, 0xd5, 0xbc, 0xca, 0x50, 0x0b, 0x52, 0x99, 0xcc, 0x50, 0x65, 0x83, 0xc3,
0x81, 0x06, 0x55, 0x87, 0x42, 0x0f, 0x4b, 0xc3, 0x71, 0xb5, 0x2a, 0xdd, 0x45, 0xa1, 0x90, 0x14,
0x0e, 0x44, 0xfa, 0x31, 0xcc, 0x1d, 0xb5, 0x7b, 0x2d, 0xab, 0x43, 0x56, 0xbb, 0x8a, 0xbf, 0x42,
0xbb, 0x00, 0x01, 0x80, 0xcf, 0x20, 0x0a, 0xb4, 0x60, 0xa0, 0xbe, 0xc3, 0x97, 0x89, 0x42, 0x68,
0xec, 0x30, 0x24, 0x3a, 0xfd, 0x2f, 0xc6, 0x01, 0xf1, 0x39, 0xc8, 0x51, 0x12, 0x57, 0xb1, 0x47,
0xc2, 0xd4, 0x2a, 0x24, 0x2a, 0xbb, 0xdc, 0xea, 0x53, 0x83, 0x7e, 0x2e, 0x61, 0x35, 0x8d, 0x44,
0x65, 0x17, 0xfd, 0x04, 0x26, 0x29, 0x1a, 0xb5, 0xf5, 0xbc, 0x3f, 0x9f, 0xcc, 0xa1, 0x98, 0x1a,
0xf4, 0x73, 0x93, 0xe4, 0xc8, 0x8a, 0x0d, 0x86, 0x8c, 0x3e, 0x84, 0xd4, 0x2e, 0x6e, 0xe3, 0x96,
0xe9, 0xd9, 0xc2, 0x77, 0x68, 0x38, 0x6a, 0x0a, 0xa0, 0xb4, 0x44, 0x01, 0x26, 0x49, 0x1c, 0x06,
0x36, 0x5d, 0xbb, 0x23, 0x27, 0x0e, 0x87, 0x42, 0xe4, 0xc4, 0xc1, 0x70, 0xd0, 0xdf, 0x68, 0x30,
0x53, 0xe8, 0x74, 0x6c, 0x76, 0x13, 0xe1, 0xf2, 0xa3, 0xef, 0xca, 0x96, 0x7f, 0x73, 0x71, 0x68,
0x9e, 0xe2, 0x76, 0x9d, 0xe4, 0x6a, 0xb7, 0xf8, 0x25, 0x89, 0x3a, 0xff, 0xd1, 0xcf, 0x3d, 0x7e,
0x93, 0xcb, 0x90, 0xad, 0x9a, 0x63, 0x5a, 0x9e, 0x4b, 0x4f, 0x02, 0xc1, 0x84, 0xb2, 0x9b, 0x49,
0x72, 0xa0, 0x1f, 0xc0, 0x24, 0x39, 0x14, 0x8a, 0xfc, 0x43, 0x17, 0x9b, 0x9c, 0x1b, 0x95, 0xaa,
0x8b, 0x62, 0xe8, 0xf7, 0x21, 0xc5, 0x2d, 0x59, 0xd9, 0x8d, 0x5b, 0x02, 0xfd, 0x19, 0x3c, 0x30,
0x6c, 0x6a, 0x5d, 0xec, 0x62, 0xef, 0xc8, 0x74, 0xdd, 0xd7, 0xb6, 0xd3, 0xa4, 0x85, 0x31, 0x77,
0x49, 0xe1, 0xcd, 0xf7, 0x61, 0x9a, 0x82, 0x7d, 0x36, 0x74, 0x65, 0x68, 0x61, 0x6d, 0x88, 0x11,
0xbd, 0x04, 0x1b, 0x07, 0xd8, 0x1b, 0xe6, 0x75, 0x2b, 0x26, 0xbf, 0xd4, 0x20, 0x57, 0x72, 0x70,
0xa4, 0x50, 0x37, 0xdb, 0xca, 0x1b, 0xfc, 0x16, 0x28, 0x11, 0x8c, 0x12, 0xa3, 0xf3, 0x9b, 0x9e,
0xef, 0xc1, 0x78, 0xad, 0x76, 0x48, 0x5d, 0x67, 0x9c, 0x5a, 0x70, 0xdc, 0xf3, 0xda, 0xff, 0xdd,
0xcf, 0x25, 0x77, 0x7b, 0xec, 0x96, 0xc8, 0x20, 0xe3, 0xfa, 0x1c, 0xcc, 0x1c, 0x59, 0x9d, 0x16,
0x9f, 0x51, 0xff, 0xcb, 0x04, 0xcc, 0xb2, 0x6f, 0xb7, 0x6b, 0x77, 0x58, 0x94, 0x97, 0x63, 0x92,
0x76, 0x83, 0x98, 0x84, 0x3e, 0x82, 0x39, 0x7e, 0x88, 0xc2, 0x0e, 0x3d, 0x0a, 0x31, 0x09, 0xe9,
0xf1, 0x9f, 0x1d, 0xa3, 0x4e, 0x2e, 0xd9, 0x88, 0xa1, 0x22, 0xa2, 0x43, 0x98, 0x67, 0x80, 0x7d,
0x6c, 0x7a, 0xbd, 0xa0, 0xa6, 0x5a, 0xe0, 0x49, 0x50, 0x80, 0x99, 0x4b, 0x70, 0x5e, 0xaf, 0x38,
0xd0, 0x08, 0xd1, 0xa2, 0x27, 0xb0, 0x70, 0xe4, 0xd8, 0x5f, 0x5f, 0x49, 0x51, 0x98, 0xed, 0x8a,
0x15, 0x52, 0x82, 0x75, 0xc9, 0xd0, 0x89, 0x1c, 0x8b, 0xc3, 0xd8, 0xfa, 0xef, 0x13, 0x90, 0xf4,
0xb9, 0x6d, 0xc9, 0xa9, 0x92, 0xc7, 0x39, 0x1a, 0xfd, 0x83, 0x7a, 0xc6, 0x90, 0x30, 0xd0, 0x3a,
0x4d, 0x9e, 0x3c, 0xc2, 0x4e, 0x93, 0x05, 0x30, 0xbb, 0x5d, 0x83, 0xc0, 0x88, 0x9f, 0xee, 0x16,
0xa9, 0x6a, 0x49, 0xe6, 0xa7, 0xcd, 0x53, 0x23, 0xb1, 0x5b, 0x24, 0x2b, 0xfa, 0xa2, 0xb2, 0x5b,
0xa2, 0x52, 0x26, 0xd9, 0x8a, 0xda, 0x56, 0xb3, 0x61, 0x50, 0x28, 0x19, 0xad, 0x16, 0x9e, 0x1d,
0xd2, 0x5d, 0xca, 0x47, 0x5d, 0xf3, 0xa2, 0x6d, 0x50, 0x28, 0x7a, 0x2c, 0x22, 0x68, 0xc9, 0xee,
0x78, 0x8e, 0xdd, 0x76, 0xe9, 0x4d, 0x53, 0x52, 0x89, 0x94, 0x0d, 0x3e, 0x64, 0x84, 0x50, 0xd1,
0x4b, 0x58, 0x2b, 0x34, 0x2f, 0xcd, 0x4e, 0x03, 0x37, 0xd9, 0xc8, 0x4b, 0xdb, 0x39, 0x7f, 0xd5,
0xb6, 0x5f, 0xbb, 0xb4, 0x70, 0x4b, 0xf2, 0x12, 0x90, 0xa3, 0x9c, 0x70, 0x76, 0xaf, 0x05, 0x92,
0x11, 0x47, 0x8d, 0x72, 0x30, 0x59, 0x6a, 0xdb, 0xbd, 0x26, 0xad, 0xd8, 0x92, 0x6c, 0x23, 0x34,
0x08, 0xc0, 0x60, 0x70, 0xfd, 0xc7, 0xb0, 0x48, 0xa2, 0x97, 0x87, 0x6f, 0x9c, 0xc2, 0xf4, 0x23,
0x80, 0x2a, 0xbe, 0x30, 0xbb, 0x67, 0x36, 0x59, 0x96, 0xa2, 0xfc, 0xc5, 0x63, 0x3a, 0xf2, 0xcf,
0x90, 0x7c, 0xa0, 0xbe, 0x23, 0x12, 0xb5, 0xc0, 0x34, 0x24, 0x2a, 0xfd, 0x5f, 0x12, 0x80, 0x0a,
0xbd, 0xa6, 0xe5, 0x55, 0x3d, 0x07, 0x9b, 0x17, 0x42, 0x8c, 0x9f, 0xc2, 0x2c, 0xdb, 0xa1, 0x0c,
0x4c, 0xc5, 0x21, 0x09, 0x83, 0xf9, 0xa2, 0x3c, 0x54, 0x1e, 0x33, 0x14, 0x54, 0x42, 0x6a, 0x60,
0xb7, 0x77, 0x21, 0x48, 0x13, 0x0a, 0xa9, 0x3c, 0x44, 0x48, 0xe5, 0x6f, 0xf4, 0x04, 0xe6, 0x4b,
0xf6, 0x45, 0x97, 0xd8, 0x84, 0x13, 0x8f, 0xf3, 0xb0, 0xcc, 0xe7, 0x55, 0x06, 0xcb, 0x63, 0x46,
0x08, 0x1d, 0x3d, 0x87, 0xa5, 0xfd, 0x76, 0xcf, 0x3d, 0x2b, 0x74, 0x9a, 0xa5, 0xb6, 0xed, 0x0a,
0x2e, 0x13, 0xfc, 0x74, 0xc2, 0x77, 0xd2, 0x30, 0x46, 0x79, 0xcc, 0x88, 0x22, 0x44, 0xdf, 0xe3,
0xd7, 0xce, 0x3c, 0x3d, 0xcc, 0x6d, 0xf1, 0x5b, 0xe9, 0x17, 0x1d, 0xfc, 0xe2, 0x55, 0x79, 0xcc,
0x60, 0xa3, 0xc5, 0x14, 0x4c, 0x8b, 0x28, 0xb2, 0x0d, 0x8b, 0x92, 0x39, 0x49, 0x42, 0xeb, 0xb9,
0x28, 0x0b, 0xc9, 0xe3, 0x2e, 0x39, 0xde, 0x8a, 0xb0, 0x68, 0xf8, 0xdf, 0xfa, 0xfb, 0xaa, 0xa5,
0xd1, 0x86, 0x5c, 0x68, 0x31, 0xe4, 0x00, 0xa0, 0x97, 0x55, 0xe3, 0x8e, 0xc6, 0x56, 0xe6, 0x4d,
0x84, 0xe6, 0x4d, 0x87, 0x6d, 0xad, 0xaf, 0x44, 0x1a, 0x4f, 0xff, 0x85, 0x06, 0xcb, 0x07, 0xd8,
0xa3, 0x97, 0x55, 0x24, 0xc6, 0xf8, 0x09, 0xe3, 0x87, 0xf2, 0xbd, 0x25, 0xf3, 0xd7, 0xb9, 0x41,
0x3f, 0x97, 0xf2, 0x6f, 0x29, 0xe5, 0x9b, 0xc9, 0xc7, 0x30, 0x5f, 0x3d, 0xb7, 0xba, 0x75, 0xb3,
0x6d, 0x35, 0x69, 0x0c, 0xe6, 0xd1, 0x81, 0x45, 0xb3, 0x73, 0xab, 0x7b, 0x72, 0xe9, 0x0f, 0x19,
0x21, 0x54, 0xfd, 0x05, 0xac, 0x84, 0x24, 0xe0, 0x21, 0xfa, 0x0f, 0x60, 0x9a, 0x83, 0xb8, 0xfb,
0x0f, 0x5d, 0x78, 0xce, 0x0c, 0xfa, 0xb9, 0x69, 0x97, 0x93, 0x09, 0x64, 0xfd, 0x19, 0xac, 0x1e,
0x77, 0x5d, 0xec, 0x04, 0x3c, 0x85, 0x52, 0x3b, 0xfe, 0x0d, 0xaa, 0x16, 0x7d, 0x83, 0x0a, 0x83,
0x7e, 0x6e, 0x8a, 0x31, 0x14, 0xb7, 0xa6, 0x7a, 0x03, 0x56, 0xd9, 0x4e, 0x1e, 0x62, 0x77, 0x2b,
0x1b, 0x89, 0xbd, 0x9f, 0x88, 0xdc, 0xfb, 0x15, 0xc8, 0xf2, 0x49, 0xda, 0xed, 0xb7, 0x5b, 0x0c,
0xfd, 0x9f, 0x35, 0x58, 0x3b, 0xc0, 0x1d, 0xec, 0x98, 0x54, 0x64, 0x25, 0xf1, 0xca, 0xc7, 0x7f,
0x6d, 0xe4, 0xf1, 0x3f, 0x27, 0x4a, 0x95, 0x04, 0x2d, 0x55, 0x68, 0x80, 0xa3, 0xa5, 0x0a, 0x2f,
0x50, 0x48, 0x1a, 0x38, 0x36, 0x2a, 0xbc, 0x84, 0xa3, 0x69, 0xa0, 0xe7, 0x58, 0x06, 0x81, 0xa1,
0x4a, 0x70, 0x75, 0x30, 0x71, 0xed, 0xd5, 0xc1, 0x12, 0x3f, 0xf4, 0x4d, 0xf3, 0xab, 0x03, 0xe5,
0xc2, 0x40, 0x7f, 0x0c, 0x99, 0x61, 0x5d, 0xb8, 0x7f, 0xe4, 0x60, 0x92, 0xdd, 0x20, 0x0e, 0x15,
0x23, 0x0c, 0xae, 0xef, 0x06, 0xbe, 0xcd, 0xef, 0xcb, 0xfc, 0x2b, 0x93, 0xd0, 0xbe, 0x1a, 0x71,
0xdc, 0xd1, 0xab, 0x81, 0x7f, 0x72, 0x2e, 0x7c, 0xfe, 0x8f, 0x89, 0x7f, 0xb2, 0x3b, 0x51, 0x2d,
0xfe, 0x4e, 0x94, 0xfb, 0x28, 0x23, 0x15, 0x04, 0xfa, 0x4b, 0x58, 0x55, 0x98, 0x06, 0x5e, 0xff,
0x29, 0x24, 0x05, 0x2c, 0x54, 0xc9, 0x2b, 0x6c, 0xe9, 0xba, 0xb9, 0x82, 0xd8, 0x27, 0xd1, 0x7f,
0xa3, 0xc1, 0x1a, 0x0b, 0x39, 0xc3, 0x7a, 0xdf, 0x7c, 0xf5, 0xff, 0x2f, 0x8e, 0x78, 0x9f, 0x4f,
0x24, 0x13, 0xe9, 0x71, 0xbd, 0x0e, 0x99, 0x61, 0x79, 0xdf, 0x81, 0x85, 0x0f, 0x60, 0x4d, 0xda,
0xb6, 0x6f, 0xbd, 0xfe, 0xc1, 0x8c, 0xef, 0x70, 0xfd, 0x03, 0xc4, 0x77, 0xb6, 0xfe, 0x15, 0x58,
0x62, 0x8c, 0xd5, 0xbd, 0x92, 0x97, 0xf7, 0x4a, 0xe4, 0x6d, 0xfb, 0xf0, 0xf6, 0x79, 0x46, 0xb7,
0x8f, 0x40, 0x09, 0x24, 0xfc, 0x10, 0xa6, 0xf8, 0x73, 0x25, 0x93, 0x2f, 0x82, 0x19, 0x8d, 0xa3,
0xec, 0x8d, 0xd2, 0xe0, 0xc8, 0x7a, 0x86, 0xaa, 0x4c, 0x0a, 0x49, 0x7e, 0x73, 0x22, 0xc2, 0x9b,
0xfe, 0x05, 0x09, 0x58, 0xa1, 0x91, 0xb7, 0xcc, 0x01, 0x2f, 0x20, 0xc3, 0x72, 0x80, 0xc4, 0xf5,
0xad, 0xb2, 0xc0, 0x47, 0x90, 0x61, 0xee, 0x14, 0xc1, 0x70, 0x74, 0x68, 0xdf, 0x84, 0x0d, 0x3f,
0xb4, 0x47, 0x69, 0xff, 0x2b, 0x0d, 0xd6, 0x0f, 0xb0, 0xa7, 0xbe, 0xb9, 0xfc, 0x3f, 0xe4, 0xe1,
0x2f, 0x21, 0x1b, 0x25, 0x06, 0x5f, 0x88, 0xcf, 0xc2, 0x0b, 0x11, 0xfb, 0xbc, 0x14, 0xbd, 0x20,
0x3f, 0x87, 0x3b, 0x6c, 0x41, 0x54, 0x7c, 0xa1, 0xe6, 0xe3, 0xd0, 0x9a, 0xc4, 0x72, 0x8f, 0x5a,
0x9b, 0xbf, 0xd2, 0xe0, 0x0e, 0x33, 0x71, 0x34, 0xf3, 0x5b, 0xd9, 0xf0, 0x3e, 0x4c, 0x95, 0x6d,
0x72, 0xea, 0xe6, 0xcb, 0x49, 0xd5, 0x39, 0xb3, 0x5d, 0x8f, 0x84, 0x05, 0x3e, 0x34, 0xfa, 0xcd,
0x42, 0x7f, 0x0e, 0x39, 0x7f, 0xc5, 0xdf, 0xc1, 0xb2, 0xea, 0x0d, 0x40, 0x82, 0x4d, 0xa9, 0x6a,
0x08, 0x16, 0xeb, 0x30, 0x5e, 0xaa, 0x1a, 0xfc, 0xca, 0x9f, 0x26, 0xe0, 0x86, 0xeb, 0x18, 0x04,
0x16, 0x8e, 0xc6, 0x89, 0x9b, 0x5c, 0xb8, 0xfd, 0x31, 0x2c, 0x29, 0x93, 0xf0, 0x75, 0xdf, 0x80,
0x89, 0x12, 0x76, 0x3c, 0x3e, 0x0d, 0xd5, 0xb4, 0x81, 0x1d, 0xcf, 0xa0, 0x50, 0xf4, 0x00, 0xa6,
0x4b, 0x05, 0x7a, 0x21, 0x4c, 0xeb, 0x84, 0x59, 0x16, 0x96, 0x1a, 0xe6, 0x49, 0x83, 0x5e, 0x12,
0x8b, 0x41, 0xfd, 0xcf, 0x35, 0x89, 0x3b, 0x21, 0xbf, 0x5e, 0x87, 0x6d, 0x72, 0xfe, 0x21, 0x36,
0x93, 0x54, 0xa0, 0x29, 0x88, 0x9f, 0x8e, 0xa9, 0x06, 0x12, 0xca, 0x4d, 0x2f, 0x06, 0xbe, 0x84,
0x65, 0x55, 0x92, 0x77, 0xaa, 0xe8, 0x77, 0xe9, 0xb5, 0x25, 0xa9, 0x90, 0x84, 0x8a, 0x48, 0x3e,
0xf3, 0x71, 0x07, 0x79, 0x04, 0x69, 0x8e, 0x15, 0x6c, 0xb0, 0xfb, 0xa2, 0xe0, 0x62, 0xdb, 0x4b,
0x6d, 0x31, 0x10, 0xb7, 0x42, 0xdf, 0x17, 0xa7, 0xca, 0xeb, 0x66, 0x38, 0x87, 0xcc, 0xb3, 0xfd,
0x42, 0xa1, 0xe7, 0x9d, 0xe1, 0x8e, 0x67, 0x35, 0x4c, 0x0f, 0x97, 0xce, 0xcc, 0x76, 0x1b, 0x77,
0x5a, 0xd4, 0x50, 0xc7, 0xf9, 0x7d, 0x3f, 0xb9, 0xf0, 0x9b, 0xfd, 0xfc, 0xbe, 0x8f, 0x61, 0x90,
0x71, 0xf4, 0x10, 0x26, 0x6a, 0x2f, 0x6a, 0x47, 0xfc, 0x88, 0xb7, 0xcc, 0xf1, 0x08, 0x28, 0x40,
0xa4, 0x18, 0xfa, 0xd7, 0xb0, 0x16, 0x9a, 0xcc, 0xd7, 0xea, 0x81, 0x98, 0x4b, 0xa3, 0xc7, 0x57,
0x7f, 0x2e, 0x81, 0x50, 0x1e, 0x63, 0x93, 0xfd, 0x40, 0x99, 0x6c, 0x49, 0x9a, 0x4c, 0xc2, 0xa4,
0x28, 0xfc, 0x95, 0x93, 0xc2, 0xf4, 0x3f, 0x85, 0x59, 0x59, 0x70, 0x72, 0x62, 0x7a, 0x8a, 0xaf,
0xca, 0x66, 0xa7, 0xd9, 0x16, 0xf6, 0x08, 0x00, 0x64, 0xd4, 0x47, 0xe5, 0x47, 0xa6, 0x00, 0x80,
0x96, 0x61, 0xb2, 0xd0, 0xed, 0x56, 0x76, 0xd9, 0xa6, 0x36, 0xd8, 0x07, 0xca, 0xc0, 0xb4, 0xb8,
0xed, 0xa1, 0x45, 0x8d, 0x21, 0x3e, 0x75, 0x0b, 0x66, 0x24, 0x45, 0xae, 0x99, 0x7a, 0x13, 0xa0,
0xd4, 0xb6, 0x70, 0x87, 0x86, 0x3f, 0x3e, 0xb7, 0x04, 0xa1, 0x47, 0x3d, 0xab, 0xd5, 0xa1, 0x57,
0x32, 0x5c, 0x80, 0x00, 0xa0, 0x2f, 0xc0, 0x9c, 0x62, 0x77, 0x5d, 0x87, 0x59, 0xd9, 0x36, 0xc4,
0x05, 0x4a, 0x76, 0xd3, 0x77, 0x01, 0xf2, 0xb3, 0xfe, 0x6b, 0x0d, 0x96, 0x9f, 0xed, 0x17, 0x0c,
0xdc, 0xb2, 0x68, 0x07, 0x8c, 0xaf, 0xe8, 0xb6, 0xbc, 0x26, 0x77, 0xe4, 0x35, 0x09, 0x61, 0x8a,
0xc5, 0xc9, 0x2b, 0x8b, 0xb3, 0xa1, 0x2c, 0xce, 0x30, 0x09, 0x5b, 0x25, 0xe9, 0xd4, 0xfc, 0x4b,
0x0d, 0x96, 0x24, 0x41, 0x7c, 0xa1, 0xb7, 0x64, 0x39, 0xb2, 0xc3, 0x72, 0x84, 0x7d, 0xe4, 0xc7,
0x8a, 0x18, 0x77, 0x22, 0xc4, 0x18, 0xe9, 0x2b, 0x4d, 0x58, 0x8e, 0x52, 0x52, 0xf5, 0x0a, 0x2d,
0xd6, 0x2b, 0x12, 0x31, 0x5e, 0x31, 0xae, 0x7a, 0x85, 0x09, 0x4b, 0x11, 0x2a, 0xa0, 0xf7, 0x20,
0xcd, 0x60, 0x2c, 0x14, 0xf1, 0x7b, 0x7a, 0x42, 0x39, 0x04, 0xbf, 0xce, 0x57, 0xf4, 0xdf, 0x6a,
0xb0, 0x12, 0x69, 0x7c, 0xb4, 0x4a, 0xb2, 0x68, 0xc3, 0xc1, 0x1e, 0xe7, 0xcd, 0xbf, 0x08, 0xbc,
0xe2, 0xba, 0x3d, 0xde, 0x15, 0x97, 0x32, 0xf8, 0x17, 0xfa, 0x2e, 0xcc, 0x1d, 0x61, 0xc7, 0xb2,
0x9b, 0x55, 0xdc, 0xb0, 0x3b, 0x4d, 0x76, 0x2b, 0x39, 0x67, 0xa8, 0x40, 0x62, 0xa0, 0x42, 0xbb,
0x65, 0x3b, 0x96, 0x77, 0x76, 0xc1, 0x37, 0x41, 0x00, 0x20, 0xbc, 0x77, 0xad, 0x96, 0xe5, 0xb1,
0x5b, 0xf6, 0x39, 0x83, 0x7f, 0x11, 0x13, 0x15, 0x1a, 0x0d, 0xbb, 0xd7, 0xf1, 0xe8, 0x85, 0x5d,
0xca, 0x10, 0x9f, 0xfa, 0x7b, 0xb0, 0x1c, 0xb5, 0x68, 0x91, 0x4e, 0xfc, 0x8b, 0x04, 0x2c, 0x15,
0x9a, 0xcd, 0x67, 0xfb, 0x85, 0x5d, 0x2c, 0x97, 0x5c, 0x3f, 0x81, 0x89, 0x4a, 0xc7, 0xf2, 0xb8,
0xf3, 0x6c, 0x72, 0x5f, 0x88, 0xc0, 0x24, 0x58, 0xc4, 0x1d, 0xc8, 0xff, 0xc8, 0x80, 0xa5, 0xbd,
0xaf, 0x2d, 0xd7, 0xb3, 0x3a, 0x2d, 0xea, 0x90, 0x6c, 0x62, 0xee, 0x50, 0x82, 0x49, 0x4c, 0x28,
0x2b, 0x8f, 0x19, 0x51, 0xc4, 0xa8, 0x06, 0xab, 0xcf, 0xf1, 0xeb, 0x08, 0xff, 0xf6, 0x9f, 0xcd,
0x7d, 0xb6, 0x11, 0x6e, 0x1a, 0x43, 0x2b, 0x6f, 0x9f, 0x5f, 0x27, 0x60, 0x59, 0x55, 0x8c, 0xcf,
0x7c, 0x0c, 0xcb, 0x92, 0x40, 0xaa, 0x0f, 0xcf, 0xe4, 0x73, 0xd1, 0xea, 0xc8, 0x3b, 0x35, 0x92,
0x1c, 0xbd, 0x84, 0x35, 0x55, 0x28, 0x35, 0x66, 0x06, 0x3b, 0x2f, 0x0a, 0xa5, 0x3c, 0x66, 0xc4,
0x51, 0xa3, 0x3c, 0x8c, 0x17, 0x1a, 0xe7, 0xdc, 0x2c, 0xd1, 0x4b, 0xc6, 0x34, 0x2b, 0x34, 0xce,
0xc9, 0x9e, 0x2f, 0x34, 0xce, 0x95, 0x0d, 0xfc, 0xb7, 0x1a, 0xac, 0xc5, 0xac, 0x30, 0xd9, 0x33,
0x0c, 0x28, 0x65, 0x42, 0x09, 0x82, 0x3e, 0x95, 0xde, 0x14, 0xe6, 0xf3, 0x3f, 0x18, 0xed, 0x2f,
0x5b, 0x0c, 0x52, 0xf3, 0x1f, 0x1d, 0xf4, 0x9c, 0x60, 0x4f, 0x9f, 0x20, 0x92, 0x2c, 0x10, 0xb1,
0xf7, 0xe6, 0xe3, 0xfc, 0x7e, 0x5a, 0xd3, 0x4b, 0x61, 0xd1, 0x7c, 0x4d, 0xd0, 0x43, 0x98, 0x62,
0x40, 0xbe, 0x30, 0xa2, 0xfd, 0x2f, 0x40, 0xe6, 0xe3, 0xfa, 0xdf, 0x6b, 0xe2, 0xaa, 0x69, 0xc8,
0xdf, 0x1f, 0x29, 0xfe, 0x2e, 0x9e, 0xe3, 0xa3, 0x91, 0x15, 0x97, 0x2f, 0xc2, 0xcc, 0x9b, 0xb8,
0xba, 0x4c, 0x24, 0x3b, 0xe3, 0x3f, 0x68, 0xe2, 0x58, 0x3d, 0xec, 0x8f, 0x7b, 0x30, 0xfb, 0x66,
0x7e, 0xa8, 0x90, 0xa1, 0x0f, 0x99, 0x9b, 0x24, 0x46, 0x6b, 0x3a, 0xd2, 0x53, 0x3e, 0x11, 0xb7,
0x69, 0x6f, 0xe2, 0x2b, 0xfa, 0x46, 0x04, 0xb5, 0x3f, 0x9d, 0xbe, 0x4a, 0x4f, 0xc5, 0xfe, 0x90,
0x7f, 0x8c, 0x2b, 0xd1, 0x6b, 0x02, 0x19, 0xee, 0x87, 0xfe, 0x69, 0x0e, 0xf2, 0x5b, 0xb0, 0xc2,
0x0e, 0x20, 0x10, 0x88, 0x8b, 0xaf, 0x1f, 0xbb, 0xd8, 0xa9, 0x5a, 0x9d, 0x56, 0x1b, 0x1f, 0xb3,
0x12, 0xd5, 0x3f, 0x34, 0xfc, 0x48, 0x71, 0x82, 0xb5, 0x98, 0x9e, 0x8c, 0xff, 0xad, 0xa5, 0xff,
0x3b, 0x0d, 0xb2, 0x51, 0xb2, 0xbd, 0xdb, 0xd5, 0xdf, 0xe2, 0x65, 0x38, 0x93, 0x36, 0xc3, 0xc9,
0xfd, 0x39, 0x85, 0xb2, 0x44, 0x49, 0xf2, 0xbf, 0xb2, 0xec, 0xbf, 0xd1, 0x60, 0xb9, 0xe2, 0x52,
0xf1, 0xbf, 0xea, 0x59, 0x0e, 0x6e, 0x0a, 0xc3, 0x6d, 0x45, 0x75, 0xee, 0xd0, 0x85, 0x2f, 0x8f,
0x45, 0x75, 0xe6, 0xfc, 0x44, 0x6a, 0xb8, 0x48, 0x8c, 0x6a, 0xc9, 0x29, 0x8f, 0x05, 0x2d, 0x17,
0xe8, 0x01, 0x4c, 0x3c, 0x27, 0xf9, 0x6b, 0x9c, 0x6f, 0x73, 0x46, 0x41, 0x40, 0x87, 0x76, 0xcb,
0xea, 0x10, 0x91, 0xc9, 0x47, 0x31, 0x09, 0x53, 0x35, 0xd3, 0x69, 0x61, 0x4f, 0xff, 0x10, 0x52,
0xfe, 0x30, 0x2d, 0xe3, 0xa5, 0xf4, 0x47, 0x7e, 0x26, 0xd5, 0x07, 0x1d, 0x14, 0xd5, 0x07, 0xfd,
0xd0, 0x77, 0x60, 0x25, 0xa4, 0x26, 0x5f, 0x83, 0x2c, 0x31, 0x06, 0x83, 0xb1, 0x87, 0x3c, 0xc3,
0xff, 0xd6, 0x4b, 0xb0, 0x38, 0x64, 0x45, 0x84, 0xa4, 0xde, 0x34, 0xb2, 0x91, 0xaa, 0xd5, 0x32,
0x81, 0xf9, 0xad, 0x68, 0x04, 0x56, 0x3b, 0xac, 0x16, 0xa7, 0xd8, 0xaa, 0x90, 0x5c, 0x44, 0x4e,
0x2e, 0xf4, 0x61, 0xc4, 0x0d, 0xae, 0x3f, 0xc2, 0x67, 0x59, 0xf9, 0x3c, 0x5d, 0x84, 0x54, 0xd5,
0x33, 0xe9, 0xb9, 0x5f, 0x18, 0x73, 0xd4, 0x75, 0x70, 0xf2, 0x9b, 0x7e, 0x6e, 0x8c, 0xde, 0x01,
0x07, 0x64, 0xe8, 0x33, 0x98, 0xde, 0xeb, 0x34, 0x29, 0x87, 0xf1, 0x5b, 0x70, 0x10, 0x44, 0x64,
0xc7, 0x53, 0x91, 0x49, 0xf4, 0x76, 0x69, 0x23, 0x61, 0xca, 0x90, 0x20, 0xd4, 0xcc, 0xd6, 0x85,
0xc5, 0x5e, 0x82, 0x26, 0x0d, 0xf6, 0x41, 0xac, 0x49, 0x45, 0x78, 0x8a, 0xaf, 0x78, 0x09, 0xe3,
0x7f, 0xeb, 0xbf, 0xa3, 0x97, 0xec, 0x1e, 0xbf, 0x76, 0x53, 0xed, 0xa1, 0x68, 0xac, 0xbd, 0xb5,
0xc6, 0x89, 0x37, 0xd1, 0xd8, 0xd7, 0x68, 0x3c, 0x4e, 0xa3, 0x89, 0x90, 0x46, 0x07, 0x30, 0xc5,
0xd4, 0x20, 0x27, 0xd1, 0x8a, 0x87, 0x2f, 0x82, 0x93, 0xa8, 0xfc, 0x2e, 0x66, 0xb0, 0x31, 0x52,
0xde, 0x1d, 0x9a, 0x2e, 0xe5, 0xc4, 0x7c, 0x53, 0x7c, 0xbe, 0xf7, 0x1e, 0xa4, 0xfc, 0xdf, 0xd8,
0x20, 0xa9, 0xb2, 0xf2, 0xbc, 0x52, 0x63, 0xa9, 0xf2, 0xe8, 0xb8, 0x96, 0xd6, 0x10, 0xc0, 0xd4,
0xee, 0xde, 0xe1, 0x5e, 0x6d, 0x2f, 0x9d, 0xc8, 0xff, 0xd3, 0x23, 0x98, 0x21, 0x71, 0x81, 0xdf,
0x89, 0xa1, 0x4f, 0x60, 0xbe, 0x8a, 0x3b, 0xcd, 0xa7, 0x18, 0x77, 0x0b, 0x6d, 0xeb, 0x12, 0xbb,
0x48, 0x04, 0x4b, 0x1f, 0x94, 0x5d, 0x1d, 0xb2, 0xc4, 0xde, 0x45, 0xd7, 0xbb, 0x7a, 0xa8, 0xa1,
0x1f, 0xc2, 0x0c, 0x6d, 0x0b, 0xe5, 0x7a, 0xcc, 0xca, 0xad, 0xa2, 0x59, 0xf1, 0x45, 0x07, 0x3f,
0xd0, 0xd0, 0xa7, 0x30, 0x7d, 0x80, 0x3d, 0xba, 0xcb, 0xbe, 0x13, 0xfa, 0x25, 0x91, 0x4a, 0xc7,
0x77, 0x5f, 0xbe, 0xa6, 0xd9, 0xf0, 0x1d, 0x21, 0x2a, 0x41, 0x92, 0x93, 0xbb, 0x48, 0x0f, 0xd1,
0xbb, 0x11, 0x0c, 0x96, 0x42, 0x0c, 0x0e, 0x2d, 0xd7, 0x43, 0xdb, 0x00, 0xec, 0x52, 0x8c, 0x8a,
0x11, 0x9e, 0x23, 0x3b, 0xa4, 0x3b, 0x3a, 0x20, 0xa9, 0x8b, 0xa4, 0xa6, 0x9b, 0xca, 0x1d, 0x63,
0x2c, 0x74, 0x08, 0xf3, 0xfe, 0x15, 0xd5, 0xcd, 0x95, 0x88, 0xe3, 0xf6, 0x31, 0x2c, 0x8a, 0x57,
0x1a, 0x3f, 0x1b, 0xa1, 0xb8, 0xfc, 0xe4, 0xaf, 0x04, 0x43, 0xc3, 0x90, 0x95, 0x69, 0xd5, 0xec,
0x82, 0xee, 0x49, 0x4c, 0x22, 0x93, 0x62, 0xf6, 0x3b, 0x23, 0x30, 0x58, 0x58, 0x7c, 0xa8, 0x7d,
0xa0, 0xa1, 0xcf, 0x61, 0x4e, 0x89, 0x99, 0x48, 0x54, 0xb1, 0x51, 0x09, 0x23, 0xbb, 0x11, 0x3d,
0xc8, 0xc3, 0xec, 0x3e, 0x51, 0xd7, 0x0b, 0x75, 0x7a, 0x65, 0xa3, 0x3a, 0xba, 0x58, 0xf3, 0x70,
0x56, 0x3c, 0x71, 0x87, 0x48, 0xf6, 0x60, 0x89, 0x3f, 0x7d, 0x28, 0xbf, 0x80, 0x10, 0xd3, 0x1b,
0x16, 0x6b, 0xfd, 0x27, 0xb0, 0xc4, 0xd7, 0x52, 0x61, 0x93, 0xf6, 0x1f, 0xe5, 0x79, 0x1b, 0x51,
0x2c, 0x83, 0xcf, 0x61, 0xa5, 0x1a, 0xd2, 0x87, 0x35, 0x6b, 0xad, 0xab, 0x2c, 0xa4, 0xae, 0xb0,
0x58, 0x5e, 0x4f, 0x01, 0x55, 0x7b, 0xa7, 0x17, 0x96, 0xcf, 0xee, 0xd2, 0xc2, 0xaf, 0xd1, 0xdd,
0x90, 0x4a, 0x04, 0x48, 0xd1, 0x68, 0xf8, 0xcc, 0xc6, 0x68, 0x8c, 0x6a, 0xec, 0xe9, 0x8d, 0xf5,
0x74, 0x98, 0x5d, 0xf3, 0xd4, 0x6a, 0x5b, 0x9e, 0x85, 0x89, 0x5b, 0xc8, 0x04, 0xf2, 0x90, 0x58,
0xc1, 0xf5, 0x58, 0x0c, 0xf4, 0x19, 0xcc, 0x1d, 0x60, 0x2f, 0x68, 0x7c, 0x43, 0x6b, 0x43, 0xad,
0x72, 0x7c, 0xdd, 0xc4, 0xa5, 0x97, 0xda, 0x6d, 0x57, 0x81, 0xf4, 0x71, 0xb7, 0x69, 0x7a, 0x58,
0x62, 0x71, 0x77, 0x88, 0x05, 0x47, 0x31, 0x1d, 0xf3, 0xc2, 0x8d, 0xb5, 0xd6, 0x36, 0x4c, 0x1c,
0x59, 0x9d, 0x16, 0x12, 0x37, 0x63, 0x52, 0xcb, 0x52, 0x76, 0x49, 0x81, 0x71, 0xd7, 0xf3, 0x20,
0x77, 0x4d, 0xc7, 0x17, 0xfa, 0x91, 0x5f, 0xaa, 0xdc, 0xa4, 0x33, 0x2c, 0x2b, 0xed, 0xfb, 0x68,
0xc4, 0xfa, 0x0e, 0xfa, 0x19, 0x5d, 0x87, 0x61, 0x0c, 0x74, 0x9f, 0xcf, 0x35, 0xaa, 0x6d, 0x2c,
0x7b, 0x27, 0x76, 0x86, 0xfa, 0x0e, 0x3a, 0x11, 0xcf, 0x7f, 0x11, 0xdc, 0x1f, 0x28, 0x1d, 0x29,
0x6f, 0x38, 0xc1, 0x36, 0x8d, 0xf3, 0xf4, 0x97, 0xb8, 0x56, 0x02, 0x69, 0xa5, 0xae, 0x9c, 0xac,
0xfa, 0x6b, 0x60, 0x68, 0x87, 0x46, 0x76, 0xda, 0x0b, 0x8a, 0x56, 0x55, 0x0a, 0x37, 0x9a, 0xe4,
0x03, 0x0d, 0xed, 0x00, 0x30, 0x29, 0xe9, 0x44, 0xea, 0x70, 0xec, 0xea, 0xef, 0x90, 0xf0, 0xdf,
0xbc, 0x25, 0xd1, 0x67, 0x22, 0x05, 0x50, 0xa2, 0x8c, 0x72, 0x3e, 0x92, 0xb5, 0x8a, 0xa3, 0xaf,
0x40, 0xba, 0xd0, 0xa0, 0x01, 0xcd, 0x6f, 0x14, 0x42, 0x9b, 0xfe, 0x66, 0x51, 0x07, 0x04, 0xaf,
0x95, 0x70, 0xdf, 0xd1, 0x21, 0x26, 0x05, 0x6f, 0x19, 0xd6, 0xfc, 0xd4, 0x14, 0x1a, 0x8a, 0xa6,
0x88, 0x15, 0x6a, 0x0f, 0x96, 0x4b, 0x66, 0xa7, 0x81, 0xdb, 0x6f, 0xc7, 0xe6, 0x63, 0xba, 0xb3,
0xa5, 0x26, 0xaa, 0xd5, 0x30, 0x3d, 0xdf, 0xd8, 0xa2, 0xf9, 0x5c, 0x42, 0x2d, 0xc0, 0x02, 0x33,
0x62, 0x60, 0x96, 0x38, 0xea, 0xb8, 0xe9, 0x1f, 0xc1, 0xfc, 0x1e, 0x89, 0x7c, 0xbd, 0xa6, 0xc5,
0x4a, 0x64, 0xa4, 0xd6, 0x4e, 0xb1, 0x84, 0x65, 0x58, 0xe4, 0x89, 0x20, 0xe8, 0x2e, 0xf2, 0x83,
0xef, 0x70, 0x03, 0x57, 0x76, 0x59, 0xb0, 0x95, 0x1b, 0x91, 0x44, 0x9a, 0x53, 0x9a, 0x69, 0xfc,
0x34, 0x17, 0xd5, 0xe4, 0xe3, 0xa7, 0xb9, 0xe8, 0xfe, 0x9b, 0x22, 0x2c, 0x84, 0xfa, 0x68, 0xd0,
0x5d, 0x91, 0x6c, 0x23, 0xfb, 0x6b, 0x22, 0x0a, 0x96, 0xb2, 0xb0, 0xea, 0x30, 0x8f, 0xe8, 0xa6,
0x9a, 0x58, 0x1b, 0x1d, 0xf9, 0x59, 0x4e, 0xee, 0x90, 0x41, 0xea, 0x05, 0x41, 0x54, 0xf7, 0x4c,
0x2c, 0xc7, 0x2a, 0x39, 0xcb, 0xa8, 0xbd, 0x25, 0x68, 0xd3, 0xb7, 0x48, 0x64, 0x03, 0x4d, 0x36,
0x17, 0x3b, 0xce, 0x8d, 0x26, 0x2d, 0x00, 0xfb, 0x55, 0xb7, 0xf0, 0x02, 0xc8, 0x9d, 0x08, 0x43,
0x0b, 0xa0, 0x36, 0x18, 0x1c, 0xd0, 0xc7, 0x24, 0xa9, 0x49, 0x04, 0xc5, 0xa8, 0x92, 0xbd, 0x1b,
0xc5, 0x27, 0x58, 0xc9, 0x2a, 0xa4, 0xc3, 0x3d, 0x16, 0xbe, 0xa6, 0x31, 0xcd, 0x22, 0xbe, 0xa6,
0xb1, 0xcd, 0x19, 0x9f, 0x43, 0x3a, 0xdc, 0x60, 0xe1, 0x33, 0x8d, 0xe9, 0xbc, 0x88, 0x5d, 0x8a,
0x7d, 0x58, 0x56, 0x17, 0xf0, 0x1a, 0x7d, 0xe3, 0x2b, 0x99, 0x39, 0xa5, 0xad, 0x02, 0x89, 0xd4,
0x10, 0xea, 0xe0, 0x18, 0xb2, 0x7e, 0x44, 0x7b, 0x07, 0xb3, 0xbe, 0xd4, 0xa2, 0x71, 0x13, 0xeb,
0x47, 0x75, 0x74, 0xf8, 0x86, 0x92, 0xe4, 0x12, 0x11, 0x37, 0x3c, 0x70, 0x1b, 0x43, 0xdd, 0x44,
0xb4, 0x38, 0x3e, 0xbb, 0x30, 0x23, 0xf5, 0x76, 0xa0, 0x75, 0xc5, 0x4c, 0x8a, 0xc7, 0x67, 0x15,
0xe5, 0x54, 0x67, 0x2f, 0xc1, 0xac, 0xdc, 0x21, 0x12, 0x2b, 0xc5, 0x9d, 0x61, 0x1e, 0xae, 0x54,
0x4d, 0xcf, 0xfb, 0x56, 0x60, 0xd2, 0x6c, 0x84, 0x8d, 0xa3, 0x08, 0x14, 0xaf, 0x12, 0x92, 0x4d,
0x73, 0x8d, 0x48, 0xf1, 0x99, 0x68, 0x89, 0xe5, 0x64, 0xf5, 0x97, 0x6c, 0x63, 0x7e, 0x57, 0x77,
0x44, 0xb4, 0x5a, 0x08, 0xb5, 0xb4, 0x20, 0xc9, 0x4b, 0x22, 0xda, 0x40, 0xb2, 0x9b, 0x71, 0xc3,
0xdc, 0x4c, 0x87, 0xb0, 0x38, 0xd4, 0xd1, 0x82, 0x72, 0x4a, 0x3c, 0x1e, 0x6e, 0x4d, 0x19, 0x71,
0xfe, 0x5b, 0x1c, 0x6a, 0x67, 0xf1, 0xb9, 0xc5, 0x35, 0xba, 0xc4, 0x72, 0xab, 0xc1, 0x4a, 0x64,
0x8b, 0x8b, 0x5f, 0x1f, 0x8e, 0x6a, 0x80, 0x89, 0xe5, 0xfa, 0x33, 0x40, 0xc3, 0x0d, 0x29, 0xfe,
0x89, 0x30, 0xb6, 0x65, 0xc6, 0x3f, 0x11, 0x8e, 0xe8, 0x66, 0x39, 0x84, 0xe5, 0xa8, 0x6e, 0x14,
0xa4, 0x2b, 0xf6, 0x8c, 0xec, 0x26, 0x89, 0x48, 0x72, 0x86, 0xd8, 0x94, 0x31, 0xdc, 0x46, 0xf4,
0xa6, 0xc4, 0x2a, 0xff, 0x73, 0xd1, 0x6f, 0x34, 0xdc, 0x43, 0xe2, 0xd7, 0xc5, 0xd7, 0x34, 0x99,
0x8c, 0x28, 0x37, 0x16, 0xaa, 0x56, 0xab, 0x23, 0xb5, 0x7b, 0xf8, 0xc5, 0xc6, 0x70, 0x9f, 0x89,
0x1f, 0x00, 0xa2, 0xba, 0x43, 0x5e, 0xc0, 0xb2, 0xc8, 0x84, 0x72, 0x53, 0x05, 0x1a, 0xa2, 0x09,
0x7a, 0x3e, 0xfc, 0x60, 0x10, 0xd9, 0x85, 0xc1, 0xaa, 0x75, 0xfa, 0x97, 0x13, 0xa4, 0x6a, 0x5d,
0xea, 0x76, 0xc8, 0xaa, 0x8d, 0x11, 0xe8, 0x31, 0xad, 0xd6, 0x59, 0x4b, 0x6a, 0xdc, 0x5e, 0x5f,
0x53, 0x39, 0x05, 0x6e, 0xb0, 0x23, 0xee, 0x5f, 0xe8, 0x84, 0x2a, 0xe7, 0xeb, 0x0b, 0x70, 0x4a,
0xa4, 0x16, 0xe0, 0xb2, 0xa0, 0xf1, 0x27, 0xe4, 0x59, 0xf9, 0xa9, 0xc8, 0xb7, 0x55, 0xc4, 0x63,
0x94, 0x6f, 0xab, 0xa8, 0xb7, 0x25, 0x5a, 0xef, 0xd5, 0x44, 0x7d, 0x15, 0xf0, 0xbb, 0x3b, 0xf2,
0x71, 0x28, 0xbb, 0x39, 0xfa, 0x45, 0x45, 0xaa, 0x22, 0x83, 0xb7, 0x0c, 0xb9, 0x88, 0x19, 0x7a,
0xf9, 0x90, 0xd3, 0x68, 0xc4, 0xf3, 0xc7, 0x33, 0x7a, 0x63, 0xfc, 0xa2, 0xb2, 0x5b, 0xe2, 0x7f,
0xc1, 0xc1, 0x76, 0x86, 0x2e, 0xae, 0xa4, 0xdf, 0xa1, 0x0b, 0xac, 0xc7, 0x50, 0x14, 0xc2, 0x7a,
0x1e, 0x55, 0xe9, 0xdd, 0x8b, 0x02, 0x8d, 0xb8, 0xbb, 0x8a, 0x60, 0x98, 0x8d, 0x66, 0x48, 0xef,
0xe1, 0x68, 0xd0, 0x27, 0x7e, 0xa0, 0x8a, 0x19, 0x23, 0xc3, 0xa8, 0xdc, 0xc1, 0xac, 0x1a, 0xcd,
0x46, 0x48, 0x77, 0x9d, 0x83, 0x30, 0x8b, 0x55, 0x0b, 0xcf, 0x0e, 0xdf, 0xc8, 0x62, 0x0a, 0xa1,
0x6f, 0x31, 0x05, 0x7a, 0x3b, 0x8b, 0x85, 0x18, 0xaa, 0x16, 0x53, 0xc5, 0x8c, 0x91, 0xe1, 0x7a,
0x8b, 0x45, 0xb3, 0xb9, 0xa9, 0xc5, 0xbe, 0xa0, 0x99, 0xe2, 0x80, 0xfe, 0xfe, 0xde, 0xad, 0x6c,
0x96, 0x11, 0x75, 0x8f, 0x4a, 0x5a, 0xdf, 0x41, 0x2f, 0x69, 0x1f, 0x6d, 0x08, 0x7e, 0x33, 0xbb,
0x6d, 0xc4, 0x31, 0xa5, 0x96, 0xab, 0xc0, 0x0a, 0xb3, 0x5c, 0x58, 0xdc, 0x58, 0x59, 0x62, 0xd5,
0x3e, 0x10, 0x69, 0x37, 0xcc, 0xea, 0xb6, 0xf6, 0xdb, 0xa5, 0x2e, 0x52, 0x73, 0x48, 0x55, 0xd3,
0x1c, 0x2e, 0x79, 0x54, 0x26, 0xe2, 0xb6, 0x4c, 0x45, 0xaf, 0xe7, 0x51, 0x85, 0xae, 0x82, 0x0a,
0x1e, 0x55, 0x13, 0x46, 0xb3, 0xa1, 0x46, 0x2a, 0x8b, 0xfc, 0x1c, 0x92, 0x29, 0x6e, 0xee, 0x78,
0xa1, 0xfc, 0x82, 0xf9, 0x86, 0xda, 0xc5, 0x99, 0x88, 0xe5, 0x19, 0x56, 0x9f, 0x5e, 0x67, 0x99,
0xf0, 0xdf, 0x56, 0x42, 0x7f, 0x08, 0x29, 0x41, 0x7c, 0xbd, 0x41, 0xc2, 0xd4, 0xd4, 0x20, 0x9f,
0xc1, 0x0c, 0x37, 0x08, 0x95, 0x20, 0x6e, 0xa6, 0x58, 0xf1, 0x3f, 0x85, 0x19, 0x6e, 0x86, 0x91,
0x1a, 0xc4, 0x91, 0xd7, 0x69, 0x6f, 0x70, 0xdc, 0xdf, 0x3e, 0x89, 0xd3, 0xe8, 0xda, 0xbf, 0xbc,
0x42, 0xf8, 0x56, 0xe3, 0xf9, 0x5e, 0x4b, 0x3f, 0xa2, 0x20, 0x5d, 0x0f, 0x5e, 0xe7, 0x42, 0x7f,
0x26, 0x25, 0x56, 0xdc, 0xeb, 0xfe, 0x42, 0x0b, 0xe1, 0x5a, 0x8d, 0xe5, 0x7a, 0x1d, 0xf5, 0xa8,
0x18, 0x48, 0x2f, 0x2e, 0x0b, 0x3d, 0xef, 0xec, 0xc8, 0xc1, 0xaf, 0xb0, 0x83, 0x3b, 0x0d, 0x7c,
0xeb, 0x83, 0xcb, 0x0e, 0xf5, 0x31, 0xfe, 0xf4, 0x25, 0x55, 0x3c, 0xca, 0xdb, 0x64, 0x76, 0x4e,
0x7e, 0x05, 0x73, 0x51, 0x81, 0xa5, 0x1a, 0xf9, 0x15, 0x53, 0xba, 0x02, 0x89, 0x7c, 0xde, 0x0c,
0xb1, 0x28, 0xa6, 0xbf, 0xf9, 0xaf, 0x4d, 0xed, 0x9b, 0x6f, 0x37, 0xb5, 0x7f, 0xfd, 0x76, 0x53,
0xfb, 0xfd, 0xb7, 0x9b, 0xda, 0xe9, 0x14, 0x1d, 0xdf, 0xf9, 0x9f, 0x00, 0x00, 0x00, 0xff, 0xff,
0xe1, 0x19, 0xce, 0xd8, 0x05, 0x4f, 0x00, 0x00,
0x33, 0x3b, 0x2b, 0xcd, 0x52, 0x33, 0xf1, 0xec, 0x7c, 0x39, 0x24, 0xf5, 0x41, 0x8e, 0x65, 0x5b,
0xd3, 0xa4, 0xe8, 0xec, 0x66, 0x00, 0xa5, 0x45, 0x3e, 0x53, 0x0d, 0x51, 0x6c, 0x4e, 0x77, 0x53,
0x1e, 0xe5, 0x94, 0x04, 0x9b, 0x4d, 0x90, 0x20, 0x40, 0x2e, 0x39, 0xe4, 0x94, 0x00, 0xb9, 0xef,
0x29, 0xd7, 0x05, 0x72, 0x1c, 0x04, 0x08, 0x36, 0xc8, 0x25, 0x40, 0x0e, 0xcc, 0x66, 0x8e, 0xfc,
0x09, 0x39, 0x05, 0xef, 0xab, 0xfb, 0xbd, 0x66, 0x37, 0x25, 0xd9, 0x4e, 0x72, 0xb1, 0xd5, 0xf5,
0xaa, 0xea, 0x55, 0xd5, 0xab, 0x57, 0x55, 0xef, 0xbd, 0x92, 0x60, 0xd1, 0xec, 0x79, 0x67, 0x2e,
0x76, 0x2e, 0xad, 0x06, 0xde, 0xea, 0x3a, 0xb6, 0x67, 0xa3, 0x49, 0xfa, 0x5f, 0x76, 0xb9, 0x65,
0xb7, 0x6c, 0xfa, 0xe3, 0x36, 0xf9, 0x89, 0x0d, 0x66, 0xef, 0xb4, 0x6c, 0xbb, 0xd5, 0xc6, 0xdb,
0xf4, 0xeb, 0xb4, 0xf7, 0x72, 0x1b, 0x5f, 0x74, 0xbd, 0x2b, 0x3e, 0x98, 0x0b, 0x0f, 0x7a, 0xd6,
0x05, 0x76, 0x3d, 0xf3, 0xa2, 0xcb, 0x11, 0x1e, 0xb5, 0x2c, 0xef, 0xac, 0x77, 0xba, 0xd5, 0xb0,
0x2f, 0xb6, 0x5b, 0x8e, 0x79, 0x69, 0x79, 0xa6, 0x67, 0xd9, 0x1d, 0xb3, 0xbd, 0xed, 0xe1, 0x36,
0xee, 0xda, 0x8e, 0xb7, 0x6d, 0x76, 0xad, 0x6d, 0xef, 0xaa, 0x8b, 0x5d, 0xf6, 0x2f, 0x27, 0x2c,
0xdd, 0x86, 0xf0, 0x95, 0x63, 0x76, 0xbb, 0xd8, 0x09, 0x7e, 0xe0, 0x4c, 0x1e, 0xdf, 0x86, 0x09,
0xbe, 0xc4, 0x1d, 0x4f, 0xfc, 0xc7, 0x18, 0xe8, 0xff, 0x36, 0x0f, 0x93, 0x7b, 0x04, 0x80, 0x3e,
0x82, 0x89, 0xda, 0x55, 0x17, 0x67, 0xb4, 0x7b, 0xda, 0xc3, 0xf9, 0x7c, 0x9a, 0x8d, 0x6f, 0x3d,
0xef, 0x62, 0x87, 0xb2, 0x2c, 0xa2, 0x41, 0x3f, 0x37, 0x4f, 0x18, 0xbd, 0x67, 0x5f, 0x58, 0x1e,
0xb5, 0x91, 0x41, 0x29, 0xd0, 0x0b, 0x98, 0x37, 0xb0, 0x6b, 0xf7, 0x9c, 0x06, 0x2e, 0x63, 0xb3,
0x89, 0x9d, 0x4c, 0xe2, 0x9e, 0xf6, 0x70, 0x26, 0xbf, 0xb2, 0xc5, 0xf4, 0x55, 0x07, 0x8b, 0xab,
0x83, 0x7e, 0x0e, 0x39, 0x1c, 0x16, 0x30, 0x2b, 0x8f, 0x19, 0x21, 0x36, 0xe8, 0x2b, 0x98, 0x2b,
0x61, 0xc7, 0x2b, 0xf4, 0xbc, 0x33, 0xdb, 0xb1, 0xbc, 0xab, 0xcc, 0x38, 0xe5, 0xbb, 0xca, 0xf9,
0x2a, 0x63, 0xf5, 0x7c, 0x71, 0x63, 0xd0, 0xcf, 0x65, 0x1a, 0xd8, 0xf1, 0x4e, 0x4c, 0x01, 0x55,
0xd8, 0xab, 0xcc, 0xd0, 0xef, 0xc1, 0x6c, 0x95, 0x98, 0xab, 0x51, 0xb3, 0xcf, 0x71, 0xc7, 0xcd,
0x4c, 0x28, 0x42, 0xcb, 0x43, 0xf5, 0x7c, 0xf1, 0xce, 0xa0, 0x9f, 0x5b, 0x73, 0x29, 0xec, 0xc4,
0xa3, 0x40, 0x85, 0xb5, 0xc2, 0x09, 0xfd, 0x01, 0xcc, 0x1f, 0x39, 0xf6, 0xa5, 0xe5, 0x5a, 0x76,
0x87, 0x82, 0x32, 0x93, 0x94, 0xf7, 0x1a, 0xe7, 0xad, 0x0e, 0xd6, 0xf3, 0xc5, 0xbb, 0x83, 0x7e,
0x6e, 0xbd, 0x2b, 0xa0, 0x6c, 0x02, 0xd5, 0x32, 0x2a, 0x09, 0xaa, 0xc1, 0x4c, 0xa9, 0xdd, 0x73,
0x3d, 0xec, 0x3c, 0x33, 0x2f, 0x70, 0x66, 0x8a, 0xb2, 0x5f, 0x16, 0x76, 0x09, 0x46, 0xea, 0xf9,
0x62, 0x76, 0xd0, 0xcf, 0xad, 0x36, 0x18, 0xe8, 0xa4, 0x63, 0x5e, 0xa8, 0x26, 0x97, 0xd9, 0x50,
0x7b, 0xb3, 0xcf, 0x92, 0xdd, 0x79, 0x69, 0xb5, 0x32, 0xd3, 0xaa, 0xbd, 0xe5, 0xb1, 0xfa, 0x0e,
0xb7, 0x37, 0xe7, 0xdc, 0xa0, 0xd0, 0x90, 0xbd, 0x65, 0x02, 0xf4, 0x08, 0x26, 0x8e, 0x5d, 0xec,
0x64, 0x92, 0x94, 0xe9, 0x1c, 0x67, 0x4a, 0x40, 0xf5, 0x3c, 0xf3, 0xae, 0x9e, 0x8b, 0x1d, 0x85,
0x03, 0x25, 0x20, 0x84, 0x86, 0xdd, 0xc6, 0x99, 0x94, 0x42, 0x48, 0x40, 0xf5, 0x1d, 0x46, 0xe8,
0xd8, 0x6d, 0x55, 0x2d, 0x4a, 0x80, 0x2a, 0x90, 0x22, 0x7a, 0xb9, 0x5d, 0xb3, 0x81, 0x33, 0x40,
0xa9, 0xd3, 0x9c, 0xda, 0x87, 0x17, 0xd7, 0x06, 0xfd, 0xdc, 0x52, 0x47, 0x7c, 0x2a, 0x5c, 0x02,
0x6a, 0xf4, 0x18, 0xa6, 0xaa, 0xd8, 0xb9, 0xc4, 0x4e, 0x66, 0x86, 0xf2, 0x59, 0x10, 0x6e, 0x42,
0x81, 0xf5, 0x7c, 0x71, 0x79, 0xd0, 0xcf, 0xa5, 0x5d, 0xfa, 0xa5, 0xf0, 0xe0, 0x64, 0xc4, 0xb6,
0x06, 0xbe, 0xc4, 0x8e, 0x8b, 0x6b, 0xbd, 0x4e, 0x07, 0xb7, 0x33, 0xb3, 0x8a, 0x6d, 0x95, 0x31,
0xe1, 0xcb, 0x0e, 0x03, 0x9e, 0x78, 0x14, 0xaa, 0xda, 0x56, 0x21, 0x40, 0x67, 0x90, 0x66, 0x3f,
0x95, 0xec, 0x4e, 0x07, 0x37, 0xc8, 0x86, 0xcd, 0xcc, 0xd1, 0x09, 0xd6, 0xf9, 0x04, 0xe1, 0xe1,
0x7a, 0xbe, 0x98, 0x1b, 0xf4, 0x73, 0x77, 0x18, 0x6f, 0xb2, 0x7c, 0x7c, 0x40, 0x99, 0x66, 0x88,
0x2b, 0xd1, 0xa3, 0xd0, 0x68, 0x60, 0xd7, 0x35, 0xf0, 0xd7, 0x3d, 0xec, 0x7a, 0x99, 0x79, 0x45,
0x0f, 0x65, 0x4c, 0xf8, 0x88, 0x49, 0x81, 0x27, 0x0e, 0x83, 0xaa, 0x7a, 0x28, 0x04, 0xe8, 0x08,
0xa0, 0xd0, 0xed, 0x56, 0xb1, 0x4b, 0x5c, 0x3d, 0xb3, 0x40, 0x59, 0x2f, 0x71, 0xd6, 0x2f, 0xf0,
0x29, 0x1f, 0xa8, 0xe7, 0x8b, 0xeb, 0x83, 0x7e, 0x6e, 0xc5, 0xec, 0x76, 0x4f, 0x5c, 0x06, 0x52,
0x98, 0x4a, 0x3c, 0x98, 0xdd, 0x2f, 0x6c, 0x0f, 0x73, 0x67, 0xcc, 0xa4, 0x43, 0x76, 0x97, 0xc6,
0x84, 0xbc, 0x0e, 0x05, 0x9e, 0x70, 0xd7, 0x0e, 0xdb, 0x5d, 0x22, 0x20, 0x3b, 0x7d, 0xd7, 0xf4,
0xcc, 0x53, 0xd3, 0xc5, 0xdc, 0x3d, 0x16, 0x95, 0x9d, 0xae, 0x0e, 0xd6, 0x77, 0xd8, 0x4e, 0x6f,
0x72, 0xe8, 0x49, 0x84, 0xbf, 0x84, 0xf8, 0x11, 0x8b, 0x04, 0x8a, 0x67, 0xd0, 0x35, 0x16, 0x79,
0x85, 0x4f, 0xa3, 0x2d, 0x12, 0xa0, 0xa2, 0x32, 0x24, 0x5f, 0xe0, 0x53, 0x16, 0x97, 0x96, 0x28,
0xbf, 0xc5, 0x80, 0x1f, 0x8b, 0x48, 0x3b, 0x6c, 0x57, 0x10, 0x6e, 0xc3, 0xb1, 0xc8, 0xa7, 0x46,
0x7f, 0xaa, 0xc1, 0x9a, 0x88, 0x1f, 0xd8, 0x7b, 0x65, 0x3b, 0xe7, 0x56, 0xa7, 0xc5, 0x43, 0xc7,
0x32, 0xe5, 0x7c, 0x2f, 0x14, 0x92, 0x42, 0x58, 0xf5, 0x7c, 0xf1, 0x87, 0x83, 0x7e, 0xee, 0xbe,
0x1f, 0x9e, 0xfc, 0xf1, 0xa8, 0x78, 0x12, 0x37, 0x17, 0xfa, 0x63, 0x0d, 0x56, 0xb9, 0x76, 0x06,
0x6e, 0xd8, 0x4e, 0x33, 0x10, 0x63, 0x85, 0x8a, 0x91, 0xf3, 0x77, 0x6b, 0x14, 0x52, 0x3d, 0x5f,
0x7c, 0x30, 0xe8, 0xe7, 0x74, 0x6e, 0xb8, 0x13, 0x47, 0x0c, 0x47, 0x09, 0x11, 0x33, 0x51, 0x11,
0x20, 0x29, 0xb2, 0x97, 0x5e, 0x86, 0xc9, 0x17, 0xa6, 0xd7, 0x38, 0x43, 0x8f, 0x61, 0xf2, 0x89,
0xd5, 0x69, 0xba, 0x19, 0xed, 0xde, 0x38, 0x0d, 0x3e, 0x2c, 0xa9, 0xd2, 0x41, 0x32, 0x50, 0x5c,
0xfb, 0xb6, 0x9f, 0x1b, 0x1b, 0xf4, 0x73, 0x0b, 0xe7, 0x04, 0x4d, 0xca, 0xac, 0x8c, 0x4e, 0xff,
0xc7, 0x04, 0xa4, 0x7c, 0x6c, 0xb4, 0x01, 0x13, 0xe4, 0x7f, 0x9a, 0xa2, 0x53, 0xc5, 0xe4, 0xa0,
0x9f, 0x9b, 0x20, 0x74, 0x06, 0x85, 0xa2, 0x3c, 0xcc, 0x1c, 0xda, 0x66, 0xb3, 0x8a, 0x1b, 0x0e,
0xf6, 0x5c, 0x9a, 0x83, 0x93, 0xc5, 0xf4, 0xa0, 0x9f, 0x9b, 0x6d, 0xdb, 0x66, 0xf3, 0xc4, 0x65,
0x70, 0x43, 0x46, 0x22, 0x1c, 0x69, 0x02, 0x19, 0x0f, 0x38, 0x92, 0x50, 0x68, 0x50, 0x28, 0xfa,
0x02, 0xa6, 0xf6, 0xad, 0x36, 0xd9, 0x34, 0x13, 0x54, 0xfe, 0x8d, 0xb0, 0xfc, 0x5b, 0x6c, 0x78,
0xaf, 0xe3, 0x39, 0x57, 0x2c, 0x02, 0xbe, 0xa4, 0x00, 0x49, 0x11, 0xce, 0x01, 0xbd, 0x0f, 0xd3,
0xd5, 0xde, 0x29, 0x15, 0x7f, 0x92, 0x4e, 0x46, 0xcb, 0x00, 0xb7, 0x77, 0x7a, 0x42, 0x54, 0x90,
0x08, 0x04, 0x5a, 0xf6, 0xa7, 0x30, 0x23, 0xb1, 0x47, 0x69, 0x18, 0x3f, 0xc7, 0x57, 0x4c, 0x77,
0x83, 0xfc, 0x88, 0x96, 0x61, 0xf2, 0xd2, 0x6c, 0xf7, 0x30, 0x55, 0x35, 0x65, 0xb0, 0x8f, 0x8f,
0x13, 0x1f, 0x69, 0xfa, 0x97, 0x30, 0x49, 0x72, 0xbd, 0x8b, 0xee, 0xc3, 0x78, 0xb5, 0x5a, 0xa6,
0x44, 0xb3, 0xc5, 0xc5, 0x41, 0x3f, 0x37, 0xe7, 0xba, 0x67, 0xd2, 0x64, 0x64, 0x94, 0x20, 0xd5,
0x0e, 0xab, 0x94, 0x0b, 0x47, 0xf2, 0xda, 0xf2, 0x5a, 0x90, 0x51, 0xfd, 0x37, 0x53, 0x90, 0x26,
0xd9, 0x88, 0xf2, 0x15, 0xe1, 0xea, 0x3d, 0x48, 0x1d, 0xf5, 0x4e, 0xdb, 0x56, 0xe3, 0x09, 0x97,
0x6c, 0xb6, 0x38, 0x3f, 0xe8, 0xe7, 0xa0, 0x4b, 0x81, 0x27, 0xe7, 0xf8, 0xca, 0x08, 0x10, 0xd0,
0x43, 0x48, 0x12, 0x0e, 0xc4, 0xc0, 0x4c, 0xe4, 0xe2, 0xec, 0xa0, 0x9f, 0x4b, 0xf6, 0x38, 0xcc,
0xf0, 0x47, 0x51, 0x15, 0xa6, 0xf7, 0xbe, 0xe9, 0x5a, 0x0e, 0x76, 0x79, 0xc9, 0x93, 0xdd, 0x62,
0x75, 0xe8, 0x96, 0xa8, 0x43, 0xb7, 0x6a, 0xa2, 0x0e, 0x2d, 0xde, 0xe5, 0x3e, 0xb4, 0x88, 0x19,
0x49, 0x20, 0xf9, 0x5f, 0xff, 0x67, 0x4e, 0x33, 0x04, 0x27, 0xf4, 0x1e, 0x4c, 0xed, 0xdb, 0xce,
0x85, 0xe9, 0xd1, 0x4a, 0x27, 0xc5, 0xd7, 0x8b, 0x42, 0x94, 0xf5, 0xa2, 0x10, 0xb4, 0x0f, 0xf3,
0x86, 0xdd, 0xf3, 0x70, 0xcd, 0x16, 0x81, 0x93, 0x2d, 0xdb, 0xe6, 0xa0, 0x9f, 0xcb, 0x3a, 0x64,
0xe4, 0xc4, 0xb3, 0x87, 0x43, 0xa4, 0x11, 0xa2, 0x42, 0x7b, 0x30, 0xaf, 0x84, 0x78, 0x37, 0x33,
0x75, 0x6f, 0xfc, 0x61, 0x8a, 0x05, 0x42, 0x35, 0x31, 0xc8, 0x36, 0x0f, 0x11, 0xa1, 0x67, 0xb0,
0xf8, 0xa4, 0x77, 0x8a, 0x9d, 0x0e, 0xf6, 0xb0, 0x2b, 0x24, 0x9a, 0xa6, 0x12, 0xdd, 0x1b, 0xf4,
0x73, 0x1b, 0xe7, 0xfe, 0x60, 0x84, 0x4c, 0xc3, 0xa4, 0x08, 0xc3, 0x02, 0x17, 0x54, 0xc4, 0x5b,
0x5e, 0x97, 0xac, 0x72, 0x1f, 0x0f, 0x8d, 0x16, 0xef, 0x73, 0x2b, 0xdf, 0xf1, 0x75, 0x17, 0x51,
0x5c, 0x9a, 0x28, 0xcc, 0x13, 0xed, 0x40, 0xf2, 0x99, 0xdd, 0xc4, 0x74, 0x8f, 0xa5, 0xa8, 0xb4,
0xac, 0xdc, 0xb0, 0x9b, 0x38, 0x54, 0x8b, 0x19, 0x3e, 0x22, 0x3a, 0x84, 0xc9, 0x63, 0xd7, 0x6c,
0xb1, 0x92, 0x65, 0x3e, 0xff, 0x3d, 0x2e, 0x51, 0xd8, 0xfb, 0x68, 0xfd, 0x4b, 0x11, 0x8b, 0x4b,
0x24, 0x84, 0xf4, 0xc8, 0x8f, 0x72, 0x08, 0xa1, 0x63, 0xe8, 0x4b, 0x00, 0x2e, 0x55, 0xa1, 0xdb,
0xe5, 0xd5, 0xcb, 0xa2, 0xaa, 0x64, 0xa1, 0xdb, 0x2d, 0x6e, 0x72, 0xfd, 0x56, 0x7d, 0xfd, 0xcc,
0x6e, 0x57, 0xe2, 0x26, 0x31, 0xd1, 0x77, 0x21, 0xe5, 0xcf, 0x8d, 0xa6, 0x61, 0xbc, 0xd0, 0x6e,
0xa7, 0xc7, 0xc8, 0x0f, 0xd5, 0x6a, 0x39, 0xad, 0xa1, 0x79, 0x80, 0xc0, 0xe0, 0xe9, 0x04, 0x9a,
0x85, 0xa4, 0x30, 0x48, 0x7a, 0x9c, 0xe2, 0x77, 0xbb, 0xe9, 0x09, 0xfd, 0xdf, 0xb5, 0xa1, 0x35,
0x20, 0x31, 0xac, 0xca, 0x4e, 0x6e, 0xd4, 0x64, 0x2c, 0xd0, 0xd1, 0x18, 0xc6, 0x0f, 0x74, 0xd4,
0x6a, 0x86, 0x8c, 0x44, 0xb6, 0xd5, 0x11, 0xd1, 0xa6, 0x61, 0xb7, 0xe5, 0x6d, 0xd5, 0xe5, 0x30,
0xc3, 0x1f, 0x45, 0x79, 0x69, 0x03, 0x8e, 0x07, 0x41, 0x48, 0x6c, 0x40, 0x79, 0x31, 0xfc, 0xad,
0x98, 0x0f, 0x84, 0xe7, 0xfb, 0x86, 0xd2, 0x44, 0x2c, 0xbe, 0x8f, 0xa7, 0xff, 0x5a, 0x93, 0x6d,
0xee, 0x07, 0x59, 0x2d, 0x32, 0xc8, 0xbe, 0x07, 0x29, 0x9e, 0x52, 0x2a, 0xbb, 0x5c, 0x7e, 0x1a,
0x43, 0x44, 0x36, 0xb2, 0x9a, 0x46, 0x80, 0x80, 0xb6, 0x01, 0x58, 0x40, 0x29, 0x34, 0x9b, 0x0e,
0x57, 0x62, 0x61, 0xd0, 0xcf, 0xcd, 0xf0, 0x90, 0x63, 0x36, 0x9b, 0x8e, 0x21, 0xa1, 0x10, 0x8b,
0xca, 0x27, 0x85, 0x89, 0xc0, 0xa2, 0xf2, 0x99, 0x40, 0x39, 0x07, 0xe8, 0x6d, 0x98, 0x3f, 0xc0,
0x1e, 0x31, 0x81, 0x08, 0x74, 0xa3, 0x55, 0xf8, 0x14, 0x66, 0x5e, 0x58, 0xde, 0x99, 0x9a, 0x79,
0xe8, 0xb9, 0xe3, 0x95, 0xe5, 0x9d, 0x89, 0xcc, 0x23, 0x99, 0x4a, 0x46, 0xd7, 0xf7, 0x60, 0x81,
0xcf, 0xe6, 0xc7, 0xd5, 0xbc, 0xca, 0x50, 0x0b, 0x52, 0x99, 0xcc, 0x50, 0x65, 0x83, 0xc3, 0x81,
0x06, 0x55, 0x87, 0x42, 0x0f, 0x4b, 0xc3, 0x71, 0xb5, 0x2a, 0xdd, 0x45, 0xa1, 0x90, 0x14, 0x0e,
0x44, 0xfa, 0x31, 0xcc, 0x1d, 0xb5, 0x7b, 0x2d, 0xab, 0x43, 0x56, 0xbb, 0x8a, 0xbf, 0x46, 0xbb,
0x00, 0x01, 0x80, 0xcf, 0x20, 0x0a, 0xb4, 0x60, 0xa0, 0xbe, 0xc3, 0x97, 0x89, 0x42, 0x68, 0xec,
0x30, 0x24, 0x3a, 0xfd, 0x2f, 0xc6, 0x01, 0xf1, 0x39, 0xc8, 0x51, 0x12, 0x57, 0xb1, 0x47, 0xc2,
0xd4, 0x2a, 0x24, 0x2a, 0xbb, 0xdc, 0xea, 0x53, 0x83, 0x7e, 0x2e, 0x61, 0x35, 0x8d, 0x44, 0x65,
0x17, 0x7d, 0x00, 0x93, 0x14, 0x8d, 0xda, 0x7a, 0xde, 0x9f, 0x4f, 0xe6, 0x50, 0x4c, 0x0d, 0xfa,
0xb9, 0x49, 0x72, 0x64, 0xc5, 0x06, 0x43, 0x46, 0x1f, 0x42, 0x6a, 0x17, 0xb7, 0x71, 0xcb, 0xf4,
0x6c, 0xe1, 0x3b, 0x34, 0x1c, 0x35, 0x05, 0x50, 0x5a, 0xa2, 0x00, 0x93, 0x24, 0x0e, 0x03, 0x9b,
0xae, 0xdd, 0x91, 0x13, 0x87, 0x43, 0x21, 0x72, 0xe2, 0x60, 0x38, 0xe8, 0x6f, 0x34, 0x98, 0x29,
0x74, 0x3a, 0x36, 0xbb, 0x89, 0x70, 0xf9, 0xd1, 0x77, 0x65, 0xcb, 0xbf, 0xb9, 0x38, 0x34, 0x4f,
0x71, 0xbb, 0x4e, 0x72, 0xb5, 0x5b, 0xfc, 0x8a, 0x44, 0x9d, 0xff, 0xe8, 0xe7, 0x3e, 0x79, 0x9d,
0xcb, 0x90, 0xad, 0x9a, 0x63, 0x5a, 0x9e, 0x4b, 0x4f, 0x02, 0xc1, 0x84, 0xb2, 0x9b, 0x49, 0x72,
0xa0, 0x77, 0x60, 0x92, 0x1c, 0x0a, 0x45, 0xfe, 0xa1, 0x8b, 0x4d, 0xce, 0x8d, 0x4a, 0xd5, 0x45,
0x31, 0xf4, 0xfb, 0x90, 0xe2, 0x96, 0xac, 0xec, 0xc6, 0x2d, 0x81, 0xfe, 0x14, 0x1e, 0x18, 0x36,
0xb5, 0x2e, 0x76, 0xb1, 0x77, 0x64, 0xba, 0xee, 0x2b, 0xdb, 0x69, 0xd2, 0xc2, 0x98, 0xbb, 0xa4,
0xf0, 0xe6, 0xfb, 0x30, 0x4d, 0xc1, 0x3e, 0x1b, 0xba, 0x32, 0xb4, 0xb0, 0x36, 0xc4, 0x88, 0x5e,
0x82, 0x8d, 0x03, 0xec, 0x0d, 0xf3, 0xba, 0x15, 0x93, 0x5f, 0x68, 0x90, 0x2b, 0x39, 0x38, 0x52,
0xa8, 0x9b, 0x6d, 0xe5, 0x0d, 0x7e, 0x0b, 0x94, 0x08, 0x46, 0x89, 0xd1, 0xf9, 0x4d, 0xcf, 0x0f,
0x60, 0xbc, 0x56, 0x3b, 0xa4, 0xae, 0x33, 0x4e, 0x2d, 0x38, 0xee, 0x79, 0xed, 0xff, 0xee, 0xe7,
0x92, 0xbb, 0x3d, 0x76, 0x4b, 0x64, 0x90, 0x71, 0x7d, 0x0e, 0x66, 0x8e, 0xac, 0x4e, 0x8b, 0xcf,
0xa8, 0xff, 0x65, 0x02, 0x66, 0xd9, 0xb7, 0xdb, 0xb5, 0x3b, 0x2c, 0xca, 0xcb, 0x31, 0x49, 0xbb,
0x41, 0x4c, 0x42, 0x1f, 0xc1, 0x1c, 0x3f, 0x44, 0x61, 0x87, 0x1e, 0x85, 0x98, 0x84, 0xf4, 0xf8,
0xcf, 0x8e, 0x51, 0x27, 0x97, 0x6c, 0xc4, 0x50, 0x11, 0xd1, 0x21, 0xcc, 0x33, 0xc0, 0x3e, 0x36,
0xbd, 0x5e, 0x50, 0x53, 0x2d, 0xf0, 0x24, 0x28, 0xc0, 0xcc, 0x25, 0x38, 0xaf, 0x97, 0x1c, 0x68,
0x84, 0x68, 0xd1, 0x63, 0x58, 0x38, 0x72, 0xec, 0x6f, 0xae, 0xa4, 0x28, 0xcc, 0x76, 0xc5, 0x0a,
0x29, 0xc1, 0xba, 0x64, 0xe8, 0x44, 0x8e, 0xc5, 0x61, 0x6c, 0xfd, 0xb7, 0x09, 0x48, 0xfa, 0xdc,
0xb6, 0xe4, 0x54, 0xc9, 0xe3, 0x1c, 0x8d, 0xfe, 0x41, 0x3d, 0x63, 0x48, 0x18, 0x68, 0x9d, 0x26,
0x4f, 0x1e, 0x61, 0xa7, 0xc9, 0x02, 0x98, 0xdd, 0xae, 0x41, 0x60, 0xc4, 0x4f, 0x77, 0x8b, 0x54,
0xb5, 0x24, 0xf3, 0xd3, 0xe6, 0xa9, 0x91, 0xd8, 0x2d, 0x92, 0x15, 0x7d, 0x5e, 0xd9, 0x2d, 0x51,
0x29, 0x93, 0x6c, 0x45, 0x6d, 0xab, 0xd9, 0x30, 0x28, 0x94, 0x8c, 0x56, 0x0b, 0x4f, 0x0f, 0xe9,
0x2e, 0xe5, 0xa3, 0xae, 0x79, 0xd1, 0x36, 0x28, 0x14, 0x7d, 0x22, 0x22, 0x68, 0xc9, 0xee, 0x78,
0x8e, 0xdd, 0x76, 0xe9, 0x4d, 0x53, 0x52, 0x89, 0x94, 0x0d, 0x3e, 0x64, 0x84, 0x50, 0xd1, 0x0b,
0x58, 0x2b, 0x34, 0x2f, 0xcd, 0x4e, 0x03, 0x37, 0xd9, 0xc8, 0x0b, 0xdb, 0x39, 0x7f, 0xd9, 0xb6,
0x5f, 0xb9, 0xb4, 0x70, 0x4b, 0xf2, 0x12, 0x90, 0xa3, 0x9c, 0x70, 0x76, 0xaf, 0x04, 0x92, 0x11,
0x47, 0x8d, 0x72, 0x30, 0x59, 0x6a, 0xdb, 0xbd, 0x26, 0xad, 0xd8, 0x92, 0x6c, 0x23, 0x34, 0x08,
0xc0, 0x60, 0x70, 0xfd, 0x27, 0xb0, 0x48, 0xa2, 0x97, 0x87, 0x6f, 0x9c, 0xc2, 0xf4, 0x23, 0x80,
0x2a, 0xbe, 0x30, 0xbb, 0x67, 0x36, 0x59, 0x96, 0xa2, 0xfc, 0xc5, 0x63, 0x3a, 0xf2, 0xcf, 0x90,
0x7c, 0xa0, 0xbe, 0x23, 0x12, 0xb5, 0xc0, 0x34, 0x24, 0x2a, 0xfd, 0x5f, 0x12, 0x80, 0x0a, 0xbd,
0xa6, 0xe5, 0x55, 0x3d, 0x07, 0x9b, 0x17, 0x42, 0x8c, 0x9f, 0xc2, 0x2c, 0xdb, 0xa1, 0x0c, 0x4c,
0xc5, 0x21, 0x09, 0x83, 0xf9, 0xa2, 0x3c, 0x54, 0x1e, 0x33, 0x14, 0x54, 0x42, 0x6a, 0x60, 0xb7,
0x77, 0x21, 0x48, 0x13, 0x0a, 0xa9, 0x3c, 0x44, 0x48, 0xe5, 0x6f, 0xf4, 0x18, 0xe6, 0x4b, 0xf6,
0x45, 0x97, 0xd8, 0x84, 0x13, 0x8f, 0xf3, 0xb0, 0xcc, 0xe7, 0x55, 0x06, 0xcb, 0x63, 0x46, 0x08,
0x1d, 0x3d, 0x83, 0xa5, 0xfd, 0x76, 0xcf, 0x3d, 0x2b, 0x74, 0x9a, 0xa5, 0xb6, 0xed, 0x0a, 0x2e,
0x13, 0xfc, 0x74, 0xc2, 0x77, 0xd2, 0x30, 0x46, 0x79, 0xcc, 0x88, 0x22, 0x44, 0x3f, 0xe0, 0xd7,
0xce, 0x3c, 0x3d, 0xcc, 0x6d, 0xf1, 0x5b, 0xe9, 0xe7, 0x1d, 0xfc, 0xfc, 0x65, 0x79, 0xcc, 0x60,
0xa3, 0xc5, 0x14, 0x4c, 0x8b, 0x28, 0xb2, 0x0d, 0x8b, 0x92, 0x39, 0x49, 0x42, 0xeb, 0xb9, 0x28,
0x0b, 0xc9, 0xe3, 0x2e, 0x39, 0xde, 0x8a, 0xb0, 0x68, 0xf8, 0xdf, 0xfa, 0x7b, 0xaa, 0xa5, 0xd1,
0x86, 0x5c, 0x68, 0x31, 0xe4, 0x00, 0xa0, 0x97, 0x55, 0xe3, 0x8e, 0xc6, 0x56, 0xe6, 0x4d, 0x84,
0xe6, 0x4d, 0x87, 0x6d, 0xad, 0xaf, 0x44, 0x1a, 0x4f, 0xff, 0x13, 0x0d, 0x96, 0x0f, 0xb0, 0x47,
0x2f, 0xab, 0x48, 0x8c, 0xf1, 0x13, 0xc6, 0x8f, 0xe4, 0x7b, 0x4b, 0xe6, 0xaf, 0x73, 0x83, 0x7e,
0x2e, 0xe5, 0xdf, 0x52, 0xca, 0x37, 0x93, 0x9f, 0xc1, 0x7c, 0xf5, 0xdc, 0xea, 0xd6, 0xcd, 0xb6,
0xd5, 0xa4, 0x31, 0x98, 0x47, 0x87, 0x15, 0x1a, 0xcd, 0xce, 0xad, 0xee, 0xc9, 0x65, 0x30, 0xa4,
0x19, 0x21, 0x64, 0xfd, 0x39, 0xac, 0x84, 0x64, 0xe0, 0x41, 0xfa, 0x77, 0x60, 0x9a, 0x83, 0xf8,
0x06, 0x18, 0xba, 0xf2, 0x9c, 0x19, 0xf4, 0x73, 0xd3, 0x2e, 0x27, 0x13, 0xc8, 0xfa, 0x53, 0x58,
0x3d, 0xee, 0xba, 0xd8, 0x09, 0x78, 0x0a, 0xb5, 0x76, 0xfc, 0x3b, 0x54, 0x2d, 0xfa, 0x0e, 0x15,
0x06, 0xfd, 0xdc, 0x14, 0x63, 0x28, 0xee, 0x4d, 0xf5, 0x06, 0xac, 0xb2, 0xbd, 0x3c, 0xc4, 0xee,
0x56, 0x56, 0x12, 0xbb, 0x3f, 0x11, 0xb9, 0xfb, 0x2b, 0x90, 0xe5, 0x93, 0xb4, 0xdb, 0x6f, 0xb6,
0x1c, 0xfa, 0x3f, 0x6b, 0xb0, 0x76, 0x80, 0x3b, 0xd8, 0x31, 0xa9, 0xc8, 0x4a, 0xea, 0x95, 0x2f,
0x00, 0xb4, 0x91, 0x17, 0x00, 0x39, 0x51, 0xac, 0x24, 0x68, 0xb1, 0x42, 0x43, 0x1c, 0x2d, 0x56,
0x78, 0x89, 0x42, 0x12, 0xc1, 0xb1, 0x51, 0xe1, 0x45, 0x1c, 0x4d, 0x04, 0x3d, 0xc7, 0x32, 0x08,
0x0c, 0x55, 0x82, 0xcb, 0x83, 0x89, 0x6b, 0x2f, 0x0f, 0x96, 0xf8, 0xb1, 0x6f, 0x9a, 0x5f, 0x1e,
0x28, 0x57, 0x06, 0xfa, 0x27, 0x90, 0x19, 0xd6, 0x85, 0xfb, 0x47, 0x0e, 0x26, 0xd9, 0x1d, 0xe2,
0x50, 0x39, 0xc2, 0xe0, 0xfa, 0x6e, 0xe0, 0xdd, 0xfc, 0xc6, 0xcc, 0xbf, 0x34, 0x09, 0xed, 0xac,
0x11, 0x07, 0x1e, 0xbd, 0x1a, 0xf8, 0x27, 0xe7, 0xc2, 0xe7, 0xff, 0x98, 0xf8, 0x27, 0xbb, 0x15,
0xd5, 0xe2, 0x6f, 0x45, 0xb9, 0x8f, 0x32, 0x52, 0x41, 0xa0, 0xbf, 0x80, 0x55, 0x85, 0x69, 0xe0,
0xf5, 0x9f, 0x41, 0x52, 0xc0, 0x42, 0xb5, 0xbc, 0xc2, 0x96, 0xae, 0x9b, 0x2b, 0x88, 0x7d, 0x12,
0xfd, 0x57, 0x1a, 0xac, 0xb1, 0xa0, 0x33, 0xac, 0xf7, 0xcd, 0x57, 0xff, 0xff, 0xe2, 0x90, 0xf7,
0xc5, 0x44, 0x32, 0x91, 0x1e, 0xd7, 0xeb, 0x90, 0x19, 0x96, 0xf7, 0x2d, 0x58, 0xf8, 0x00, 0xd6,
0xa4, 0x6d, 0xfb, 0xc6, 0xeb, 0x1f, 0xcc, 0xf8, 0x16, 0xd7, 0x3f, 0x40, 0x7c, 0x6b, 0xeb, 0x5f,
0x81, 0x25, 0xc6, 0x58, 0xdd, 0x2b, 0x79, 0x79, 0xaf, 0x44, 0xde, 0xb7, 0x0f, 0x6f, 0x9f, 0xa7,
0x74, 0xfb, 0x08, 0x94, 0x40, 0xc2, 0x0f, 0x61, 0x8a, 0x3f, 0x58, 0x32, 0xf9, 0x22, 0x98, 0xd1,
0x38, 0xca, 0x5e, 0x29, 0x0d, 0x8e, 0xac, 0x67, 0xa8, 0xca, 0xa4, 0x94, 0xe4, 0x77, 0x27, 0x22,
0xbc, 0xe9, 0x5f, 0x92, 0x80, 0x15, 0x1a, 0x79, 0xc3, 0x1c, 0xf0, 0x1c, 0x32, 0x2c, 0x07, 0x48,
0x5c, 0xdf, 0x28, 0x0b, 0x7c, 0x04, 0x19, 0xe6, 0x4e, 0x11, 0x0c, 0x47, 0x87, 0xf6, 0x4d, 0xd8,
0xf0, 0x43, 0x7b, 0x94, 0xf6, 0x7f, 0xa6, 0xc1, 0xfa, 0x01, 0xf6, 0xd4, 0x57, 0x97, 0xff, 0x97,
0x4c, 0xfc, 0x15, 0x64, 0xa3, 0x04, 0xe1, 0x4b, 0xf1, 0x79, 0x78, 0x29, 0x62, 0x9f, 0x98, 0xa2,
0x97, 0xe4, 0xe7, 0x70, 0x87, 0x2d, 0x89, 0x8a, 0x2f, 0x14, 0xfd, 0x24, 0xb4, 0x2a, 0xb1, 0xdc,
0xa3, 0x56, 0xe7, 0xaf, 0x34, 0xb8, 0xc3, 0x8c, 0x1c, 0xcd, 0xfc, 0x56, 0x56, 0xbc, 0x0f, 0x53,
0x65, 0x9b, 0x9c, 0xbc, 0xf9, 0x82, 0x52, 0x75, 0xce, 0x6c, 0xd7, 0x23, 0x81, 0x81, 0x0f, 0x8d,
0x7e, 0xb7, 0xd0, 0x9f, 0x41, 0xce, 0x5f, 0xf3, 0xb7, 0xb0, 0xb0, 0x7a, 0x03, 0x90, 0x60, 0x53,
0xaa, 0x1a, 0x82, 0xc5, 0x3a, 0x8c, 0x97, 0xaa, 0x06, 0xbf, 0xf6, 0xa7, 0x29, 0xb8, 0xe1, 0x3a,
0x06, 0x81, 0x85, 0xe3, 0x71, 0xe2, 0x26, 0x97, 0x6e, 0xbf, 0x0f, 0x4b, 0xca, 0x24, 0x7c, 0xdd,
0x37, 0x60, 0xa2, 0x84, 0x1d, 0x8f, 0x4f, 0x43, 0x35, 0x6d, 0x60, 0xc7, 0x33, 0x28, 0x14, 0x3d,
0x80, 0xe9, 0x52, 0x81, 0x5e, 0x0a, 0xd3, 0x4a, 0x61, 0x96, 0x05, 0xa6, 0x86, 0x79, 0xd2, 0xa0,
0x17, 0xc5, 0x62, 0x50, 0xff, 0x73, 0x4d, 0xe2, 0x4e, 0xc8, 0xaf, 0xd7, 0x61, 0x9b, 0x9c, 0x81,
0x88, 0xcd, 0x24, 0x15, 0x68, 0x12, 0xe2, 0x27, 0x64, 0xaa, 0x81, 0x84, 0x72, 0xd3, 0xcb, 0x81,
0xaf, 0x60, 0x59, 0x95, 0xe4, 0xad, 0x2a, 0xfa, 0x7d, 0x7a, 0x75, 0x49, 0x6a, 0x24, 0xa1, 0x22,
0x92, 0xcf, 0x7d, 0xdc, 0x41, 0x1e, 0x41, 0x9a, 0x63, 0x05, 0x1b, 0xec, 0xbe, 0x28, 0xb9, 0xd8,
0xf6, 0x52, 0xdb, 0x0c, 0xc4, 0xcd, 0xd0, 0x0f, 0xc5, 0xc9, 0xf2, 0xba, 0x19, 0xce, 0x21, 0xf3,
0x74, 0xbf, 0x50, 0xe8, 0x79, 0x67, 0xb8, 0xe3, 0x59, 0x0d, 0xd3, 0xc3, 0xa5, 0x33, 0xb3, 0xdd,
0xc6, 0x9d, 0x16, 0x35, 0xd4, 0x71, 0x7e, 0xdf, 0x4f, 0x2f, 0xfc, 0x76, 0x3f, 0xbf, 0xef, 0x63,
0x18, 0x64, 0x1c, 0x3d, 0x84, 0x89, 0xda, 0xf3, 0xda, 0x11, 0x3f, 0xe6, 0x2d, 0x73, 0x3c, 0x02,
0x0a, 0x10, 0x29, 0x86, 0xfe, 0x0d, 0xac, 0x85, 0x26, 0xf3, 0xb5, 0x7a, 0x20, 0xe6, 0xd2, 0xe8,
0x11, 0xd6, 0x9f, 0x4b, 0x20, 0x94, 0xc7, 0xd8, 0x64, 0xef, 0x28, 0x93, 0x2d, 0x49, 0x93, 0x49,
0x98, 0x14, 0x85, 0xbf, 0x74, 0x52, 0x98, 0xfe, 0x87, 0x30, 0x2b, 0x0b, 0x4e, 0x4e, 0x4d, 0x4f,
0xf0, 0x55, 0xd9, 0xec, 0x34, 0xdb, 0xc2, 0x1e, 0x01, 0x80, 0x8c, 0xfa, 0xa8, 0xfc, 0xd8, 0x14,
0x00, 0xd0, 0x32, 0x4c, 0x16, 0xba, 0xdd, 0xca, 0x2e, 0xdb, 0xd4, 0x06, 0xfb, 0x40, 0x19, 0x98,
0x16, 0x37, 0x3e, 0xb4, 0xac, 0x31, 0xc4, 0xa7, 0x6e, 0xc1, 0x8c, 0xa4, 0xc8, 0x35, 0x53, 0x6f,
0x02, 0x94, 0xda, 0x16, 0xee, 0xd0, 0xf0, 0xc7, 0xe7, 0x96, 0x20, 0xf4, 0xb8, 0x67, 0xb5, 0x3a,
0xf4, 0x5a, 0x86, 0x0b, 0x10, 0x00, 0xf4, 0x05, 0x98, 0x53, 0xec, 0xae, 0xeb, 0x30, 0x2b, 0xdb,
0x86, 0xb8, 0x40, 0xc9, 0x6e, 0xfa, 0x2e, 0x40, 0x7e, 0xd6, 0x7f, 0xa9, 0xc1, 0xf2, 0xd3, 0xfd,
0x82, 0x81, 0x5b, 0x16, 0xed, 0x82, 0xf1, 0x15, 0xdd, 0x96, 0xd7, 0xe4, 0x8e, 0xbc, 0x26, 0x21,
0x4c, 0xb1, 0x38, 0x79, 0x65, 0x71, 0x36, 0x94, 0xc5, 0x19, 0x26, 0x61, 0xab, 0x24, 0x9d, 0x9c,
0x7f, 0xa1, 0xc1, 0x92, 0x24, 0x88, 0x2f, 0xf4, 0x96, 0x2c, 0x47, 0x76, 0x58, 0x8e, 0xb0, 0x8f,
0xfc, 0x44, 0x11, 0xe3, 0x4e, 0x84, 0x18, 0x23, 0x7d, 0xa5, 0x09, 0xcb, 0x51, 0x4a, 0xaa, 0x5e,
0xa1, 0xc5, 0x7a, 0x45, 0x22, 0xc6, 0x2b, 0xc6, 0x55, 0xaf, 0x30, 0x61, 0x29, 0x42, 0x05, 0xf4,
0x2e, 0xa4, 0x19, 0x8c, 0x85, 0x22, 0x7e, 0x57, 0x4f, 0x28, 0x87, 0xe0, 0xd7, 0xf9, 0x8a, 0xfe,
0x6b, 0x0d, 0x56, 0x22, 0x8d, 0x8f, 0x56, 0x49, 0x16, 0x6d, 0x38, 0xd8, 0xe3, 0xbc, 0xf9, 0x17,
0x81, 0x57, 0x5c, 0xb7, 0xc7, 0x3b, 0xe3, 0x52, 0x06, 0xff, 0x42, 0xdf, 0x87, 0xb9, 0x23, 0xec,
0x58, 0x76, 0xb3, 0x8a, 0x1b, 0x76, 0xa7, 0xc9, 0x6e, 0x26, 0xe7, 0x0c, 0x15, 0x48, 0x0c, 0x54,
0x68, 0xb7, 0x6c, 0xc7, 0xf2, 0xce, 0x2e, 0xf8, 0x26, 0x08, 0x00, 0x84, 0xf7, 0xae, 0xd5, 0xb2,
0x3c, 0x76, 0xd3, 0x3e, 0x67, 0xf0, 0x2f, 0x62, 0xa2, 0x42, 0xa3, 0x61, 0xf7, 0x3a, 0x1e, 0xbd,
0xb4, 0x4b, 0x19, 0xe2, 0x53, 0x7f, 0x17, 0x96, 0xa3, 0x16, 0x2d, 0xd2, 0x89, 0xff, 0x28, 0x01,
0x4b, 0x85, 0x66, 0xf3, 0xe9, 0x7e, 0x61, 0x17, 0xcb, 0x45, 0xd7, 0x07, 0x30, 0x51, 0xe9, 0x58,
0x1e, 0x77, 0x9e, 0x4d, 0xee, 0x0b, 0x11, 0x98, 0x04, 0x8b, 0xb8, 0x03, 0xf9, 0x1f, 0x19, 0xb0,
0xb4, 0xf7, 0x8d, 0xe5, 0x7a, 0x56, 0xa7, 0x45, 0x1d, 0x92, 0x4d, 0xcc, 0x1d, 0x4a, 0x30, 0x89,
0x09, 0x65, 0xe5, 0x31, 0x23, 0x8a, 0x18, 0xd5, 0x60, 0xf5, 0x19, 0x7e, 0x15, 0xe1, 0xdf, 0xfe,
0xd3, 0xb9, 0xcf, 0x36, 0xc2, 0x4d, 0x63, 0x68, 0xe5, 0xed, 0xf3, 0xcb, 0x04, 0x2c, 0xab, 0x8a,
0xf1, 0x99, 0x8f, 0x61, 0x59, 0x12, 0x48, 0xf5, 0xe1, 0x99, 0x7c, 0x2e, 0x5a, 0x1d, 0x79, 0xa7,
0x46, 0x92, 0xa3, 0x17, 0xb0, 0xa6, 0x0a, 0xa5, 0xc6, 0xcc, 0x60, 0xe7, 0x45, 0xa1, 0x94, 0xc7,
0x8c, 0x38, 0x6a, 0x94, 0x87, 0xf1, 0x42, 0xe3, 0x9c, 0x9b, 0x25, 0x7a, 0xc9, 0x98, 0x66, 0x85,
0xc6, 0x39, 0xd9, 0xf3, 0x85, 0xc6, 0xb9, 0xb2, 0x81, 0xff, 0x56, 0x83, 0xb5, 0x98, 0x15, 0x26,
0x7b, 0x86, 0x01, 0xa5, 0x4c, 0x28, 0x41, 0xd0, 0x67, 0xd2, 0xbb, 0xc2, 0x7c, 0xfe, 0x9d, 0xd1,
0xfe, 0xb2, 0xc5, 0x20, 0x35, 0xff, 0xe1, 0x41, 0xcf, 0x09, 0xf6, 0xf4, 0x19, 0x22, 0xc9, 0x02,
0x11, 0x7b, 0x73, 0x3e, 0xce, 0xef, 0xa7, 0x35, 0xbd, 0x14, 0x16, 0xcd, 0xd7, 0x04, 0x3d, 0x84,
0x29, 0x06, 0xe4, 0x0b, 0x23, 0x5a, 0x00, 0x03, 0x64, 0x3e, 0xae, 0xff, 0xbd, 0x26, 0x2e, 0x9b,
0x86, 0xfc, 0xfd, 0x91, 0xe2, 0xef, 0xe2, 0x49, 0x3e, 0x1a, 0x59, 0x71, 0xf9, 0x22, 0xcc, 0xbc,
0x8e, 0xab, 0xcb, 0x44, 0xb2, 0x33, 0xfe, 0x83, 0x26, 0x0e, 0xd6, 0xc3, 0xfe, 0xb8, 0x07, 0xb3,
0xaf, 0xe7, 0x87, 0x0a, 0x19, 0xfa, 0x90, 0xb9, 0x49, 0x62, 0xb4, 0xa6, 0x23, 0x3d, 0xe5, 0x53,
0x71, 0x9f, 0xf6, 0x3a, 0xbe, 0xa2, 0x6f, 0x44, 0x50, 0xfb, 0xd3, 0xe9, 0xab, 0xf4, 0x5c, 0xec,
0x0f, 0xf9, 0x07, 0xb9, 0x12, 0xbd, 0x28, 0x90, 0xe1, 0x7e, 0xe8, 0x9f, 0xe6, 0x20, 0xbf, 0x0d,
0x2b, 0xec, 0x00, 0x02, 0x81, 0xb8, 0xf8, 0xfa, 0xb1, 0x8b, 0x9d, 0xaa, 0xd5, 0x69, 0xb5, 0xf1,
0x31, 0x2b, 0x51, 0xfd, 0x43, 0xc3, 0x8f, 0x15, 0x27, 0x58, 0x8b, 0xe9, 0xcb, 0xf8, 0xdf, 0x5a,
0xfa, 0xbf, 0xd3, 0x20, 0x1b, 0x25, 0xdb, 0xdb, 0x5d, 0xfd, 0x2d, 0x5e, 0x86, 0x33, 0x69, 0x33,
0x9c, 0xdc, 0x9f, 0x53, 0x28, 0x4b, 0x94, 0x24, 0xff, 0x2b, 0xcb, 0xfe, 0x2b, 0x0d, 0x96, 0x2b,
0x2e, 0x15, 0xff, 0xeb, 0x9e, 0xe5, 0xe0, 0xa6, 0x30, 0xdc, 0x56, 0x54, 0xf7, 0x0e, 0x5d, 0xf8,
0xf2, 0x58, 0x54, 0x77, 0xce, 0x07, 0x52, 0xd3, 0x45, 0x62, 0x54, 0x5b, 0x4e, 0x79, 0x2c, 0x68,
0xbb, 0x40, 0x0f, 0x60, 0xe2, 0x19, 0xc9, 0x5f, 0xe3, 0x7c, 0x9b, 0x33, 0x0a, 0x02, 0x3a, 0xb4,
0x5b, 0x56, 0x87, 0x88, 0x4c, 0x3e, 0x8a, 0x49, 0x98, 0xaa, 0x99, 0x4e, 0x0b, 0x7b, 0xfa, 0x87,
0x90, 0xf2, 0x87, 0x69, 0x19, 0x2f, 0xa5, 0x3f, 0xf2, 0x33, 0xa9, 0x3e, 0xe8, 0xa0, 0xa8, 0x3e,
0xe8, 0x87, 0xbe, 0x03, 0x2b, 0x21, 0x35, 0xf9, 0x1a, 0x64, 0x89, 0x31, 0x18, 0x8c, 0x3d, 0xe6,
0x19, 0xfe, 0xb7, 0x5e, 0x82, 0xc5, 0x21, 0x2b, 0x22, 0x24, 0xf5, 0xa7, 0x91, 0x8d, 0x54, 0xad,
0x96, 0x09, 0xcc, 0x6f, 0x47, 0x23, 0xb0, 0xda, 0x61, 0xb5, 0x38, 0xc5, 0x56, 0x85, 0xe4, 0x22,
0x72, 0x72, 0xa1, 0x8f, 0x23, 0x6e, 0x70, 0x01, 0x12, 0x3e, 0xcb, 0xca, 0xe7, 0xe9, 0x22, 0xa4,
0xaa, 0x9e, 0x49, 0xcf, 0xfd, 0xc2, 0x98, 0xa3, 0x2e, 0x84, 0x93, 0xdf, 0xf6, 0x73, 0x63, 0xf4,
0x16, 0x38, 0x20, 0x43, 0x9f, 0xc3, 0xf4, 0x5e, 0xa7, 0x49, 0x39, 0x8c, 0xdf, 0x82, 0x83, 0x20,
0x22, 0x3b, 0x9e, 0x8a, 0x4c, 0xa2, 0xb7, 0x4b, 0x9b, 0x09, 0x53, 0x86, 0x04, 0xa1, 0x66, 0xb6,
0x2e, 0x2c, 0xf6, 0x1a, 0x34, 0x69, 0xb0, 0x0f, 0x62, 0x4d, 0x2a, 0xc2, 0x13, 0x7c, 0xc5, 0x4b,
0x18, 0xff, 0x5b, 0xff, 0x0d, 0xbd, 0x66, 0xf7, 0xf8, 0xc5, 0x9b, 0x6a, 0x0f, 0x45, 0x63, 0xed,
0x8d, 0x35, 0x4e, 0xbc, 0x8e, 0xc6, 0xbe, 0x46, 0xe3, 0x71, 0x1a, 0x4d, 0x84, 0x34, 0x3a, 0x80,
0x29, 0xa6, 0x06, 0x39, 0x89, 0x56, 0x3c, 0x7c, 0x11, 0x9c, 0x44, 0xe5, 0xb7, 0x31, 0x83, 0x8d,
0x91, 0xf2, 0xee, 0xd0, 0x74, 0x29, 0x27, 0xe6, 0x9b, 0xe2, 0xf3, 0xdd, 0x77, 0x21, 0xe5, 0xff,
0xd6, 0x06, 0x49, 0x95, 0x95, 0x67, 0x95, 0x1a, 0x4b, 0x95, 0x47, 0xc7, 0xb5, 0xb4, 0x86, 0x00,
0xa6, 0x76, 0xf7, 0x0e, 0xf7, 0x6a, 0x7b, 0xe9, 0x44, 0xfe, 0x9f, 0x1e, 0xc1, 0x0c, 0x89, 0x0b,
0xfc, 0x56, 0x0c, 0x7d, 0x0a, 0xf3, 0x55, 0xdc, 0x69, 0x3e, 0xc1, 0xb8, 0x5b, 0x68, 0x5b, 0x97,
0xd8, 0x45, 0x22, 0x58, 0xfa, 0xa0, 0xec, 0xea, 0x90, 0x25, 0xf6, 0x2e, 0xba, 0xde, 0xd5, 0x43,
0x0d, 0xfd, 0x08, 0x66, 0x68, 0x6b, 0x28, 0xd7, 0x63, 0x56, 0x6e, 0x17, 0xcd, 0x8a, 0x2f, 0x3a,
0xf8, 0xbe, 0x86, 0x3e, 0x83, 0xe9, 0x03, 0xec, 0xd1, 0x5d, 0xf6, 0xbd, 0xd0, 0x2f, 0x8a, 0x54,
0x3a, 0xbe, 0xfb, 0xf2, 0x35, 0xcd, 0x86, 0x6f, 0x09, 0x51, 0x09, 0x92, 0x9c, 0xdc, 0x45, 0x7a,
0x88, 0xde, 0x8d, 0x60, 0xb0, 0x14, 0x62, 0x70, 0x68, 0xb9, 0x1e, 0xda, 0x06, 0x60, 0x97, 0x62,
0x54, 0x8c, 0xf0, 0x1c, 0xd9, 0x21, 0xdd, 0xd1, 0x01, 0x49, 0x5d, 0x24, 0x35, 0xdd, 0x54, 0xee,
0x18, 0x63, 0xa1, 0x43, 0x98, 0xf7, 0xaf, 0xa8, 0x6e, 0xae, 0x44, 0x1c, 0xb7, 0x8f, 0x61, 0x51,
0xbc, 0xd3, 0xf8, 0xd9, 0x08, 0xc5, 0xe5, 0x27, 0x7f, 0x25, 0x18, 0x1a, 0x86, 0xac, 0x4c, 0xab,
0x66, 0x17, 0x74, 0x4f, 0x62, 0x12, 0x99, 0x14, 0xb3, 0xdf, 0x1b, 0x81, 0xc1, 0xc2, 0xe2, 0x43,
0xed, 0x7d, 0x0d, 0x7d, 0x01, 0x73, 0x4a, 0xcc, 0x44, 0xa2, 0x8a, 0x8d, 0x4a, 0x18, 0xd9, 0x8d,
0xe8, 0x41, 0x1e, 0x66, 0xf7, 0x89, 0xba, 0x5e, 0xa8, 0xdb, 0x2b, 0x1b, 0xd5, 0xd5, 0xc5, 0x1a,
0x88, 0xb3, 0xe2, 0x99, 0x3b, 0x44, 0xb2, 0x07, 0x4b, 0xfc, 0xf1, 0x43, 0xf9, 0x25, 0x84, 0x98,
0xfe, 0xb0, 0x58, 0xeb, 0x3f, 0x86, 0x25, 0xbe, 0x96, 0x0a, 0x9b, 0xb4, 0xff, 0x30, 0xcf, 0x5b,
0x89, 0x62, 0x19, 0x7c, 0x01, 0x2b, 0xd5, 0x90, 0x3e, 0xac, 0x61, 0x6b, 0x5d, 0x65, 0x21, 0x75,
0x86, 0xc5, 0xf2, 0x7a, 0x02, 0xa8, 0xda, 0x3b, 0xbd, 0xb0, 0x7c, 0x76, 0x97, 0x16, 0x7e, 0x85,
0xee, 0x86, 0x54, 0x22, 0x40, 0x8a, 0x46, 0xc3, 0x67, 0x36, 0x46, 0x63, 0x54, 0x63, 0x8f, 0x6f,
0xac, 0xaf, 0xc3, 0xec, 0x9a, 0xa7, 0x56, 0xdb, 0xf2, 0x2c, 0x4c, 0xdc, 0x42, 0x26, 0x90, 0x87,
0xc4, 0x0a, 0xae, 0xc7, 0x62, 0xa0, 0xcf, 0x61, 0xee, 0x00, 0x7b, 0x41, 0xf3, 0x1b, 0x5a, 0x1b,
0x6a, 0x97, 0xe3, 0xeb, 0x26, 0x2e, 0xbd, 0xd4, 0x8e, 0xbb, 0x0a, 0xa4, 0x8f, 0xbb, 0x4d, 0xd3,
0xc3, 0x12, 0x8b, 0xbb, 0x43, 0x2c, 0x38, 0x8a, 0xe9, 0x98, 0x17, 0x6e, 0xac, 0xb5, 0xb6, 0x61,
0xe2, 0xc8, 0xea, 0xb4, 0x90, 0xb8, 0x19, 0x93, 0xda, 0x96, 0xb2, 0x4b, 0x0a, 0x8c, 0xbb, 0x9e,
0x07, 0xb9, 0x6b, 0xba, 0xbe, 0xd0, 0x8f, 0xfd, 0x52, 0xe5, 0x26, 0xdd, 0x61, 0x59, 0x69, 0xdf,
0x47, 0x23, 0xd6, 0x77, 0xd0, 0xcf, 0xe8, 0x3a, 0x0c, 0x63, 0xa0, 0xfb, 0x7c, 0xae, 0x51, 0xad,
0x63, 0xd9, 0x3b, 0xb1, 0x33, 0xd4, 0x77, 0xd0, 0x89, 0x78, 0x00, 0x8c, 0xe0, 0xfe, 0x40, 0xe9,
0x4a, 0x79, 0xcd, 0x09, 0xb6, 0x69, 0x9c, 0xa7, 0xbf, 0xc8, 0xb5, 0x12, 0x48, 0x2b, 0x75, 0xe6,
0x64, 0xd5, 0x5f, 0x05, 0x43, 0x3b, 0x34, 0xb2, 0xd3, 0x7e, 0x50, 0xb4, 0xaa, 0x52, 0xb8, 0xd1,
0x24, 0xef, 0x6b, 0x68, 0x07, 0x80, 0x49, 0x49, 0x27, 0x52, 0x87, 0x63, 0x57, 0x7f, 0x87, 0x84,
0xff, 0xe6, 0x2d, 0x89, 0x3e, 0x17, 0x29, 0x80, 0x12, 0x65, 0x94, 0xf3, 0x91, 0xac, 0x55, 0x1c,
0x7d, 0x05, 0xd2, 0x85, 0x06, 0x0d, 0x68, 0x7e, 0xb3, 0x10, 0xda, 0xf4, 0x37, 0x8b, 0x3a, 0x20,
0x78, 0xad, 0x84, 0x7b, 0x8f, 0x0e, 0x31, 0x29, 0x78, 0xcb, 0xb0, 0xe6, 0xa7, 0xa6, 0xd0, 0x50,
0x34, 0x45, 0xac, 0x50, 0x7b, 0xb0, 0x5c, 0x32, 0x3b, 0x0d, 0xdc, 0x7e, 0x33, 0x36, 0x1f, 0xd3,
0x9d, 0x2d, 0x35, 0x52, 0xad, 0x86, 0xe9, 0xf9, 0xc6, 0x16, 0x0d, 0xe8, 0x12, 0x6a, 0x01, 0x16,
0x98, 0x11, 0x03, 0xb3, 0xc4, 0x51, 0xc7, 0x4d, 0xff, 0x08, 0xe6, 0xf7, 0x48, 0xe4, 0xeb, 0x35,
0x2d, 0x56, 0x22, 0x23, 0xb5, 0x76, 0x8a, 0x25, 0x2c, 0xc3, 0x22, 0x4f, 0x04, 0x41, 0x87, 0x91,
0x1f, 0x7c, 0x87, 0x9b, 0xb8, 0xb2, 0xcb, 0x82, 0xad, 0xdc, 0x8c, 0x24, 0xd2, 0x9c, 0xd2, 0x4e,
0xe3, 0xa7, 0xb9, 0xa8, 0x46, 0x1f, 0x3f, 0xcd, 0x45, 0x77, 0xe0, 0x14, 0x61, 0x21, 0xd4, 0x49,
0x83, 0xee, 0x8a, 0x64, 0x1b, 0xd9, 0x61, 0x13, 0x51, 0xb0, 0x94, 0x85, 0x55, 0x87, 0x79, 0x44,
0xb7, 0xd5, 0xc4, 0xda, 0xe8, 0xc8, 0xcf, 0x72, 0x72, 0x8f, 0x0c, 0x52, 0x2f, 0x08, 0xa2, 0xfa,
0x67, 0x62, 0x39, 0x56, 0xc9, 0x59, 0x46, 0xed, 0x2e, 0x41, 0x9b, 0xbe, 0x45, 0x22, 0x5b, 0x68,
0xb2, 0xb9, 0xd8, 0x71, 0x6e, 0x34, 0x69, 0x01, 0xd8, 0xaf, 0xbb, 0x85, 0x17, 0x40, 0xee, 0x45,
0x18, 0x5a, 0x00, 0xb5, 0xc5, 0xe0, 0x80, 0x3e, 0x26, 0x49, 0x6d, 0x22, 0x28, 0x46, 0x95, 0xec,
0xdd, 0x28, 0x3e, 0xc1, 0x4a, 0x56, 0x21, 0x1d, 0xee, 0xb2, 0xf0, 0x35, 0x8d, 0x69, 0x17, 0xf1,
0x35, 0x8d, 0x6d, 0xcf, 0xf8, 0x02, 0xd2, 0xe1, 0x16, 0x0b, 0x9f, 0x69, 0x4c, 0xef, 0x45, 0xec,
0x52, 0xec, 0xc3, 0xb2, 0xba, 0x80, 0xd7, 0xe8, 0x1b, 0x5f, 0xc9, 0xcc, 0x29, 0x8d, 0x15, 0x48,
0xa4, 0x86, 0x50, 0x0f, 0xc7, 0x90, 0xf5, 0x23, 0x1a, 0x3c, 0x98, 0xf5, 0xa5, 0x26, 0x8d, 0x9b,
0x58, 0x3f, 0xaa, 0xa7, 0xc3, 0x37, 0x94, 0x24, 0x97, 0x88, 0xb8, 0xe1, 0x81, 0xdb, 0x18, 0xea,
0x26, 0xa2, 0xc5, 0xf1, 0xd9, 0x85, 0x19, 0xa9, 0xbb, 0x03, 0xad, 0x2b, 0x66, 0x52, 0x3c, 0x3e,
0xab, 0x28, 0xa7, 0x3a, 0x7b, 0x09, 0x66, 0xe5, 0x1e, 0x91, 0x58, 0x29, 0xee, 0x0c, 0xf3, 0x70,
0xa5, 0x6a, 0x7a, 0xde, 0xb7, 0x02, 0x93, 0x66, 0x23, 0x6c, 0x1c, 0x45, 0xa0, 0x78, 0x95, 0x90,
0x6c, 0x9a, 0x6b, 0x44, 0x8a, 0xcf, 0x44, 0x4b, 0x2c, 0x27, 0xab, 0xbf, 0x68, 0x1b, 0xf3, 0xfb,
0xba, 0x23, 0xa2, 0xd5, 0x42, 0xa8, 0xa9, 0x05, 0x49, 0x5e, 0x12, 0xd1, 0x08, 0x92, 0xdd, 0x8c,
0x1b, 0xe6, 0x66, 0x3a, 0x84, 0xc5, 0xa1, 0x9e, 0x16, 0x94, 0x53, 0xe2, 0xf1, 0x70, 0x73, 0xca,
0x88, 0xf3, 0xdf, 0xe2, 0x50, 0x43, 0x8b, 0xcf, 0x2d, 0xae, 0xd5, 0x25, 0x96, 0x5b, 0x0d, 0x56,
0x22, 0x9b, 0x5c, 0xfc, 0xfa, 0x70, 0x54, 0x0b, 0x4c, 0x2c, 0xd7, 0x9f, 0x01, 0x1a, 0x6e, 0x48,
0xf1, 0x4f, 0x84, 0xb1, 0x4d, 0x33, 0xfe, 0x89, 0x70, 0x44, 0x37, 0xcb, 0x21, 0x2c, 0x47, 0x75,
0xa3, 0x20, 0x5d, 0xb1, 0x67, 0x64, 0x37, 0x49, 0x44, 0x92, 0x33, 0xc4, 0xa6, 0x8c, 0xe1, 0x36,
0xa2, 0x37, 0x25, 0x56, 0xf9, 0x9f, 0x8b, 0x8e, 0xa3, 0xe1, 0x1e, 0x12, 0xbf, 0x2e, 0xbe, 0xa6,
0xc9, 0x64, 0x44, 0xb9, 0xb1, 0x50, 0xb5, 0x5a, 0x1d, 0xa9, 0xdd, 0xc3, 0x2f, 0x36, 0x86, 0xfb,
0x4c, 0xfc, 0x00, 0x10, 0xd5, 0x1d, 0xf2, 0x1c, 0x96, 0x45, 0x26, 0x94, 0x9b, 0x2a, 0xd0, 0x10,
0x4d, 0xd0, 0xf3, 0xe1, 0x07, 0x83, 0xc8, 0x2e, 0x0c, 0x56, 0xad, 0xd3, 0xbf, 0x9e, 0x20, 0x55,
0xeb, 0x52, 0xb7, 0x43, 0x56, 0x6d, 0x8c, 0x40, 0x9f, 0xd0, 0x6a, 0x9d, 0x35, 0xa5, 0xc6, 0xed,
0xf5, 0x35, 0x95, 0x53, 0xe0, 0x06, 0x3b, 0xe2, 0xfe, 0x85, 0x4e, 0xa8, 0x72, 0xbe, 0xbe, 0x00,
0xa7, 0x44, 0x6a, 0x01, 0x2e, 0x0b, 0x1a, 0x7f, 0x42, 0x9e, 0x95, 0x9f, 0x8a, 0x7c, 0x5b, 0x45,
0x3c, 0x46, 0xf9, 0xb6, 0x8a, 0x7a, 0x5b, 0xa2, 0xf5, 0x5e, 0x4d, 0xd4, 0x57, 0x01, 0xbf, 0xbb,
0x23, 0x1f, 0x87, 0xb2, 0x9b, 0xa3, 0x5f, 0x54, 0xa4, 0x2a, 0x32, 0x78, 0xcb, 0x90, 0x8b, 0x98,
0xa1, 0x97, 0x0f, 0x39, 0x8d, 0x46, 0x3c, 0x7f, 0x3c, 0xa5, 0x37, 0xc6, 0xcf, 0x2b, 0xbb, 0x25,
0xfe, 0x57, 0x1c, 0x6c, 0x67, 0xe8, 0xe2, 0x4a, 0xfa, 0x3d, 0xba, 0xc0, 0x7a, 0x0c, 0x45, 0x21,
0xac, 0xe7, 0x51, 0x95, 0xde, 0xbd, 0x28, 0xd0, 0x88, 0xbb, 0xab, 0x08, 0x86, 0xd9, 0x68, 0x86,
0xf4, 0x1e, 0x8e, 0x06, 0x7d, 0xe2, 0x07, 0xaa, 0x98, 0x31, 0x32, 0x8c, 0xca, 0x1d, 0xcc, 0xaa,
0xd1, 0x6c, 0x84, 0x74, 0xd7, 0x39, 0x08, 0xb3, 0x58, 0xb5, 0xf0, 0xf4, 0xf0, 0xb5, 0x2c, 0xa6,
0x10, 0xfa, 0x16, 0x53, 0xa0, 0xb7, 0xb3, 0x58, 0x88, 0xa1, 0x6a, 0x31, 0x55, 0xcc, 0x18, 0x19,
0xae, 0xb7, 0x58, 0x34, 0x9b, 0x9b, 0x5a, 0xec, 0x4b, 0x9a, 0x29, 0x0e, 0xe8, 0xef, 0xf0, 0xdd,
0xca, 0x66, 0x19, 0x51, 0xf7, 0xa8, 0xa4, 0xf5, 0x1d, 0xf4, 0x82, 0x76, 0xd2, 0x86, 0xe0, 0x37,
0xb3, 0xdb, 0x46, 0x1c, 0x53, 0x6a, 0xb9, 0x0a, 0xac, 0x30, 0xcb, 0x85, 0xc5, 0x8d, 0x95, 0x25,
0x56, 0xed, 0x03, 0x91, 0x76, 0xc3, 0xac, 0x6e, 0x6b, 0xbf, 0x5d, 0xea, 0x22, 0x35, 0x87, 0x54,
0x35, 0xcd, 0xe1, 0x92, 0x47, 0x65, 0x22, 0x6e, 0xcb, 0x54, 0xf4, 0x7a, 0x1e, 0x55, 0xe8, 0x2a,
0xa8, 0xe0, 0x51, 0x35, 0x61, 0x34, 0x1b, 0x6a, 0xa4, 0xb2, 0xc8, 0xcf, 0x21, 0x99, 0xe2, 0xe6,
0x8e, 0x17, 0xca, 0x2f, 0x98, 0x6f, 0xa8, 0x5d, 0x9c, 0x89, 0x58, 0x9e, 0x61, 0xf5, 0xe9, 0x75,
0x96, 0x09, 0xff, 0x7d, 0x25, 0xf4, 0xbb, 0x90, 0x12, 0xc4, 0xd7, 0x1b, 0x24, 0x4c, 0x4d, 0x0d,
0xf2, 0x39, 0xcc, 0x70, 0x83, 0x50, 0x09, 0xe2, 0x66, 0x8a, 0x15, 0xff, 0x33, 0x98, 0xe1, 0x66,
0x18, 0xa9, 0x41, 0x1c, 0x79, 0x9d, 0xf6, 0x06, 0xc7, 0xfd, 0xfd, 0x93, 0x38, 0x8d, 0xae, 0xfd,
0xeb, 0x2b, 0x84, 0x6f, 0x35, 0x9e, 0xef, 0xb5, 0xf4, 0x23, 0x0a, 0xd2, 0xf5, 0xe0, 0x75, 0x2e,
0xf4, 0xa7, 0x52, 0x62, 0xc5, 0xbd, 0xee, 0xaf, 0xb4, 0x10, 0xae, 0xd5, 0x58, 0xae, 0xd7, 0x51,
0x8f, 0x8a, 0x81, 0xf4, 0xe2, 0xb2, 0xd0, 0xf3, 0xce, 0x8e, 0x1c, 0xfc, 0x12, 0x3b, 0xb8, 0xd3,
0xc0, 0xb7, 0x3e, 0xb8, 0xec, 0x50, 0x1f, 0xe3, 0x4f, 0x5f, 0x52, 0xc5, 0xa3, 0xbc, 0x4d, 0x66,
0xe7, 0xe4, 0x57, 0x30, 0x17, 0x15, 0x58, 0xaa, 0x91, 0x5f, 0x31, 0xa5, 0x2b, 0x90, 0xc8, 0xe7,
0xcd, 0x10, 0x8b, 0x62, 0xfa, 0xdb, 0xff, 0xda, 0xd4, 0xbe, 0xfd, 0x6e, 0x53, 0xfb, 0xd7, 0xef,
0x36, 0xb5, 0xdf, 0x7e, 0xb7, 0xa9, 0x9d, 0x4e, 0xd1, 0xf1, 0x9d, 0xff, 0x09, 0x00, 0x00, 0xff,
0xff, 0xbd, 0xc5, 0x66, 0x26, 0x09, 0x4f, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.

View file

@ -375,8 +375,8 @@ message FlushAndCloseStream {}
message GetAppServersRequest {
// Namespace is the namespace for application.
string Namespace = 1 [ (gogoproto.jsontag) = "namespace" ];
// SkipValidation is used to skip JSON schema validation.
bool SkipValidation = 2 [ (gogoproto.jsontag) = "skip_validation" ];
// DEPRECATED: SkipValidation is used to skip JSON schema validation.
bool SkipValidation = 2 [ deprecated = true, (gogoproto.jsontag) = "skip_validation" ];
}
// GetAppServersResponse contains all requested application servers.
@ -511,8 +511,8 @@ message DeleteAllKubeServicesRequest {}
message GetDatabaseServersRequest {
// Namespace is the database server namespace.
string Namespace = 1 [ (gogoproto.jsontag) = "namespace" ];
// SkipValidation allows to turn off JSON schema validation.
bool SkipValidation = 2 [ (gogoproto.jsontag) = "skip_validation" ];
// DEPRECATED: SkipValidation allows to turn off JSON schema validation.
bool SkipValidation = 2 [ deprecated = true, (gogoproto.jsontag) = "skip_validation" ];
}
// GetDatabaseServersResponse contains all registered database servers.

View file

@ -267,6 +267,9 @@ func (r *AccessRequestV3) CheckAndSetDefaults() error {
if err := r.Metadata.CheckAndSetDefaults(); err != nil {
return trace.Wrap(err)
}
if r.Version == "" {
r.Version = V3
}
if r.GetState().IsNone() {
if err := r.SetState(RequestState_PENDING); err != nil {
return trace.Wrap(err)

View file

@ -249,6 +249,9 @@ func (c *AuthPreferenceV2) CheckAndSetDefaults() error {
if err != nil {
return trace.Wrap(err)
}
if c.Version == "" {
c.Version = V2
}
// Make sure origin value is always set.
if c.Origin() == "" {

View file

@ -361,6 +361,9 @@ func (ca *CertAuthorityV2) CheckAndSetDefaults() error {
if err != nil {
return trace.Wrap(err)
}
if ca.Version == "" {
ca.Version = V2
}
if err = ca.ID().Check(); err != nil {
return trace.Wrap(err)

View file

@ -208,7 +208,14 @@ func (c *ClusterConfigV3) SetLocalAuth(b bool) {
// CheckAndSetDefaults checks validity of all parameters and sets defaults.
func (c *ClusterConfigV3) CheckAndSetDefaults() error {
// make sure we have defaults for all metadata fields
return trace.Wrap(c.Metadata.CheckAndSetDefaults())
err := c.Metadata.CheckAndSetDefaults()
if err != nil {
return trace.Wrap(err)
}
if c.Version == "" {
c.Version = V3
}
return nil
}
// HasNetworkingConfig returns true if embedded networking configuration is set.

View file

@ -134,6 +134,9 @@ func (c *ClusterNameV2) CheckAndSetDefaults() error {
if err != nil {
return trace.Wrap(err)
}
if c.Version == "" {
c.Version = V2
}
if c.Spec.ClusterName == "" {
return trace.BadParameter("cluster name is required")

View file

@ -296,6 +296,9 @@ func (s *DatabaseServerV3) CheckAndSetDefaults() error {
if err := s.Metadata.CheckAndSetDefaults(); err != nil {
return trace.Wrap(err)
}
if s.Version == "" {
s.Version = V3
}
if s.Kind == "" {
return trace.BadParameter("database server %q kind is empty", s.GetName())
}

View file

@ -159,6 +159,12 @@ func (c *GithubConnectorV3) CheckAndSetDefaults() error {
if err := c.Metadata.CheckAndSetDefaults(); err != nil {
return trace.Wrap(err)
}
if c.Version == "" {
c.Version = V3
}
if c.Kind == "" {
c.Kind = KindGithubConnector
}
return nil
}

View file

@ -39,6 +39,9 @@ func (n *Namespace) CheckAndSetDefaults() error {
if err := n.Metadata.CheckAndSetDefaults(); err != nil {
return trace.Wrap(err)
}
if n.Version == "" {
n.Version = V1
}
isValid := IsValidNamespace(n.Metadata.Name)
if !isValid {
return trace.BadParameter("namespace %q is invalid", n.Metadata.Name)

View file

@ -371,6 +371,9 @@ func (o *OIDCConnectorV2) CheckAndSetDefaults() error {
if err != nil {
return trace.Wrap(err)
}
if o.Version == "" {
o.Version = V2
}
err = o.Check()
if err != nil {

View file

@ -131,6 +131,9 @@ func (r *PluginDataV3) CheckAndSetDefaults() error {
if err := r.Metadata.CheckAndSetDefaults(); err != nil {
return trace.Wrap(err)
}
if r.Version == "" {
r.Version = V3
}
if r.SubKind == "" {
return trace.BadParameter("plugin data missing subkind")
}

View file

@ -79,6 +79,9 @@ func (p *ProvisionTokenV2) CheckAndSetDefaults() error {
if err != nil {
return trace.Wrap(err)
}
if p.Version == "" {
p.Version = V2
}
if len(p.Spec.Roles) == 0 {
return trace.BadParameter("provisioning token is missing roles")
}

View file

@ -20,6 +20,8 @@ import (
"fmt"
"time"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/api/defaults"
)
@ -86,7 +88,13 @@ func (c *RemoteClusterV3) SetResourceID(id int64) {
// CheckAndSetDefaults checks and sets default values
func (c *RemoteClusterV3) CheckAndSetDefaults() error {
return c.Metadata.CheckAndSetDefaults()
if err := c.Metadata.CheckAndSetDefaults(); err != nil {
return trace.Wrap(err)
}
if c.Version == "" {
c.Version = V3
}
return nil
}
// GetLastHeartbeat returns last heartbeat of the cluster

View file

@ -20,6 +20,8 @@ import (
"fmt"
"time"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/api/defaults"
)
@ -147,7 +149,13 @@ func (u *ResetPasswordTokenV3) SetSubKind(s string) {
// CheckAndSetDefaults checks and set default values for any missing fields.
func (u ResetPasswordTokenV3) CheckAndSetDefaults() error {
return u.Metadata.CheckAndSetDefaults()
if err := u.Metadata.CheckAndSetDefaults(); err != nil {
return trace.Wrap(err)
}
if u.Version == "" {
u.Version = V3
}
return nil
}
// // String represents a human readable version of the token

View file

@ -153,7 +153,13 @@ func (u *ResetPasswordTokenSecretsV3) SetSubKind(s string) {
// CheckAndSetDefaults checks and set default values for any missing fields.
func (u ResetPasswordTokenSecretsV3) CheckAndSetDefaults() error {
return u.Metadata.CheckAndSetDefaults()
if err := u.Metadata.CheckAndSetDefaults(); err != nil {
return trace.Wrap(err)
}
if u.Version == "" {
u.Version = V3
}
return nil
}
// // String represents a human readable version of the token secrets

View file

@ -501,6 +501,9 @@ func (r *RoleV3) CheckAndSetDefaults() error {
if err != nil {
return trace.Wrap(err)
}
if r.Version == "" {
r.Version = V3
}
// Make sure all fields have defaults.
if r.Spec.Options.CertificateFormat == "" {

View file

@ -337,6 +337,9 @@ func (o *SAMLConnectorV2) CheckAndSetDefaults() error {
if err := o.Metadata.CheckAndSetDefaults(); err != nil {
return trace.Wrap(err)
}
if o.Version == "" {
o.Version = V2
}
if o.Metadata.Name == constants.Local {
return trace.BadParameter("ID: invalid connector name, %v is a reserved name", constants.Local)
}

View file

@ -285,6 +285,9 @@ func (c *SemaphoreV3) CheckAndSetDefaults() error {
if err != nil {
return trace.Wrap(err)
}
if c.Version == "" {
c.Version = V3
}
// While theoretically there are scenarios with non-expiring semaphores
// however the flow don't need them right now, and they add a lot of edge
// cases, so the code does not support them.

View file

@ -311,6 +311,9 @@ func (s *ServerV2) CheckAndSetDefaults() error {
if err != nil {
return trace.Wrap(err)
}
if s.Version == "" {
s.Version = V2
}
if s.Kind == "" {
return trace.BadParameter("server Kind is empty")
}

View file

@ -177,6 +177,9 @@ func (ws *WebSessionV2) CheckAndSetDefaults() error {
if err != nil {
return trace.Wrap(err)
}
if ws.Version == "" {
ws.Version = V2
}
if ws.Spec.User == "" {
return trace.BadParameter("missing User")
}
@ -450,6 +453,9 @@ func (r *WebTokenV3) CheckAndSetDefaults() error {
if err := r.Metadata.CheckAndSetDefaults(); err != nil {
return trace.Wrap(err)
}
if r.Version == "" {
r.Version = V3
}
if r.Spec.User == "" {
return trace.BadParameter("User required")
}

View file

@ -134,6 +134,9 @@ func (c *StaticTokensV2) CheckAndSetDefaults() error {
if err != nil {
return trace.Wrap(err)
}
if c.Version == "" {
c.Version = V2
}
return nil
}

View file

@ -85,6 +85,9 @@ func (c *TrustedClusterV2) CheckAndSetDefaults() error {
if err := c.Metadata.CheckAndSetDefaults(); err != nil {
return trace.Wrap(err)
}
if c.Version == "" {
c.Version = V2
}
// This is to force users to migrate
if len(c.Spec.Roles) != 0 && len(c.Spec.RoleMap) != 0 {
return trace.BadParameter("should set either 'roles' or 'role_map', not both")

View file

@ -129,6 +129,9 @@ func (r *ReverseTunnelV2) CheckAndSetDefaults() error {
if err != nil {
return trace.Wrap(err)
}
if r.Version == "" {
r.Version = V2
}
err = r.Check()
if err != nil {

View file

@ -155,6 +155,9 @@ func (r *TunnelConnectionV2) CheckAndSetDefaults() error {
if err != nil {
return trace.Wrap(err)
}
if r.Version == "" {
r.Version = V2
}
err = r.Check()
if err != nil {

View file

@ -176,6 +176,9 @@ func (u *UserV2) CheckAndSetDefaults() error {
if err != nil {
return trace.Wrap(err)
}
if u.Version == "" {
u.Version = V2
}
err = u.Check()
if err != nil {

View file

@ -305,7 +305,7 @@ func testAuditOn(t *testing.T, suite *integrationTestSuite) {
for {
select {
case <-tickCh:
nodesInSite, err := site.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
nodesInSite, err := site.GetNodes(ctx, defaults.Namespace)
if err != nil && !trace.IsNotFound(err) {
return trace.Wrap(err)
}
@ -763,7 +763,7 @@ func testUUIDBasedProxy(t *testing.T, suite *integrationTestSuite) {
for {
select {
case <-tickCh:
nodesInSite, err := site.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
nodesInSite, err := site.GetNodes(ctx, defaults.Namespace)
if err != nil && !trace.IsNotFound(err) {
return trace.Wrap(err)
}
@ -1767,7 +1767,7 @@ func testMapRoles(t *testing.T, suite *integrationTestSuite) {
// correct nodes that identity aware GetNodes is done in TestList.
var nodes []services.Server
for i := 0; i < 10; i++ {
nodes, err = aux.Process.GetAuthServer().GetNodes(ctx, defaults.Namespace, services.SkipValidation())
nodes, err = aux.Process.GetAuthServer().GetNodes(ctx, defaults.Namespace)
require.NoError(t, err)
if len(nodes) != 2 {
time.Sleep(100 * time.Millisecond)
@ -4314,7 +4314,7 @@ func testList(t *testing.T, suite *integrationTestSuite) {
for {
select {
case <-tickCh:
nodesInCluster, err := clt.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
nodesInCluster, err := clt.GetNodes(ctx, defaults.Namespace)
if err != nil && !trace.IsNotFound(err) {
return trace.Wrap(err)
}

View file

@ -436,16 +436,8 @@ func (s *APIServer) getNodes(auth ClientI, w http.ResponseWriter, r *http.Reques
if !services.IsValidNamespace(namespace) {
return nil, trace.BadParameter("invalid namespace %q", namespace)
}
skipValidation, _, err := httplib.ParseBool(r.URL.Query(), "skip_validation")
if err != nil {
return nil, trace.Wrap(err)
}
var opts []services.MarshalOption
if skipValidation {
opts = append(opts, services.SkipValidation())
}
servers, err := auth.GetNodes(r.Context(), namespace, opts...)
servers, err := auth.GetNodes(r.Context(), namespace)
if err != nil {
return nil, trace.Wrap(err)
}

View file

@ -336,7 +336,7 @@ func (a *Server) runPeriodicOperations() {
}
}
case <-heartbeatCheckTicker.Next():
nodes, err := a.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
nodes, err := a.GetNodes(ctx, defaults.Namespace)
if err != nil {
log.Errorf("Failed to load nodes for heartbeat metric calculation: %v", err)
}
@ -1092,10 +1092,6 @@ func (a *Server) ExtendWebSession(req WebSessionReq, identity tlsca.Identity) (s
return nil, trace.Wrap(err)
}
sess, err = services.ExtendWebSession(sess)
if err != nil {
return nil, trace.Wrap(err)
}
return sess, nil
}
@ -1732,7 +1728,7 @@ func (a *Server) DeleteNamespace(namespace string) error {
if namespace == defaults.Namespace {
return trace.AccessDenied("can't delete default namespace")
}
nodes, err := a.Presence.GetNodes(ctx, namespace, services.SkipValidation())
nodes, err := a.Presence.GetNodes(ctx, namespace)
if err != nil {
return trace.Wrap(err)
}
@ -2169,7 +2165,7 @@ func (a *Server) isMFARequired(ctx context.Context, checker services.AccessCheck
return nil, trace.BadParameter("empty Login field")
}
// Find the target node and check whether MFA is required.
nodes, err := a.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
nodes, err := a.GetNodes(ctx, defaults.Namespace)
if err != nil {
return nil, trace.Wrap(err)
}
@ -2237,7 +2233,7 @@ func (a *Server) isMFARequired(ctx context.Context, checker services.AccessCheck
if t.Database.ServiceName == "" {
return nil, trace.BadParameter("missing ServiceName field in a database-only UserCertsRequest")
}
dbs, err := a.GetDatabaseServers(ctx, defaults.Namespace, services.SkipValidation())
dbs, err := a.GetDatabaseServers(ctx, defaults.Namespace)
if err != nil {
return nil, trace.Wrap(err)
}

View file

@ -499,7 +499,7 @@ func (c *Client) GetCertAuthorities(caType services.CertAuthType, loadKeys bool,
}
re := make([]services.CertAuthority, len(items))
for i, raw := range items {
ca, err := services.UnmarshalCertAuthority(raw, services.SkipValidation())
ca, err := services.UnmarshalCertAuthority(raw)
if err != nil {
return nil, trace.Wrap(err)
}
@ -520,8 +520,7 @@ func (c *Client) GetCertAuthority(id services.CertAuthID, loadSigningKeys bool,
if err != nil {
return nil, trace.Wrap(err)
}
return services.UnmarshalCertAuthority(
out.Bytes(), services.SkipValidation())
return services.UnmarshalCertAuthority(out.Bytes())
}
// DeleteCertAuthority deletes cert authority by ID
@ -669,7 +668,7 @@ func (c *Client) GetReverseTunnels(opts ...services.MarshalOption) ([]services.R
}
tunnels := make([]services.ReverseTunnel, len(items))
for i, raw := range items {
tunnel, err := services.UnmarshalReverseTunnel(raw, services.SkipValidation())
tunnel, err := services.UnmarshalReverseTunnel(raw)
if err != nil {
return nil, trace.Wrap(err)
}
@ -718,7 +717,7 @@ func (c *Client) GetTunnelConnections(clusterName string, opts ...services.Marsh
}
conns := make([]services.TunnelConnection, len(items))
for i, raw := range items {
conn, err := services.UnmarshalTunnelConnection(raw, services.SkipValidation())
conn, err := services.UnmarshalTunnelConnection(raw)
if err != nil {
return nil, trace.Wrap(err)
}
@ -739,7 +738,7 @@ func (c *Client) GetAllTunnelConnections(opts ...services.MarshalOption) ([]serv
}
conns := make([]services.TunnelConnection, len(items))
for i, raw := range items {
conn, err := services.UnmarshalTunnelConnection(raw, services.SkipValidation())
conn, err := services.UnmarshalTunnelConnection(raw)
if err != nil {
return nil, trace.Wrap(err)
}
@ -802,7 +801,7 @@ func (c *Client) GetRemoteClusters(opts ...services.MarshalOption) ([]services.R
}
conns := make([]services.RemoteCluster, len(items))
for i, raw := range items {
conn, err := services.UnmarshalRemoteCluster(raw, services.SkipValidation())
conn, err := services.UnmarshalRemoteCluster(raw)
if err != nil {
return nil, trace.Wrap(err)
}
@ -820,7 +819,7 @@ func (c *Client) GetRemoteCluster(clusterName string) (services.RemoteCluster, e
if err != nil {
return nil, trace.Wrap(err)
}
return services.UnmarshalRemoteCluster(out.Bytes(), services.SkipValidation())
return services.UnmarshalRemoteCluster(out.Bytes())
}
// DeleteRemoteCluster deletes remote cluster by name
@ -877,7 +876,7 @@ func (c *Client) GetAuthServers() ([]services.Server, error) {
}
re := make([]services.Server, len(items))
for i, raw := range items {
server, err := services.UnmarshalServer(raw, services.KindAuthServer, services.SkipValidation())
server, err := services.UnmarshalServer(raw, services.KindAuthServer)
if err != nil {
return nil, trace.Wrap(err)
}
@ -922,7 +921,7 @@ func (c *Client) GetProxies() ([]services.Server, error) {
}
re := make([]services.Server, len(items))
for i, raw := range items {
server, err := services.UnmarshalServer(raw, services.KindProxy, services.SkipValidation())
server, err := services.UnmarshalServer(raw, services.KindProxy)
if err != nil {
return nil, trace.Wrap(err)
}
@ -1493,7 +1492,7 @@ func (c *Client) GetNamespace(name string) (*services.Namespace, error) {
if err != nil {
return nil, trace.Wrap(err)
}
return services.UnmarshalNamespace(out.Bytes(), services.SkipValidation())
return services.UnmarshalNamespace(out.Bytes())
}
// UpsertNamespace upserts namespace
@ -1520,7 +1519,7 @@ func (c *Client) GetClusterConfig(opts ...services.MarshalOption) (services.Clus
return nil, trace.Wrap(err)
}
cc, err := services.UnmarshalClusterConfig(out.Bytes(), services.SkipValidation())
cc, err := services.UnmarshalClusterConfig(out.Bytes())
if err != nil {
return nil, trace.Wrap(err)
}
@ -1550,7 +1549,7 @@ func (c *Client) GetClusterName(opts ...services.MarshalOption) (services.Cluste
return nil, trace.Wrap(err)
}
cn, err := services.UnmarshalClusterName(out.Bytes(), services.SkipValidation())
cn, err := services.UnmarshalClusterName(out.Bytes())
if err != nil {
return nil, trace.Wrap(err)
}
@ -1592,7 +1591,7 @@ func (c *Client) GetStaticTokens() (services.StaticTokens, error) {
return nil, trace.Wrap(err)
}
st, err := services.UnmarshalStaticTokens(out.Bytes(), services.SkipValidation())
st, err := services.UnmarshalStaticTokens(out.Bytes())
if err != nil {
return nil, trace.Wrap(err)
}
@ -1734,12 +1733,7 @@ func (c *Client) CreateResetPasswordToken(ctx context.Context, req CreateResetPa
// GetAppServers gets all application servers.
func (c *Client) GetAppServers(ctx context.Context, namespace string, opts ...services.MarshalOption) ([]types.Server, error) {
cfg, err := services.CollectOptions(opts)
if err != nil {
return nil, trace.Wrap(err)
}
resp, err := c.APIClient.GetAppServers(ctx, namespace, cfg.SkipValidation)
resp, err := c.APIClient.GetAppServers(ctx, namespace)
if err != nil {
return nil, trail.FromGRPC(err)
}
@ -1749,12 +1743,7 @@ func (c *Client) GetAppServers(ctx context.Context, namespace string, opts ...se
// GetDatabaseServers returns all registered database proxy servers.
func (c *Client) GetDatabaseServers(ctx context.Context, namespace string, opts ...services.MarshalOption) ([]types.DatabaseServer, error) {
cfg, err := services.CollectOptions(opts)
if err != nil {
return nil, trace.Wrap(err)
}
resp, err := c.APIClient.GetDatabaseServers(ctx, namespace, cfg.SkipValidation)
resp, err := c.APIClient.GetDatabaseServers(ctx, namespace)
if err != nil {
return nil, trail.FromGRPC(err)
}

View file

@ -839,11 +839,7 @@ func (g *GRPCServer) GetDatabaseServers(ctx context.Context, req *proto.GetDatab
if err != nil {
return nil, trail.ToGRPC(err)
}
var opts []services.MarshalOption
if req.GetSkipValidation() {
opts = append(opts, services.SkipValidation())
}
databaseServers, err := auth.GetDatabaseServers(ctx, req.GetNamespace(), opts...)
databaseServers, err := auth.GetDatabaseServers(ctx, req.GetNamespace())
if err != nil {
return nil, trail.ToGRPC(err)
}
@ -934,12 +930,7 @@ func (g *GRPCServer) GetAppServers(ctx context.Context, req *proto.GetAppServers
return nil, trail.ToGRPC(err)
}
var opts []services.MarshalOption
if req.GetSkipValidation() {
opts = append(opts, services.SkipValidation())
}
appServers, err := auth.GetAppServers(ctx, req.GetNamespace(), opts...)
appServers, err := auth.GetAppServers(ctx, req.GetNamespace())
if err != nil {
return nil, trail.ToGRPC(err)
}

View file

@ -55,7 +55,7 @@ func (c *Client) GetRoles(ctx context.Context) ([]services.Role, error) {
}
roles := make([]services.Role, len(items))
for i, roleBytes := range items {
role, err := services.UnmarshalRole(roleBytes, services.SkipValidation())
role, err := services.UnmarshalRole(roleBytes)
if err != nil {
return nil, trace.Wrap(err)
}
@ -99,7 +99,7 @@ func (c *Client) GetRole(ctx context.Context, name string) (services.Role, error
if err != nil {
return nil, trace.Wrap(err)
}
role, err := services.UnmarshalRole(out.Bytes(), services.SkipValidation())
role, err := services.UnmarshalRole(out.Bytes())
if err != nil {
return nil, trace.Wrap(err)
}
@ -181,7 +181,7 @@ func (c *Client) GetToken(ctx context.Context, token string) (services.Provision
if err != nil {
return nil, trace.Wrap(err)
}
return services.UnmarshalProvisionToken(out.Bytes(), services.SkipValidation())
return services.UnmarshalProvisionToken(out.Bytes())
}
// DeleteToken deletes a given provisioning token on the auth server (CA). It
@ -240,7 +240,7 @@ func (c *Client) GetOIDCConnector(ctx context.Context, id string, withSecrets bo
if err != nil {
return nil, err
}
return services.UnmarshalOIDCConnector(out.Bytes(), services.SkipValidation())
return services.UnmarshalOIDCConnector(out.Bytes())
}
// GetOIDCConnectors gets OIDC connectors list
@ -264,7 +264,7 @@ func (c *Client) GetOIDCConnectors(ctx context.Context, withSecrets bool) ([]ser
}
connectors := make([]services.OIDCConnector, len(items))
for i, raw := range items {
connector, err := services.UnmarshalOIDCConnector(raw, services.SkipValidation())
connector, err := services.UnmarshalOIDCConnector(raw)
if err != nil {
return nil, trace.Wrap(err)
}
@ -331,7 +331,7 @@ func (c *Client) GetSAMLConnector(ctx context.Context, id string, withSecrets bo
if err != nil {
return nil, trace.Wrap(err)
}
return services.UnmarshalSAMLConnector(out.Bytes(), services.SkipValidation())
return services.UnmarshalSAMLConnector(out.Bytes())
}
// GetSAMLConnectors gets SAML connectors list
@ -355,7 +355,7 @@ func (c *Client) GetSAMLConnectors(ctx context.Context, withSecrets bool) ([]ser
}
connectors := make([]services.SAMLConnector, len(items))
for i, raw := range items {
connector, err := services.UnmarshalSAMLConnector(raw, services.SkipValidation())
connector, err := services.UnmarshalSAMLConnector(raw)
if err != nil {
return nil, trace.Wrap(err)
}
@ -485,7 +485,7 @@ func (c *Client) GetTrustedCluster(ctx context.Context, name string) (services.T
return nil, trace.Wrap(err)
}
trustedCluster, err := services.UnmarshalTrustedCluster(out.Bytes(), services.SkipValidation())
trustedCluster, err := services.UnmarshalTrustedCluster(out.Bytes())
if err != nil {
return nil, trace.Wrap(err)
}
@ -513,7 +513,7 @@ func (c *Client) GetTrustedClusters(ctx context.Context) ([]services.TrustedClus
}
trustedClusters := make([]services.TrustedCluster, len(items))
for i, bytes := range items {
trustedCluster, err := services.UnmarshalTrustedCluster(bytes, services.SkipValidation())
trustedCluster, err := services.UnmarshalTrustedCluster(bytes)
if err != nil {
return nil, trace.Wrap(err)
}
@ -604,14 +604,7 @@ func (c *Client) GetNodes(ctx context.Context, namespace string, opts ...service
return resp, nil
}
cfg, err := services.CollectOptions(opts)
if err != nil {
return nil, trace.Wrap(err)
}
out, err := c.Get(c.Endpoint("namespaces", namespace, "nodes"), url.Values{
"skip_validation": []string{fmt.Sprintf("%t", cfg.SkipValidation)},
})
out, err := c.Get(c.Endpoint("namespaces", namespace, "nodes"), url.Values{})
if err != nil {
return nil, trace.Wrap(err)
}
@ -625,7 +618,7 @@ func (c *Client) GetNodes(ctx context.Context, namespace string, opts ...service
s, err := services.UnmarshalServer(
raw,
services.KindNode,
services.AddOptions(opts, services.SkipValidation())...)
opts...)
if err != nil {
return nil, trace.Wrap(err)
}

View file

@ -556,11 +556,11 @@ func ClientCertPool(client AccessCache, clusterName string) (*x509.CertPool, err
pool := x509.NewCertPool()
var authorities []services.CertAuthority
if clusterName == "" {
hostCAs, err := client.GetCertAuthorities(services.HostCA, false, services.SkipValidation())
hostCAs, err := client.GetCertAuthorities(services.HostCA, false)
if err != nil {
return nil, trace.Wrap(err)
}
userCAs, err := client.GetCertAuthorities(services.UserCA, false, services.SkipValidation())
userCAs, err := client.GetCertAuthorities(services.UserCA, false)
if err != nil {
return nil, trace.Wrap(err)
}
@ -569,13 +569,13 @@ func ClientCertPool(client AccessCache, clusterName string) (*x509.CertPool, err
} else {
hostCA, err := client.GetCertAuthority(
services.CertAuthID{Type: services.HostCA, DomainName: clusterName},
false, services.SkipValidation())
false)
if err != nil {
return nil, trace.Wrap(err)
}
userCA, err := client.GetCertAuthority(
services.CertAuthID{Type: services.UserCA, DomainName: clusterName},
false, services.SkipValidation())
false)
if err != nil {
return nil, trace.Wrap(err)
}

View file

@ -19,7 +19,6 @@ package auth
import (
"context"
"encoding/json"
"fmt"
"strings"
"github.com/gravitational/teleport"
@ -64,9 +63,12 @@ func (p *ProcessStorage) GetState(role teleport.Role) (*StateV2, error) {
return nil, trace.Wrap(err)
}
var res StateV2
if err := utils.UnmarshalWithSchema(GetStateSchema(), &res, item.Value); err != nil {
if err := utils.FastUnmarshal(item.Value, &res); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := res.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
}
return &res, nil
}
@ -120,9 +122,12 @@ func (p *ProcessStorage) ReadIdentity(name string, role teleport.Role) (*Identit
return nil, trace.Wrap(err)
}
var res IdentityV2
if err := utils.UnmarshalWithSchema(GetIdentitySchema(), &res, item.Value); err != nil {
if err := utils.FastUnmarshal(item.Value, &res); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := res.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
}
return ReadIdentityFromKeyPair(&PackedKeys{
Key: res.Spec.Key,
Cert: res.Spec.SSHCert,
@ -241,43 +246,3 @@ type IdentitySpecV2 struct {
// authorized_keys format.
SSHCACerts [][]byte `json:"ssh_ca_certs,omitempty"`
}
// IdentitySpecV2Schema is a schema for identity spec.
const IdentitySpecV2Schema = `{
"type": "object",
"additionalProperties": false,
"required": ["key", "ssh_cert", "tls_cert", "tls_ca_certs"],
"properties": {
"key": {"type": "string"},
"ssh_cert": {"type": "string"},
"tls_cert": {"type": "string"},
"tls_ca_certs": {
"type": "array",
"items": {"type": "string"}
},
"ssh_ca_certs": {
"type": "array",
"items": {"type": "string"}
}
}
}`
// GetIdentitySchema returns JSON Schema for cert authorities.
func GetIdentitySchema() string {
return fmt.Sprintf(services.V2SchemaTemplate, services.MetadataSchema, IdentitySpecV2Schema, services.DefaultDefinitions)
}
// StateSpecV2Schema is a schema for local server state.
const StateSpecV2Schema = `{
"type": "object",
"additionalProperties": false,
"required": ["rotation"],
"properties": {
"rotation": %v
}
}`
// GetStateSchema returns JSON Schema for cert authorities.
func GetStateSchema() string {
return fmt.Sprintf(services.V2SchemaTemplate, services.MetadataSchema, fmt.Sprintf(StateSpecV2Schema, services.RotationSchema), services.DefaultDefinitions)
}

View file

@ -110,7 +110,7 @@ func (s *TLSSuite) TestRemoteBuiltinRole(c *check.C) {
// certificate authority is not recognized, because
// the trust has not been established yet
_, err = remoteProxy.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = remoteProxy.GetNodes(ctx, defaults.Namespace)
fixtures.ExpectConnectionProblem(c, err)
// after trust is established, things are good
@ -122,7 +122,7 @@ func (s *TLSSuite) TestRemoteBuiltinRole(c *check.C) {
TestBuiltin(teleport.RoleProxy), s.server.Addr(), certPool)
c.Assert(err, check.IsNil)
_, err = remoteProxy.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = remoteProxy.GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// remote auth server will get rejected even with established trust
@ -160,7 +160,7 @@ func (s *TLSSuite) TestAcceptedUsage(c *check.C) {
// certificate authority is not recognized, because
// the trust has not been established yet
_, err = client.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = client.GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// restricted clients can use restricted servers if restrictions
@ -170,7 +170,7 @@ func (s *TLSSuite) TestAcceptedUsage(c *check.C) {
client, err = tlsServer.NewClient(identity)
c.Assert(err, check.IsNil)
_, err = client.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = client.GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// restricted clients can will be rejected if usage does not match
@ -179,7 +179,7 @@ func (s *TLSSuite) TestAcceptedUsage(c *check.C) {
client, err = tlsServer.NewClient(identity)
c.Assert(err, check.IsNil)
_, err = client.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = client.GetNodes(ctx, defaults.Namespace)
fixtures.ExpectAccessDenied(c, err)
// restricted clients can will be rejected, for now if there is any mismatch,
@ -189,7 +189,7 @@ func (s *TLSSuite) TestAcceptedUsage(c *check.C) {
client, err = tlsServer.NewClient(identity)
c.Assert(err, check.IsNil)
_, err = client.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = client.GetNodes(ctx, defaults.Namespace)
fixtures.ExpectAccessDenied(c, err)
}
@ -288,11 +288,11 @@ func (s *TLSSuite) TestRemoteRotation(c *check.C) {
TestBuiltin(teleport.RoleProxy), s.server.Addr(), certPool)
c.Assert(err, check.IsNil)
_, err = newRemoteProxy.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = newRemoteProxy.GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// old proxy client is still trusted
_, err = s.server.CloneClient(remoteProxy).GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = s.server.CloneClient(remoteProxy).GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
}
@ -344,7 +344,7 @@ func (s *TLSSuite) TestAutoRotation(c *check.C) {
c.Assert(err, check.IsNil)
// client works before rotation is initiated
_, err = proxy.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = proxy.GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// starts rotation
@ -371,7 +371,7 @@ func (s *TLSSuite) TestAutoRotation(c *check.C) {
c.Assert(ca.GetRotation().Phase, check.Equals, services.RotationPhaseUpdateClients)
// old clients should work
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// new clients work as well
@ -391,14 +391,14 @@ func (s *TLSSuite) TestAutoRotation(c *check.C) {
c.Assert(ca.GetRotation().Phase, check.Equals, services.RotationPhaseUpdateServers)
// old clients should work
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// new clients work as well
newProxy, err := s.server.NewClient(TestBuiltin(teleport.RoleProxy))
c.Assert(err, check.IsNil)
_, err = newProxy.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = newProxy.GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// complete rotation - advance rotation by clock
@ -418,11 +418,11 @@ func (s *TLSSuite) TestAutoRotation(c *check.C) {
// connection instead of re-using the one from pool
// this is not going to be a problem in real teleport
// as it reloads the full server after reload
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.ErrorMatches, ".*bad certificate.*")
// new clients work
_, err = s.server.CloneClient(newProxy).GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = s.server.CloneClient(newProxy).GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
}
@ -438,7 +438,7 @@ func (s *TLSSuite) TestAutoFallback(c *check.C) {
c.Assert(err, check.IsNil)
// client works before rotation is initiated
_, err = proxy.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = proxy.GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// starts rotation
@ -494,7 +494,7 @@ func (s *TLSSuite) TestManualRotation(c *check.C) {
c.Assert(err, check.IsNil)
// client works before rotation is initiated
_, err = proxy.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = proxy.GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// can't jump to mid-phase
@ -519,7 +519,7 @@ func (s *TLSSuite) TestManualRotation(c *check.C) {
c.Assert(err, check.IsNil)
// old clients should work
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// clients reconnect
@ -532,14 +532,14 @@ func (s *TLSSuite) TestManualRotation(c *check.C) {
c.Assert(err, check.IsNil)
// old clients should work
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// new clients work as well
newProxy, err := s.server.NewClient(TestBuiltin(teleport.RoleProxy))
c.Assert(err, check.IsNil)
_, err = newProxy.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = newProxy.GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// can't jump to standy
@ -561,11 +561,11 @@ func (s *TLSSuite) TestManualRotation(c *check.C) {
c.Assert(err, check.IsNil)
// old clients should work
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// new clients work as well
_, err = s.server.CloneClient(newProxy).GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = s.server.CloneClient(newProxy).GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// complete rotation
@ -582,11 +582,11 @@ func (s *TLSSuite) TestManualRotation(c *check.C) {
// connection instead of re-using the one from pool
// this is not going to be a problem in real teleport
// as it reloads the full server after reload
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.ErrorMatches, ".*bad certificate.*")
// new clients work
_, err = s.server.CloneClient(newProxy).GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = s.server.CloneClient(newProxy).GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
}
@ -600,7 +600,7 @@ func (s *TLSSuite) TestRollback(c *check.C) {
c.Assert(err, check.IsNil)
// client works before rotation is initiated
_, err = proxy.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = proxy.GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// starts rotation
@ -628,7 +628,7 @@ func (s *TLSSuite) TestRollback(c *check.C) {
newProxy, err := s.server.NewClient(TestBuiltin(teleport.RoleProxy))
c.Assert(err, check.IsNil)
_, err = newProxy.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = newProxy.GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// advance rotation:
@ -651,7 +651,7 @@ func (s *TLSSuite) TestRollback(c *check.C) {
// new clients work, server still accepts the creds
// because new clients should re-register and receive new certs
_, err = s.server.CloneClient(newProxy).GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = s.server.CloneClient(newProxy).GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
// can't jump to other phases
@ -673,11 +673,11 @@ func (s *TLSSuite) TestRollback(c *check.C) {
c.Assert(err, check.IsNil)
// clients with new creds will no longer work
_, err = s.server.CloneClient(newProxy).GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = s.server.CloneClient(newProxy).GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.ErrorMatches, ".*bad certificate.*")
// clients with old creds will still work
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = s.server.CloneClient(proxy).GetNodes(ctx, defaults.Namespace)
c.Assert(err, check.IsNil)
}
@ -876,7 +876,7 @@ func (s *TLSSuite) TestNopUser(c *check.C) {
_, err = client.GetUsers(false)
fixtures.ExpectAccessDenied(c, err)
_, err = client.GetNodes(ctx, defaults.Namespace, services.SkipValidation())
_, err = client.GetNodes(ctx, defaults.Namespace)
fixtures.ExpectAccessDenied(c, err)
// Endpoints that allow current user access should return access denied to

View file

@ -502,7 +502,7 @@ func (a *Server) validateTrustedCluster(validateRequest *ValidateTrustedClusterR
for _, caType := range []services.CertAuthType{services.HostCA, services.UserCA} {
certAuthority, err := a.GetCertAuthority(
services.CertAuthID{Type: caType, DomainName: domainName},
false, services.SkipValidation())
false)
if err != nil {
return nil, trace.Wrap(err)
}

18
lib/cache/cache.go vendored
View file

@ -962,13 +962,13 @@ func (c *Cache) GetCertAuthority(id services.CertAuthID, loadSigningKeys bool, o
return nil, trace.Wrap(err)
}
defer rg.Release()
ca, err := rg.trust.GetCertAuthority(id, loadSigningKeys, services.AddOptions(opts, services.SkipValidation())...)
ca, err := rg.trust.GetCertAuthority(id, loadSigningKeys, opts...)
if trace.IsNotFound(err) && rg.IsCacheRead() {
// release read lock early
rg.Release()
// fallback is sane because method is never used
// in construction of derivative caches.
if ca, err := c.Config.Trust.GetCertAuthority(id, loadSigningKeys, services.AddOptions(opts, services.SkipValidation())...); err == nil {
if ca, err := c.Config.Trust.GetCertAuthority(id, loadSigningKeys, opts...); err == nil {
return ca, nil
}
}
@ -983,7 +983,7 @@ func (c *Cache) GetCertAuthorities(caType services.CertAuthType, loadSigningKeys
return nil, trace.Wrap(err)
}
defer rg.Release()
return rg.trust.GetCertAuthorities(caType, loadSigningKeys, services.AddOptions(opts, services.SkipValidation())...)
return rg.trust.GetCertAuthorities(caType, loadSigningKeys, opts...)
}
// GetStaticTokens gets the list of static tokens used to provision nodes.
@ -1003,7 +1003,7 @@ func (c *Cache) GetTokens(ctx context.Context, opts ...services.MarshalOption) (
return nil, trace.Wrap(err)
}
defer rg.Release()
return rg.provisioner.GetTokens(ctx, services.AddOptions(opts, services.SkipValidation())...)
return rg.provisioner.GetTokens(ctx, opts...)
}
// GetToken finds and returns token by ID
@ -1034,7 +1034,7 @@ func (c *Cache) GetClusterConfig(opts ...services.MarshalOption) (services.Clust
return nil, trace.Wrap(err)
}
defer rg.Release()
return rg.clusterConfig.GetClusterConfig(services.AddOptions(opts, services.SkipValidation())...)
return rg.clusterConfig.GetClusterConfig(opts...)
}
// GetClusterNetworkingConfig gets ClusterNetworkingConfig from the backend.
@ -1044,7 +1044,7 @@ func (c *Cache) GetClusterNetworkingConfig(ctx context.Context, opts ...services
return nil, trace.Wrap(err)
}
defer rg.Release()
return rg.clusterConfig.GetClusterNetworkingConfig(ctx, services.AddOptions(opts, services.SkipValidation())...)
return rg.clusterConfig.GetClusterNetworkingConfig(ctx, opts...)
}
// GetClusterName gets the name of the cluster from the backend.
@ -1054,7 +1054,7 @@ func (c *Cache) GetClusterName(opts ...services.MarshalOption) (services.Cluster
return nil, trace.Wrap(err)
}
defer rg.Release()
return rg.clusterConfig.GetClusterName(services.AddOptions(opts, services.SkipValidation())...)
return rg.clusterConfig.GetClusterName(opts...)
}
// GetRoles is a part of auth.AccessPoint implementation
@ -1144,7 +1144,7 @@ func (c *Cache) GetReverseTunnels(opts ...services.MarshalOption) ([]services.Re
return nil, trace.Wrap(err)
}
defer rg.Release()
return rg.presence.GetReverseTunnels(services.AddOptions(opts, services.SkipValidation())...)
return rg.presence.GetReverseTunnels(opts...)
}
// GetProxies is a part of auth.AccessPoint implementation
@ -1315,5 +1315,5 @@ func (c *Cache) GetSessionRecordingConfig(ctx context.Context, opts ...services.
return nil, trace.Wrap(err)
}
defer rg.Release()
return rg.clusterConfig.GetSessionRecordingConfig(ctx, services.AddOptions(opts, services.SkipValidation())...)
return rg.clusterConfig.GetSessionRecordingConfig(ctx, opts...)
}

View file

@ -433,7 +433,7 @@ func (c *reverseTunnel) erase(ctx context.Context) error {
}
func (c *reverseTunnel) fetch(ctx context.Context) (apply func(ctx context.Context) error, err error) {
resources, err := c.Presence.GetReverseTunnels(services.SkipValidation())
resources, err := c.Presence.GetReverseTunnels()
if err != nil {
return nil, trace.Wrap(err)
}
@ -804,7 +804,7 @@ func (c *certAuthority) fetch(ctx context.Context) (apply func(ctx context.Conte
}
func (c *certAuthority) fetchCertAuthorities(caType services.CertAuthType) (apply func(ctx context.Context) error, err error) {
authorities, err := c.Trust.GetCertAuthorities(caType, c.watch.LoadSecrets, services.SkipValidation())
authorities, err := c.Trust.GetCertAuthorities(caType, c.watch.LoadSecrets)
if err != nil {
// DELETE IN: 5.1
//

View file

@ -1444,7 +1444,7 @@ func (tc *TeleportClient) Join(ctx context.Context, namespace string, sessionID
serverID := session.Parties[0].ServerID
// find a server address by its ID
nodes, err := site.GetNodes(ctx, namespace, services.SkipValidation())
nodes, err := site.GetNodes(ctx, namespace)
if err != nil {
return trace.Wrap(err)
}

View file

@ -122,7 +122,7 @@ func (proxy *ProxyClient) GetLeafClusters(ctx context.Context) ([]services.Remot
}
defer clt.Close()
remoteClusters, err := clt.GetRemoteClusters(services.SkipValidation())
remoteClusters, err := clt.GetRemoteClusters()
if err != nil {
return nil, trace.Wrap(err)
}
@ -545,7 +545,7 @@ func (proxy *ProxyClient) FindServersByLabels(ctx context.Context, namespace str
return nil, trace.Wrap(err)
}
siteNodes, err := site.GetNodes(ctx, namespace, services.SkipValidation())
siteNodes, err := site.GetNodes(ctx, namespace)
if err != nil {
return nil, trace.Wrap(err)
}
@ -566,7 +566,7 @@ func (proxy *ProxyClient) GetAppServers(ctx context.Context, namespace string) (
return nil, trace.Wrap(err)
}
servers, err := authClient.GetAppServers(ctx, namespace, services.SkipValidation())
servers, err := authClient.GetAppServers(ctx, namespace)
if err != nil {
return nil, trace.Wrap(err)
}
@ -619,7 +619,7 @@ func (proxy *ProxyClient) GetDatabaseServers(ctx context.Context, namespace stri
if err != nil {
return nil, trace.Wrap(err)
}
servers, err := authClient.GetDatabaseServers(ctx, namespace, services.SkipValidation())
servers, err := authClient.GetDatabaseServers(ctx, namespace)
if err != nil {
return nil, trace.Wrap(err)
}

View file

@ -87,7 +87,7 @@ func unmarshalDiscoveryRequest(data []byte) (*discoveryRequest, error) {
}
var out discoveryRequest
for _, bytes := range raw.Proxies {
proxy, err := services.UnmarshalServer([]byte(bytes), services.KindProxy, services.SkipValidation())
proxy, err := services.UnmarshalServer([]byte(bytes), services.KindProxy)
if err != nil {
return nil, trace.Wrap(err)
}

View file

@ -26,6 +26,7 @@ import (
"time"
"github.com/coreos/go-semver/semver"
"github.com/gravitational/teleport"
"github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/api/types"
@ -712,7 +713,7 @@ func (s *server) findLocalCluster(sconn *ssh.ServerConn) (*localSite, error) {
}
func (s *server) getTrustedCAKeysByID(id services.CertAuthID) ([]ssh.PublicKey, error) {
ca, err := s.localAccessPoint.GetCertAuthority(id, false, services.SkipValidation())
ca, err := s.localAccessPoint.GetCertAuthority(id, false)
if err != nil {
return nil, trace.Wrap(err)
}

View file

@ -18,7 +18,6 @@ package services
import (
"context"
"fmt"
"sort"
"github.com/google/go-cmp/cmp"
@ -1154,35 +1153,6 @@ func ValidateAccessRequestForUser(getter UserAndRoleGetter, req AccessRequest, o
return trace.Wrap(v.Validate(req))
}
// AccessRequestSpecSchema is JSON schema for AccessRequestSpec
const AccessRequestSpecSchema = `{
"type": "object",
"additionalProperties": false,
"properties": {
"user": { "type": "string" },
"roles": {
"type": "array",
"items": { "type": "string" }
},
"state": { "type": "integer" },
"created": { "type": "string" },
"expires": { "type": "string" },
"request_reason": { "type": "string" },
"resolve_reason": { "type": "string" },
"resolve_annotations": { "type": "object" },
"system_annotations": { "type": "object" },
"thresholds": { "type": "array" },
"rtm": { "type": "object" },
"reviews": { "type": "array" },
"suggested_reviewers": { "type": "array" }
}
}`
// GetAccessRequestSchema gets the full AccessRequest JSON schema
func GetAccessRequestSchema() string {
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, AccessRequestSpecSchema, DefaultDefinitions)
}
// UnmarshalAccessRequest unmarshals the AccessRequest resource from JSON.
func UnmarshalAccessRequest(data []byte, opts ...MarshalOption) (AccessRequest, error) {
cfg, err := CollectOptions(opts)
@ -1190,14 +1160,8 @@ func UnmarshalAccessRequest(data []byte, opts ...MarshalOption) (AccessRequest,
return nil, trace.Wrap(err)
}
var req AccessRequestV3
if cfg.SkipValidation {
if err := utils.FastUnmarshal(data, &req); err != nil {
return nil, trace.Wrap(err)
}
} else {
if err := utils.UnmarshalWithSchema(GetAccessRequestSchema(), &req, data); err != nil {
return nil, trace.Wrap(err)
}
if err := utils.FastUnmarshal(data, &req); err != nil {
return nil, trace.Wrap(err)
}
if err := ValidateAccessRequest(&req); err != nil {
return nil, trace.Wrap(err)

View file

@ -20,7 +20,6 @@ package services
import (
"encoding/json"
"fmt"
"time"
"github.com/gravitational/teleport/api/types"
@ -94,120 +93,6 @@ func validateTOTPDevice(d *types.TOTPDevice) error {
return nil
}
// AuthPreferenceSpecSchemaTemplate is JSON schema for AuthPreferenceSpec
const AuthPreferenceSpecSchemaTemplate = `{
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "string"
},
"second_factor": {
"type": "string"
},
"connector_name": {
"type": "string"
},
"u2f": {
"type": "object",
"additionalProperties": false,
"properties": {
"app_id": {
"type": "string"
},
"facets": {
"type": "array",
"items": {
"type": "string"
}
},
"device_attestation_cas": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"require_session_mfa": {
"type": "boolean"
}%v
}
}`
// LocalAuthSecretsSchema is a JSON schema for LocalAuthSecrets
const LocalAuthSecretsSchema = `{
"type": "object",
"additionalProperties": false,
"properties": {
"password_hash": {"type": "string"},
"totp_key": {"type": "string"},
"u2f_registration": {
"type": "object",
"additionalProperties": false,
"properties": {
"raw": {"type": "string"},
"key_handle": {"type": "string"},
"pubkey": {"type": "string"}
}
},
"u2f_counter": {"type": "number"},
"mfa": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"kind": {"type": "string"},
"subKind": {"type": "string"},
"version": {"type": "string"},
"metadata": {
"type": "object",
"additionalProperties": false,
"properties": {
"Name": {"type": "string"},
"Namespace": {"type": "string"}
}
},
"id": {"type": "string"},
"name": {"type": "string"},
"addedAt": {"type": "string"},
"lastUsed": {"type": "string"},
"totp": {
"type": "object",
"additionalProperties": false,
"properties": {
"key": {"type": "string"}
}
},
"u2f": {
"type": "object",
"additionalProperties": false,
"properties": {
"raw": {"type": "string"},
"keyHandle": {"type": "string"},
"pubKey": {"type": "string"},
"counter": {"type": "number"}
}
}
}
}
}
}
}`
// GetAuthPreferenceSchema returns the schema with optionally injected
// schema for extensions.
func GetAuthPreferenceSchema(extensionSchema string) string {
var authPreferenceSchema string
if authPreferenceSchema == "" {
authPreferenceSchema = fmt.Sprintf(AuthPreferenceSpecSchemaTemplate, "")
} else {
authPreferenceSchema = fmt.Sprintf(AuthPreferenceSpecSchemaTemplate, ","+extensionSchema)
}
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, authPreferenceSchema, DefaultDefinitions)
}
// UnmarshalAuthPreference unmarshals the AuthPreference resource from JSON.
func UnmarshalAuthPreference(bytes []byte, opts ...MarshalOption) (AuthPreference, error) {
var authPreference AuthPreferenceV2
@ -221,15 +106,11 @@ func UnmarshalAuthPreference(bytes []byte, opts ...MarshalOption) (AuthPreferenc
return nil, trace.Wrap(err)
}
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &authPreference); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
err := utils.UnmarshalWithSchema(GetAuthPreferenceSchema(""), &authPreference, bytes)
if err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &authPreference); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := authPreference.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
}
err = authPreference.CheckAndSetDefaults()

View file

@ -20,7 +20,6 @@ import (
"crypto"
"crypto/x509"
"encoding/json"
"fmt"
"time"
"github.com/gravitational/teleport"
@ -335,21 +334,6 @@ func CertPool(ca CertAuthority) (*x509.CertPool, error) {
return certPool, nil
}
// CertRolesSchema defines cert roles schema
const CertRolesSchema = `{
"type": "object",
"additionalProperties": false,
"properties": {
"version": {"type": "string"},
"roles": {
"type": "array",
"items": {
"type": "string"
}
}
}
}`
// MarshalCertRoles marshal roles list to OpenSSH
func MarshalCertRoles(roles []string) (string, error) {
out, err := json.Marshal(CertRoles{Version: V1, Roles: roles})
@ -362,94 +346,12 @@ func MarshalCertRoles(roles []string) (string, error) {
// UnmarshalCertRoles marshals roles list to OpenSSH format
func UnmarshalCertRoles(data string) ([]string, error) {
var certRoles CertRoles
if err := utils.UnmarshalWithSchema(CertRolesSchema, &certRoles, []byte(data)); err != nil {
if err := utils.FastUnmarshal([]byte(data), &certRoles); err != nil {
return nil, trace.BadParameter(err.Error())
}
return certRoles.Roles, nil
}
// CertAuthoritySpecV2Schema is JSON schema for cert authority V2
const CertAuthoritySpecV2Schema = `{
"type": "object",
"additionalProperties": false,
"required": ["type", "cluster_name"],
"properties": {
"type": {"type": "string"},
"cluster_name": {"type": "string"},
"checking_keys": {
"type": "array",
"items": {
"type": "string"
}
},
"signing_keys": {
"type": "array",
"items": {
"type": "string"
}
},
"roles": {
"type": "array",
"items": {
"type": "string"
}
},
"tls_key_pairs": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"cert": {"type": "string"},
"key": {"type": "string"}
}
}
},
"jwt_key_pairs": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"public_key": {"type": "string"},
"private_key": {"type": "string"}
}
}
},
"signing_alg": {"type": "integer"},
"rotation": %v,
"role_map": %v
}
}`
// RotationSchema is a JSON validation schema of the CA rotation state object.
const RotationSchema = `{
"type": "object",
"additionalProperties": false,
"properties": {
"state": {"type": "string"},
"phase": {"type": "string"},
"mode": {"type": "string"},
"current_id": {"type": "string"},
"started": {"type": "string"},
"grace_period": {"type": "string"},
"last_rotated": {"type": "string"},
"schedule": {
"type": "object",
"properties": {
"update_clients": {"type": "string"},
"update_servers": {"type": "string"},
"standby": {"type": "string"}
}
}
}
}`
// GetCertAuthoritySchema returns JSON Schema for cert authorities
func GetCertAuthoritySchema() string {
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, fmt.Sprintf(CertAuthoritySpecV2Schema, RotationSchema, RoleMapSchema), DefaultDefinitions)
}
// UnmarshalCertAuthority unmarshals the CertAuthority resource to JSON.
func UnmarshalCertAuthority(bytes []byte, opts ...MarshalOption) (CertAuthority, error) {
cfg, err := CollectOptions(opts)
@ -464,14 +366,8 @@ func UnmarshalCertAuthority(bytes []byte, opts ...MarshalOption) (CertAuthority,
switch h.Version {
case V2:
var ca CertAuthorityV2
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &ca); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
if err := utils.UnmarshalWithSchema(GetCertAuthoritySchema(), &ca, bytes); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &ca); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := ValidateCertAuthority(&ca); err != nil {
return nil, trace.Wrap(err)

View file

@ -17,11 +17,10 @@ limitations under the License.
package services
import (
"fmt"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// DefaultClusterConfig is used as the default cluster configuration when
@ -58,81 +57,6 @@ func ShouldUploadSessions(a AuditConfig) bool {
return a.AuditSessionsURI != ""
}
// ClusterConfigSpecSchemaTemplate is a template for ClusterConfig schema.
const ClusterConfigSpecSchemaTemplate = `{
"type": "object",
"additionalProperties": false,
"properties": {
"session_recording": {
"type": "string"
},
"proxy_checks_host_keys": {
"anyOf": [{"type": "string"}, { "type": "boolean"}]
},
"cluster_id": {
"type": "string"
},
"client_idle_timeout": {
"type": "string"
},
"session_control_timeout": {
"type": "string"
},
"disconnect_expired_cert": {
"anyOf": [{"type": "string"}, { "type": "boolean"}]
},
"keep_alive_interval": {
"type": "string"
},
"keep_alive_count_max": {
"type": "number"
},
"local_auth": {
"anyOf": [{"type": "string"}, { "type": "boolean"}]
},
"audit": {
"type": "object",
"additionalProperties": false,
"properties": {
"type": {
"type": "string"
},
"region": {
"type": "string"
},
"audit_events_uri": {
"anyOf": [
{"type": "string"},
{"type": "array",
"items": {
"type": "string"
}
}
]
},
"audit_sessions_uri": {
"type": "string"
},
"audit_table_name": {
"type": "string"
}
}
}%v
}
}`
// GetClusterConfigSchema returns the schema with optionally injected
// schema for extensions.
func GetClusterConfigSchema(extensionSchema string) string {
var clusterConfigSchema string
if clusterConfigSchema == "" {
clusterConfigSchema = fmt.Sprintf(ClusterConfigSpecSchemaTemplate, "")
} else {
clusterConfigSchema = fmt.Sprintf(ClusterConfigSpecSchemaTemplate, ","+extensionSchema)
}
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, clusterConfigSchema, DefaultDefinitions)
}
// UnmarshalClusterConfig unmarshals the ClusterConfig resource from JSON.
func UnmarshalClusterConfig(bytes []byte, opts ...MarshalOption) (ClusterConfig, error) {
var clusterConfig ClusterConfigV3
@ -146,15 +70,8 @@ func UnmarshalClusterConfig(bytes []byte, opts ...MarshalOption) (ClusterConfig,
return nil, trace.Wrap(err)
}
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &clusterConfig); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
err = utils.UnmarshalWithSchema(GetClusterConfigSchema(""), &clusterConfig, bytes)
if err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &clusterConfig); err != nil {
return nil, trace.BadParameter(err.Error())
}
err = clusterConfig.CheckAndSetDefaults()

View file

@ -17,35 +17,11 @@ limitations under the License.
package services
import (
"fmt"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// ClusterNameSpecSchemaTemplate is a template for ClusterName schema.
const ClusterNameSpecSchemaTemplate = `{
"type": "object",
"additionalProperties": false,
"properties": {
"cluster_name": {
"type": "string"
}%v
}
}`
// GetClusterNameSchema returns the schema with optionally injected
// schema for extensions.
func GetClusterNameSchema(extensionSchema string) string {
var clusterNameSchema string
if clusterNameSchema == "" {
clusterNameSchema = fmt.Sprintf(ClusterNameSpecSchemaTemplate, "")
} else {
clusterNameSchema = fmt.Sprintf(ClusterNameSpecSchemaTemplate, ","+extensionSchema)
}
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, clusterNameSchema, DefaultDefinitions)
}
// UnmarshalClusterName unmarshals the ClusterName resource from JSON.
func UnmarshalClusterName(bytes []byte, opts ...MarshalOption) (ClusterName, error) {
var clusterName ClusterNameV2
@ -59,15 +35,8 @@ func UnmarshalClusterName(bytes []byte, opts ...MarshalOption) (ClusterName, err
return nil, trace.Wrap(err)
}
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &clusterName); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
err = utils.UnmarshalWithSchema(GetClusterNameSchema(""), &clusterName, bytes)
if err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &clusterName); err != nil {
return nil, trace.BadParameter(err.Error())
}
err = clusterName.CheckAndSetDefaults()

View file

@ -17,72 +17,12 @@ limitations under the License.
package services
import (
"fmt"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// DatabaseServerSpecV3Schema is JSON schema for a database server spec.
const DatabaseServerSpecV3Schema = `{
"type": "object",
"additionalProperties": false,
"properties": {
"description": {"type": "string"},
"protocol": {"type": "string"},
"uri": {"type": "string"},
"ca_cert": {"type": "string"},
"aws": {
"type": "object",
"additionalProperties": false,
"properties": {
"region": {"type": "string"},
"redshift": {
"type": "object",
"additionalProperties": false,
"properties": {
"cluster_id": {"type": "string"}
}
}
}
},
"gcp": {
"type": "object",
"additionalProperties": false,
"properties": {
"project_id": {"type": "string"},
"instance_id": {"type": "string"}
}
},
"version": {"type": "string"},
"hostname": {"type": "string"},
"host_id": {"type": "string"},
"dynamic_labels": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^.*$": {
"type": "object",
"additionalProperties": false,
"required": ["command"],
"properties": {
"command": {"type": "array", "items": {"type": "string"}},
"period": {"type": "string"},
"result": {"type": "string"}
}
}
}
},
"rotation": %v
}
}`
// GetDatabaseServerSchema returns full database server JSON schema.
func GetDatabaseServerSchema() string {
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, fmt.Sprintf(DatabaseServerSpecV3Schema, RotationSchema), DefaultDefinitions)
}
// MarshalDatabaseServer marshals the DatabaseServer resource to JSON.
func MarshalDatabaseServer(databaseServer types.DatabaseServer, opts ...MarshalOption) ([]byte, error) {
if err := databaseServer.CheckAndSetDefaults(); err != nil {
@ -127,14 +67,8 @@ func UnmarshalDatabaseServer(data []byte, opts ...MarshalOption) (types.Database
switch h.Version {
case V3:
var s types.DatabaseServerV3
if cfg.SkipValidation {
if err := utils.FastUnmarshal(data, &s); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
if err := utils.UnmarshalWithSchema(GetDatabaseServerSchema(), &s, data); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(data, &s); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := s.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)

View file

@ -18,76 +18,12 @@ package services
import (
"encoding/json"
"fmt"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// GithubConnectorV3SchemaTemplate is the JSON schema for a Github connector
const GithubConnectorV3SchemaTemplate = `{
"type": "object",
"additionalProperties": false,
"required": ["kind", "spec", "metadata", "version"],
"properties": {
"kind": {"type": "string"},
"version": {"type": "string", "default": "v3"},
"metadata": %v,
"spec": %v
}
}`
// GithubConnectorSpecV3Schema is the JSON schema for Github connector spec
var GithubConnectorSpecV3Schema = fmt.Sprintf(`{
"type": "object",
"additionalProperties": false,
"required": ["client_id", "client_secret", "redirect_url"],
"properties": {
"client_id": {"type": "string"},
"client_secret": {"type": "string"},
"redirect_url": {"type": "string"},
"display": {"type": "string"},
"teams_to_logins": {
"type": "array",
"items": %v
}
}
}`, TeamMappingSchema)
// TeamMappingSchema is the JSON schema for team membership mapping
var TeamMappingSchema = `{
"type": "object",
"additionalProperties": false,
"required": ["organization", "team"],
"properties": {
"organization": {"type": "string"},
"team": {"type": "string"},
"logins": {
"type": "array",
"items": {
"type": "string"
}
},
"kubernetes_groups": {
"type": "array",
"items": {
"type": "string"
}
},
"kubernetes_users": {
"type": "array",
"items": {
"type": "string"
}
}
}
}`
// GetGithubConnectorSchema returns schema for Github connector
func GetGithubConnectorSchema() string {
return fmt.Sprintf(GithubConnectorV3SchemaTemplate, MetadataSchema, GithubConnectorSpecV3Schema)
}
// UnmarshalGithubConnector unmarshals the GithubConnector resource from JSON.
func UnmarshalGithubConnector(bytes []byte) (GithubConnector, error) {
var h ResourceHeader
@ -97,7 +33,7 @@ func UnmarshalGithubConnector(bytes []byte) (GithubConnector, error) {
switch h.Version {
case V3:
var c GithubConnectorV3
if err := utils.UnmarshalWithSchema(GetGithubConnectorSchema(), &c, bytes); err != nil {
if err := utils.FastUnmarshal(bytes, &c); err != nil {
return nil, trace.Wrap(err)
}
if err := c.CheckAndSetDefaults(); err != nil {

View file

@ -17,57 +17,19 @@ limitations under the License.
package services
import (
"fmt"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// LicenseSpecV3Template is a template for V3 License JSON schema
const LicenseSpecV3Template = `{
"type": "object",
"additionalProperties": false,
"properties": {
"account_id": {
"type": ["string"]
},
"plan_id": {
"type": ["string"]
},
"usage": {
"type": ["string", "boolean"]
},
"aws_pid": {
"type": ["string"]
},
"aws_account": {
"type": ["string"]
},
"k8s": {
"type": ["string", "boolean"]
},
"app": {
"type": ["string", "boolean"]
},
"db": {
"type": ["string", "boolean"]
},
"cloud": {
"type": ["string", "boolean"]
}
}
}`
// UnmarshalLicense unmarshals the License resource from JSON.
func UnmarshalLicense(bytes []byte) (License, error) {
if len(bytes) == 0 {
return nil, trace.BadParameter("missing resource data")
}
schema := fmt.Sprintf(V2SchemaTemplate, MetadataSchema, LicenseSpecV3Template, DefaultDefinitions)
var license LicenseV3
err := utils.UnmarshalWithSchema(schema, &license, bytes)
err := utils.FastUnmarshal(bytes, &license)
if err != nil {
return nil, trace.BadParameter(err.Error())
}

View file

@ -19,12 +19,13 @@ package local
import (
"context"
"github.com/gravitational/trace"
"github.com/gravitational/teleport"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/backend"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
"github.com/prometheus/client_golang/prometheus"
)
@ -280,7 +281,7 @@ func (s *ClusterConfigurationService) syncClusterConfigWithNetworkingConfig(clus
}
return nil
}
netConfig, err := s.GetClusterNetworkingConfig(context.TODO(), services.SkipValidation())
netConfig, err := s.GetClusterNetworkingConfig(context.TODO())
if err != nil {
return trace.Wrap(err)
}
@ -305,7 +306,7 @@ func (s *ClusterConfigurationService) syncClusterConfigWithSessionRecordingConfi
}
return nil
}
recConfig, err := s.GetSessionRecordingConfig(context.TODO(), services.SkipValidation())
recConfig, err := s.GetSessionRecordingConfig(context.TODO())
if err != nil {
return trace.Wrap(err)
}

View file

@ -232,7 +232,7 @@ func (s *DynamicAccessService) GetAccessRequests(ctx context.Context, filter ser
// same namespace.
continue
}
req, err := itemToAccessRequest(item, services.SkipValidation())
req, err := itemToAccessRequest(item)
if err != nil {
return nil, trace.Wrap(err)
}

View file

@ -278,7 +278,7 @@ func (p *certAuthorityParser) parse(event backend.Event) (services.Resource, err
}, nil
case backend.OpPut:
ca, err := services.UnmarshalCertAuthority(event.Item.Value,
services.WithResourceID(event.Item.ID), services.WithExpires(event.Item.Expires), services.SkipValidation())
services.WithResourceID(event.Item.ID), services.WithExpires(event.Item.Expires))
if err != nil {
return nil, trace.Wrap(err)
}
@ -376,7 +376,6 @@ func (p *clusterConfigParser) parse(event backend.Event) (services.Resource, err
event.Item.Value,
services.WithResourceID(event.Item.ID),
services.WithExpires(event.Item.Expires),
services.SkipValidation(),
)
if err != nil {
return nil, trace.Wrap(err)
@ -411,7 +410,6 @@ func (p *clusterNetworkingConfigParser) parse(event backend.Event) (services.Res
event.Item.Value,
services.WithResourceID(event.Item.ID),
services.WithExpires(event.Item.Expires),
services.SkipValidation(),
)
if err != nil {
return nil, trace.Wrap(err)
@ -446,7 +444,6 @@ func (p *authPreferenceParser) parse(event backend.Event) (services.Resource, er
event.Item.Value,
services.WithResourceID(event.Item.ID),
services.WithExpires(event.Item.Expires),
services.SkipValidation(),
)
if err != nil {
return nil, trace.Wrap(err)
@ -481,7 +478,6 @@ func (p *sessionRecordingConfigParser) parse(event backend.Event) (services.Reso
event.Item.Value,
services.WithResourceID(event.Item.ID),
services.WithExpires(event.Item.Expires),
services.SkipValidation(),
)
if err != nil {
return nil, trace.Wrap(err)
@ -921,7 +917,7 @@ func (p *databaseServerParser) parse(event backend.Event) (services.Resource, er
event.Item.Value,
services.WithResourceID(event.Item.ID),
services.WithExpires(event.Item.Expires),
services.SkipValidation())
)
default:
return nil, trace.BadParameter("event %v is not supported", event.Type)
}
@ -936,7 +932,6 @@ func parseServer(event backend.Event, kind string) (services.Resource, error) {
kind,
services.WithResourceID(event.Item.ID),
services.WithExpires(event.Item.Expires),
services.SkipValidation(),
)
if err != nil {
return nil, trace.Wrap(err)

View file

@ -38,39 +38,30 @@ func BenchmarkGetNodes(b *testing.B) {
ctx := context.Background()
type testCase struct {
validation, memory bool
nodes int
memory bool
nodes int
}
var tts []testCase
for _, validation := range []bool{true, false} {
for _, memory := range []bool{true, false} {
for _, nodes := range []int{100, 1000, 10000} {
tts = append(tts, testCase{
validation: validation,
memory: memory,
nodes: nodes,
})
}
for _, memory := range []bool{true, false} {
for _, nodes := range []int{100, 1000, 10000} {
tts = append(tts, testCase{
memory: memory,
nodes: nodes,
})
}
}
for _, tt := range tts {
// create a descriptive name for the sub-benchmark.
name := fmt.Sprintf("tt(validation=%v,memory=%v,nodes=%d)", tt.validation, tt.memory, tt.nodes)
name := fmt.Sprintf("tt(memory=%v,nodes=%d)", tt.memory, tt.nodes)
// run the sub benchmark
b.Run(name, func(sb *testing.B) {
sb.StopTimer() // stop timer while running setup
// set up marshal options
var opts []services.MarshalOption
if !tt.validation {
opts = append(opts, services.SkipValidation())
}
// configure the backend instance
var bk backend.Backend
var err error
@ -95,7 +86,7 @@ func BenchmarkGetNodes(b *testing.B) {
sb.StartTimer() // restart timer for benchmark operations
benchmarkGetNodes(ctx, sb, svc, tt.nodes, opts...)
benchmarkGetNodes(ctx, sb, svc, tt.nodes)
sb.StopTimer() // stop timer to exclude deferred cleanup
})

View file

@ -162,7 +162,6 @@ func (s *PresenceService) getServers(ctx context.Context, kind, prefix string) (
for i, item := range result.Items {
server, err := services.UnmarshalServer(
item.Value, kind,
services.SkipValidation(),
services.WithResourceID(item.ID),
services.WithExpires(item.Expires),
)
@ -219,7 +218,6 @@ func (s *PresenceService) GetNode(ctx context.Context, namespace, name string) (
types.KindNode,
services.WithResourceID(item.ID),
services.WithExpires(item.Expires),
services.SkipValidation(),
)
}
@ -298,8 +296,7 @@ func (s *PresenceService) KeepAliveNode(ctx context.Context, h services.KeepAliv
return trace.Wrap(err)
}
// UpsertNodes is used for bulk insertion of nodes. Schema validation is
// always skipped during bulk insertion.
// UpsertNodes is used for bulk insertion of nodes.
func (s *PresenceService) UpsertNodes(namespace string, servers []services.Server) error {
batch, ok := s.Backend.(backend.Batch)
if !ok {

View file

@ -77,8 +77,7 @@ func (s *ProvisioningService) GetToken(ctx context.Context, token string) (servi
if err != nil {
return nil, trace.Wrap(err)
}
return services.UnmarshalProvisionToken(item.Value, services.SkipValidation(),
services.WithResourceID(item.ID), services.WithExpires(item.Expires))
return services.UnmarshalProvisionToken(item.Value, services.WithResourceID(item.ID), services.WithExpires(item.Expires))
}
func (s *ProvisioningService) DeleteToken(ctx context.Context, token string) error {
@ -99,8 +98,7 @@ func (s *ProvisioningService) GetTokens(ctx context.Context, opts ...services.Ma
tokens := make([]services.ProvisionToken, len(result.Items))
for i, item := range result.Items {
t, err := services.UnmarshalProvisionToken(item.Value,
services.AddOptions(opts, services.SkipValidation(),
services.WithResourceID(item.ID), services.WithExpires(item.Expires))...)
services.AddOptions(opts, services.WithResourceID(item.ID), services.WithExpires(item.Expires))...)
if err != nil {
return nil, trace.Wrap(err)
}

View file

@ -37,7 +37,7 @@ func (s *IdentityService) GetAppSession(ctx context.Context, req types.GetAppSes
if err != nil {
return nil, trace.Wrap(err)
}
session, err := services.UnmarshalWebSession(item.Value, services.SkipValidation())
session, err := services.UnmarshalWebSession(item.Value)
if err != nil {
return nil, trace.Wrap(err)
}
@ -54,7 +54,7 @@ func (s *IdentityService) GetAppSessions(ctx context.Context) ([]types.WebSessio
out := make([]types.WebSession, len(result.Items))
for i, item := range result.Items {
session, err := services.UnmarshalWebSession(item.Value, services.SkipValidation())
session, err := services.UnmarshalWebSession(item.Value)
if err != nil {
return nil, trace.Wrap(err)
}
@ -112,7 +112,7 @@ func (r *webSessions) Get(ctx context.Context, req types.GetWebSessionRequest) (
if err != nil {
return nil, trace.Wrap(err)
}
session, err := services.UnmarshalWebSession(item.Value, services.SkipValidation())
session, err := services.UnmarshalWebSession(item.Value)
if err != nil && !trace.IsNotFound(err) {
return nil, trace.Wrap(err)
}
@ -132,7 +132,7 @@ func (r *webSessions) List(ctx context.Context) (out []types.WebSession, err err
return nil, trace.Wrap(err)
}
for _, item := range result.Items {
session, err := services.UnmarshalWebSession(item.Value, services.SkipValidation())
session, err := services.UnmarshalWebSession(item.Value)
if err != nil {
return nil, trace.Wrap(err)
}
@ -197,7 +197,7 @@ func (r *webSessions) listLegacySessions(ctx context.Context) ([]types.WebSessio
if suffix != sessionsPrefix {
continue
}
session, err := services.UnmarshalWebSession(item.Value, services.SkipValidation())
session, err := services.UnmarshalWebSession(item.Value)
if err != nil {
return nil, trace.Wrap(err)
}
@ -225,7 +225,7 @@ func (r *webTokens) Get(ctx context.Context, req types.GetWebTokenRequest) (type
if err != nil {
return nil, trace.Wrap(err)
}
token, err := services.UnmarshalWebToken(item.Value, services.SkipValidation())
token, err := services.UnmarshalWebToken(item.Value)
if err != nil {
return nil, trace.Wrap(err)
}
@ -240,7 +240,7 @@ func (r *webTokens) List(ctx context.Context) (out []types.WebToken, err error)
return nil, trace.Wrap(err)
}
for _, item := range result.Items {
token, err := services.UnmarshalWebToken(item.Value, services.SkipValidation())
token, err := services.UnmarshalWebToken(item.Value)
if err != nil {
return nil, trace.Wrap(err)
}
@ -298,7 +298,7 @@ func getLegacyWebSession(ctx context.Context, backend backend.Backend, user, ses
if err != nil {
return nil, trace.Wrap(err)
}
session, err := services.UnmarshalWebSession(item.Value, services.SkipValidation())
session, err := services.UnmarshalWebSession(item.Value)
if err != nil {
return nil, trace.Wrap(err)
}

View file

@ -17,38 +17,11 @@ limitations under the License.
package services
import (
"fmt"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// NamespaceSpecSchema is JSON schema for NameSpace resource spec
const NamespaceSpecSchema = `{
"type": "object",
"additionalProperties": false,
"default": {}
}`
// NamespaceSchemaTemplate is JSON schema for the Namespace resource
const NamespaceSchemaTemplate = `{
"type": "object",
"additionalProperties": false,
"default": {},
"required": ["kind", "spec", "metadata"],
"properties": {
"kind": {"type": "string"},
"version": {"type": "string", "default": "v1"},
"metadata": %v,
"spec": %v
}
}`
// GetNamespaceSchema returns Namespace schema
func GetNamespaceSchema() string {
return fmt.Sprintf(NamespaceSchemaTemplate, MetadataSchema, NamespaceSpecSchema)
}
// MarshalNamespace marshals the Namespace resource to JSON.
func MarshalNamespace(resource Namespace, opts ...MarshalOption) ([]byte, error) {
cfg, err := CollectOptions(opts)

View file

@ -17,30 +17,12 @@ limitations under the License.
package services
import (
"fmt"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// ClusterNetworkingConfigSpecSchema is JSON schema for ClusterNetworkingConfig spec.
const ClusterNetworkingConfigSpecSchema = `{
"type": "object",
"additionalProperties": false,
"properties": {
"client_idle_timeout": {"type": "string"},
"keep_alive_interval": {"type": "string"},
"keep_alive_count_max": {"type": "number"},
"session_control_timeout": {"type": "string"}
}
}`
// GetClusterNetworkingConfigSchema returns full ClusterNetworkingConfig JSON schema.
func GetClusterNetworkingConfigSchema() string {
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, ClusterNetworkingConfigSpecSchema, DefaultDefinitions)
}
// UnmarshalClusterNetworkingConfig unmarshals the ClusterNetworkingConfig resource from JSON.
func UnmarshalClusterNetworkingConfig(bytes []byte, opts ...MarshalOption) (types.ClusterNetworkingConfig, error) {
var netConfig types.ClusterNetworkingConfigV2
@ -54,15 +36,8 @@ func UnmarshalClusterNetworkingConfig(bytes []byte, opts ...MarshalOption) (type
return nil, trace.Wrap(err)
}
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &netConfig); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
err = utils.UnmarshalWithSchema(GetClusterNetworkingConfigSchema(), &netConfig, bytes)
if err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &netConfig); err != nil {
return nil, trace.BadParameter(err.Error())
}
err = netConfig.CheckAndSetDefaults()

View file

@ -17,14 +17,14 @@ limitations under the License.
package services
import (
"fmt"
"net/url"
"github.com/coreos/go-oidc/jose"
"github.com/gravitational/trace"
"github.com/gravitational/teleport"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// ValidateOIDCConnector validates the OIDC connector and sets default values
@ -90,71 +90,6 @@ func OIDCClaimsToTraits(claims jose.Claims) map[string][]string {
return traits
}
// OIDCConnectorSpecV2Schema is a JSON Schema for OIDC Connector
var OIDCConnectorSpecV2Schema = fmt.Sprintf(`{
"type": "object",
"additionalProperties": false,
"required": ["issuer_url", "client_id", "client_secret", "redirect_url"],
"properties": {
"issuer_url": {"type": "string"},
"client_id": {"type": "string"},
"client_secret": {"type": "string"},
"redirect_url": {"type": "string"},
"acr_values": {"type": "string"},
"provider": {"type": "string"},
"display": {"type": "string"},
"prompt": {"type": "string"},
"google_service_account_uri": {"type": "string"},
"google_service_account": {"type": "string"},
"google_admin_email": {"type": "string"},
"scope": {
"type": "array",
"items": {
"type": "string"
}
},
"claims_to_roles": {
"type": "array",
"items": %v
}
}
}`, ClaimMappingSchema)
// OIDCConnectorV2SchemaTemplate is a template JSON Schema for OIDC connector
const OIDCConnectorV2SchemaTemplate = `{
"type": "object",
"additionalProperties": false,
"required": ["kind", "spec", "metadata", "version"],
"properties": {
"kind": {"type": "string"},
"version": {"type": "string", "default": "v1"},
"metadata": %v,
"spec": %v
}
}`
// ClaimMappingSchema is JSON schema for claim mapping
var ClaimMappingSchema = `{
"type": "object",
"additionalProperties": false,
"required": ["claim", "value" ],
"properties": {
"claim": {"type": "string"},
"value": {"type": "string"},
"roles": {
"type": "array",
"items": {
"type": "string"
}
}
}
}`
// GetOIDCConnectorSchema returns schema for OIDCConnector
func GetOIDCConnectorSchema() string {
return fmt.Sprintf(OIDCConnectorV2SchemaTemplate, MetadataSchema, OIDCConnectorSpecV2Schema)
}
// UnmarshalOIDCConnector unmarshals the OIDCConnector resource from JSON.
func UnmarshalOIDCConnector(bytes []byte, opts ...MarshalOption) (OIDCConnector, error) {
cfg, err := CollectOptions(opts)
@ -169,16 +104,9 @@ func UnmarshalOIDCConnector(bytes []byte, opts ...MarshalOption) (OIDCConnector,
switch h.Version {
case V2:
var c OIDCConnectorV2
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &c); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
if err := utils.UnmarshalWithSchema(GetOIDCConnectorSchema(), &c, bytes); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &c); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := ValidateOIDCConnector(&c); err != nil {
return nil, trace.Wrap(err)
}

View file

@ -17,26 +17,11 @@ limitations under the License.
package services
import (
"fmt"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// PluginDataSpecSchema is JSON schema for PluginData
const PluginDataSpecSchema = `{
"type": "object",
"additionalProperties": false,
"properties": {
"entries": { "type":"object" }
}
}`
// GetPluginDataSchema returns the full PluginDataSchema string
func GetPluginDataSchema() string {
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, PluginDataSpecSchema, DefaultDefinitions)
}
//MarshalPluginData marshals the PluginData resource to JSON.
func MarshalPluginData(pluginData PluginData, opts ...MarshalOption) ([]byte, error) {
cfg, err := CollectOptions(opts)
@ -69,14 +54,8 @@ func UnmarshalPluginData(raw []byte, opts ...MarshalOption) (PluginData, error)
return nil, trace.Wrap(err)
}
var data PluginDataV3
if cfg.SkipValidation {
if err := utils.FastUnmarshal(raw, &data); err != nil {
return nil, trace.Wrap(err)
}
} else {
if err := utils.UnmarshalWithSchema(GetPluginDataSchema(), &data, raw); err != nil {
return nil, trace.Wrap(err)
}
if err := utils.FastUnmarshal(raw, &data); err != nil {
return nil, trace.Wrap(err)
}
if err := data.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)

View file

@ -37,8 +37,7 @@ type Presence interface {
// GetNode returns a node by name and namespace.
GetNode(ctx context.Context, namespace, name string) (Server, error)
// GetNodes returns a list of registered servers. Schema validation can be
// skipped to improve performance.
// GetNodes returns a list of registered servers.
GetNodes(ctx context.Context, namespace string, opts ...MarshalOption) ([]Server, error)
// DeleteAllNodes deletes all nodes in a namespace.

View file

@ -18,12 +18,12 @@ package services
import (
"context"
"fmt"
"time"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// Provisioner governs adding new nodes to the cluster
@ -54,20 +54,6 @@ func MustCreateProvisionToken(token string, roles types.SystemRoles, expires tim
return t
}
// ProvisionTokenSpecV2Schema is a JSON schema for provision token
const ProvisionTokenSpecV2Schema = `{
"type": "object",
"additionalProperties": false,
"properties": {
"roles": {"type": "array", "items": {"type": "string"}}
}
}`
// GetProvisionTokenSchema returns provision token schema
func GetProvisionTokenSchema() string {
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, ProvisionTokenSpecV2Schema, DefaultDefinitions)
}
// UnmarshalProvisionToken unmarshals the ProvisionToken resource from JSON.
func UnmarshalProvisionToken(data []byte, opts ...MarshalOption) (ProvisionToken, error) {
if len(data) == 0 {
@ -99,14 +85,8 @@ func UnmarshalProvisionToken(data []byte, opts ...MarshalOption) (ProvisionToken
return v2, nil
case V2:
var p ProvisionTokenV2
if cfg.SkipValidation {
if err := utils.FastUnmarshal(data, &p); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
if err := utils.UnmarshalWithSchema(GetProvisionTokenSchema(), &p, data); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(data, &p); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := p.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)

View file

@ -17,41 +17,11 @@ limitations under the License.
package services
import (
"fmt"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// RemoteClusterV3SchemaTemplate is a template JSON Schema for V3 style objects
const RemoteClusterV3SchemaTemplate = `{
"type": "object",
"additionalProperties": false,
"required": ["kind", "metadata", "version"],
"properties": {
"kind": {"type": "string"},
"version": {"type": "string", "default": "v3"},
"metadata": %v,
"status": %v
}
}`
// RemoteClusterV3StatusSchema is a template for remote cluster
const RemoteClusterV3StatusSchema = `{
"type": "object",
"additionalProperties": false,
"required": ["connection", "last_heartbeat"],
"properties": {
"connection": {"type": "string"},
"last_heartbeat": {"type": "string"}
}
}`
// GetRemoteClusterSchema returns the schema for remote cluster
func GetRemoteClusterSchema() string {
return fmt.Sprintf(RemoteClusterV3SchemaTemplate, MetadataSchema, RemoteClusterV3StatusSchema)
}
// UnmarshalRemoteCluster unmarshals the RemoteCluster resource from JSON.
func UnmarshalRemoteCluster(bytes []byte, opts ...MarshalOption) (RemoteCluster, error) {
cfg, err := CollectOptions(opts)
@ -65,16 +35,8 @@ func UnmarshalRemoteCluster(bytes []byte, opts ...MarshalOption) (RemoteCluster,
return nil, trace.BadParameter("missing resource data")
}
if cfg.SkipValidation {
err := utils.FastUnmarshal(bytes, &cluster)
if err != nil {
return nil, trace.Wrap(err)
}
} else {
err = utils.UnmarshalWithSchema(GetRemoteClusterSchema(), &cluster, bytes)
if err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &cluster); err != nil {
return nil, trace.Wrap(err)
}
err = cluster.CheckAndSetDefaults()

View file

@ -17,29 +17,11 @@ limitations under the License.
package services
import (
"fmt"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// ResetPasswordTokenSpecV3Template is a template for V3 ResetPasswordToken JSON schema
const ResetPasswordTokenSpecV3Template = `{
"type": "object",
"additionalProperties": false,
"properties": {
"user": {
"type": ["string"]
},
"created": {
"type": ["string"]
},
"url": {
"type": ["string"]
}
}
}`
// UnmarshalResetPasswordToken unmarshals the ResetPasswordToken resource from JSON.
func UnmarshalResetPasswordToken(bytes []byte, opts ...MarshalOption) (ResetPasswordToken, error) {
if len(bytes) == 0 {
@ -47,11 +29,12 @@ func UnmarshalResetPasswordToken(bytes []byte, opts ...MarshalOption) (ResetPass
}
var token ResetPasswordTokenV3
schema := fmt.Sprintf(V2SchemaTemplate, MetadataSchema, ResetPasswordTokenSpecV3Template, DefaultDefinitions)
err := utils.UnmarshalWithSchema(schema, &token, bytes)
if err != nil {
if err := utils.FastUnmarshal(bytes, &token); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := token.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
}
return &token, nil
}

View file

@ -17,29 +17,11 @@ limitations under the License.
package services
import (
"fmt"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// ResetPasswordTokenSecretsSpecV3Template is a template for V3 ResetPasswordTokenSecrets JSON schema
const ResetPasswordTokenSecretsSpecV3Template = `{
"type": "object",
"additionalProperties": false,
"properties": {
"opt_key": {
"type": ["string"]
},
"qr_code": {
"type": ["string"]
},
"created": {
"type": ["string"]
}
}
}`
// UnmarshalResetPasswordTokenSecrets unmarshals the ResetPasswordTokenSecrets resource from JSON.
func UnmarshalResetPasswordTokenSecrets(bytes []byte, opts ...MarshalOption) (ResetPasswordTokenSecrets, error) {
if len(bytes) == 0 {
@ -47,11 +29,12 @@ func UnmarshalResetPasswordTokenSecrets(bytes []byte, opts ...MarshalOption) (Re
}
var secrets ResetPasswordTokenSecretsV3
schema := fmt.Sprintf(V2SchemaTemplate, MetadataSchema, ResetPasswordTokenSecretsSpecV3Template, DefaultDefinitions)
err := utils.UnmarshalWithSchema(schema, &secrets, bytes)
if err != nil {
if err := utils.FastUnmarshal(bytes, &secrets); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := secrets.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
}
return &secrets, nil
}

View file

@ -23,7 +23,6 @@ import (
"sync"
"time"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/trace"
)
@ -32,9 +31,6 @@ type MarshalConfig struct {
// Version specifies particular version we should marshal resources with
Version string
// SkipValidation is used to skip schema validation.
SkipValidation bool
// ID is a record ID to assign
ID int64
@ -113,14 +109,6 @@ func PreserveResourceID() MarshalOption {
}
}
// SkipValidation is used to disable schema validation.
func SkipValidation() MarshalOption {
return func(c *MarshalConfig) error {
c.SkipValidation = true
return nil
}
}
// ParseShortcut parses resource shortcut
func ParseShortcut(in string) (string, error) {
if in == "" {
@ -536,44 +524,3 @@ func (u *UnknownResource) UnmarshalJSON(raw []byte) error {
copy(u.Raw, raw)
return nil
}
const baseMetadataSchema = `{
"type": "object",
"additionalProperties": false,
"default": {},
"required": ["name"],
"properties": {
"name": {"type": "string"},
"namespace": {"type": "string", "default": "default"},
"description": {"type": "string"},
"expires": {"type": "string"},
"id": {"type": "integer"},
"labels": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"%s": { "type": "string" }
}
}
}
}`
// V2SchemaTemplate is a template JSON Schema for V2 style objects
const V2SchemaTemplate = `{
"type": "object",
"additionalProperties": false,
"required": ["kind", "spec", "metadata", "version"],
"properties": {
"kind": {"type": "string"},
"sub_kind": {"type": "string"},
"version": {"type": "string", "default": "v2"},
"metadata": %v,
"spec": %v
}%v
}`
// MetadataSchema is a schema for resource metadata
var MetadataSchema = fmt.Sprintf(baseMetadataSchema, types.LabelPattern)
// DefaultDefinitions the default list of JSON schema definitions which is none.
const DefaultDefinitions = ``

View file

@ -2145,181 +2145,6 @@ func (s SortedRoles) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
// RoleSpecV3SchemaTemplate is JSON schema for RoleSpecV3
const RoleSpecV3SchemaTemplate = `{
"type": "object",
"additionalProperties": false,
"properties": {
"max_session_ttl": { "type": "string" },
"options": {
"type": "object",
"additionalProperties": false,
"properties": {
"forward_agent": { "type": ["boolean", "string"] },
"permit_x11_forwarding": { "type": ["boolean", "string"] },
"max_session_ttl": { "type": "string" },
"port_forwarding": { "type": ["boolean", "string"] },
"cert_format": { "type": "string" },
"client_idle_timeout": { "type": "string" },
"disconnect_expired_cert": { "type": ["boolean", "string"] },
"enhanced_recording": {
"type": "array",
"items": { "type": "string" }
},
"max_connections": { "type": "number" },
"max_sessions": {"type": "number"},
"request_access": { "type": "string" },
"request_prompt": { "type": "string" },
"require_session_mfa": { "type": ["boolean", "string"] }
}
},
"allow": { "$ref": "#/definitions/role_condition" },
"deny": { "$ref": "#/definitions/role_condition" }%v
}
}`
// RoleSpecV3SchemaDefinitions is JSON schema for RoleSpecV3 definitions
const RoleSpecV3SchemaDefinitions = `
"definitions": {
"role_condition": {
"namespaces": {
"type": "array",
"items": { "type": "string" }
},
"node_labels": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-zA-Z/.0-9_*-]+$": { "anyOf": [{"type": "string"}, { "type": "array", "items": {"type": "string"}}]}
}
},
"cluster_labels": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-zA-Z/.0-9_*-]+$": { "anyOf": [{"type": "string"}, { "type": "array", "items": {"type": "string"}}]}
}
},
"logins": {
"type": "array",
"items": { "type": "string" }
},
"kubernetes_groups": {
"type": "array",
"items": { "type": "string" }
},
"db_labels": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-zA-Z/.0-9_*-]+$": {"anyOf": [{"type": "string"}, {"type": "array", "items": {"type": "string"}}]}
}
},
"kubernetes_labels": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^[a-zA-Z/.0-9_*-]+$": {"anyOf": [{"type": "string"}, {"type": "array", "items": {"type": "string"}}]}
}
},
"db_names": {
"type": "array",
"items": {"type": "string"}
},
"db_users": {
"type": "array",
"items": {"type": "string"}
},
"request": {
"type": "object",
"additionalProperties": false,
"properties": {
"roles": {
"type": "array",
"items": { "type": "string" }
},
"claims_to_roles": {
"type": "object",
"additionalProperties": false,
"properties": {
"claim": {"type": "string"},
"value": {"type": "string"},
"roles": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"thresholds": {
"type": "array",
"items": { "type": "object" }
}
}
},
"impersonate": {
"type": "object",
"additionalProperties": false,
"properties": {
"users": {
"type": "array",
"items": { "type": "string" }
},
"roles": {
"type": "array",
"items": { "type": "string" }
},
"where": {
"type": "string"
}
}
},
"review_requests": {
"type": "object"
},
"rules": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"resources": {
"type": "array",
"items": { "type": "string" }
},
"verbs": {
"type": "array",
"items": { "type": "string" }
},
"where": {
"type": "string"
},
"actions": {
"type": "array",
"items": { "type": "string" }
}
}
}
}
}
}
`
// GetRoleSchema returns role schema for the version requested with optionally
// injected schema for extensions.
func GetRoleSchema(version string, extensionSchema string) string {
schemaDefinitions := "," + RoleSpecV3SchemaDefinitions
schemaTemplate := RoleSpecV3SchemaTemplate
schema := fmt.Sprintf(schemaTemplate, ``)
if extensionSchema != "" {
schema = fmt.Sprintf(schemaTemplate, ","+extensionSchema)
}
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, schema, schemaDefinitions)
}
// UnmarshalRole unmarshals the Role resource from JSON.
func UnmarshalRole(bytes []byte, opts ...MarshalOption) (Role, error) {
var h ResourceHeader
@ -2336,14 +2161,8 @@ func UnmarshalRole(bytes []byte, opts ...MarshalOption) (Role, error) {
switch h.Version {
case V3:
var role RoleV3
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &role); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
if err := utils.UnmarshalWithSchema(GetRoleSchema(V3, ""), &role, bytes); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &role); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := ValidateRole(&role); err != nil {

View file

@ -21,15 +21,15 @@ import (
"crypto/x509/pkix"
"encoding/base64"
"encoding/xml"
"fmt"
"net/http"
"strings"
"time"
log "github.com/sirupsen/logrus"
"github.com/gravitational/teleport"
"github.com/gravitational/teleport/lib/tlsca"
"github.com/gravitational/teleport/lib/utils"
log "github.com/sirupsen/logrus"
"github.com/gravitational/trace"
"github.com/jonboulle/clockwork"
@ -213,76 +213,6 @@ func GetSAMLServiceProvider(sc SAMLConnector, clock clockwork.Clock) (*saml2.SAM
return sp, nil
}
// SAMLConnectorV2SchemaTemplate is a template JSON Schema for SAMLConnector
const SAMLConnectorV2SchemaTemplate = `{
"type": "object",
"additionalProperties": false,
"required": ["kind", "spec", "metadata", "version"],
"properties": {
"kind": {"type": "string"},
"version": {"type": "string", "default": "v1"},
"metadata": %v,
"spec": %v
}
}`
// SAMLConnectorSpecV2Schema is a JSON Schema for SAML Connector
var SAMLConnectorSpecV2Schema = fmt.Sprintf(`{
"type": "object",
"additionalProperties": false,
"required": ["acs"],
"properties": {
"issuer": {"type": "string"},
"sso": {"type": "string"},
"cert": {"type": "string"},
"provider": {"type": "string"},
"display": {"type": "string"},
"acs": {"type": "string"},
"audience": {"type": "string"},
"service_provider_issuer": {"type": "string"},
"entity_descriptor": {"type": "string"},
"entity_descriptor_url": {"type": "string"},
"attributes_to_roles": {
"type": "array",
"items": %v
},
"signing_key_pair": %v,
"assertion_key_pair": %v
}
}`, AttributeMappingSchema, SigningKeyPairSchema, SigningKeyPairSchema)
// AttributeMappingSchema is JSON schema for claim mapping
var AttributeMappingSchema = `{
"type": "object",
"additionalProperties": false,
"required": ["name", "value" ],
"properties": {
"name": {"type": "string"},
"value": {"type": "string"},
"roles": {
"type": "array",
"items": {
"type": "string"
}
}
}
}`
// SigningKeyPairSchema is the JSON schema for signing key pair.
var SigningKeyPairSchema = `{
"type": "object",
"additionalProperties": false,
"properties": {
"private_key": {"type": "string"},
"cert": {"type": "string"}
}
}`
// GetSAMLConnectorSchema returns schema for SAMLConnector
func GetSAMLConnectorSchema() string {
return fmt.Sprintf(SAMLConnectorV2SchemaTemplate, MetadataSchema, SAMLConnectorSpecV2Schema)
}
// UnmarshalSAMLConnector unmarshals the SAMLConnector resource from JSON.
func UnmarshalSAMLConnector(bytes []byte, opts ...MarshalOption) (SAMLConnector, error) {
cfg, err := CollectOptions(opts)
@ -297,14 +227,8 @@ func UnmarshalSAMLConnector(bytes []byte, opts ...MarshalOption) (SAMLConnector,
switch h.Version {
case V2:
var c SAMLConnectorV2
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &c); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
if err := utils.UnmarshalWithSchema(GetSAMLConnectorSchema(), &c, bytes); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &c); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := ValidateSAMLConnector(&c); err != nil {

View file

@ -2,7 +2,6 @@ package services
import (
"context"
"fmt"
"sync"
"time"
@ -218,30 +217,6 @@ func AcquireSemaphoreLock(ctx context.Context, cfg SemaphoreLockConfig) (*Semaph
return lock, nil
}
// SemaphoreSpecSchemaTemplate is a template for Semaphore schema.
const SemaphoreSpecSchemaTemplate = `{
"type": "object",
"additionalProperties": false,
"properties": {
"leases": {
"type": "array",
"items": {
"type": "object",
"properties": {
"lease_id": { "type": "string" },
"expires": { "type": "string" },
"holder": { "type": "string" }
}
}
}
}
}`
// GetSemaphoreSchema returns the validation schema for this object
func GetSemaphoreSchema() string {
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, SemaphoreSpecSchemaTemplate, DefaultDefinitions)
}
// UnmarshalSemaphore unmarshals the Semaphore resource from JSON.
func UnmarshalSemaphore(bytes []byte, opts ...MarshalOption) (Semaphore, error) {
var semaphore SemaphoreV3
@ -255,15 +230,8 @@ func UnmarshalSemaphore(bytes []byte, opts ...MarshalOption) (Semaphore, error)
return nil, trace.Wrap(err)
}
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &semaphore); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
err = utils.UnmarshalWithSchema(GetSemaphoreSchema(), &semaphore, bytes)
if err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &semaphore); err != nil {
return nil, trace.BadParameter(err.Error())
}
err = semaphore.CheckAndSetDefaults()

View file

@ -212,141 +212,6 @@ func GuessProxyHostAndVersion(proxies []Server) (string, string, error) {
return guessProxyHost, proxies[0].GetTeleportVersion(), nil
}
// ServerSpecV2Schema is JSON schema for server
const ServerSpecV2Schema = `{
"type": "object",
"additionalProperties": false,
"properties": {
"version": {"type": "string"},
"addr": {"type": "string"},
"protocol": {"type": "integer"},
"public_addr": {"type": "string"},
"apps": {
"type": ["array"],
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": {"type": "string"},
"description": {"type": "string"},
"uri": {"type": "string"},
"public_addr": {"type": "string"},
"insecure_skip_verify": {"type": "boolean"},
"rewrite": {
"type": "object",
"additionalProperties": false,
"properties": {
"redirect": {
"type": ["array", "null"],
"items": {"type": "string"}
},
"headers": {
"type": ["array", "null"],
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"name": {"type": "string"},
"value": {"type": "string"}
}
}
}
}
},
"labels": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^.*$": { "type": "string" }
}
},
"commands": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^.*$": {
"type": "object",
"additionalProperties": false,
"required": ["command"],
"properties": {
"command": {"type": "array", "items": {"type": "string"}},
"period": {"type": "string"},
"result": {"type": "string"}
}
}
}
}
}
}
},
"hostname": {"type": "string"},
"use_tunnel": {"type": "boolean"},
"labels": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^.*$": { "type": "string" }
}
},
"cmd_labels": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^.*$": {
"type": "object",
"additionalProperties": false,
"required": ["command"],
"properties": {
"command": {"type": "array", "items": {"type": "string"}},
"period": {"type": "string"},
"result": {"type": "string"}
}
}
}
},
"kube_clusters": {
"type": "array",
"items": {
"type": "object",
"required": ["name"],
"properties": {
"name": {"type": "string"},
"static_labels": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^.*$": { "type": "string" }
}
},
"dynamic_labels": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^.*$": {
"type": "object",
"additionalProperties": false,
"required": ["command"],
"properties": {
"command": {"type": "array", "items": {"type": "string"}},
"period": {"type": "string"},
"result": {"type": "string"}
}
}
}
}
}
}
},
"rotation": %v
}
}`
// GetServerSchema returns role schema with optionally injected
// schema for extensions
func GetServerSchema() string {
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, fmt.Sprintf(ServerSpecV2Schema, RotationSchema), DefaultDefinitions)
}
// UnmarshalServer unmarshals the Server resource from JSON.
func UnmarshalServer(bytes []byte, kind string, opts ...MarshalOption) (Server, error) {
cfg, err := CollectOptions(opts)
@ -367,14 +232,8 @@ func UnmarshalServer(bytes []byte, kind string, opts ...MarshalOption) (Server,
case V2:
var s ServerV2
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &s); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
if err := utils.UnmarshalWithSchema(GetServerSchema(), &s, bytes); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &s); err != nil {
return nil, trace.BadParameter(err.Error())
}
s.Kind = kind
if err := s.CheckAndSetDefaults(); err != nil {

View file

@ -58,13 +58,12 @@ func (s *ServicesSuite) TestOptions(c *check.C) {
c.Assert(cfg.ID, check.Equals, int64(1))
// Add a couple of other parameters
out = AddOptions(in, WithResourceID(2), SkipValidation(), WithVersion(V2))
c.Assert(out, check.HasLen, 3)
out = AddOptions(in, WithResourceID(2), WithVersion(V2))
c.Assert(out, check.HasLen, 2)
c.Assert(in, check.HasLen, 0)
cfg, err = CollectOptions(out)
c.Assert(err, check.IsNil)
c.Assert(cfg.ID, check.Equals, int64(2))
c.Assert(cfg.SkipValidation, check.Equals, true)
c.Assert(cfg.Version, check.Equals, V2)
}

View file

@ -18,7 +18,6 @@ package services
import (
"encoding/json"
"fmt"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/utils"
@ -26,39 +25,6 @@ import (
"github.com/gravitational/trace"
)
// WebSessionSpecV2Schema is JSON schema for cert authority V2
const WebSessionSpecV2Schema = `{
"type": "object",
"additionalProperties": false,
"required": ["pub", "bearer_token", "bearer_token_expires", "expires", "user"],
"properties": {
"user": {"type": "string"},
"pub": {"type": "string"},
"priv": {"type": "string"},
"tls_cert": {"type": "string"},
"bearer_token": {"type": "string"},
"bearer_token_expires": {"type": "string"},
"expires": {"type": "string"},
"login_time": {"type": "string"}%v
}
}`
// GetWebSessionSchema returns JSON Schema for web session
func GetWebSessionSchema() string {
return GetWebSessionSchemaWithExtensions("")
}
// GetWebSessionSchemaWithExtensions returns JSON Schema for web session with user-supplied extensions
func GetWebSessionSchemaWithExtensions(extension string) string {
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, fmt.Sprintf(WebSessionSpecV2Schema, extension), DefaultDefinitions)
}
// ExtendWebSession renews web session and is used to
// inject additional data in extenstions when session is getting renewed
func ExtendWebSession(ws WebSession) (WebSession, error) {
return ws, nil
}
// UnmarshalWebSession unmarshals the WebSession resource from JSON.
func UnmarshalWebSession(bytes []byte, opts ...MarshalOption) (types.WebSession, error) {
cfg, err := CollectOptions(opts)
@ -74,8 +40,8 @@ func UnmarshalWebSession(bytes []byte, opts ...MarshalOption) (types.WebSession,
switch h.Version {
case V2:
var ws types.WebSessionV2
if err := utils.UnmarshalWithSchema(GetWebSessionSchema(), &ws, bytes); err != nil {
return nil, trace.BadParameter(err.Error())
if err := utils.FastUnmarshal(bytes, &ws); err != nil {
return nil, trace.Wrap(err)
}
utils.UTC(&ws.Spec.BearerTokenExpires)
utils.UTC(&ws.Spec.Expires)
@ -160,7 +126,7 @@ func UnmarshalWebToken(bytes []byte, opts ...MarshalOption) (types.WebToken, err
switch hdr.Version {
case V3:
var token types.WebTokenV3
if err := utils.UnmarshalWithSchema(GetWebTokenSchema(), &token, bytes); err != nil {
if err := utils.FastUnmarshal(bytes, &token); err != nil {
return nil, trace.BadParameter("invalid web token: %v", err.Error())
}
if err := token.CheckAndSetDefaults(); err != nil {
@ -177,19 +143,3 @@ func UnmarshalWebToken(bytes []byte, opts ...MarshalOption) (types.WebToken, err
}
return nil, trace.BadParameter("web token resource version %v is not supported", hdr.Version)
}
// GetWebTokenSchema returns JSON schema for the web token resource
func GetWebTokenSchema() string {
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, WebTokenSpecV3Schema, "")
}
// WebTokenSpecV3Schema is JSON schema for the web token V3
const WebTokenSpecV3Schema = `{
"type": "object",
"additionalProperties": false,
"required": ["token", "user"],
"properties": {
"user": {"type": "string"},
"token": {"type": "string"}
}
}`

View file

@ -17,8 +17,6 @@ limitations under the License.
package services
import (
"fmt"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/utils"
@ -35,21 +33,6 @@ func IsRecordSync(mode string) bool {
return mode == RecordAtProxySync || mode == RecordAtNodeSync
}
// SessionRecordingConfigSpecSchema is JSON schema for SessionRecordingConfig spec.
const SessionRecordingConfigSpecSchema = `{
"type": "object",
"additionalProperties": false,
"properties": {
"mode": {"type": "string"},
"proxy_checks_host_keys": {"anyOf": [{"type": "string"}, { "type": "boolean"}]}
}
}`
// GetSessionRecordingConfigSchema returns full SessionRecordingConfig JSON schema.
func GetSessionRecordingConfigSchema() string {
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, SessionRecordingConfigSpecSchema, DefaultDefinitions)
}
// UnmarshalSessionRecordingConfig unmarshals the SessionRecordingConfig resource from JSON.
func UnmarshalSessionRecordingConfig(bytes []byte, opts ...MarshalOption) (types.SessionRecordingConfig, error) {
var recConfig types.SessionRecordingConfigV2
@ -62,16 +45,8 @@ func UnmarshalSessionRecordingConfig(bytes []byte, opts ...MarshalOption) (types
if err != nil {
return nil, trace.Wrap(err)
}
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &recConfig); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
err = utils.UnmarshalWithSchema(GetSessionRecordingConfigSchema(), &recConfig, bytes)
if err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &recConfig); err != nil {
return nil, trace.BadParameter(err.Error())
}
err = recConfig.CheckAndSetDefaults()

View file

@ -17,11 +17,10 @@ limitations under the License.
package services
import (
"fmt"
"github.com/gravitational/trace"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/utils"
"github.com/gravitational/trace"
)
// DefaultStaticTokens is used to get the default static tokens (empty list)
@ -40,47 +39,6 @@ func DefaultStaticTokens() StaticTokens {
}
}
// StaticTokensSpecSchemaTemplate is a template for StaticTokens schema.
const StaticTokensSpecSchemaTemplate = `{
"type": "object",
"additionalProperties": false,
"properties": {
"static_tokens": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"expires": {
"type": "string"
},
"roles": {
"type": "array",
"items": {
"type": "string"
}
},
"token": {
"type": "string"
}
}
}
}%v
}
}`
// GetStaticTokensSchema returns the schema with optionally injected
// schema for extensions.
func GetStaticTokensSchema(extensionSchema string) string {
var staticTokensSchema string
if staticTokensSchema == "" {
staticTokensSchema = fmt.Sprintf(StaticTokensSpecSchemaTemplate, "")
} else {
staticTokensSchema = fmt.Sprintf(StaticTokensSpecSchemaTemplate, ","+extensionSchema)
}
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, staticTokensSchema, DefaultDefinitions)
}
// UnmarshalStaticTokens unmarshals the StaticTokens resource from JSON.
func UnmarshalStaticTokens(bytes []byte, opts ...MarshalOption) (StaticTokens, error) {
var staticTokens StaticTokensV2
@ -94,19 +52,10 @@ func UnmarshalStaticTokens(bytes []byte, opts ...MarshalOption) (StaticTokens, e
return nil, trace.Wrap(err)
}
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &staticTokens); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
err = utils.UnmarshalWithSchema(GetStaticTokensSchema(""), &staticTokens, bytes)
if err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &staticTokens); err != nil {
return nil, trace.BadParameter(err.Error())
}
err = staticTokens.CheckAndSetDefaults()
if err != nil {
if err := staticTokens.CheckAndSetDefaults(); err != nil {
return nil, trace.Wrap(err)
}

View file

@ -295,7 +295,7 @@ func (s *ServicesTestSuite) CertAuthCRUD(c *check.C) {
c.Assert(err, check.IsNil)
fixtures.DeepCompare(c, cas[0], ca)
cas, err = s.CAS.GetCertAuthorities(services.UserCA, true, services.SkipValidation())
cas, err = s.CAS.GetCertAuthorities(services.UserCA, true)
c.Assert(err, check.IsNil)
fixtures.DeepCompare(c, cas[0], ca)

View file

@ -135,55 +135,6 @@ func MapRoles(r RoleMap, remoteRoles []string) ([]string, error) {
return outRoles, nil
}
// TrustedClusterSpecSchemaTemplate is a template for trusted cluster schema
const TrustedClusterSpecSchemaTemplate = `{
"type": "object",
"additionalProperties": false,
"properties": {
"enabled": {"type": "boolean"},
"roles": {
"type": "array",
"items": {
"type": "string"
}
},
"role_map": %v,
"token": {"type": "string"},
"web_proxy_addr": {"type": "string"},
"tunnel_addr": {"type": "string"}%v
}
}`
// RoleMapSchema is a schema for role mappings of trusted clusters
const RoleMapSchema = `{
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"properties": {
"local": {
"type": "array",
"items": {
"type": "string"
}
},
"remote": {"type": "string"}
}
}
}`
// GetTrustedClusterSchema returns the schema with optionally injected
// schema for extensions.
func GetTrustedClusterSchema(extensionSchema string) string {
var trustedClusterSchema string
if extensionSchema == "" {
trustedClusterSchema = fmt.Sprintf(TrustedClusterSpecSchemaTemplate, RoleMapSchema, "")
} else {
trustedClusterSchema = fmt.Sprintf(TrustedClusterSpecSchemaTemplate, RoleMapSchema, ","+extensionSchema)
}
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, trustedClusterSchema, DefaultDefinitions)
}
// UnmarshalTrustedCluster unmarshals the TrustedCluster resource from JSON.
func UnmarshalTrustedCluster(bytes []byte, opts ...MarshalOption) (TrustedCluster, error) {
cfg, err := CollectOptions(opts)
@ -196,15 +147,8 @@ func UnmarshalTrustedCluster(bytes []byte, opts ...MarshalOption) (TrustedCluste
return nil, trace.BadParameter("missing resource data")
}
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &trustedCluster); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
err := utils.UnmarshalWithSchema(GetTrustedClusterSchema(""), &trustedCluster, bytes)
if err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &trustedCluster); err != nil {
return nil, trace.BadParameter(err.Error())
}
// DELETE IN(7.0)

View file

@ -18,7 +18,6 @@ package services
import (
"encoding/json"
"fmt"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/utils"
@ -39,29 +38,6 @@ func ValidateReverseTunnel(rt types.ReverseTunnel) error {
return nil
}
// ReverseTunnelSpecV2Schema is JSON schema for reverse tunnel spec
const ReverseTunnelSpecV2Schema = `{
"type": "object",
"additionalProperties": false,
"required": ["cluster_name", "dial_addrs"],
"properties": {
"cluster_name": {"type": "string"},
"type": {"type": "string"},
"dial_addrs": {
"type": "array",
"items": {
"type": "string"
}
}
}
}`
// GetReverseTunnelSchema returns role schema with optionally injected
// schema for extensions
func GetReverseTunnelSchema() string {
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, ReverseTunnelSpecV2Schema, DefaultDefinitions)
}
// UnmarshalReverseTunnel unmarshals the ReverseTunnel resource from JSON.
func UnmarshalReverseTunnel(bytes []byte, opts ...MarshalOption) (ReverseTunnel, error) {
if len(bytes) == 0 {
@ -80,14 +56,8 @@ func UnmarshalReverseTunnel(bytes []byte, opts ...MarshalOption) (ReverseTunnel,
switch h.Version {
case V2:
var r ReverseTunnelV2
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &r); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
if err := utils.UnmarshalWithSchema(GetReverseTunnelSchema(), &r, bytes); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &r); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := ValidateReverseTunnel(&r); err != nil {
return nil, trace.Wrap(err)

View file

@ -17,7 +17,6 @@ limitations under the License.
package services
import (
"fmt"
"time"
"github.com/gravitational/teleport"
@ -53,25 +52,6 @@ func TunnelConnectionStatus(clock clockwork.Clock, conn TunnelConnection, offlin
return teleport.RemoteClusterStatusOffline
}
// TunnelConnectionSpecV2Schema is JSON schema for reverse tunnel spec
const TunnelConnectionSpecV2Schema = `{
"type": "object",
"additionalProperties": false,
"required": ["cluster_name", "proxy_name", "last_heartbeat"],
"properties": {
"cluster_name": {"type": "string"},
"proxy_name": {"type": "string"},
"last_heartbeat": {"type": "string"},
"type": {"type": "string"}
}
}`
// GetTunnelConnectionSchema returns role schema with optionally injected
// schema for extensions
func GetTunnelConnectionSchema() string {
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, TunnelConnectionSpecV2Schema, DefaultDefinitions)
}
// UnmarshalTunnelConnection unmarshals TunnelConnection resource from JSON or YAML,
// sets defaults and checks the schema
func UnmarshalTunnelConnection(data []byte, opts ...MarshalOption) (TunnelConnection, error) {
@ -91,14 +71,8 @@ func UnmarshalTunnelConnection(data []byte, opts ...MarshalOption) (TunnelConnec
case V2:
var r TunnelConnectionV2
if cfg.SkipValidation {
if err := utils.FastUnmarshal(data, &r); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
if err := utils.UnmarshalWithSchema(GetTunnelConnectionSchema(), &r, data); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(data, &r); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := r.CheckAndSetDefaults(); err != nil {

View file

@ -18,7 +18,6 @@ package services
import (
"encoding/json"
"fmt"
"time"
"github.com/google/go-cmp/cmp"
@ -68,105 +67,6 @@ func (la *LoginAttempt) Check() error {
return nil
}
// UserSpecV2SchemaTemplate is JSON schema for V2 user
const UserSpecV2SchemaTemplate = `{
"type": "object",
"additionalProperties": false,
"properties": {
"expires": {"type": "string"},
"roles": {
"type": "array",
"items": {
"type": "string"
}
},
"traits": {
"type": "object",
"additionalProperties": false,
"patternProperties": {
"^.+$": {
"type": ["array", "null"],
"items": {
"type": "string"
}
}
}
},
"oidc_identities": {
"type": "array",
"items": %v
},
"saml_identities": {
"type": "array",
"items": %v
},
"github_identities": {
"type": "array",
"items": %v
},
"status": %v,
"created_by": %v,
"local_auth": %v%v
}
}`
// CreatedBySchema is JSON schema for CreatedBy
const CreatedBySchema = `{
"type": "object",
"additionalProperties": false,
"properties": {
"connector": {
"additionalProperties": false,
"type": "object",
"properties": {
"type": {"type": "string"},
"id": {"type": "string"},
"identity": {"type": "string"}
}
},
"time": {"type": "string"},
"user": {
"type": "object",
"additionalProperties": false,
"properties": {"name": {"type": "string"}}
}
}
}`
// ExternalIdentitySchema is JSON schema for ExternalIdentity
const ExternalIdentitySchema = `{
"type": "object",
"additionalProperties": false,
"properties": {
"connector_id": {"type": "string"},
"username": {"type": "string"}
}
}`
// LoginStatusSchema is JSON schema for LoginStatus
const LoginStatusSchema = `{
"type": "object",
"additionalProperties": false,
"properties": {
"is_locked": {"type": "boolean"},
"locked_message": {"type": "string"},
"locked_time": {"type": "string"},
"lock_expires": {"type": "string"}
}
}`
// GetUserSchema returns role schema with optionally injected
// schema for extensions
func GetUserSchema(extensionSchema string) string {
var userSchema string
if extensionSchema == "" {
userSchema = fmt.Sprintf(UserSpecV2SchemaTemplate, ExternalIdentitySchema, ExternalIdentitySchema, ExternalIdentitySchema, LoginStatusSchema, CreatedBySchema, LocalAuthSecretsSchema, ``)
} else {
userSchema = fmt.Sprintf(UserSpecV2SchemaTemplate, ExternalIdentitySchema, ExternalIdentitySchema, ExternalIdentitySchema, LoginStatusSchema, CreatedBySchema, LocalAuthSecretsSchema, ", "+extensionSchema)
}
return fmt.Sprintf(V2SchemaTemplate, MetadataSchema, userSchema, DefaultDefinitions)
}
// UnmarshalUser unmarshals the User resource from JSON.
func UnmarshalUser(bytes []byte, opts ...MarshalOption) (User, error) {
var h ResourceHeader
@ -183,14 +83,8 @@ func UnmarshalUser(bytes []byte, opts ...MarshalOption) (User, error) {
switch h.Version {
case V2:
var u UserV2
if cfg.SkipValidation {
if err := utils.FastUnmarshal(bytes, &u); err != nil {
return nil, trace.BadParameter(err.Error())
}
} else {
if err := utils.UnmarshalWithSchema(GetUserSchema(""), &u, bytes); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := utils.FastUnmarshal(bytes, &u); err != nil {
return nil, trace.BadParameter(err.Error())
}
if err := ValidateUser(&u); err != nil {

View file

@ -314,7 +314,7 @@ func (t *proxySubsys) proxyToHost(
// going to "local" CA? lets use the caching 'auth service' directly and avoid
// hitting the reverse tunnel link (it can be offline if the CA is down)
if site.GetName() == localCluster.GetName() {
servers, err = t.srv.authService.GetNodes(ctx.CancelContext(), t.namespace, services.SkipValidation())
servers, err = t.srv.authService.GetNodes(ctx.CancelContext(), t.namespace)
if err != nil {
t.log.Warn(err)
}
@ -324,7 +324,7 @@ func (t *proxySubsys) proxyToHost(
if err != nil {
t.log.Warn(err)
} else {
servers, err = siteClient.GetNodes(ctx.CancelContext(), t.namespace, services.SkipValidation())
servers, err = siteClient.GetNodes(ctx.CancelContext(), t.namespace)
if err != nil {
t.log.Warn(err)
}

View file

@ -1,56 +0,0 @@
/*
Copyright 2015-2021 Gravitational, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package utils
import (
"encoding/json"
"github.com/gravitational/configure/jsonschema"
"github.com/gravitational/trace"
)
// UnmarshalWithSchema processes YAML or JSON encoded object with JSON schema, sets defaults
// and unmarshals resulting object into given struct
func UnmarshalWithSchema(schemaDefinition string, object interface{}, data []byte) error {
schema, err := jsonschema.New([]byte(schemaDefinition))
if err != nil {
return trace.Wrap(err)
}
jsonData, err := ToJSON(data)
if err != nil {
return trace.Wrap(err)
}
raw := map[string]interface{}{}
if err := json.Unmarshal(jsonData, &raw); err != nil {
return trace.Wrap(err)
}
// schema will check format and set defaults
processed, err := schema.ProcessObject(raw)
if err != nil {
return trace.Wrap(err)
}
// since ProcessObject works with unstructured data, the
// data needs to be re-interpreted in structured form
bytes, err := json.Marshal(processed)
if err != nil {
return trace.Wrap(err)
}
if err := json.Unmarshal(bytes, object); err != nil {
return trace.Wrap(err)
}
return nil
}

View file

@ -1587,7 +1587,7 @@ func (h *Handler) getClusters(w http.ResponseWriter, r *http.Request, p httprout
if err != nil {
return nil, trace.Wrap(err)
}
remoteClusters, err := clt.GetRemoteClusters(services.SkipValidation())
remoteClusters, err := clt.GetRemoteClusters()
if err != nil {
return nil, trace.Wrap(err)
}
@ -1654,7 +1654,7 @@ func (h *Handler) siteNodesGet(w http.ResponseWriter, r *http.Request, p httprou
if err != nil {
return nil, trace.Wrap(err)
}
servers, err := clt.GetNodes(r.Context(), namespace, services.SkipValidation())
servers, err := clt.GetNodes(r.Context(), namespace)
if err != nil {
return nil, trace.Wrap(err)
}
@ -1763,7 +1763,7 @@ func (h *Handler) siteSessionGenerate(w http.ResponseWriter, r *http.Request, p
}
if req.Session.ServerID != "" {
servers, err := clt.GetNodes(r.Context(), namespace, services.SkipValidation())
servers, err := clt.GetNodes(r.Context(), namespace)
if err != nil {
return nil, trace.Wrap(err)
}

View file

@ -102,7 +102,7 @@ func NewTerminal(ctx context.Context, req TerminalRequest, authProvider AuthProv
return nil, trace.BadParameter("term: bad term dimensions")
}
servers, err := authProvider.GetNodes(ctx, req.Namespace, services.SkipValidation())
servers, err := authProvider.GetNodes(ctx, req.Namespace)
if err != nil {
return nil, trace.Wrap(err)
}

View file

@ -47,39 +47,30 @@ func BenchmarkGetClusterDetails(b *testing.B) {
const proxyCount = 6
type testCase struct {
validation, memory bool
nodes int
memory bool
nodes int
}
var tts []testCase
for _, validation := range []bool{true, false} {
for _, memory := range []bool{true, false} {
for _, nodes := range []int{100, 1000, 10000} {
tts = append(tts, testCase{
validation: validation,
memory: memory,
nodes: nodes,
})
}
for _, memory := range []bool{true, false} {
for _, nodes := range []int{100, 1000, 10000} {
tts = append(tts, testCase{
memory: memory,
nodes: nodes,
})
}
}
for _, tt := range tts {
// create a descriptive name for the sub-benchmark.
name := fmt.Sprintf("tt(validation=%v,memory=%v,nodes=%d)", tt.validation, tt.memory, tt.nodes)
name := fmt.Sprintf("tt(memory=%v,nodes=%d)", tt.memory, tt.nodes)
// run the sub benchmark
b.Run(name, func(sb *testing.B) {
sb.StopTimer() // stop timer while running setup
// set up marshal options
var opts []services.MarshalOption
if !tt.validation {
opts = append(opts, services.SkipValidation())
}
// configure the backend instance
var bk backend.Backend
var err error
@ -113,7 +104,7 @@ func BenchmarkGetClusterDetails(b *testing.B) {
sb.StartTimer() // restart timer for benchmark operations
benchmarkGetClusterDetails(ctx, sb, site, tt.nodes, opts...)
benchmarkGetClusterDetails(ctx, sb, site, tt.nodes)
sb.StopTimer() // stop timer to exclude deferred cleanup
})

View file

@ -21,12 +21,12 @@ import (
"os"
"github.com/gravitational/kingpin"
"github.com/gravitational/trace"
"github.com/gravitational/teleport"
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/service"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/trace"
)
// AppsCommand implements "tctl apps" group of commands.
@ -63,7 +63,7 @@ func (c *AppsCommand) TryRun(cmd string, client auth.ClientI) (match bool, err e
// ListApps prints the list of applications that have recently sent heartbeats
// to the cluster.
func (c *AppsCommand) ListApps(client auth.ClientI) error {
servers, err := client.GetAppServers(context.TODO(), defaults.Namespace, services.SkipValidation())
servers, err := client.GetAppServers(context.TODO(), defaults.Namespace)
if err != nil {
return trace.Wrap(err)
}

View file

@ -25,7 +25,6 @@ import (
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/service"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/kingpin"
"github.com/gravitational/trace"
@ -65,7 +64,7 @@ func (c *DBCommand) TryRun(cmd string, client auth.ClientI) (match bool, err err
// ListDatabases prints the list of database proxies that have recently sent
// heartbeats to the cluster.
func (c *DBCommand) ListDatabases(client auth.ClientI) error {
servers, err := client.GetDatabaseServers(context.TODO(), defaults.Namespace, services.SkipValidation())
servers, err := client.GetDatabaseServers(context.TODO(), defaults.Namespace)
if err != nil {
return trace.Wrap(err)
}

View file

@ -25,12 +25,12 @@ import (
"time"
"github.com/gravitational/kingpin"
"github.com/gravitational/trace"
"github.com/gravitational/teleport"
"github.com/gravitational/teleport/lib/auth"
"github.com/gravitational/teleport/lib/defaults"
"github.com/gravitational/teleport/lib/service"
"github.com/gravitational/teleport/lib/services"
"github.com/gravitational/trace"
)
// NodeCommand implements `tctl nodes` group of commands
@ -170,7 +170,7 @@ func (c *NodeCommand) Invite(client auth.ClientI) error {
// to a cluster and prints it to stdout
func (c *NodeCommand) ListActive(client auth.ClientI) error {
ctx := context.TODO()
nodes, err := client.GetNodes(ctx, c.namespace, services.SkipValidation())
nodes, err := client.GetNodes(ctx, c.namespace)
if err != nil {
return trace.Wrap(err)
}