| // Code generated by protoc-gen-go. DO NOT EDIT. |
| // source: go.chromium.org/luci/swarming/proto/config/bots.proto |
| |
| package configpb |
| |
| import ( |
| fmt "fmt" |
| proto "github.com/golang/protobuf/proto" |
| _ "go.chromium.org/luci/common/proto" |
| math "math" |
| ) |
| |
| // Reference imports to suppress errors if they are not otherwise used. |
| var _ = proto.Marshal |
| var _ = fmt.Errorf |
| var _ = math.Inf |
| |
| // This is a compile-time assertion to ensure that this generated file |
| // is compatible with the proto package it is being compiled against. |
| // A compilation error at this line likely means your copy of the |
| // proto package needs to be updated. |
| const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package |
| |
| // Schema for bots.cfg service config file in luci-config. |
| // |
| // It defines a function bot_id => (required credentials, trusted_dimensions, |
| // config), where |
| // * "bot_id" is identifier of a bot as sent by the bot itself (usually |
| // machine hostname, short one, not FQDN) |
| // * "required credentials" describes how server should authenticate calls |
| // from the bot. |
| // * "trusted_dimensions" is a set of dimension set by the server itself. |
| // Such dimensions can't be spoofed by the bot. |
| // * "config" is any additional bot configuration. |
| // |
| // Connections from bots that do not appear in this config are rejected. |
| // |
| // The default config (used if bots.cfg is missing) represents IP-whitelist only |
| // authentication, as was used before bots.cfg was implemented: |
| // |
| // bot_group { |
| // auth { |
| // ip_whitelist: "<swarming-app-id>-bots" |
| // } |
| // } |
| type BotsCfg struct { |
| // List of dimension names that are provided by the server. |
| // |
| // If bot attempts to set such dimension, it'll be ignored. Trusted dimensions |
| // are defined through bot_group configs below. Swarming users can trust such |
| // dimensions, since they are set by the server based on validated credentials |
| // (unlike other dimensions that can be arbitrary defined by the bot itself). |
| TrustedDimensions []string `protobuf:"bytes,1,rep,name=trusted_dimensions,json=trustedDimensions,proto3" json:"trusted_dimensions,omitempty"` |
| // A list of groups of bots. Each group defines a bunch of bots that all |
| // have same dimensions and authenticate in the same way. |
| // |
| // The order of entries here is irrelevant. The server uses the following |
| // search algorithm when trying to pick a group for a bot with some bot_id: |
| // 1) First it tries to find a direct match: a group that lists the bot in |
| // bot_id field. |
| // 2) Next it tries to find a group with matching bot_id_prefix. The config |
| // validation process makes sure prefixes do not "intersect", so there |
| // will be at most one matching group. |
| // 3) Finally, if there's a group with no defined bot_id or bot_id_prefix |
| // fields (the "default" group), the bot is categorized to that group. |
| // If there's no such group, the connection from the bot is rejected. |
| // Config validation process ensures there can be only one such group. |
| BotGroup []*BotGroup `protobuf:"bytes,2,rep,name=bot_group,json=botGroup,proto3" json:"bot_group,omitempty"` |
| XXX_NoUnkeyedLiteral struct{} `json:"-"` |
| XXX_unrecognized []byte `json:"-"` |
| XXX_sizecache int32 `json:"-"` |
| } |
| |
| func (m *BotsCfg) Reset() { *m = BotsCfg{} } |
| func (m *BotsCfg) String() string { return proto.CompactTextString(m) } |
| func (*BotsCfg) ProtoMessage() {} |
| func (*BotsCfg) Descriptor() ([]byte, []int) { |
| return fileDescriptor_ecc3522ef1feaf58, []int{0} |
| } |
| |
| func (m *BotsCfg) XXX_Unmarshal(b []byte) error { |
| return xxx_messageInfo_BotsCfg.Unmarshal(m, b) |
| } |
| func (m *BotsCfg) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { |
| return xxx_messageInfo_BotsCfg.Marshal(b, m, deterministic) |
| } |
| func (m *BotsCfg) XXX_Merge(src proto.Message) { |
| xxx_messageInfo_BotsCfg.Merge(m, src) |
| } |
| func (m *BotsCfg) XXX_Size() int { |
| return xxx_messageInfo_BotsCfg.Size(m) |
| } |
| func (m *BotsCfg) XXX_DiscardUnknown() { |
| xxx_messageInfo_BotsCfg.DiscardUnknown(m) |
| } |
| |
| var xxx_messageInfo_BotsCfg proto.InternalMessageInfo |
| |
| func (m *BotsCfg) GetTrustedDimensions() []string { |
| if m != nil { |
| return m.TrustedDimensions |
| } |
| return nil |
| } |
| |
| func (m *BotsCfg) GetBotGroup() []*BotGroup { |
| if m != nil { |
| return m.BotGroup |
| } |
| return nil |
| } |
| |
| // A group of bots that share authentication method, dimensions and owners. |
| // |
| // Union of bot_id and bot_id_prefix define a set of bots that belong to this |
| // group. The rest of the fields define properties of this group. |
| // |
| // If bot_id and bot_id_prefix are both missing, the group defines all bots that |
| // didn't fit into other groups. There can be only one such "default" group. |
| // |
| // NOTE: Swarming allows 'derivative' bots where multiple bots run on the same |
| // host machine in some sort of container (such as Docker containers) and SHARE |
| // A SINGLE CREDENTIAL. These bots have hostnames such as 'hostmachine--001', |
| // where the "--001" suffix indicates which of the contained bots on |
| // 'hostmachine' it is. When Swarming checks the bot affiliation for this |
| // contained machine, it checks ONLY the 'hostmachine' portion. This means that |
| // if your contained bot is 'vm10-vlan2--001', it would match: |
| // `bot_id: "vm10-vlan2` |
| // `bot_id: "vm{0...100}-vlan2` |
| // `bot_id_prefix: "vm10-vlan` |
| // but would NOT match: |
| // `bot_id: "vm10-vlan2--001` |
| // `bot_id_prefix: "vm10-vlan2-` |
| // `bot_id_prefix: "vm10-vlan2--` |
| // |
| // TODO(vadimsh): Introduce explicit field "use_as_default" instead. |
| type BotGroup struct { |
| // Explicit enumeration of bot IDs belonging to this group. |
| // |
| // It supports subset of bash brace expansion syntax, in particular ranges |
| // and lists. For example: |
| // * vm{1..3}-m1 will expand into vm1-m1, vm2-m1 and vm3-m1. |
| // * vm{100,150,200}-m1 will expand into vm100-m1, vm150-m1 and vm200-m1. |
| // |
| // There can be only one "{...}" section in the string. |
| BotId []string `protobuf:"bytes,1,rep,name=bot_id,json=botId,proto3" json:"bot_id,omitempty"` |
| // A prefix to match against bot ID string. |
| BotIdPrefix []string `protobuf:"bytes,2,rep,name=bot_id_prefix,json=botIdPrefix,proto3" json:"bot_id_prefix,omitempty"` |
| // Defines authentication methods for bots from this group. |
| // |
| // Evaluated sequentially until first match. |
| Auth []*BotAuth `protobuf:"bytes,20,rep,name=auth,proto3" json:"auth,omitempty"` |
| // Emails of owners of these bots. Optional. |
| Owners []string `protobuf:"bytes,21,rep,name=owners,proto3" json:"owners,omitempty"` |
| // List of dimensions to assign to these bots. |
| // |
| // Each dimension is a "<key>:<value>" pair. |
| Dimensions []string `protobuf:"bytes,22,rep,name=dimensions,proto3" json:"dimensions,omitempty"` |
| // Path to an additional config script to inject into the swarming bot upon |
| // handshake. |
| // |
| // The path is relative to 'scripts/' directory in the service config repo. |
| BotConfigScript string `protobuf:"bytes,23,opt,name=bot_config_script,json=botConfigScript,proto3" json:"bot_config_script,omitempty"` |
| // The actual body of the config script to inject into the swarming bot upon |
| // handshake (in whatever encoding it happened to be in the config repo). |
| // |
| // For internal use (unless you fancy writing python scripts as single line |
| // escaped text proto string). If present, overrides 'bot_config_script'. |
| BotConfigScriptContent []byte `protobuf:"bytes,25,opt,name=bot_config_script_content,json=botConfigScriptContent,proto3" json:"bot_config_script_content,omitempty"` |
| // A service account to use on bots when authenticating calls to various |
| // system-level services (like Isolate and CIPD), required for correct |
| // operation of the bot. |
| // |
| // Tasks will be able to access this account too, but it is not recommended |
| // and should be used extremely rare. |
| // |
| // If set to a service account email (*@*.iam.gserviceaccount.com), bots will |
| // use this account, generating access token through Swarming server. For this |
| // to work, the server account (<app-id>@appspot.gserviceaccount.com) must |
| // have "serviceAccountActor" IAM role set on the account. |
| // |
| // If set to a special string "bot", bots will use exact same token they use |
| // when authenticating calls to Swarming server itself. This works only if |
| // bots use OAuth for authentication (see 'require_service_account' in |
| // BotAuth). This mode exists for cases when proliferation of various service |
| // accounts is undesirable. Note that in this mode Swarming processes won't be |
| // able to request a system account token with some new scopes: they get exact |
| // same token as returned by get_authentication_headers bot_config.py hook. |
| // |
| // If not set, bots will not use authentication at all. |
| SystemServiceAccount string `protobuf:"bytes,24,opt,name=system_service_account,json=systemServiceAccount,proto3" json:"system_service_account,omitempty"` |
| XXX_NoUnkeyedLiteral struct{} `json:"-"` |
| XXX_unrecognized []byte `json:"-"` |
| XXX_sizecache int32 `json:"-"` |
| } |
| |
| func (m *BotGroup) Reset() { *m = BotGroup{} } |
| func (m *BotGroup) String() string { return proto.CompactTextString(m) } |
| func (*BotGroup) ProtoMessage() {} |
| func (*BotGroup) Descriptor() ([]byte, []int) { |
| return fileDescriptor_ecc3522ef1feaf58, []int{1} |
| } |
| |
| func (m *BotGroup) XXX_Unmarshal(b []byte) error { |
| return xxx_messageInfo_BotGroup.Unmarshal(m, b) |
| } |
| func (m *BotGroup) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { |
| return xxx_messageInfo_BotGroup.Marshal(b, m, deterministic) |
| } |
| func (m *BotGroup) XXX_Merge(src proto.Message) { |
| xxx_messageInfo_BotGroup.Merge(m, src) |
| } |
| func (m *BotGroup) XXX_Size() int { |
| return xxx_messageInfo_BotGroup.Size(m) |
| } |
| func (m *BotGroup) XXX_DiscardUnknown() { |
| xxx_messageInfo_BotGroup.DiscardUnknown(m) |
| } |
| |
| var xxx_messageInfo_BotGroup proto.InternalMessageInfo |
| |
| func (m *BotGroup) GetBotId() []string { |
| if m != nil { |
| return m.BotId |
| } |
| return nil |
| } |
| |
| func (m *BotGroup) GetBotIdPrefix() []string { |
| if m != nil { |
| return m.BotIdPrefix |
| } |
| return nil |
| } |
| |
| func (m *BotGroup) GetAuth() []*BotAuth { |
| if m != nil { |
| return m.Auth |
| } |
| return nil |
| } |
| |
| func (m *BotGroup) GetOwners() []string { |
| if m != nil { |
| return m.Owners |
| } |
| return nil |
| } |
| |
| func (m *BotGroup) GetDimensions() []string { |
| if m != nil { |
| return m.Dimensions |
| } |
| return nil |
| } |
| |
| func (m *BotGroup) GetBotConfigScript() string { |
| if m != nil { |
| return m.BotConfigScript |
| } |
| return "" |
| } |
| |
| func (m *BotGroup) GetBotConfigScriptContent() []byte { |
| if m != nil { |
| return m.BotConfigScriptContent |
| } |
| return nil |
| } |
| |
| func (m *BotGroup) GetSystemServiceAccount() string { |
| if m != nil { |
| return m.SystemServiceAccount |
| } |
| return "" |
| } |
| |
| // Defines what kind of authentication to perform when handling requests from |
| // bots belonging to some bot group. |
| // |
| // The following combinations are valid: |
| // * Either one of require_* alone. |
| // * IP whitelist alone. |
| // * IP + require_luci_machine_token: requires both to pass. |
| // * IP + require_service_account: requires both to pass. |
| // * IP + require_gce_vm_token: requires both to pass. |
| // |
| // Next ID: 6. |
| type BotAuth struct { |
| // If true, log an error (but proceed) if this method didn't succeed. |
| // |
| // This field is totally optional and makes sense only when there are more |
| // than one auth method. Affects only logging levels. |
| // |
| // Doesn't apply to methods that were skipped because some method before them |
| // succeeded. Thus methods that have 'log_if_failed' should be in front of |
| // BotGroup.auth list. |
| // |
| // This is useful when migrating from one auth method to another to verify |
| // the new method is used in 100% of cases, while still keeping a fallback |
| // to an old method. |
| LogIfFailed bool `protobuf:"varint,5,opt,name=log_if_failed,json=logIfFailed,proto3" json:"log_if_failed,omitempty"` |
| // If true, the bot should provide valid X-Luci-Machine-Token header. |
| // |
| // The machine FQDN embedded in the token should have hostname equal to the |
| // bot_id. |
| RequireLuciMachineToken bool `protobuf:"varint,1,opt,name=require_luci_machine_token,json=requireLuciMachineToken,proto3" json:"require_luci_machine_token,omitempty"` |
| // If set, the bot should use OAuth access token belonging to any of these |
| // service accounts. |
| // |
| // The token should have "https://www.googleapis.com/auth/userinfo.email" |
| // scope. |
| RequireServiceAccount []string `protobuf:"bytes,2,rep,name=require_service_account,json=requireServiceAccount,proto3" json:"require_service_account,omitempty"` |
| // If set, the bot should provide valid X-Luci-Gce-Vm-Token header. |
| // |
| // This header should contain JWT with signed VM metadata with the following |
| // expectations: |
| // * Audience matches https://[*-dot-]<app>.appspot.com |
| // * google.compute_engine.project_id field matches the value of 'project'. |
| // * instance_name matches bot_id reported by the bot (case insensitive). |
| RequireGceVmToken *BotAuth_GCE `protobuf:"bytes,4,opt,name=require_gce_vm_token,json=requireGceVmToken,proto3" json:"require_gce_vm_token,omitempty"` |
| // If set, defines an IP whitelist name (in auth_service database) with a set |
| // of IPs allowed to be used by the bots in this group. |
| // |
| // Works in conjunction with other checks, e.g. if require_luci_machine_token |
| // is true, both valid X-Luci-Machine-Token and a whitelisted IP are needed to |
| // successfully authenticate. |
| // |
| // Can also be used on its own (when all other fields are empty). In that case |
| // the IP whitelist is the primary authentication mechanism. Note that in this |
| // case all bots that share the IP whitelist are effectively in a single trust |
| // domain (any bot can pretend to be some other bot). |
| IpWhitelist string `protobuf:"bytes,3,opt,name=ip_whitelist,json=ipWhitelist,proto3" json:"ip_whitelist,omitempty"` |
| XXX_NoUnkeyedLiteral struct{} `json:"-"` |
| XXX_unrecognized []byte `json:"-"` |
| XXX_sizecache int32 `json:"-"` |
| } |
| |
| func (m *BotAuth) Reset() { *m = BotAuth{} } |
| func (m *BotAuth) String() string { return proto.CompactTextString(m) } |
| func (*BotAuth) ProtoMessage() {} |
| func (*BotAuth) Descriptor() ([]byte, []int) { |
| return fileDescriptor_ecc3522ef1feaf58, []int{2} |
| } |
| |
| func (m *BotAuth) XXX_Unmarshal(b []byte) error { |
| return xxx_messageInfo_BotAuth.Unmarshal(m, b) |
| } |
| func (m *BotAuth) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { |
| return xxx_messageInfo_BotAuth.Marshal(b, m, deterministic) |
| } |
| func (m *BotAuth) XXX_Merge(src proto.Message) { |
| xxx_messageInfo_BotAuth.Merge(m, src) |
| } |
| func (m *BotAuth) XXX_Size() int { |
| return xxx_messageInfo_BotAuth.Size(m) |
| } |
| func (m *BotAuth) XXX_DiscardUnknown() { |
| xxx_messageInfo_BotAuth.DiscardUnknown(m) |
| } |
| |
| var xxx_messageInfo_BotAuth proto.InternalMessageInfo |
| |
| func (m *BotAuth) GetLogIfFailed() bool { |
| if m != nil { |
| return m.LogIfFailed |
| } |
| return false |
| } |
| |
| func (m *BotAuth) GetRequireLuciMachineToken() bool { |
| if m != nil { |
| return m.RequireLuciMachineToken |
| } |
| return false |
| } |
| |
| func (m *BotAuth) GetRequireServiceAccount() []string { |
| if m != nil { |
| return m.RequireServiceAccount |
| } |
| return nil |
| } |
| |
| func (m *BotAuth) GetRequireGceVmToken() *BotAuth_GCE { |
| if m != nil { |
| return m.RequireGceVmToken |
| } |
| return nil |
| } |
| |
| func (m *BotAuth) GetIpWhitelist() string { |
| if m != nil { |
| return m.IpWhitelist |
| } |
| return "" |
| } |
| |
| // See require_gce_vm_token below. |
| type BotAuth_GCE struct { |
| Project string `protobuf:"bytes,1,opt,name=project,proto3" json:"project,omitempty"` |
| XXX_NoUnkeyedLiteral struct{} `json:"-"` |
| XXX_unrecognized []byte `json:"-"` |
| XXX_sizecache int32 `json:"-"` |
| } |
| |
| func (m *BotAuth_GCE) Reset() { *m = BotAuth_GCE{} } |
| func (m *BotAuth_GCE) String() string { return proto.CompactTextString(m) } |
| func (*BotAuth_GCE) ProtoMessage() {} |
| func (*BotAuth_GCE) Descriptor() ([]byte, []int) { |
| return fileDescriptor_ecc3522ef1feaf58, []int{2, 0} |
| } |
| |
| func (m *BotAuth_GCE) XXX_Unmarshal(b []byte) error { |
| return xxx_messageInfo_BotAuth_GCE.Unmarshal(m, b) |
| } |
| func (m *BotAuth_GCE) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { |
| return xxx_messageInfo_BotAuth_GCE.Marshal(b, m, deterministic) |
| } |
| func (m *BotAuth_GCE) XXX_Merge(src proto.Message) { |
| xxx_messageInfo_BotAuth_GCE.Merge(m, src) |
| } |
| func (m *BotAuth_GCE) XXX_Size() int { |
| return xxx_messageInfo_BotAuth_GCE.Size(m) |
| } |
| func (m *BotAuth_GCE) XXX_DiscardUnknown() { |
| xxx_messageInfo_BotAuth_GCE.DiscardUnknown(m) |
| } |
| |
| var xxx_messageInfo_BotAuth_GCE proto.InternalMessageInfo |
| |
| func (m *BotAuth_GCE) GetProject() string { |
| if m != nil { |
| return m.Project |
| } |
| return "" |
| } |
| |
| func init() { |
| proto.RegisterType((*BotsCfg)(nil), "swarming.config.BotsCfg") |
| proto.RegisterType((*BotGroup)(nil), "swarming.config.BotGroup") |
| proto.RegisterType((*BotAuth)(nil), "swarming.config.BotAuth") |
| proto.RegisterType((*BotAuth_GCE)(nil), "swarming.config.BotAuth.GCE") |
| } |
| |
| func init() { |
| proto.RegisterFile("go.chromium.org/luci/swarming/proto/config/bots.proto", fileDescriptor_ecc3522ef1feaf58) |
| } |
| |
| var fileDescriptor_ecc3522ef1feaf58 = []byte{ |
| // 576 bytes of a gzipped FileDescriptorProto |
| 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x93, 0x51, 0x4f, 0x13, 0x41, |
| 0x10, 0xc7, 0x53, 0x5a, 0xa0, 0xdd, 0x62, 0x90, 0x0d, 0x94, 0x85, 0x18, 0xad, 0xf5, 0xa5, 0x31, |
| 0x72, 0x97, 0x80, 0x92, 0x08, 0x4f, 0xb4, 0x60, 0x83, 0x91, 0xc4, 0x1c, 0x46, 0x13, 0x5f, 0x36, |
| 0x77, 0xdb, 0xbd, 0xbb, 0xd5, 0xde, 0xcd, 0xba, 0x3b, 0x07, 0xfa, 0xe0, 0x97, 0xf1, 0x3b, 0xf8, |
| 0x35, 0xfc, 0x48, 0xc6, 0xdc, 0xde, 0x95, 0x20, 0x60, 0xe2, 0x53, 0xbb, 0xff, 0xdf, 0xcc, 0x7f, |
| 0x66, 0x76, 0x6f, 0xc8, 0x8b, 0x04, 0x3c, 0x91, 0x1a, 0xc8, 0x54, 0x91, 0x79, 0x60, 0x12, 0x7f, |
| 0x56, 0x08, 0xe5, 0xdb, 0xcb, 0xd0, 0x64, 0x2a, 0x4f, 0x7c, 0x6d, 0x00, 0xc1, 0x17, 0x90, 0xc7, |
| 0x2a, 0xf1, 0x23, 0x40, 0xeb, 0x39, 0x85, 0xae, 0xce, 0x23, 0xbc, 0x8a, 0x6d, 0xfb, 0x77, 0xfa, |
| 0x08, 0xc8, 0x32, 0xc8, 0x6b, 0x17, 0xd0, 0xa8, 0x20, 0xaf, 0x1d, 0x06, 0x9a, 0x2c, 0x8f, 0x00, |
| 0xed, 0x38, 0x4e, 0xe8, 0x0e, 0xa1, 0x68, 0x0a, 0x8b, 0x72, 0xca, 0xa7, 0x2a, 0x93, 0xb9, 0x2d, |
| 0xc3, 0x58, 0xa3, 0xdf, 0x1c, 0x76, 0x82, 0xb5, 0x9a, 0x1c, 0x5f, 0x01, 0xba, 0x4f, 0x3a, 0x11, |
| 0x20, 0x4f, 0x0c, 0x14, 0x9a, 0x2d, 0xf4, 0x9b, 0xc3, 0xee, 0xee, 0x96, 0x77, 0xa3, 0x1f, 0x6f, |
| 0x04, 0x38, 0x29, 0x03, 0x82, 0x76, 0x54, 0xff, 0x1b, 0xfc, 0x5a, 0x20, 0xed, 0xb9, 0x4c, 0x37, |
| 0xc8, 0x52, 0x69, 0xa2, 0xa6, 0x75, 0x9d, 0xc5, 0x08, 0xf0, 0x74, 0x4a, 0x07, 0xe4, 0x5e, 0x25, |
| 0x73, 0x6d, 0x64, 0xac, 0xbe, 0x3a, 0xff, 0x4e, 0xd0, 0x75, 0xf4, 0xad, 0x93, 0xe8, 0x33, 0xd2, |
| 0x0a, 0x0b, 0x4c, 0xd9, 0xba, 0x2b, 0xcd, 0xee, 0x2a, 0x7d, 0x54, 0x60, 0x1a, 0xb8, 0x28, 0xda, |
| 0x23, 0x4b, 0x70, 0x99, 0x4b, 0x63, 0xd9, 0x86, 0xb3, 0xaa, 0x4f, 0xf4, 0x21, 0x21, 0xd7, 0x86, |
| 0xed, 0x39, 0x76, 0x4d, 0xa1, 0x4f, 0xc9, 0x5a, 0xd9, 0x49, 0xe5, 0xc9, 0xad, 0x30, 0x4a, 0x23, |
| 0xdb, 0xec, 0x37, 0x86, 0x9d, 0x60, 0x35, 0x02, 0x1c, 0x3b, 0xfd, 0xdc, 0xc9, 0xf4, 0x25, 0xd9, |
| 0xba, 0x15, 0x5b, 0x9e, 0x50, 0xe6, 0xc8, 0xb6, 0xfa, 0x8d, 0xe1, 0x4a, 0xd0, 0xbb, 0x91, 0x33, |
| 0xae, 0x28, 0x7d, 0x4e, 0x7a, 0xf6, 0x9b, 0x45, 0x99, 0x71, 0x2b, 0xcd, 0x85, 0x12, 0x92, 0x87, |
| 0x42, 0x40, 0x91, 0x23, 0x63, 0xae, 0xd6, 0x7a, 0x45, 0xcf, 0x2b, 0x78, 0x54, 0xb1, 0xd7, 0xad, |
| 0x76, 0xf3, 0x7e, 0x6b, 0xf0, 0x73, 0xc1, 0xbd, 0x61, 0x39, 0x6c, 0x79, 0x71, 0x33, 0x48, 0xb8, |
| 0x8a, 0x79, 0x1c, 0xaa, 0x99, 0x9c, 0xb2, 0xc5, 0x7e, 0x63, 0xd8, 0x0e, 0xba, 0x33, 0x48, 0x4e, |
| 0xe3, 0x57, 0x4e, 0xa2, 0x87, 0x64, 0xdb, 0xc8, 0x2f, 0x85, 0x32, 0x92, 0x97, 0x5f, 0x07, 0xcf, |
| 0x42, 0x91, 0xaa, 0x5c, 0x72, 0x84, 0xcf, 0x32, 0x67, 0x0d, 0x97, 0xb0, 0x59, 0x47, 0xbc, 0x29, |
| 0x84, 0x3a, 0xab, 0xf8, 0xbb, 0x12, 0xd3, 0x7d, 0x32, 0x47, 0xb7, 0x3a, 0xad, 0xde, 0x68, 0xa3, |
| 0xc6, 0x7f, 0xb7, 0x4a, 0xcf, 0xc8, 0xfa, 0x3c, 0x2f, 0x11, 0x92, 0x5f, 0x64, 0x75, 0xb9, 0x56, |
| 0xbf, 0x31, 0xec, 0xee, 0x3e, 0xf8, 0xd7, 0xeb, 0x79, 0x93, 0xf1, 0x49, 0xb0, 0x56, 0x67, 0x4e, |
| 0x84, 0x7c, 0x9f, 0x55, 0x6d, 0x3c, 0x26, 0x2b, 0x4a, 0xf3, 0xcb, 0x54, 0xa1, 0x9c, 0x29, 0x8b, |
| 0xac, 0xe9, 0x6e, 0xa9, 0xab, 0xf4, 0x87, 0xb9, 0xb4, 0xfd, 0x88, 0x34, 0x27, 0xe3, 0x13, 0xca, |
| 0xc8, 0xb2, 0x36, 0xf0, 0x49, 0x0a, 0x74, 0xa3, 0x75, 0x82, 0xf9, 0x71, 0xf4, 0xfd, 0xc7, 0xef, |
| 0x27, 0xc7, 0x64, 0x94, 0x22, 0x6a, 0x7b, 0xe0, 0xbb, 0x4d, 0xd9, 0xa9, 0xab, 0x87, 0x5a, 0x5b, |
| 0x0d, 0xe8, 0x09, 0xc8, 0x7c, 0x2b, 0x52, 0x99, 0x85, 0xd6, 0xaf, 0xc7, 0xb5, 0x57, 0x5b, 0x79, |
| 0xe0, 0x16, 0x51, 0xc4, 0xc9, 0xc7, 0xbd, 0xff, 0xdf, 0xde, 0xc3, 0xea, 0x47, 0x47, 0xd1, 0x92, |
| 0x93, 0xf7, 0xfe, 0x04, 0x00, 0x00, 0xff, 0xff, 0x3d, 0xac, 0x01, 0x24, 0xfb, 0x03, 0x00, 0x00, |
| } |