From 0fd8c9cb1b5a927e5afb370718073fcdfb41ade4 Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Thu, 10 Nov 2022 17:50:03 +0000 Subject: [PATCH 01/17] Add Extended Coverage list to .proto, initialize a go module, touches Dockerfile. --- Dockerfile | 0 go.mod | 14 ++++++++++++++ internal/webrisk_proto/webrisk.proto | 4 ++++ 3 files changed, 18 insertions(+) create mode 100644 Dockerfile create mode 100644 go.mod diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e69de29 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..fa024cb --- /dev/null +++ b/go.mod @@ -0,0 +1,14 @@ +module github.com/google/webrisk + +go 1.20 + +require ( + github.com/golang/protobuf v1.5.2 + github.com/rakyll/statik v0.1.7 + golang.org/x/net v0.2.0 +) + +require ( + golang.org/x/text v0.4.0 // indirect + google.golang.org/protobuf v1.26.0 // indirect +) diff --git a/internal/webrisk_proto/webrisk.proto b/internal/webrisk_proto/webrisk.proto index 08817ee..dd4dda5 100644 --- a/internal/webrisk_proto/webrisk.proto +++ b/internal/webrisk_proto/webrisk.proto @@ -195,6 +195,10 @@ enum ThreatType { // Unwanted software targeting any platform. UNWANTED_SOFTWARE = 3; + + // A list of extended coverage social engineering URIs targeting any + // platform. + SOCIAL_ENGINEERING_EXTENDED_COVERAGE = 4; } // The ways in which threat entry sets can be compressed. From 22fb396ca8ed18418808b5da41d3ea14a848a170 Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Thu, 10 Nov 2022 19:01:25 +0000 Subject: [PATCH 02/17] Adds Extended Coverage List to Go App. --- internal/webrisk_proto/webrisk.pb.go | 1723 +++++++++++++++++++------- internal/webrisk_proto/webrisk.proto | 2 + webrisk_client.go | 2 + 3 files changed, 1304 insertions(+), 423 deletions(-) diff --git a/internal/webrisk_proto/webrisk.pb.go b/internal/webrisk_proto/webrisk.pb.go index 7c75e3d..4356f15 100644 --- a/internal/webrisk_proto/webrisk.pb.go +++ b/internal/webrisk_proto/webrisk.pb.go @@ -1,56 +1,40 @@ -// Copyright 2019 Google LLC +// Copyright 2019 Google LLC. // // 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 // -// https://www.apache.org/licenses/LICENSE-2.0 +// 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. +// // Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.12.4 // source: webrisk.proto -/* -Package google_cloud_webrisk_v1 is a generated protocol buffer package. - -It is generated from these files: - webrisk.proto - -It has these top-level messages: - ComputeThreatListDiffRequest - ComputeThreatListDiffResponse - SearchUrisRequest - SearchUrisResponse - SearchHashesRequest - SearchHashesResponse - ThreatEntryAdditions - ThreatEntryRemovals - RawIndices - RawHashes - RiceDeltaEncoding -*/ -package google_cloud_webrisk_v1 - -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" -import google_protobuf "github.com/golang/protobuf/ptypes/timestamp" - -// 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.ProtoPackageIsVersion2 // please upgrade the proto package +package webrisk + +import ( + timestamp "github.com/golang/protobuf/ptypes/timestamp" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) // The type of threat. This maps dirrectly to the threat list a threat may // belong to. @@ -65,25 +49,55 @@ const ( ThreatType_SOCIAL_ENGINEERING ThreatType = 2 // Unwanted software targeting any platform. ThreatType_UNWANTED_SOFTWARE ThreatType = 3 + // A list of extended coverage social engineering URIs targeting any + // platform. + ThreatType_SOCIAL_ENGINEERING_EXTENDED_COVERAGE ThreatType = 4 ) -var ThreatType_name = map[int32]string{ - 0: "THREAT_TYPE_UNSPECIFIED", - 1: "MALWARE", - 2: "SOCIAL_ENGINEERING", - 3: "UNWANTED_SOFTWARE", -} -var ThreatType_value = map[string]int32{ - "THREAT_TYPE_UNSPECIFIED": 0, - "MALWARE": 1, - "SOCIAL_ENGINEERING": 2, - "UNWANTED_SOFTWARE": 3, +// Enum value maps for ThreatType. +var ( + ThreatType_name = map[int32]string{ + 0: "THREAT_TYPE_UNSPECIFIED", + 1: "MALWARE", + 2: "SOCIAL_ENGINEERING", + 3: "UNWANTED_SOFTWARE", + 4: "SOCIAL_ENGINEERING_EXTENDED_COVERAGE", + } + ThreatType_value = map[string]int32{ + "THREAT_TYPE_UNSPECIFIED": 0, + "MALWARE": 1, + "SOCIAL_ENGINEERING": 2, + "UNWANTED_SOFTWARE": 3, + "SOCIAL_ENGINEERING_EXTENDED_COVERAGE": 4, + } +) + +func (x ThreatType) Enum() *ThreatType { + p := new(ThreatType) + *p = x + return p } func (x ThreatType) String() string { - return proto.EnumName(ThreatType_name, int32(x)) + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ThreatType) Descriptor() protoreflect.EnumDescriptor { + return file_webrisk_proto_enumTypes[0].Descriptor() +} + +func (ThreatType) Type() protoreflect.EnumType { + return &file_webrisk_proto_enumTypes[0] +} + +func (x ThreatType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ThreatType.Descriptor instead. +func (ThreatType) EnumDescriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{0} } -func (ThreatType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } // The ways in which threat entry sets can be compressed. type CompressionType int32 @@ -97,21 +111,46 @@ const ( CompressionType_RICE CompressionType = 2 ) -var CompressionType_name = map[int32]string{ - 0: "COMPRESSION_TYPE_UNSPECIFIED", - 1: "RAW", - 2: "RICE", -} -var CompressionType_value = map[string]int32{ - "COMPRESSION_TYPE_UNSPECIFIED": 0, - "RAW": 1, - "RICE": 2, +// Enum value maps for CompressionType. +var ( + CompressionType_name = map[int32]string{ + 0: "COMPRESSION_TYPE_UNSPECIFIED", + 1: "RAW", + 2: "RICE", + } + CompressionType_value = map[string]int32{ + "COMPRESSION_TYPE_UNSPECIFIED": 0, + "RAW": 1, + "RICE": 2, + } +) + +func (x CompressionType) Enum() *CompressionType { + p := new(CompressionType) + *p = x + return p } func (x CompressionType) String() string { - return proto.EnumName(CompressionType_name, int32(x)) + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (CompressionType) Descriptor() protoreflect.EnumDescriptor { + return file_webrisk_proto_enumTypes[1].Descriptor() +} + +func (CompressionType) Type() protoreflect.EnumType { + return &file_webrisk_proto_enumTypes[1] +} + +func (x CompressionType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use CompressionType.Descriptor instead. +func (CompressionType) EnumDescriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{1} } -func (CompressionType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } // The type of response sent to the client. type ComputeThreatListDiffResponse_ResponseType int32 @@ -127,363 +166,436 @@ const ( ComputeThreatListDiffResponse_RESET ComputeThreatListDiffResponse_ResponseType = 2 ) -var ComputeThreatListDiffResponse_ResponseType_name = map[int32]string{ - 0: "RESPONSE_TYPE_UNSPECIFIED", - 1: "DIFF", - 2: "RESET", -} -var ComputeThreatListDiffResponse_ResponseType_value = map[string]int32{ - "RESPONSE_TYPE_UNSPECIFIED": 0, - "DIFF": 1, - "RESET": 2, +// Enum value maps for ComputeThreatListDiffResponse_ResponseType. +var ( + ComputeThreatListDiffResponse_ResponseType_name = map[int32]string{ + 0: "RESPONSE_TYPE_UNSPECIFIED", + 1: "DIFF", + 2: "RESET", + } + ComputeThreatListDiffResponse_ResponseType_value = map[string]int32{ + "RESPONSE_TYPE_UNSPECIFIED": 0, + "DIFF": 1, + "RESET": 2, + } +) + +func (x ComputeThreatListDiffResponse_ResponseType) Enum() *ComputeThreatListDiffResponse_ResponseType { + p := new(ComputeThreatListDiffResponse_ResponseType) + *p = x + return p } func (x ComputeThreatListDiffResponse_ResponseType) String() string { - return proto.EnumName(ComputeThreatListDiffResponse_ResponseType_name, int32(x)) + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ComputeThreatListDiffResponse_ResponseType) Descriptor() protoreflect.EnumDescriptor { + return file_webrisk_proto_enumTypes[2].Descriptor() +} + +func (ComputeThreatListDiffResponse_ResponseType) Type() protoreflect.EnumType { + return &file_webrisk_proto_enumTypes[2] } + +func (x ComputeThreatListDiffResponse_ResponseType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ComputeThreatListDiffResponse_ResponseType.Descriptor instead. func (ComputeThreatListDiffResponse_ResponseType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor0, []int{1, 0} + return file_webrisk_proto_rawDescGZIP(), []int{1, 0} } // Describes an API diff request. type ComputeThreatListDiffRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + // Required. The ThreatList to update. - ThreatType ThreatType `protobuf:"varint,1,opt,name=threat_type,json=threatType,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_type,omitempty"` + ThreatType ThreatType `protobuf:"varint,1,opt,name=threat_type,json=threatType,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_type,omitempty"` // The current version token of the client for the requested list (the // client version that was received from the last successful diff). VersionToken []byte `protobuf:"bytes,2,opt,name=version_token,json=versionToken,proto3" json:"version_token,omitempty"` // The constraints associated with this request. - Constraints *ComputeThreatListDiffRequest_Constraints `protobuf:"bytes,3,opt,name=constraints" json:"constraints,omitempty"` + Constraints *ComputeThreatListDiffRequest_Constraints `protobuf:"bytes,3,opt,name=constraints,proto3" json:"constraints,omitempty"` } -func (m *ComputeThreatListDiffRequest) Reset() { *m = ComputeThreatListDiffRequest{} } -func (m *ComputeThreatListDiffRequest) String() string { return proto.CompactTextString(m) } -func (*ComputeThreatListDiffRequest) ProtoMessage() {} -func (*ComputeThreatListDiffRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - -func (m *ComputeThreatListDiffRequest) GetThreatType() ThreatType { - if m != nil { - return m.ThreatType +func (x *ComputeThreatListDiffRequest) Reset() { + *x = ComputeThreatListDiffRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } - return ThreatType_THREAT_TYPE_UNSPECIFIED } -func (m *ComputeThreatListDiffRequest) GetVersionToken() []byte { - if m != nil { - return m.VersionToken - } - return nil +func (x *ComputeThreatListDiffRequest) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *ComputeThreatListDiffRequest) GetConstraints() *ComputeThreatListDiffRequest_Constraints { - if m != nil { - return m.Constraints - } - return nil -} +func (*ComputeThreatListDiffRequest) ProtoMessage() {} -// The constraints for this diff. -type ComputeThreatListDiffRequest_Constraints struct { - // The maximum size in number of entries. The diff will not contain more - // entries than this value. This should be a power of 2 between 2**10 and - // 2**20. If zero, no diff size limit is set. - MaxDiffEntries int32 `protobuf:"varint,1,opt,name=max_diff_entries,json=maxDiffEntries" json:"max_diff_entries,omitempty"` - // Sets the maximum number of entries that the client is willing to have - // in the local database. This should be a power of 2 between 2**10 and - // 2**20. If zero, no database size limit is set. - MaxDatabaseEntries int32 `protobuf:"varint,2,opt,name=max_database_entries,json=maxDatabaseEntries" json:"max_database_entries,omitempty"` - // The compression types supported by the client. - SupportedCompressions []CompressionType `protobuf:"varint,3,rep,packed,name=supported_compressions,json=supportedCompressions,enum=google.cloud.webrisk.v1.CompressionType" json:"supported_compressions,omitempty"` +func (x *ComputeThreatListDiffRequest) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (m *ComputeThreatListDiffRequest_Constraints) Reset() { - *m = ComputeThreatListDiffRequest_Constraints{} -} -func (m *ComputeThreatListDiffRequest_Constraints) String() string { return proto.CompactTextString(m) } -func (*ComputeThreatListDiffRequest_Constraints) ProtoMessage() {} -func (*ComputeThreatListDiffRequest_Constraints) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{0, 0} +// Deprecated: Use ComputeThreatListDiffRequest.ProtoReflect.Descriptor instead. +func (*ComputeThreatListDiffRequest) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{0} } -func (m *ComputeThreatListDiffRequest_Constraints) GetMaxDiffEntries() int32 { - if m != nil { - return m.MaxDiffEntries +func (x *ComputeThreatListDiffRequest) GetThreatType() ThreatType { + if x != nil { + return x.ThreatType } - return 0 + return ThreatType_THREAT_TYPE_UNSPECIFIED } -func (m *ComputeThreatListDiffRequest_Constraints) GetMaxDatabaseEntries() int32 { - if m != nil { - return m.MaxDatabaseEntries +func (x *ComputeThreatListDiffRequest) GetVersionToken() []byte { + if x != nil { + return x.VersionToken } - return 0 + return nil } -func (m *ComputeThreatListDiffRequest_Constraints) GetSupportedCompressions() []CompressionType { - if m != nil { - return m.SupportedCompressions +func (x *ComputeThreatListDiffRequest) GetConstraints() *ComputeThreatListDiffRequest_Constraints { + if x != nil { + return x.Constraints } return nil } type ComputeThreatListDiffResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + // The type of response. This may indicate that an action is required by the // client when the response is received. - ResponseType ComputeThreatListDiffResponse_ResponseType `protobuf:"varint,4,opt,name=response_type,json=responseType,enum=google.cloud.webrisk.v1.ComputeThreatListDiffResponse_ResponseType" json:"response_type,omitempty"` + ResponseType ComputeThreatListDiffResponse_ResponseType `protobuf:"varint,4,opt,name=response_type,json=responseType,proto3,enum=google.cloud.webrisk.v1.ComputeThreatListDiffResponse_ResponseType" json:"response_type,omitempty"` // A set of entries to add to a local threat type's list. - Additions *ThreatEntryAdditions `protobuf:"bytes,5,opt,name=additions" json:"additions,omitempty"` + Additions *ThreatEntryAdditions `protobuf:"bytes,5,opt,name=additions,proto3" json:"additions,omitempty"` // A set of entries to remove from a local threat type's list. // This field may be empty. - Removals *ThreatEntryRemovals `protobuf:"bytes,6,opt,name=removals" json:"removals,omitempty"` + Removals *ThreatEntryRemovals `protobuf:"bytes,6,opt,name=removals,proto3" json:"removals,omitempty"` // The new opaque client version token. NewVersionToken []byte `protobuf:"bytes,7,opt,name=new_version_token,json=newVersionToken,proto3" json:"new_version_token,omitempty"` // The expected SHA256 hash of the client state; that is, of the sorted list // of all hashes present in the database after applying the provided diff. // If the client state doesn't match the expected state, the client must // disregard this diff and retry later. - Checksum *ComputeThreatListDiffResponse_Checksum `protobuf:"bytes,8,opt,name=checksum" json:"checksum,omitempty"` + Checksum *ComputeThreatListDiffResponse_Checksum `protobuf:"bytes,8,opt,name=checksum,proto3" json:"checksum,omitempty"` // The soonest the client should wait before issuing any diff // request. Querying sooner is unlikely to produce a meaningful diff. // Waiting longer is acceptable considering the use case. // If this field is not set clients may update as soon as they want. - RecommendedNextDiff *google_protobuf.Timestamp `protobuf:"bytes,2,opt,name=recommended_next_diff,json=recommendedNextDiff" json:"recommended_next_diff,omitempty"` + RecommendedNextDiff *timestamp.Timestamp `protobuf:"bytes,2,opt,name=recommended_next_diff,json=recommendedNextDiff,proto3" json:"recommended_next_diff,omitempty"` +} + +func (x *ComputeThreatListDiffResponse) Reset() { + *x = ComputeThreatListDiffResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ComputeThreatListDiffResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ComputeThreatListDiffResponse) ProtoMessage() {} + +func (x *ComputeThreatListDiffResponse) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (m *ComputeThreatListDiffResponse) Reset() { *m = ComputeThreatListDiffResponse{} } -func (m *ComputeThreatListDiffResponse) String() string { return proto.CompactTextString(m) } -func (*ComputeThreatListDiffResponse) ProtoMessage() {} -func (*ComputeThreatListDiffResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } +// Deprecated: Use ComputeThreatListDiffResponse.ProtoReflect.Descriptor instead. +func (*ComputeThreatListDiffResponse) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{1} +} -func (m *ComputeThreatListDiffResponse) GetResponseType() ComputeThreatListDiffResponse_ResponseType { - if m != nil { - return m.ResponseType +func (x *ComputeThreatListDiffResponse) GetResponseType() ComputeThreatListDiffResponse_ResponseType { + if x != nil { + return x.ResponseType } return ComputeThreatListDiffResponse_RESPONSE_TYPE_UNSPECIFIED } -func (m *ComputeThreatListDiffResponse) GetAdditions() *ThreatEntryAdditions { - if m != nil { - return m.Additions +func (x *ComputeThreatListDiffResponse) GetAdditions() *ThreatEntryAdditions { + if x != nil { + return x.Additions } return nil } -func (m *ComputeThreatListDiffResponse) GetRemovals() *ThreatEntryRemovals { - if m != nil { - return m.Removals +func (x *ComputeThreatListDiffResponse) GetRemovals() *ThreatEntryRemovals { + if x != nil { + return x.Removals } return nil } -func (m *ComputeThreatListDiffResponse) GetNewVersionToken() []byte { - if m != nil { - return m.NewVersionToken +func (x *ComputeThreatListDiffResponse) GetNewVersionToken() []byte { + if x != nil { + return x.NewVersionToken } return nil } -func (m *ComputeThreatListDiffResponse) GetChecksum() *ComputeThreatListDiffResponse_Checksum { - if m != nil { - return m.Checksum +func (x *ComputeThreatListDiffResponse) GetChecksum() *ComputeThreatListDiffResponse_Checksum { + if x != nil { + return x.Checksum } return nil } -func (m *ComputeThreatListDiffResponse) GetRecommendedNextDiff() *google_protobuf.Timestamp { - if m != nil { - return m.RecommendedNextDiff +func (x *ComputeThreatListDiffResponse) GetRecommendedNextDiff() *timestamp.Timestamp { + if x != nil { + return x.RecommendedNextDiff } return nil } -// The expected state of a client's local database. -type ComputeThreatListDiffResponse_Checksum struct { - // The SHA256 hash of the client state; that is, of the sorted list of all - // hashes present in the database. - Sha256 []byte `protobuf:"bytes,1,opt,name=sha256,proto3" json:"sha256,omitempty"` +// Request to check URI entries against threatLists. +type SearchUrisRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The URI to be checked for matches. + Uri string `protobuf:"bytes,1,opt,name=uri,proto3" json:"uri,omitempty"` + // Required. The ThreatLists to search in. + ThreatTypes []ThreatType `protobuf:"varint,2,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` } -func (m *ComputeThreatListDiffResponse_Checksum) Reset() { - *m = ComputeThreatListDiffResponse_Checksum{} +func (x *SearchUrisRequest) Reset() { + *x = SearchUrisRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *ComputeThreatListDiffResponse_Checksum) String() string { return proto.CompactTextString(m) } -func (*ComputeThreatListDiffResponse_Checksum) ProtoMessage() {} -func (*ComputeThreatListDiffResponse_Checksum) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{1, 0} + +func (x *SearchUrisRequest) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *ComputeThreatListDiffResponse_Checksum) GetSha256() []byte { - if m != nil { - return m.Sha256 +func (*SearchUrisRequest) ProtoMessage() {} + +func (x *SearchUrisRequest) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms } - return nil + return mi.MessageOf(x) } -// Request to check URI entries against threatLists. -type SearchUrisRequest struct { - // The URI to be checked for matches. - Uri string `protobuf:"bytes,1,opt,name=uri" json:"uri,omitempty"` - // Required. The ThreatLists to search in. - ThreatTypes []ThreatType `protobuf:"varint,2,rep,packed,name=threat_types,json=threatTypes,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` +// Deprecated: Use SearchUrisRequest.ProtoReflect.Descriptor instead. +func (*SearchUrisRequest) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{2} } -func (m *SearchUrisRequest) Reset() { *m = SearchUrisRequest{} } -func (m *SearchUrisRequest) String() string { return proto.CompactTextString(m) } -func (*SearchUrisRequest) ProtoMessage() {} -func (*SearchUrisRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } - -func (m *SearchUrisRequest) GetUri() string { - if m != nil { - return m.Uri +func (x *SearchUrisRequest) GetUri() string { + if x != nil { + return x.Uri } return "" } -func (m *SearchUrisRequest) GetThreatTypes() []ThreatType { - if m != nil { - return m.ThreatTypes +func (x *SearchUrisRequest) GetThreatTypes() []ThreatType { + if x != nil { + return x.ThreatTypes } return nil } type SearchUrisResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + // The threat list matches. This may be empty if the URI is on no list. - Threat *SearchUrisResponse_ThreatUri `protobuf:"bytes,1,opt,name=threat" json:"threat,omitempty"` + Threat *SearchUrisResponse_ThreatUri `protobuf:"bytes,1,opt,name=threat,proto3" json:"threat,omitempty"` } -func (m *SearchUrisResponse) Reset() { *m = SearchUrisResponse{} } -func (m *SearchUrisResponse) String() string { return proto.CompactTextString(m) } -func (*SearchUrisResponse) ProtoMessage() {} -func (*SearchUrisResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } - -func (m *SearchUrisResponse) GetThreat() *SearchUrisResponse_ThreatUri { - if m != nil { - return m.Threat +func (x *SearchUrisResponse) Reset() { + *x = SearchUrisResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } - return nil } -// Contains threat information on a matching uri. -type SearchUrisResponse_ThreatUri struct { - // The ThreatList this threat belongs to. - ThreatTypes []ThreatType `protobuf:"varint,1,rep,packed,name=threat_types,json=threatTypes,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` - // The cache lifetime for the returned match. Clients must not cache this - // response past this timestamp to avoid false positives. - ExpireTime *google_protobuf.Timestamp `protobuf:"bytes,2,opt,name=expire_time,json=expireTime" json:"expire_time,omitempty"` +func (x *SearchUrisResponse) String() string { + return protoimpl.X.MessageStringOf(x) } -func (m *SearchUrisResponse_ThreatUri) Reset() { *m = SearchUrisResponse_ThreatUri{} } -func (m *SearchUrisResponse_ThreatUri) String() string { return proto.CompactTextString(m) } -func (*SearchUrisResponse_ThreatUri) ProtoMessage() {} -func (*SearchUrisResponse_ThreatUri) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3, 0} } +func (*SearchUrisResponse) ProtoMessage() {} -func (m *SearchUrisResponse_ThreatUri) GetThreatTypes() []ThreatType { - if m != nil { - return m.ThreatTypes +func (x *SearchUrisResponse) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms } - return nil + return mi.MessageOf(x) } -func (m *SearchUrisResponse_ThreatUri) GetExpireTime() *google_protobuf.Timestamp { - if m != nil { - return m.ExpireTime +// Deprecated: Use SearchUrisResponse.ProtoReflect.Descriptor instead. +func (*SearchUrisResponse) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{3} +} + +func (x *SearchUrisResponse) GetThreat() *SearchUrisResponse_ThreatUri { + if x != nil { + return x.Threat } return nil } // Request to return full hashes matched by the provided hash prefixes. type SearchHashesRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + // A hash prefix, consisting of the most significant 4-32 bytes of a SHA256 // hash. For JSON requests, this field is base64-encoded. HashPrefix []byte `protobuf:"bytes,1,opt,name=hash_prefix,json=hashPrefix,proto3" json:"hash_prefix,omitempty"` // Required. The ThreatLists to search in. - ThreatTypes []ThreatType `protobuf:"varint,2,rep,packed,name=threat_types,json=threatTypes,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` + ThreatTypes []ThreatType `protobuf:"varint,2,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` } -func (m *SearchHashesRequest) Reset() { *m = SearchHashesRequest{} } -func (m *SearchHashesRequest) String() string { return proto.CompactTextString(m) } -func (*SearchHashesRequest) ProtoMessage() {} -func (*SearchHashesRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } +func (x *SearchHashesRequest) Reset() { + *x = SearchHashesRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SearchHashesRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SearchHashesRequest) ProtoMessage() {} + +func (x *SearchHashesRequest) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SearchHashesRequest.ProtoReflect.Descriptor instead. +func (*SearchHashesRequest) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{4} +} -func (m *SearchHashesRequest) GetHashPrefix() []byte { - if m != nil { - return m.HashPrefix +func (x *SearchHashesRequest) GetHashPrefix() []byte { + if x != nil { + return x.HashPrefix } return nil } -func (m *SearchHashesRequest) GetThreatTypes() []ThreatType { - if m != nil { - return m.ThreatTypes +func (x *SearchHashesRequest) GetThreatTypes() []ThreatType { + if x != nil { + return x.ThreatTypes } return nil } type SearchHashesResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + // The full hashes that matched the requested prefixes. // The hash will be populated in the key. - Threats []*SearchHashesResponse_ThreatHash `protobuf:"bytes,1,rep,name=threats" json:"threats,omitempty"` + Threats []*SearchHashesResponse_ThreatHash `protobuf:"bytes,1,rep,name=threats,proto3" json:"threats,omitempty"` // For requested entities that did not match the threat list, how long to // cache the response until. - NegativeExpireTime *google_protobuf.Timestamp `protobuf:"bytes,2,opt,name=negative_expire_time,json=negativeExpireTime" json:"negative_expire_time,omitempty"` + NegativeExpireTime *timestamp.Timestamp `protobuf:"bytes,2,opt,name=negative_expire_time,json=negativeExpireTime,proto3" json:"negative_expire_time,omitempty"` } -func (m *SearchHashesResponse) Reset() { *m = SearchHashesResponse{} } -func (m *SearchHashesResponse) String() string { return proto.CompactTextString(m) } -func (*SearchHashesResponse) ProtoMessage() {} -func (*SearchHashesResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} } - -func (m *SearchHashesResponse) GetThreats() []*SearchHashesResponse_ThreatHash { - if m != nil { - return m.Threats +func (x *SearchHashesResponse) Reset() { + *x = SearchHashesResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) } - return nil } -func (m *SearchHashesResponse) GetNegativeExpireTime() *google_protobuf.Timestamp { - if m != nil { - return m.NegativeExpireTime - } - return nil +func (x *SearchHashesResponse) String() string { + return protoimpl.X.MessageStringOf(x) } -// Contains threat information on a matching hash. -type SearchHashesResponse_ThreatHash struct { - // The ThreatList this threat belongs to. - // This must contain at least one entry. - ThreatTypes []ThreatType `protobuf:"varint,1,rep,packed,name=threat_types,json=threatTypes,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` - // A 32 byte SHA256 hash. This field is in binary format. For JSON - // requests, hashes are base64-encoded. - Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` - // The cache lifetime for the returned match. Clients must not cache this - // response past this timestamp to avoid false positives. - ExpireTime *google_protobuf.Timestamp `protobuf:"bytes,3,opt,name=expire_time,json=expireTime" json:"expire_time,omitempty"` -} +func (*SearchHashesResponse) ProtoMessage() {} -func (m *SearchHashesResponse_ThreatHash) Reset() { *m = SearchHashesResponse_ThreatHash{} } -func (m *SearchHashesResponse_ThreatHash) String() string { return proto.CompactTextString(m) } -func (*SearchHashesResponse_ThreatHash) ProtoMessage() {} -func (*SearchHashesResponse_ThreatHash) Descriptor() ([]byte, []int) { - return fileDescriptor0, []int{5, 0} +func (x *SearchHashesResponse) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (m *SearchHashesResponse_ThreatHash) GetThreatTypes() []ThreatType { - if m != nil { - return m.ThreatTypes - } - return nil +// Deprecated: Use SearchHashesResponse.ProtoReflect.Descriptor instead. +func (*SearchHashesResponse) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{5} } -func (m *SearchHashesResponse_ThreatHash) GetHash() []byte { - if m != nil { - return m.Hash +func (x *SearchHashesResponse) GetThreats() []*SearchHashesResponse_ThreatHash { + if x != nil { + return x.Threats } return nil } -func (m *SearchHashesResponse_ThreatHash) GetExpireTime() *google_protobuf.Timestamp { - if m != nil { - return m.ExpireTime +func (x *SearchHashesResponse) GetNegativeExpireTime() *timestamp.Timestamp { + if x != nil { + return x.NegativeExpireTime } return nil } @@ -491,78 +603,171 @@ func (m *SearchHashesResponse_ThreatHash) GetExpireTime() *google_protobuf.Times // Contains the set of entries to add to a local database. // May contain a combination of compressed and raw data in a single response. type ThreatEntryAdditions struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + // The raw SHA256-formatted entries. // Repeated to allow returning sets of hashes with different prefix sizes. - RawHashes []*RawHashes `protobuf:"bytes,1,rep,name=raw_hashes,json=rawHashes" json:"raw_hashes,omitempty"` + RawHashes []*RawHashes `protobuf:"bytes,1,rep,name=raw_hashes,json=rawHashes,proto3" json:"raw_hashes,omitempty"` // The encoded 4-byte prefixes of SHA256-formatted entries, using a // Golomb-Rice encoding. The hashes are converted to uint32, sorted in // ascending order, then delta encoded and stored as encoded_data. - RiceHashes *RiceDeltaEncoding `protobuf:"bytes,2,opt,name=rice_hashes,json=riceHashes" json:"rice_hashes,omitempty"` + RiceHashes *RiceDeltaEncoding `protobuf:"bytes,2,opt,name=rice_hashes,json=riceHashes,proto3" json:"rice_hashes,omitempty"` } -func (m *ThreatEntryAdditions) Reset() { *m = ThreatEntryAdditions{} } -func (m *ThreatEntryAdditions) String() string { return proto.CompactTextString(m) } -func (*ThreatEntryAdditions) ProtoMessage() {} -func (*ThreatEntryAdditions) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} } +func (x *ThreatEntryAdditions) Reset() { + *x = ThreatEntryAdditions{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ThreatEntryAdditions) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ThreatEntryAdditions) ProtoMessage() {} + +func (x *ThreatEntryAdditions) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ThreatEntryAdditions.ProtoReflect.Descriptor instead. +func (*ThreatEntryAdditions) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{6} +} -func (m *ThreatEntryAdditions) GetRawHashes() []*RawHashes { - if m != nil { - return m.RawHashes +func (x *ThreatEntryAdditions) GetRawHashes() []*RawHashes { + if x != nil { + return x.RawHashes } return nil } -func (m *ThreatEntryAdditions) GetRiceHashes() *RiceDeltaEncoding { - if m != nil { - return m.RiceHashes +func (x *ThreatEntryAdditions) GetRiceHashes() *RiceDeltaEncoding { + if x != nil { + return x.RiceHashes } return nil } // Contains the set of entries to remove from a local database. type ThreatEntryRemovals struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + // The raw removal indices for a local list. - RawIndices *RawIndices `protobuf:"bytes,1,opt,name=raw_indices,json=rawIndices" json:"raw_indices,omitempty"` + RawIndices *RawIndices `protobuf:"bytes,1,opt,name=raw_indices,json=rawIndices,proto3" json:"raw_indices,omitempty"` // The encoded local, lexicographically-sorted list indices, using a // Golomb-Rice encoding. Used for sending compressed removal indices. The // removal indices (uint32) are sorted in ascending order, then delta encoded // and stored as encoded_data. - RiceIndices *RiceDeltaEncoding `protobuf:"bytes,2,opt,name=rice_indices,json=riceIndices" json:"rice_indices,omitempty"` + RiceIndices *RiceDeltaEncoding `protobuf:"bytes,2,opt,name=rice_indices,json=riceIndices,proto3" json:"rice_indices,omitempty"` +} + +func (x *ThreatEntryRemovals) Reset() { + *x = ThreatEntryRemovals{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ThreatEntryRemovals) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ThreatEntryRemovals) ProtoMessage() {} + +func (x *ThreatEntryRemovals) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[7] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) } -func (m *ThreatEntryRemovals) Reset() { *m = ThreatEntryRemovals{} } -func (m *ThreatEntryRemovals) String() string { return proto.CompactTextString(m) } -func (*ThreatEntryRemovals) ProtoMessage() {} -func (*ThreatEntryRemovals) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} } +// Deprecated: Use ThreatEntryRemovals.ProtoReflect.Descriptor instead. +func (*ThreatEntryRemovals) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{7} +} -func (m *ThreatEntryRemovals) GetRawIndices() *RawIndices { - if m != nil { - return m.RawIndices +func (x *ThreatEntryRemovals) GetRawIndices() *RawIndices { + if x != nil { + return x.RawIndices } return nil } -func (m *ThreatEntryRemovals) GetRiceIndices() *RiceDeltaEncoding { - if m != nil { - return m.RiceIndices +func (x *ThreatEntryRemovals) GetRiceIndices() *RiceDeltaEncoding { + if x != nil { + return x.RiceIndices } return nil } // A set of raw indices to remove from a local list. type RawIndices struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + // The indices to remove from a lexicographically-sorted local list. - Indices []int32 `protobuf:"varint,1,rep,packed,name=indices" json:"indices,omitempty"` + Indices []int32 `protobuf:"varint,1,rep,packed,name=indices,proto3" json:"indices,omitempty"` +} + +func (x *RawIndices) Reset() { + *x = RawIndices{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } } -func (m *RawIndices) Reset() { *m = RawIndices{} } -func (m *RawIndices) String() string { return proto.CompactTextString(m) } -func (*RawIndices) ProtoMessage() {} -func (*RawIndices) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} } +func (x *RawIndices) String() string { + return protoimpl.X.MessageStringOf(x) +} -func (m *RawIndices) GetIndices() []int32 { - if m != nil { - return m.Indices +func (*RawIndices) ProtoMessage() {} + +func (x *RawIndices) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[8] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RawIndices.ProtoReflect.Descriptor instead. +func (*RawIndices) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{8} +} + +func (x *RawIndices) GetIndices() []int32 { + if x != nil { + return x.Indices } return nil } @@ -576,30 +781,61 @@ func (m *RawIndices) GetIndices() []int32 { // compression, or when sending non-4-byte hashes to clients that do support // compression. type RawHashes struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + // The number of bytes for each prefix encoded below. This field can be // anywhere from 4 (shortest prefix) to 32 (full SHA256 hash). - PrefixSize int32 `protobuf:"varint,1,opt,name=prefix_size,json=prefixSize" json:"prefix_size,omitempty"` + PrefixSize int32 `protobuf:"varint,1,opt,name=prefix_size,json=prefixSize,proto3" json:"prefix_size,omitempty"` // The hashes, in binary format, concatenated into one long string. Hashes are // sorted in lexicographic order. For JSON API users, hashes are // base64-encoded. RawHashes []byte `protobuf:"bytes,2,opt,name=raw_hashes,json=rawHashes,proto3" json:"raw_hashes,omitempty"` } -func (m *RawHashes) Reset() { *m = RawHashes{} } -func (m *RawHashes) String() string { return proto.CompactTextString(m) } -func (*RawHashes) ProtoMessage() {} -func (*RawHashes) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } +func (x *RawHashes) Reset() { + *x = RawHashes{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RawHashes) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RawHashes) ProtoMessage() {} -func (m *RawHashes) GetPrefixSize() int32 { - if m != nil { - return m.PrefixSize +func (x *RawHashes) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[9] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RawHashes.ProtoReflect.Descriptor instead. +func (*RawHashes) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{9} +} + +func (x *RawHashes) GetPrefixSize() int32 { + if x != nil { + return x.PrefixSize } return 0 } -func (m *RawHashes) GetRawHashes() []byte { - if m != nil { - return m.RawHashes +func (x *RawHashes) GetRawHashes() []byte { + if x != nil { + return x.RawHashes } return nil } @@ -607,146 +843,787 @@ func (m *RawHashes) GetRawHashes() []byte { // The Rice-Golomb encoded data. Used for sending compressed 4-byte hashes or // compressed removal indices. type RiceDeltaEncoding struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + // The offset of the first entry in the encoded data, or, if only a single // integer was encoded, that single integer's value. If the field is empty or // missing, assume zero. - FirstValue int64 `protobuf:"varint,1,opt,name=first_value,json=firstValue" json:"first_value,omitempty"` + FirstValue int64 `protobuf:"varint,1,opt,name=first_value,json=firstValue,proto3" json:"first_value,omitempty"` // The Golomb-Rice parameter, which is a number between 2 and 28. This field // is missing (that is, zero) if `num_entries` is zero. - RiceParameter int32 `protobuf:"varint,2,opt,name=rice_parameter,json=riceParameter" json:"rice_parameter,omitempty"` + RiceParameter int32 `protobuf:"varint,2,opt,name=rice_parameter,json=riceParameter,proto3" json:"rice_parameter,omitempty"` // The number of entries that are delta encoded in the encoded data. If only a // single integer was encoded, this will be zero and the single value will be // stored in `first_value`. - EntryCount int32 `protobuf:"varint,3,opt,name=entry_count,json=entryCount" json:"entry_count,omitempty"` + EntryCount int32 `protobuf:"varint,3,opt,name=entry_count,json=entryCount,proto3" json:"entry_count,omitempty"` // The encoded deltas that are encoded using the Golomb-Rice coder. EncodedData []byte `protobuf:"bytes,4,opt,name=encoded_data,json=encodedData,proto3" json:"encoded_data,omitempty"` } -func (m *RiceDeltaEncoding) Reset() { *m = RiceDeltaEncoding{} } -func (m *RiceDeltaEncoding) String() string { return proto.CompactTextString(m) } -func (*RiceDeltaEncoding) ProtoMessage() {} -func (*RiceDeltaEncoding) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} } +func (x *RiceDeltaEncoding) Reset() { + *x = RiceDeltaEncoding{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RiceDeltaEncoding) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RiceDeltaEncoding) ProtoMessage() {} + +func (x *RiceDeltaEncoding) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[10] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RiceDeltaEncoding.ProtoReflect.Descriptor instead. +func (*RiceDeltaEncoding) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{10} +} -func (m *RiceDeltaEncoding) GetFirstValue() int64 { - if m != nil { - return m.FirstValue +func (x *RiceDeltaEncoding) GetFirstValue() int64 { + if x != nil { + return x.FirstValue } return 0 } -func (m *RiceDeltaEncoding) GetRiceParameter() int32 { - if m != nil { - return m.RiceParameter +func (x *RiceDeltaEncoding) GetRiceParameter() int32 { + if x != nil { + return x.RiceParameter } return 0 } -func (m *RiceDeltaEncoding) GetEntryCount() int32 { - if m != nil { - return m.EntryCount +func (x *RiceDeltaEncoding) GetEntryCount() int32 { + if x != nil { + return x.EntryCount } return 0 } -func (m *RiceDeltaEncoding) GetEncodedData() []byte { - if m != nil { - return m.EncodedData +func (x *RiceDeltaEncoding) GetEncodedData() []byte { + if x != nil { + return x.EncodedData } return nil } -func init() { - proto.RegisterType((*ComputeThreatListDiffRequest)(nil), "google.cloud.webrisk.v1.ComputeThreatListDiffRequest") - proto.RegisterType((*ComputeThreatListDiffRequest_Constraints)(nil), "google.cloud.webrisk.v1.ComputeThreatListDiffRequest.Constraints") - proto.RegisterType((*ComputeThreatListDiffResponse)(nil), "google.cloud.webrisk.v1.ComputeThreatListDiffResponse") - proto.RegisterType((*ComputeThreatListDiffResponse_Checksum)(nil), "google.cloud.webrisk.v1.ComputeThreatListDiffResponse.Checksum") - proto.RegisterType((*SearchUrisRequest)(nil), "google.cloud.webrisk.v1.SearchUrisRequest") - proto.RegisterType((*SearchUrisResponse)(nil), "google.cloud.webrisk.v1.SearchUrisResponse") - proto.RegisterType((*SearchUrisResponse_ThreatUri)(nil), "google.cloud.webrisk.v1.SearchUrisResponse.ThreatUri") - proto.RegisterType((*SearchHashesRequest)(nil), "google.cloud.webrisk.v1.SearchHashesRequest") - proto.RegisterType((*SearchHashesResponse)(nil), "google.cloud.webrisk.v1.SearchHashesResponse") - proto.RegisterType((*SearchHashesResponse_ThreatHash)(nil), "google.cloud.webrisk.v1.SearchHashesResponse.ThreatHash") - proto.RegisterType((*ThreatEntryAdditions)(nil), "google.cloud.webrisk.v1.ThreatEntryAdditions") - proto.RegisterType((*ThreatEntryRemovals)(nil), "google.cloud.webrisk.v1.ThreatEntryRemovals") - proto.RegisterType((*RawIndices)(nil), "google.cloud.webrisk.v1.RawIndices") - proto.RegisterType((*RawHashes)(nil), "google.cloud.webrisk.v1.RawHashes") - proto.RegisterType((*RiceDeltaEncoding)(nil), "google.cloud.webrisk.v1.RiceDeltaEncoding") - proto.RegisterEnum("google.cloud.webrisk.v1.ThreatType", ThreatType_name, ThreatType_value) - proto.RegisterEnum("google.cloud.webrisk.v1.CompressionType", CompressionType_name, CompressionType_value) - proto.RegisterEnum("google.cloud.webrisk.v1.ComputeThreatListDiffResponse_ResponseType", ComputeThreatListDiffResponse_ResponseType_name, ComputeThreatListDiffResponse_ResponseType_value) -} - -func init() { proto.RegisterFile("webrisk.proto", fileDescriptor0) } - -var fileDescriptor0 = []byte{ - // 1095 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x56, 0xcf, 0x6e, 0x1b, 0xb7, - 0x13, 0xfe, 0xad, 0xe4, 0x7f, 0x9a, 0x95, 0x1d, 0x99, 0x71, 0x12, 0xfd, 0xd4, 0x04, 0x71, 0x37, - 0x68, 0x21, 0x18, 0xad, 0xd2, 0xaa, 0x48, 0x51, 0xa0, 0x87, 0x42, 0x95, 0x56, 0x89, 0x60, 0x5b, - 0x16, 0x28, 0x39, 0x46, 0xd1, 0xc3, 0x82, 0x5e, 0x51, 0x16, 0x61, 0xef, 0x9f, 0x92, 0x94, 0x25, - 0xe7, 0xd0, 0x67, 0xe8, 0x1b, 0xf4, 0xd4, 0x1e, 0xfa, 0x0a, 0x7d, 0x83, 0x3e, 0x45, 0xfb, 0x12, - 0x3d, 0x17, 0xe4, 0x72, 0x25, 0x39, 0xb6, 0x1c, 0x3b, 0xc8, 0x8d, 0xfb, 0x71, 0xe6, 0x9b, 0xe1, - 0x37, 0xc3, 0x59, 0xc2, 0xfa, 0x98, 0x1e, 0x73, 0x26, 0x4e, 0x2b, 0x31, 0x8f, 0x64, 0x84, 0x1e, - 0x9d, 0x44, 0xd1, 0xc9, 0x19, 0xad, 0xf8, 0x67, 0xd1, 0xa8, 0x5f, 0x49, 0xf7, 0xce, 0xbf, 0x2c, - 0x3d, 0x4d, 0x36, 0x9e, 0x6b, 0xb3, 0xe3, 0xd1, 0xe0, 0xb9, 0x64, 0x01, 0x15, 0x92, 0x04, 0x71, - 0xe2, 0xe9, 0xfc, 0x99, 0x85, 0xc7, 0xf5, 0x28, 0x88, 0x47, 0x92, 0xf6, 0x86, 0x9c, 0x12, 0xb9, - 0xc7, 0x84, 0x6c, 0xb0, 0xc1, 0x00, 0xd3, 0x9f, 0x46, 0x54, 0x48, 0xd4, 0x00, 0x5b, 0xea, 0x0d, - 0x4f, 0x5e, 0xc4, 0xb4, 0x68, 0x6d, 0x5b, 0xe5, 0x8d, 0xea, 0xb3, 0xca, 0x82, 0x80, 0x95, 0x84, - 0xa4, 0x77, 0x11, 0x53, 0x0c, 0x72, 0xba, 0x46, 0xcf, 0x60, 0xfd, 0x9c, 0x72, 0xc1, 0xa2, 0xd0, - 0x93, 0xd1, 0x29, 0x0d, 0x8b, 0x99, 0x6d, 0xab, 0x9c, 0xc7, 0x79, 0x03, 0xf6, 0x14, 0x86, 0x7c, - 0xb0, 0xfd, 0x28, 0x14, 0x92, 0x13, 0x16, 0x4a, 0x51, 0xcc, 0x6e, 0x5b, 0x65, 0xbb, 0x5a, 0x5b, - 0x18, 0xea, 0xa6, 0xb4, 0x2b, 0xf5, 0x19, 0x11, 0x9e, 0x67, 0x2d, 0xfd, 0x65, 0x81, 0x3d, 0xb7, - 0x89, 0xca, 0x50, 0x08, 0xc8, 0xc4, 0xeb, 0xb3, 0xc1, 0xc0, 0xa3, 0xa1, 0xe4, 0x8c, 0x0a, 0x7d, - 0xc8, 0x65, 0xbc, 0x11, 0x90, 0x89, 0xa2, 0x74, 0x13, 0x14, 0x7d, 0x01, 0x5b, 0xda, 0x92, 0x48, - 0x72, 0x4c, 0x04, 0x9d, 0x5a, 0x67, 0xb4, 0x35, 0x52, 0xd6, 0x66, 0x2b, 0xf5, 0xf0, 0xe0, 0xa1, - 0x18, 0xc5, 0x71, 0xc4, 0x25, 0xed, 0x7b, 0x7e, 0x14, 0xc4, 0x9c, 0x0a, 0x75, 0x5c, 0x75, 0xb6, - 0x6c, 0x79, 0xa3, 0x5a, 0xbe, 0xf1, 0x6c, 0xc6, 0x58, 0x6b, 0xf9, 0x60, 0xca, 0x33, 0xb7, 0x23, - 0x9c, 0x7f, 0x96, 0xe0, 0xc9, 0x02, 0x19, 0x44, 0x1c, 0x85, 0x82, 0xa2, 0x21, 0xac, 0x73, 0xb3, - 0x4e, 0x0a, 0xb8, 0xa4, 0x0b, 0x58, 0xbf, 0xab, 0xaa, 0x09, 0x45, 0x25, 0x5d, 0xe8, 0xa4, 0xf2, - 0x7c, 0xee, 0x0b, 0xed, 0x42, 0x8e, 0xf4, 0xfb, 0x4c, 0xea, 0xf3, 0x2d, 0xeb, 0xda, 0x7d, 0xfe, - 0x8e, 0x36, 0x51, 0x3a, 0x5d, 0xd4, 0x52, 0x27, 0x3c, 0xf3, 0x47, 0xaf, 0x60, 0x8d, 0xd3, 0x20, - 0x3a, 0x27, 0x67, 0xa2, 0xb8, 0xa2, 0xb9, 0x3e, 0xbb, 0x0d, 0x17, 0x36, 0x3e, 0x78, 0xea, 0x8d, - 0x76, 0x60, 0x33, 0xa4, 0x63, 0xef, 0x72, 0xf7, 0xad, 0xea, 0xee, 0xbb, 0x17, 0xd2, 0xf1, 0xeb, - 0xf9, 0x06, 0xfc, 0x11, 0xd6, 0xfc, 0x21, 0xf5, 0x4f, 0xc5, 0x28, 0x28, 0xae, 0xe9, 0xa8, 0xdf, - 0xbd, 0xa7, 0x4e, 0x75, 0x43, 0x83, 0xa7, 0x84, 0xa8, 0x0d, 0x0f, 0x38, 0xf5, 0xa3, 0x20, 0xa0, - 0x61, 0x9f, 0xf6, 0xbd, 0x90, 0x4e, 0xa4, 0xee, 0x3a, 0xdd, 0x3f, 0x76, 0xb5, 0x94, 0x46, 0x4a, - 0xaf, 0x6a, 0xa5, 0x97, 0x5e, 0x55, 0x7c, 0x7f, 0xce, 0xb1, 0x4d, 0x27, 0x3a, 0x54, 0xc9, 0x81, - 0xb5, 0x34, 0x0a, 0x7a, 0x08, 0x2b, 0x62, 0x48, 0xaa, 0x2f, 0xbe, 0xd6, 0xad, 0x9b, 0xc7, 0xe6, - 0xcb, 0xf9, 0x1e, 0xf2, 0xf3, 0x15, 0x43, 0x4f, 0xe0, 0xff, 0xd8, 0xed, 0x76, 0x0e, 0xda, 0x5d, - 0xd7, 0xeb, 0xfd, 0xd0, 0x71, 0xbd, 0xc3, 0x76, 0xb7, 0xe3, 0xd6, 0x5b, 0xcd, 0x96, 0xdb, 0x28, - 0xfc, 0x0f, 0xad, 0xc1, 0x52, 0xa3, 0xd5, 0x6c, 0x16, 0x2c, 0x94, 0x83, 0x65, 0xec, 0x76, 0xdd, - 0x5e, 0x21, 0xe3, 0x04, 0xb0, 0xd9, 0xa5, 0x84, 0xfb, 0xc3, 0x43, 0xce, 0x44, 0x3a, 0x15, 0x0a, - 0x90, 0x1d, 0x71, 0xa6, 0xa3, 0xe5, 0xb0, 0x5a, 0xa2, 0x26, 0xe4, 0xe7, 0xe6, 0x84, 0xba, 0x15, - 0xd9, 0xdb, 0x0e, 0x0a, 0x7b, 0x36, 0x28, 0x84, 0xf3, 0xaf, 0x05, 0x68, 0x3e, 0x9e, 0xe9, 0xe3, - 0x7d, 0x58, 0x49, 0xac, 0x74, 0x4c, 0xbb, 0xfa, 0x62, 0x21, 0xf1, 0x55, 0x67, 0x13, 0xeb, 0x90, - 0x33, 0x6c, 0x48, 0x4a, 0xbf, 0x58, 0x90, 0x9b, 0xa2, 0x57, 0x72, 0xb7, 0xde, 0x2f, 0x77, 0xf4, - 0x2d, 0xd8, 0x74, 0x12, 0x33, 0x4e, 0x3d, 0x35, 0x66, 0x6f, 0x51, 0x58, 0x48, 0xcc, 0x15, 0xe0, - 0xfc, 0x0c, 0xf7, 0x93, 0xd4, 0x5f, 0x11, 0x31, 0xa4, 0x53, 0xa5, 0x9f, 0x82, 0x3d, 0x24, 0x62, - 0xe8, 0xc5, 0x9c, 0x0e, 0xd8, 0xc4, 0xd4, 0x17, 0x14, 0xd4, 0xd1, 0xc8, 0x07, 0x13, 0xfe, 0xef, - 0x0c, 0x6c, 0x5d, 0x4e, 0xc0, 0x48, 0x8f, 0x61, 0x35, 0xb1, 0x4b, 0x84, 0xb1, 0xab, 0xdf, 0xbc, - 0x43, 0xfb, 0xcb, 0xfe, 0x26, 0xa0, 0x02, 0x71, 0x4a, 0x84, 0xf6, 0x60, 0x2b, 0xa4, 0x27, 0x44, - 0xb2, 0x73, 0xea, 0xdd, 0x4d, 0x32, 0x94, 0xfa, 0xb9, 0x53, 0xe9, 0x4a, 0xbf, 0x59, 0x00, 0xb3, - 0x28, 0x1f, 0xac, 0x9c, 0x08, 0x96, 0x94, 0xce, 0xe6, 0x5f, 0xa5, 0xd7, 0x6f, 0x97, 0x38, 0x7b, - 0xa7, 0x12, 0xff, 0x6e, 0xc1, 0xd6, 0x75, 0x93, 0x0f, 0xd5, 0x00, 0x38, 0x19, 0x7b, 0x43, 0x2d, - 0x9c, 0x51, 0xd9, 0x59, 0x98, 0x2f, 0x26, 0x63, 0x23, 0x71, 0x8e, 0xa7, 0x4b, 0xb4, 0x0b, 0x36, - 0x67, 0x3e, 0x4d, 0x39, 0x12, 0x21, 0x77, 0x16, 0x73, 0x30, 0x9f, 0x36, 0xe8, 0x99, 0x24, 0x6e, - 0xe8, 0x47, 0x7d, 0x16, 0x9e, 0x60, 0x50, 0xee, 0x09, 0x99, 0xf3, 0x87, 0x05, 0xf7, 0xaf, 0x19, - 0xab, 0xea, 0x31, 0xa0, 0xf2, 0x64, 0x61, 0x9f, 0xf9, 0xe6, 0x3f, 0x69, 0xdf, 0x20, 0x2c, 0x26, - 0xe3, 0x56, 0x62, 0x8a, 0xd5, 0xf9, 0xcc, 0x1a, 0xed, 0x43, 0x5e, 0xa7, 0x9a, 0xd2, 0xdc, 0x3d, - 0x57, 0x7d, 0x54, 0x43, 0xe7, 0x7c, 0x0a, 0x30, 0x0b, 0x84, 0x8a, 0xb0, 0x3a, 0x4b, 0x2f, 0x5b, - 0x5e, 0xc6, 0xe9, 0xa7, 0xb3, 0x0b, 0xb9, 0xa9, 0x72, 0xea, 0x5a, 0x25, 0x37, 0xca, 0x13, 0xec, - 0x0d, 0x35, 0x7f, 0x7c, 0x48, 0xa0, 0x2e, 0x7b, 0xa3, 0x46, 0xe5, 0x7c, 0x49, 0x92, 0x16, 0x98, - 0xc9, 0xed, 0xfc, 0x6a, 0xc1, 0xe6, 0x95, 0xbc, 0x14, 0xeb, 0x80, 0x71, 0x21, 0xbd, 0x73, 0x72, - 0x36, 0x4a, 0x58, 0xb3, 0x18, 0x34, 0xf4, 0x5a, 0x21, 0xe8, 0x13, 0xd8, 0xd0, 0x47, 0x8f, 0x09, - 0x27, 0x01, 0x95, 0x94, 0x9b, 0xd7, 0xc3, 0xba, 0x42, 0x3b, 0x29, 0xa8, 0x78, 0xd4, 0xeb, 0xe2, - 0xc2, 0xf3, 0xa3, 0x51, 0x28, 0x75, 0x97, 0x2d, 0x63, 0xd0, 0x50, 0x5d, 0x21, 0xe8, 0x63, 0xc8, - 0x53, 0x15, 0x94, 0xf6, 0xf5, 0x7b, 0x44, 0xff, 0xd5, 0xf3, 0xd8, 0x36, 0x98, 0x7a, 0x87, 0xec, - 0xd0, 0xf4, 0x4e, 0xe8, 0xc9, 0xff, 0x11, 0x3c, 0xea, 0xbd, 0xc2, 0x6e, 0xad, 0x77, 0xdd, 0xdc, - 0xb7, 0x61, 0x75, 0xbf, 0xb6, 0x77, 0x54, 0xc3, 0x6e, 0xc1, 0x42, 0x0f, 0x01, 0x75, 0x0f, 0xea, - 0xad, 0xda, 0x9e, 0xe7, 0xb6, 0x5f, 0xb6, 0xda, 0xae, 0x8b, 0x5b, 0xed, 0x97, 0x85, 0x0c, 0x7a, - 0x00, 0x9b, 0x87, 0xed, 0xa3, 0x5a, 0xbb, 0xe7, 0x36, 0xbc, 0xee, 0x41, 0xb3, 0xa7, 0xcd, 0xb3, - 0x3b, 0x4d, 0xb8, 0xf7, 0xd6, 0x63, 0x05, 0x6d, 0xc3, 0xe3, 0xfa, 0xc1, 0x7e, 0x07, 0xbb, 0xdd, - 0x6e, 0xeb, 0xa0, 0x7d, 0x5d, 0xc0, 0x55, 0xc8, 0xe2, 0xda, 0x51, 0xc1, 0x52, 0x7f, 0x1c, 0xdc, - 0xaa, 0xbb, 0x85, 0xcc, 0xf1, 0x8a, 0xbe, 0x3b, 0x5f, 0xfd, 0x17, 0x00, 0x00, 0xff, 0xff, 0xf9, - 0x0f, 0x45, 0xae, 0xda, 0x0a, 0x00, 0x00, +// The constraints for this diff. +type ComputeThreatListDiffRequest_Constraints struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The maximum size in number of entries. The diff will not contain more + // entries than this value. This should be a power of 2 between 2**10 and + // 2**20. If zero, no diff size limit is set. + MaxDiffEntries int32 `protobuf:"varint,1,opt,name=max_diff_entries,json=maxDiffEntries,proto3" json:"max_diff_entries,omitempty"` + // Sets the maximum number of entries that the client is willing to have + // in the local database. This should be a power of 2 between 2**10 and + // 2**20. If zero, no database size limit is set. + MaxDatabaseEntries int32 `protobuf:"varint,2,opt,name=max_database_entries,json=maxDatabaseEntries,proto3" json:"max_database_entries,omitempty"` + // The compression types supported by the client. + SupportedCompressions []CompressionType `protobuf:"varint,3,rep,packed,name=supported_compressions,json=supportedCompressions,proto3,enum=google.cloud.webrisk.v1.CompressionType" json:"supported_compressions,omitempty"` +} + +func (x *ComputeThreatListDiffRequest_Constraints) Reset() { + *x = ComputeThreatListDiffRequest_Constraints{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[11] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ComputeThreatListDiffRequest_Constraints) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ComputeThreatListDiffRequest_Constraints) ProtoMessage() {} + +func (x *ComputeThreatListDiffRequest_Constraints) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[11] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ComputeThreatListDiffRequest_Constraints.ProtoReflect.Descriptor instead. +func (*ComputeThreatListDiffRequest_Constraints) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{0, 0} +} + +func (x *ComputeThreatListDiffRequest_Constraints) GetMaxDiffEntries() int32 { + if x != nil { + return x.MaxDiffEntries + } + return 0 +} + +func (x *ComputeThreatListDiffRequest_Constraints) GetMaxDatabaseEntries() int32 { + if x != nil { + return x.MaxDatabaseEntries + } + return 0 +} + +func (x *ComputeThreatListDiffRequest_Constraints) GetSupportedCompressions() []CompressionType { + if x != nil { + return x.SupportedCompressions + } + return nil +} + +// The expected state of a client's local database. +type ComputeThreatListDiffResponse_Checksum struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The SHA256 hash of the client state; that is, of the sorted list of all + // hashes present in the database. + Sha256 []byte `protobuf:"bytes,1,opt,name=sha256,proto3" json:"sha256,omitempty"` +} + +func (x *ComputeThreatListDiffResponse_Checksum) Reset() { + *x = ComputeThreatListDiffResponse_Checksum{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ComputeThreatListDiffResponse_Checksum) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ComputeThreatListDiffResponse_Checksum) ProtoMessage() {} + +func (x *ComputeThreatListDiffResponse_Checksum) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[12] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ComputeThreatListDiffResponse_Checksum.ProtoReflect.Descriptor instead. +func (*ComputeThreatListDiffResponse_Checksum) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{1, 0} +} + +func (x *ComputeThreatListDiffResponse_Checksum) GetSha256() []byte { + if x != nil { + return x.Sha256 + } + return nil +} + +// Contains threat information on a matching uri. +type SearchUrisResponse_ThreatUri struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The ThreatList this threat belongs to. + ThreatTypes []ThreatType `protobuf:"varint,1,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` + // The cache lifetime for the returned match. Clients must not cache this + // response past this timestamp to avoid false positives. + ExpireTime *timestamp.Timestamp `protobuf:"bytes,2,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"` +} + +func (x *SearchUrisResponse_ThreatUri) Reset() { + *x = SearchUrisResponse_ThreatUri{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[13] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SearchUrisResponse_ThreatUri) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SearchUrisResponse_ThreatUri) ProtoMessage() {} + +func (x *SearchUrisResponse_ThreatUri) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[13] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SearchUrisResponse_ThreatUri.ProtoReflect.Descriptor instead. +func (*SearchUrisResponse_ThreatUri) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{3, 0} +} + +func (x *SearchUrisResponse_ThreatUri) GetThreatTypes() []ThreatType { + if x != nil { + return x.ThreatTypes + } + return nil +} + +func (x *SearchUrisResponse_ThreatUri) GetExpireTime() *timestamp.Timestamp { + if x != nil { + return x.ExpireTime + } + return nil +} + +// Contains threat information on a matching hash. +type SearchHashesResponse_ThreatHash struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // The ThreatList this threat belongs to. + // This must contain at least one entry. + ThreatTypes []ThreatType `protobuf:"varint,1,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` + // A 32 byte SHA256 hash. This field is in binary format. For JSON + // requests, hashes are base64-encoded. + Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` + // The cache lifetime for the returned match. Clients must not cache this + // response past this timestamp to avoid false positives. + ExpireTime *timestamp.Timestamp `protobuf:"bytes,3,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"` +} + +func (x *SearchHashesResponse_ThreatHash) Reset() { + *x = SearchHashesResponse_ThreatHash{} + if protoimpl.UnsafeEnabled { + mi := &file_webrisk_proto_msgTypes[14] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SearchHashesResponse_ThreatHash) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SearchHashesResponse_ThreatHash) ProtoMessage() {} + +func (x *SearchHashesResponse_ThreatHash) ProtoReflect() protoreflect.Message { + mi := &file_webrisk_proto_msgTypes[14] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SearchHashesResponse_ThreatHash.ProtoReflect.Descriptor instead. +func (*SearchHashesResponse_ThreatHash) Descriptor() ([]byte, []int) { + return file_webrisk_proto_rawDescGZIP(), []int{5, 0} +} + +func (x *SearchHashesResponse_ThreatHash) GetThreatTypes() []ThreatType { + if x != nil { + return x.ThreatTypes + } + return nil +} + +func (x *SearchHashesResponse_ThreatHash) GetHash() []byte { + if x != nil { + return x.Hash + } + return nil +} + +func (x *SearchHashesResponse_ThreatHash) GetExpireTime() *timestamp.Timestamp { + if x != nil { + return x.ExpireTime + } + return nil +} + +var File_webrisk_proto protoreflect.FileDescriptor + +var file_webrisk_proto_rawDesc = []byte{ + 0x0a, 0x0d, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, + 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, + 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbb, 0x03, 0x0a, 0x1c, 0x43, 0x6f, + 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, + 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x44, 0x0a, 0x0b, 0x74, 0x68, + 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, + 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, + 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, + 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x63, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, + 0x69, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, + 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, + 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x0b, 0x63, + 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0xca, 0x01, 0x0a, 0x0b, 0x43, + 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, + 0x78, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x44, 0x69, 0x66, 0x66, 0x45, 0x6e, 0x74, + 0x72, 0x69, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x61, 0x74, 0x61, + 0x62, 0x61, 0x73, 0x65, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x12, 0x6d, 0x61, 0x78, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x45, + 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x5f, 0x0a, 0x16, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x03, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, + 0x52, 0x15, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x72, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe1, 0x04, 0x0a, 0x1d, 0x43, 0x6f, 0x6d, 0x70, + 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, + 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0d, 0x72, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x43, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, + 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, + 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x4b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x41, 0x64, 0x64, 0x69, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x12, 0x48, 0x0a, 0x08, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x72, + 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, + 0x52, 0x08, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6e, 0x65, + 0x77, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6e, 0x65, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x5b, 0x0a, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, + 0x75, 0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, + 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x52, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, + 0x73, 0x75, 0x6d, 0x12, 0x4e, 0x0a, 0x15, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, + 0x65, 0x64, 0x5f, 0x6e, 0x65, 0x78, 0x74, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x13, + 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x65, 0x64, 0x4e, 0x65, 0x78, 0x74, 0x44, + 0x69, 0x66, 0x66, 0x1a, 0x22, 0x0a, 0x08, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, + 0x16, 0x0a, 0x06, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x06, 0x73, 0x68, 0x61, 0x32, 0x35, 0x36, 0x22, 0x42, 0x0a, 0x0c, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x45, 0x53, 0x50, 0x4f, + 0x4e, 0x53, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x49, 0x46, 0x46, 0x10, 0x01, + 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x53, 0x45, 0x54, 0x10, 0x02, 0x22, 0x6d, 0x0a, 0x11, 0x53, + 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x72, 0x69, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, + 0x72, 0x69, 0x12, 0x46, 0x0a, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, + 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0xf6, 0x01, 0x0a, 0x12, 0x53, + 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x72, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x4d, 0x0a, 0x06, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, + 0x63, 0x68, 0x55, 0x72, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, + 0x68, 0x72, 0x65, 0x61, 0x74, 0x55, 0x72, 0x69, 0x52, 0x06, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, + 0x1a, 0x90, 0x01, 0x0a, 0x09, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x55, 0x72, 0x69, 0x12, 0x46, + 0x0a, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, + 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, + 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, + 0x69, 0x6d, 0x65, 0x22, 0x7e, 0x0a, 0x13, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x61, 0x73, + 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x61, + 0x73, 0x68, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x0a, 0x68, 0x61, 0x73, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x46, 0x0a, 0x0c, 0x74, + 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x72, 0x65, + 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x73, 0x22, 0xe0, 0x02, 0x0a, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x61, + 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x07, + 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, + 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x61, + 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x68, 0x72, + 0x65, 0x61, 0x74, 0x48, 0x61, 0x73, 0x68, 0x52, 0x07, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x73, + 0x12, 0x4c, 0x0a, 0x14, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x65, 0x78, 0x70, + 0x69, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x12, 0x6e, 0x65, 0x67, 0x61, + 0x74, 0x69, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x1a, 0xa5, + 0x01, 0x0a, 0x0a, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x46, 0x0a, + 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, + 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, + 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x70, + 0x69, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, + 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0xa6, 0x01, 0x0a, 0x14, 0x54, 0x68, 0x72, 0x65, 0x61, + 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, + 0x41, 0x0a, 0x0a, 0x72, 0x61, 0x77, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, + 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x61, + 0x77, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x52, 0x09, 0x72, 0x61, 0x77, 0x48, 0x61, 0x73, 0x68, + 0x65, 0x73, 0x12, 0x4b, 0x0a, 0x0b, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, + 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, + 0x31, 0x2e, 0x52, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x45, 0x6e, 0x63, 0x6f, 0x64, + 0x69, 0x6e, 0x67, 0x52, 0x0a, 0x72, 0x69, 0x63, 0x65, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, + 0xaa, 0x01, 0x0a, 0x13, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x44, 0x0a, 0x0b, 0x72, 0x61, 0x77, 0x5f, 0x69, + 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, + 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x61, 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, + 0x73, 0x52, 0x0a, 0x72, 0x61, 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x4d, 0x0a, + 0x0c, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, + 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x69, + 0x63, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, + 0x0b, 0x72, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x26, 0x0a, 0x0a, + 0x52, 0x61, 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, + 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x52, 0x07, 0x69, 0x6e, 0x64, + 0x69, 0x63, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x09, 0x52, 0x61, 0x77, 0x48, 0x61, 0x73, 0x68, 0x65, + 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x73, 0x69, 0x7a, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x53, 0x69, + 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x61, 0x77, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x72, 0x61, 0x77, 0x48, 0x61, 0x73, 0x68, 0x65, + 0x73, 0x22, 0x9f, 0x01, 0x0a, 0x11, 0x52, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x45, + 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x72, 0x73, 0x74, + 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x66, 0x69, + 0x72, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x69, 0x63, 0x65, + 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x0d, 0x72, 0x69, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, + 0x1f, 0x0a, 0x0b, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x44, + 0x61, 0x74, 0x61, 0x2a, 0x8f, 0x01, 0x0a, 0x0a, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x54, 0x48, 0x52, 0x45, 0x41, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x0b, 0x0a, 0x07, 0x4d, 0x41, 0x4c, 0x57, 0x41, 0x52, 0x45, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, + 0x53, 0x4f, 0x43, 0x49, 0x41, 0x4c, 0x5f, 0x45, 0x4e, 0x47, 0x49, 0x4e, 0x45, 0x45, 0x52, 0x49, + 0x4e, 0x47, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x4e, 0x57, 0x41, 0x4e, 0x54, 0x45, 0x44, + 0x5f, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x10, 0x03, 0x12, 0x28, 0x0a, 0x24, 0x53, + 0x4f, 0x43, 0x49, 0x41, 0x4c, 0x5f, 0x45, 0x4e, 0x47, 0x49, 0x4e, 0x45, 0x45, 0x52, 0x49, 0x4e, + 0x47, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x44, 0x45, 0x44, 0x5f, 0x43, 0x4f, 0x56, 0x45, 0x52, + 0x41, 0x47, 0x45, 0x10, 0x04, 0x2a, 0x46, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x43, 0x4f, 0x4d, 0x50, + 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, + 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x52, 0x41, + 0x57, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x52, 0x49, 0x43, 0x45, 0x10, 0x02, 0x42, 0x1b, 0x5a, + 0x19, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2f, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, +} + +var ( + file_webrisk_proto_rawDescOnce sync.Once + file_webrisk_proto_rawDescData = file_webrisk_proto_rawDesc +) + +func file_webrisk_proto_rawDescGZIP() []byte { + file_webrisk_proto_rawDescOnce.Do(func() { + file_webrisk_proto_rawDescData = protoimpl.X.CompressGZIP(file_webrisk_proto_rawDescData) + }) + return file_webrisk_proto_rawDescData +} + +var file_webrisk_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_webrisk_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_webrisk_proto_goTypes = []interface{}{ + (ThreatType)(0), // 0: google.cloud.webrisk.v1.ThreatType + (CompressionType)(0), // 1: google.cloud.webrisk.v1.CompressionType + (ComputeThreatListDiffResponse_ResponseType)(0), // 2: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.ResponseType + (*ComputeThreatListDiffRequest)(nil), // 3: google.cloud.webrisk.v1.ComputeThreatListDiffRequest + (*ComputeThreatListDiffResponse)(nil), // 4: google.cloud.webrisk.v1.ComputeThreatListDiffResponse + (*SearchUrisRequest)(nil), // 5: google.cloud.webrisk.v1.SearchUrisRequest + (*SearchUrisResponse)(nil), // 6: google.cloud.webrisk.v1.SearchUrisResponse + (*SearchHashesRequest)(nil), // 7: google.cloud.webrisk.v1.SearchHashesRequest + (*SearchHashesResponse)(nil), // 8: google.cloud.webrisk.v1.SearchHashesResponse + (*ThreatEntryAdditions)(nil), // 9: google.cloud.webrisk.v1.ThreatEntryAdditions + (*ThreatEntryRemovals)(nil), // 10: google.cloud.webrisk.v1.ThreatEntryRemovals + (*RawIndices)(nil), // 11: google.cloud.webrisk.v1.RawIndices + (*RawHashes)(nil), // 12: google.cloud.webrisk.v1.RawHashes + (*RiceDeltaEncoding)(nil), // 13: google.cloud.webrisk.v1.RiceDeltaEncoding + (*ComputeThreatListDiffRequest_Constraints)(nil), // 14: google.cloud.webrisk.v1.ComputeThreatListDiffRequest.Constraints + (*ComputeThreatListDiffResponse_Checksum)(nil), // 15: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.Checksum + (*SearchUrisResponse_ThreatUri)(nil), // 16: google.cloud.webrisk.v1.SearchUrisResponse.ThreatUri + (*SearchHashesResponse_ThreatHash)(nil), // 17: google.cloud.webrisk.v1.SearchHashesResponse.ThreatHash + (*timestamp.Timestamp)(nil), // 18: google.protobuf.Timestamp +} +var file_webrisk_proto_depIdxs = []int32{ + 0, // 0: google.cloud.webrisk.v1.ComputeThreatListDiffRequest.threat_type:type_name -> google.cloud.webrisk.v1.ThreatType + 14, // 1: google.cloud.webrisk.v1.ComputeThreatListDiffRequest.constraints:type_name -> google.cloud.webrisk.v1.ComputeThreatListDiffRequest.Constraints + 2, // 2: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.response_type:type_name -> google.cloud.webrisk.v1.ComputeThreatListDiffResponse.ResponseType + 9, // 3: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.additions:type_name -> google.cloud.webrisk.v1.ThreatEntryAdditions + 10, // 4: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.removals:type_name -> google.cloud.webrisk.v1.ThreatEntryRemovals + 15, // 5: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.checksum:type_name -> google.cloud.webrisk.v1.ComputeThreatListDiffResponse.Checksum + 18, // 6: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.recommended_next_diff:type_name -> google.protobuf.Timestamp + 0, // 7: google.cloud.webrisk.v1.SearchUrisRequest.threat_types:type_name -> google.cloud.webrisk.v1.ThreatType + 16, // 8: google.cloud.webrisk.v1.SearchUrisResponse.threat:type_name -> google.cloud.webrisk.v1.SearchUrisResponse.ThreatUri + 0, // 9: google.cloud.webrisk.v1.SearchHashesRequest.threat_types:type_name -> google.cloud.webrisk.v1.ThreatType + 17, // 10: google.cloud.webrisk.v1.SearchHashesResponse.threats:type_name -> google.cloud.webrisk.v1.SearchHashesResponse.ThreatHash + 18, // 11: google.cloud.webrisk.v1.SearchHashesResponse.negative_expire_time:type_name -> google.protobuf.Timestamp + 12, // 12: google.cloud.webrisk.v1.ThreatEntryAdditions.raw_hashes:type_name -> google.cloud.webrisk.v1.RawHashes + 13, // 13: google.cloud.webrisk.v1.ThreatEntryAdditions.rice_hashes:type_name -> google.cloud.webrisk.v1.RiceDeltaEncoding + 11, // 14: google.cloud.webrisk.v1.ThreatEntryRemovals.raw_indices:type_name -> google.cloud.webrisk.v1.RawIndices + 13, // 15: google.cloud.webrisk.v1.ThreatEntryRemovals.rice_indices:type_name -> google.cloud.webrisk.v1.RiceDeltaEncoding + 1, // 16: google.cloud.webrisk.v1.ComputeThreatListDiffRequest.Constraints.supported_compressions:type_name -> google.cloud.webrisk.v1.CompressionType + 0, // 17: google.cloud.webrisk.v1.SearchUrisResponse.ThreatUri.threat_types:type_name -> google.cloud.webrisk.v1.ThreatType + 18, // 18: google.cloud.webrisk.v1.SearchUrisResponse.ThreatUri.expire_time:type_name -> google.protobuf.Timestamp + 0, // 19: google.cloud.webrisk.v1.SearchHashesResponse.ThreatHash.threat_types:type_name -> google.cloud.webrisk.v1.ThreatType + 18, // 20: google.cloud.webrisk.v1.SearchHashesResponse.ThreatHash.expire_time:type_name -> google.protobuf.Timestamp + 21, // [21:21] is the sub-list for method output_type + 21, // [21:21] is the sub-list for method input_type + 21, // [21:21] is the sub-list for extension type_name + 21, // [21:21] is the sub-list for extension extendee + 0, // [0:21] is the sub-list for field type_name +} + +func init() { file_webrisk_proto_init() } +func file_webrisk_proto_init() { + if File_webrisk_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_webrisk_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ComputeThreatListDiffRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_webrisk_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ComputeThreatListDiffResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_webrisk_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SearchUrisRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_webrisk_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SearchUrisResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_webrisk_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SearchHashesRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_webrisk_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SearchHashesResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_webrisk_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ThreatEntryAdditions); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_webrisk_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ThreatEntryRemovals); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_webrisk_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RawIndices); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_webrisk_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RawHashes); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_webrisk_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RiceDeltaEncoding); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_webrisk_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ComputeThreatListDiffRequest_Constraints); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_webrisk_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ComputeThreatListDiffResponse_Checksum); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_webrisk_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SearchUrisResponse_ThreatUri); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_webrisk_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SearchHashesResponse_ThreatHash); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_webrisk_proto_rawDesc, + NumEnums: 3, + NumMessages: 15, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_webrisk_proto_goTypes, + DependencyIndexes: file_webrisk_proto_depIdxs, + EnumInfos: file_webrisk_proto_enumTypes, + MessageInfos: file_webrisk_proto_msgTypes, + }.Build() + File_webrisk_proto = out.File + file_webrisk_proto_rawDesc = nil + file_webrisk_proto_goTypes = nil + file_webrisk_proto_depIdxs = nil } diff --git a/internal/webrisk_proto/webrisk.proto b/internal/webrisk_proto/webrisk.proto index dd4dda5..6ca5548 100644 --- a/internal/webrisk_proto/webrisk.proto +++ b/internal/webrisk_proto/webrisk.proto @@ -19,6 +19,8 @@ package google.cloud.webrisk.v1; import "google/protobuf/timestamp.proto"; +option go_package = "github.com/google/webrisk"; + // Describes an API diff request. message ComputeThreatListDiffRequest { // The constraints for this diff. diff --git a/webrisk_client.go b/webrisk_client.go index 46c5866..fef761f 100644 --- a/webrisk_client.go +++ b/webrisk_client.go @@ -115,6 +115,7 @@ const ( ThreatTypeMalware = ThreatType(pb.ThreatType_MALWARE) ThreatTypeSocialEngineering = ThreatType(pb.ThreatType_SOCIAL_ENGINEERING) ThreatTypeUnwantedSoftware = ThreatType(pb.ThreatType_UNWANTED_SOFTWARE) + ThreatTypeSocialEngineeringExtended = ThreatType(pb.ThreatType_SOCIAL_ENGINEERING_EXTENDED_COVERAGE) ) // DefaultThreatLists is the default list of threat lists that WebriskClient @@ -122,6 +123,7 @@ const ( var DefaultThreatLists = []ThreatType{ ThreatTypeMalware, ThreatTypeSocialEngineering, + ThreatTypeSocialEngineeringExtended, ThreatTypeUnwantedSoftware, } From a6e982bd75f7d16fd1397420ad804a5b3815996b Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Thu, 10 Nov 2022 19:02:14 +0000 Subject: [PATCH 03/17] Bump protobuf version. --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index fa024cb..0b78b40 100644 --- a/go.mod +++ b/go.mod @@ -10,5 +10,5 @@ require ( require ( golang.org/x/text v0.4.0 // indirect - google.golang.org/protobuf v1.26.0 // indirect + google.golang.org/protobuf v1.28.1 // indirect ) From 4e0aeeedb97d91a6ea141d966c797edf3ce91cee Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Thu, 10 Nov 2022 19:02:37 +0000 Subject: [PATCH 04/17] Distroless Dockerfile template. --- Dockerfile | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/Dockerfile b/Dockerfile index e69de29..3f361b4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM golang:1.20 as build + +WORKDIR /go/src/webrisk +COPY . . + +RUN go mod download +RUN go vet -v +RUN go test -v + +RUN CGO_ENABLED=0 go build -o /go/bin/webrisk + +FROM gcr.io/distroless/static-debian11 + +COPY --from=build /go/bin/webrisk / +CMD ["/cmd/wrserver"] From e6661b28114e57463626c43df823de75790c61ed Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Tue, 15 Nov 2022 17:54:35 +0000 Subject: [PATCH 05/17] Adds go.sum and Dockerfile cache setup. --- Dockerfile | 2 +- go.sum | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 go.sum diff --git a/Dockerfile b/Dockerfile index 3f361b4..3a21af5 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.20 as build +FROM golang:1.19 as build WORKDIR /go/src/webrisk COPY . . diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..d971496 --- /dev/null +++ b/go.sum @@ -0,0 +1,18 @@ +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= +github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= +github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= +golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= +google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= From fd2225a85f006ceae658a328555c59d5241175b8 Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Tue, 15 Nov 2022 17:55:12 +0000 Subject: [PATCH 06/17] Update Dockerfile to include go.sum. --- Dockerfile | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 3a21af5..d7f5dd2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,9 +1,13 @@ FROM golang:1.19 as build WORKDIR /go/src/webrisk + +# cache go.mod to pre-download dependencies +COPY go.mod go.sum ./ +RUN go mod download && go mod verify + COPY . . -RUN go mod download RUN go vet -v RUN go test -v From 4576869846257198ec10d97620b9e9de18ef05d4 Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Tue, 15 Nov 2022 19:04:38 +0000 Subject: [PATCH 07/17] Updates github.com/golang/protobuf -> google.golang.org/protobuf --- generate.sh | 0 go.mod | 8 +++----- go.sum | 5 +---- 3 files changed, 4 insertions(+), 9 deletions(-) mode change 100644 => 100755 generate.sh diff --git a/generate.sh b/generate.sh old mode 100644 new mode 100755 diff --git a/go.mod b/go.mod index 0b78b40..301226c 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,10 @@ module github.com/google/webrisk go 1.20 require ( - github.com/golang/protobuf v1.5.2 + github.com/golang/protobuf v1.5.0 github.com/rakyll/statik v0.1.7 golang.org/x/net v0.2.0 + google.golang.org/protobuf v1.28.1 ) -require ( - golang.org/x/text v0.4.0 // indirect - google.golang.org/protobuf v1.28.1 // indirect -) +require golang.org/x/text v0.4.0 // indirect diff --git a/go.sum b/go.sum index d971496..d426f99 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,5 @@ +github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= @@ -12,7 +11,5 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= From 895f0077a41f373e67c7c6ca39d7922e6218aa82 Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Tue, 15 Nov 2022 19:40:43 +0000 Subject: [PATCH 08/17] Changes pass by value to pass by reference in newResp. --- database_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/database_test.go b/database_test.go index 4ae9361..83e3f09 100644 --- a/database_test.go +++ b/database_test.go @@ -4,7 +4,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// https://www.apache.org/licenses/LICENSE-2.0 +// https://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, @@ -29,8 +29,8 @@ import ( "testing" "time" - pb "github.com/google/webrisk/internal/webrisk_proto" pt "github.com/golang/protobuf/ptypes" + pb "github.com/google/webrisk/internal/webrisk_proto" ) func mustGetTempFile(t *testing.T) string { @@ -292,8 +292,8 @@ func TestDatabaseUpdate(t *testing.T) { ) // Helper function to aid in the construction on responses. - newResp := func(td ThreatType, rtype int, dels []int32, adds []string, state string, chksum string) pb.ComputeThreatListDiffResponse { - resp := pb.ComputeThreatListDiffResponse{ + newResp := func(td ThreatType, rtype int, dels []int32, adds []string, state string, chksum string) *pb.ComputeThreatListDiffResponse { + resp := &pb.ComputeThreatListDiffResponse{ ResponseType: pb.ComputeThreatListDiffResponse_ResponseType(rtype), NewVersionToken: []byte(state), Checksum: &pb.ComputeThreatListDiffResponse_Checksum{Sha256: mustDecodeHex(t, chksum)}, @@ -325,11 +325,11 @@ func TestDatabaseUpdate(t *testing.T) { mockNow := func() time.Time { return now } config.now = mockNow - var resp pb.ComputeThreatListDiffResponse + var resp *pb.ComputeThreatListDiffResponse var errResponse error mockAPI := &mockAPI{ listUpdate: func(context.Context, pb.ThreatType, []byte, []pb.CompressionType) (*pb.ComputeThreatListDiffResponse, error) { - return &resp, errResponse + return resp, errResponse }, } From 4677e1ec621cf12b8de4c5d73e8390ace8f42fbb Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Wed, 16 Nov 2022 18:42:47 +0000 Subject: [PATCH 09/17] Simplifies Dockerfile. Adds fallback ENV variables to wrserver. --- Dockerfile | 18 +++++++++++------- cmd/wrserver/main.go | 16 +++++++++------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/Dockerfile b/Dockerfile index d7f5dd2..d69047d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,18 +2,22 @@ FROM golang:1.19 as build WORKDIR /go/src/webrisk -# cache go.mod to pre-download dependencies +# Cache go.mod to pre-download dependencies COPY go.mod go.sum ./ RUN go mod download && go mod verify COPY . . -RUN go vet -v -RUN go test -v +# Uncomment the lines below to vet and test this container before building. +# RUN go vet -v +# RUN go test -v -RUN CGO_ENABLED=0 go build -o /go/bin/webrisk +RUN CGO_ENABLED=0 go build -o /go/bin/wrserver cmd/wrserver/main.go -FROM gcr.io/distroless/static-debian11 +FROM gcr.io/distroless/static-debian11 as wrserver -COPY --from=build /go/bin/webrisk / -CMD ["/cmd/wrserver"] +COPY --from=build /go/bin/wrserver / + +# The APIKEY Environmental Variable should be passed in at runtime. Example: +# docker run -e APIKEY=XXXXXXXXXXXXXXXXXXXXX -p 8080:8080 +ENTRYPOINT [ "/wrserver"] diff --git a/cmd/wrserver/main.go b/cmd/wrserver/main.go index 26e5254..191bc04 100644 --- a/cmd/wrserver/main.go +++ b/cmd/wrserver/main.go @@ -23,6 +23,7 @@ // Web Risk API over the internet. // // Usage of wrserver looks something like this: +// // _________________ // | | // | Web Risk | @@ -66,12 +67,12 @@ // // By default, the wrserver listens on localhost:8080 and serves the following // API endpoints: +// // /v4/threatMatches:find // /v4/threatLists // /status // /r // -// // Endpoint: /v4/threatMatches:find // // This is a lightweight implementation of the API v4 threatMatches endpoint. @@ -79,6 +80,7 @@ // for those URLs. Unlike the Web Risk API, it does not require an API key. // // Example usage: +// // # Send request to server: // $ curl \ // -H "Content-Type: application/json" \ @@ -116,7 +118,6 @@ // }] // } // -// // Endpoint: /v4/threatLists // // The endpoint returns a list of the threat lists that the wrserver is @@ -124,6 +125,7 @@ // API call may only be one of these types. // // Example usage: +// // # Send request to server: // $ curl -X GET localhost:8080/v4/threatLists // @@ -144,7 +146,6 @@ // }] // } // -// // Endpoint: /status // // The status endpoint allows a client to obtain some statistical information @@ -153,6 +154,7 @@ // were forwarded to the Web Risk API servers. // // Example usage: +// // $ curl localhost:8080/status // { // "Stats" : { @@ -164,7 +166,6 @@ // "Error" : "" // } // -// // Endpoint: /r // // The redirector endpoint allows a client to pass in a query URL. @@ -172,6 +173,7 @@ // If the URL is unsafe, then an interstitial warning page is shown instead. // // Example usage: +// // $ curl -i localhost:8080/r?url=http://google.com // HTTP/1.1 302 Found // Location: http://google.com @@ -201,9 +203,9 @@ import ( "github.com/google/webrisk" pb "github.com/google/webrisk/internal/webrisk_proto" - _ "github.com/google/webrisk/cmd/wrserver/statik" "github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/proto" + _ "github.com/google/webrisk/cmd/wrserver/statik" "github.com/rakyll/statik/fs" ) @@ -219,8 +221,8 @@ const ( ) var ( - apiKeyFlag = flag.String("apikey", "", "specify your Web Risk API key") - srvAddrFlag = flag.String("srvaddr", "localhost:8080", "TCP network address the HTTP server should use") + apiKeyFlag = flag.String("apikey", os.Getenv("APIKEY"), "specify your Web Risk API key") + srvAddrFlag = flag.String("srvaddr", "0.0.0.0:8080", "TCP network address the HTTP server should use") proxyFlag = flag.String("proxy", "", "proxy to use to connect to the HTTP server") databaseFlag = flag.String("db", "", "path to the Web Risk database.") ) From e07bc1bc5e8865381d90f7a1ce8bbced5eee5209 Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Wed, 25 Jan 2023 20:24:23 +0000 Subject: [PATCH 10/17] Internal change PiperOrigin-RevId: 504630686 --- Dockerfile | 11 +- LICENSE | 2 +- api.go | 29 +- api_test.go | 43 ++- cache.go | 12 +- cache_test.go | 10 +- cmd/wrlookup/main.go | 10 +- cmd/wrserver/main.go | 46 +-- cmd/wrserver/public/interstitial.js | 3 +- cmd/wrserver/statik/statik.go | 14 + database.go | 23 +- database_test.go | 11 +- generate.sh | 0 go.mod | 7 +- go.sum | 9 +- hash.go | 11 +- hash_test.go | 46 ++- internal/webrisk_proto/webrisk.pb.go | 459 ++++++++++++++------------- internal/webrisk_proto/webrisk.proto | 4 +- urls.go | 19 +- urls_test.go | 2 +- webrisk_client.go | 74 ++--- webrisk_client_system_test.go | 4 +- 23 files changed, 452 insertions(+), 397 deletions(-) mode change 100755 => 100644 generate.sh diff --git a/Dockerfile b/Dockerfile index d69047d..36c3a71 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,9 +8,10 @@ RUN go mod download && go mod verify COPY . . -# Uncomment the lines below to vet and test this container before building. -# RUN go vet -v -# RUN go test -v +# Analyze our Go code and run all tests. To speed up building, such as during +# development, consider commenting out these lines. +RUN go vet -v +RUN go test -v RUN CGO_ENABLED=0 go build -o /go/bin/wrserver cmd/wrserver/main.go @@ -19,5 +20,5 @@ FROM gcr.io/distroless/static-debian11 as wrserver COPY --from=build /go/bin/wrserver / # The APIKEY Environmental Variable should be passed in at runtime. Example: -# docker run -e APIKEY=XXXXXXXXXXXXXXXXXXXXX -p 8080:8080 -ENTRYPOINT [ "/wrserver"] +# docker run -e APIKEY=XXXXXXXXXXXXXXXXXXXXX -p 8080:8080 +ENTRYPOINT [ "/wrserver"] \ No newline at end of file diff --git a/LICENSE b/LICENSE index d645695..7a4a3ea 100644 --- a/LICENSE +++ b/LICENSE @@ -199,4 +199,4 @@ 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. + limitations under the License. \ No newline at end of file diff --git a/api.go b/api.go index e04193d..4c15ff3 100644 --- a/api.go +++ b/api.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,24 +22,24 @@ import ( "net/url" "strings" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" pb "github.com/google/webrisk/internal/webrisk_proto" - "github.com/golang/protobuf/proto" - "github.com/golang/protobuf/jsonpb" ) const ( - findHashPath = "v1/hashes:search" - fetchUpdatePath = "v1/threatLists:computeDiff" - threatTypeString = "threat_type" - versionTokenString = "version_token" + findHashPath = "v1/hashes:search" + fetchUpdatePath = "v1/threatLists:computeDiff" + threatTypeString = "threat_type" + versionTokenString = "version_token" supportedCompressionsString = "constraints.supported_compressions" - hashPrefixString = "hash_prefix" - threatTypesString = "threat_types" + hashPrefixString = "hash_prefix" + threatTypesString = "threat_types" ) // The api interface specifies wrappers around the Web Risk API. type api interface { - ListUpdate(ctx context.Context, threat_type pb.ThreatType, version_token []byte, + ListUpdate(ctx context.Context, threatType pb.ThreatType, versionToken []byte, compressionTypes []pb.CompressionType) (*pb.ComputeThreatListDiffResponse, error) HashLookup(ctx context.Context, hashPrefix []byte, threatTypes []pb.ThreatType) (*pb.SearchHashesResponse, error) @@ -67,11 +67,11 @@ func newNetAPI(root string, key string, proxy string) (*netAPI, error) { httpClient := &http.Client{} if proxy != "" { - proxyUrl, err := url.Parse(proxy) + proxyURL, err := url.Parse(proxy) if err != nil { return nil, err } - httpClient = &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyUrl)}} + httpClient = &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)}} } q := u.Query() @@ -84,6 +84,9 @@ func newNetAPI(root string, key string, proxy string) (*netAPI, error) { // response body payload as resp. func (a *netAPI) doRequest(ctx context.Context, urlString string, resp proto.Message) error { httpReq, err := http.NewRequest("GET", urlString, nil) + if err != nil { + return err + } httpReq.Header.Add("Content-Type", "application/json") httpReq.Header.Add("User-Agent", "Webrisk-Client/0.1.3") httpReq = httpReq.WithContext(ctx) @@ -99,7 +102,7 @@ func (a *netAPI) doRequest(ctx context.Context, urlString string, resp proto.Mes if err != nil { return err } - return jsonpb.UnmarshalString(string(body), resp) + return protojson.Unmarshal(body, resp) } // ListUpdate issues a ComputeThreatListDiff API call and returns the response. diff --git a/api_test.go b/api_test.go index c7fedf8..8450793 100644 --- a/api_test.go +++ b/api_test.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,9 +21,9 @@ import ( "reflect" "testing" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" pb "github.com/google/webrisk/internal/webrisk_proto" - "github.com/golang/protobuf/jsonpb" - "github.com/golang/protobuf/proto" ) type mockAPI struct { @@ -51,47 +51,46 @@ func TestNetAPI(t *testing.T) { var gotResp, wantResp proto.Message responseMisformatter := "" ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var p string + var p []byte var err error - marshaler := jsonpb.Marshaler{} for key, value := range r.URL.Query() { - if (key == "threat_type") { - if (len(value) == 0) { + if key == "threat_type" { + if len(value) == 0 { t.Fatalf("missing value for key: %v", key) } gotReqThreatType = pb.ThreatType(pb.ThreatType_value[value[0]]) - } else if (key == "constraints.supported_compressions") { - if (len(value) == 0) { + } else if key == "constraints.supported_compressions" { + if len(value) == 0 { t.Fatalf("missing value for key: %v", key) } for _, comp := range value { gotReqCompressionTypes = append(gotReqCompressionTypes, pb.CompressionType(pb.CompressionType_value[comp])) } - } else if (key == "hash_prefix") { - if (len(value) == 0) { + } else if key == "hash_prefix" { + if len(value) == 0 { t.Fatalf("missing value for key: %v", key) } gotReqHashPrefix, err = base64.StdEncoding.DecodeString(value[0]) - if (err != nil) { + if err != nil { t.Fatalf("unexpected hash prefix decoding error for: %v", value[0]) } - } else if (key == "threat_types") { - if (len(value) == 0) { + } else if key == "threat_types" { + if len(value) == 0 { t.Fatalf("missing value for key: %v", key) } for _, threat := range value { gotReqThreatTypes = append(gotReqThreatTypes, pb.ThreatType(pb.ThreatType_value[threat])) } - } else if (key != "key") { + } else if key != "key" { t.Fatalf("unexpected request param error for key: %v", key) } } - if p, err = marshaler.MarshalToString(wantResp); err != nil { - t.Fatalf("unexpected jsonpb MarshalToString error: %v", err) + if p, err = protojson.Marshal(wantResp); err != nil { + t.Fatalf("unexpected json MarshalToString error: %v", err) } - if _, err := w.Write([]byte(responseMisformatter + p)); err != nil { + if _, err := w.Write([]byte(responseMisformatter + string(p))); err != nil { t.Fatalf("unexpected ResponseWriter.Write error: %v", err) } })) @@ -113,8 +112,8 @@ func TestNetAPI(t *testing.T) { RawIndices: &pb.RawIndices{Indices: []int32{1, 2, 3}}, }, } - resp1, err := api.ListUpdate(context.Background(), wantReqThreatType, []byte {}, - wantReqCompressionTypes) + resp1, err := api.ListUpdate(context.Background(), wantReqThreatType, []byte{}, + wantReqCompressionTypes) gotResp = resp1 if err != nil { t.Errorf("unexpected ListUpdate error: %v", err) @@ -127,7 +126,7 @@ func TestNetAPI(t *testing.T) { t.Errorf("mismatching ListUpdate requests for compression types:\ngot %+v\nwant %+v", gotReqCompressionTypes, wantReqCompressionTypes) } - if !reflect.DeepEqual(gotResp, wantResp) { + if !proto.Equal(gotResp, wantResp) { t.Errorf("mismatching ListUpdate responses:\ngot %+v\nwant %+v", gotResp, wantResp) } @@ -151,7 +150,7 @@ func TestNetAPI(t *testing.T) { t.Errorf("mismatching HashLookup requests for threat types:\ngot %+v\nwant %+v", gotReqThreatTypes, wantReqThreatTypes) } - if !reflect.DeepEqual(gotResp, wantResp) { + if !proto.Equal(gotResp, wantResp) { t.Errorf("mismatching HashLookup responses:\ngot %+v\nwant %+v", gotResp, wantResp) } diff --git a/cache.go b/cache.go index 3c4cca5..acf3a0b 100644 --- a/cache.go +++ b/cache.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,12 +14,10 @@ package webrisk import ( - "fmt" "sync" "time" pb "github.com/google/webrisk/internal/webrisk_proto" - pt "github.com/golang/protobuf/ptypes" ) type cacheResult int @@ -85,17 +83,13 @@ func (c *cache) Update(req *pb.SearchHashesRequest, resp *pb.SearchHashesRespons c.pttls[fullHash] = make(map[ThreatType]time.Time) } for _, tt := range threat.ThreatTypes { - var err error - c.pttls[fullHash][ThreatType(tt)], err = pt.Timestamp(threat.ExpireTime) - if err != nil { - return fmt.Errorf("pt.Timestamp: %v", err) - } + c.pttls[fullHash][ThreatType(tt)] = threat.ExpireTime.AsTime() } } // Insert negative TTLs for partial hashes. if resp.GetNegativeExpireTime() != nil { - nttl, _ := pt.Timestamp(resp.GetNegativeExpireTime()) + nttl := resp.GetNegativeExpireTime().AsTime() partialHash := hashPrefix(req.HashPrefix) c.nttls[partialHash] = nttl } diff --git a/cache_test.go b/cache_test.go index 5aea45c..5fa13a4 100644 --- a/cache_test.go +++ b/cache_test.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,8 +18,9 @@ import ( "testing" "time" + timepb "google.golang.org/protobuf/types/known/timestamppb" + pb "github.com/google/webrisk/internal/webrisk_proto" - pt "github.com/golang/protobuf/ptypes" ) func TestCacheLookup(t *testing.T) { @@ -164,8 +165,9 @@ func TestCacheLookup(t *testing.T) { func TestCacheUpdate(t *testing.T) { now := time.Unix(1451436338, 951473000) mockNow := func() time.Time { return now } - ts, _ := pt.TimestampProto(now.Add(1000 * time.Second)) - tft, _ := pt.Timestamp(ts) + + ts := timepb.New(now.Add(1000 * time.Second)) + tft := ts.AsTime() vectors := []struct { req *pb.SearchHashesRequest diff --git a/cmd/wrlookup/main.go b/cmd/wrlookup/main.go index b2c0eb5..92e7fe4 100644 --- a/cmd/wrlookup/main.go +++ b/cmd/wrlookup/main.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,7 +11,6 @@ // 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. - // Command wrlookup is a tool for looking up URLs via the command-line. // // The tool reads one URL per line from STDIN and checks every URL against @@ -19,9 +18,11 @@ // If an error occurred, debug information may be printed to STDERR. // // To build the tool: +// // $ go get github.com/google/webrisk/cmd/wrlookup // // Example usage: +// // $ wrlookup -apikey $APIKEY // https://google.com // Safe URL: https://google.com @@ -33,8 +34,9 @@ import ( "bufio" "flag" "fmt" - "github.com/google/webrisk" "os" + + "github.com/google/webrisk" ) var ( @@ -77,7 +79,7 @@ func main() { fmt.Fprintln(os.Stderr, "No -apikey specified") os.Exit(codeInvalid) } - sb, err := webrisk.NewWebriskClient(webrisk.Config{ + sb, err := webrisk.NewUpdateClient(webrisk.Config{ APIKey: *apiKeyFlag, DBPath: *databaseFlag, Logger: os.Stderr, diff --git a/cmd/wrserver/main.go b/cmd/wrserver/main.go index 191bc04..55f5ba6 100644 --- a/cmd/wrserver/main.go +++ b/cmd/wrserver/main.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,7 +11,6 @@ // 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. - // Command wrserver is an application for serving URL lookups via a simple API. // // In order to abstract away the complexities of the Web Risk API v4, the @@ -189,7 +188,6 @@ package main import ( - "bytes" "encoding/json" "errors" "flag" @@ -200,13 +198,12 @@ import ( "net/url" "os" - "github.com/google/webrisk" - pb "github.com/google/webrisk/internal/webrisk_proto" - - "github.com/golang/protobuf/jsonpb" - "github.com/golang/protobuf/proto" - _ "github.com/google/webrisk/cmd/wrserver/statik" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" "github.com/rakyll/statik/fs" + _ "github.com/google/webrisk/cmd/wrserver/statik" + pb "github.com/google/webrisk/internal/webrisk_proto" + "github.com/google/webrisk" ) const ( @@ -228,9 +225,10 @@ var ( ) var threatTemplate = map[webrisk.ThreatType]string{ - webrisk.ThreatTypeMalware: "/malware.tmpl", - webrisk.ThreatTypeUnwantedSoftware: "/unwanted.tmpl", - webrisk.ThreatTypeSocialEngineering: "/social_engineering.tmpl", + webrisk.ThreatTypeMalware: "/malware.tmpl", + webrisk.ThreatTypeUnwantedSoftware: "/unwanted.tmpl", + webrisk.ThreatTypeSocialEngineering: "/social_engineering.tmpl", + webrisk.ThreatTypeSocialEngineeringExtended: "/social_engineering.tmpl", } const usage = `wrserver: starts a Web Risk API proxy server. @@ -265,7 +263,11 @@ func unmarshal(req *http.Request, pbReq proto.Message) (string, error) { switch req.Header.Get("Content-Type") { case mimeJSON: - if err := jsonpb.Unmarshal(req.Body, pbReq); err != nil { + body, err := ioutil.ReadAll(req.Body) + if err != nil { + return mime, err + } + if err := protojson.Unmarshal(body, pbReq); err != nil { return mime, err } case mimeProto: @@ -293,12 +295,11 @@ func marshal(resp http.ResponseWriter, pbResp proto.Message, mime string) error return err } case mimeJSON: - var m jsonpb.Marshaler - var b bytes.Buffer - if err := m.Marshal(&b, pbResp); err != nil { + b, err := protojson.Marshal(pbResp) + if err != nil { return err } - if _, err := resp.Write(b.Bytes()); err != nil { + if _, err := resp.Write(b); err != nil { return err } default: @@ -308,7 +309,7 @@ func marshal(resp http.ResponseWriter, pbResp proto.Message, mime string) error } // serveStatus writes a simple JSON with server status information to resp. -func serveStatus(resp http.ResponseWriter, req *http.Request, sb *webrisk.WebriskClient) { +func serveStatus(resp http.ResponseWriter, req *http.Request, sb *webrisk.UpdateClient) { stats, sbErr := sb.Status() errStr := "" if sbErr != nil { @@ -330,7 +331,7 @@ func serveStatus(resp http.ResponseWriter, req *http.Request, sb *webrisk.Webris // API endpoint. This allows clients to look up whether a given URL is safe. // Unlike the official API, it does not require an API key. // It supports both JSON and ProtoBuf. -func serveLookups(resp http.ResponseWriter, req *http.Request, sb *webrisk.WebriskClient) { +func serveLookups(resp http.ResponseWriter, req *http.Request, sb *webrisk.UpdateClient) { if req.Method != "POST" { http.Error(resp, "invalid method", http.StatusBadRequest) return @@ -400,7 +401,7 @@ func parseTemplates(fs http.FileSystem, t *template.Template, paths ...string) ( // serveRedirector implements a basic HTTP redirector that will filter out // redirect URLs that are unsafe according to the Web Risk API. -func serveRedirector(resp http.ResponseWriter, req *http.Request, sb *webrisk.WebriskClient, fs http.FileSystem) { +func serveRedirector(resp http.ResponseWriter, req *http.Request, sb *webrisk.UpdateClient, fs http.FileSystem) { rawURL := req.URL.Query().Get("url") if rawURL == "" || req.URL.Path != "/r" { http.NotFound(resp, req) @@ -429,7 +430,7 @@ func serveRedirector(resp http.ResponseWriter, req *http.Request, sb *webrisk.We http.Error(resp, err.Error(), http.StatusInternalServerError) return } - err = t.Execute(resp, map[string]interface{}{ + err = t.Execute(resp, map[string]any{ "Threat": threat, "Url": parsedURL}) if err != nil { @@ -438,7 +439,6 @@ func serveRedirector(resp http.ResponseWriter, req *http.Request, sb *webrisk.We return } } - http.Error(resp, err.Error(), http.StatusInternalServerError) } func main() { @@ -457,7 +457,7 @@ func main() { DBPath: *databaseFlag, Logger: os.Stderr, } - sb, err := webrisk.NewWebriskClient(conf) + sb, err := webrisk.NewUpdateClient(conf) if err != nil { fmt.Fprintln(os.Stderr, "Unable to initialize Web Risk client: ", err) os.Exit(1) diff --git a/cmd/wrserver/public/interstitial.js b/cmd/wrserver/public/interstitial.js index 77612f9..ea60b4a 100644 --- a/cmd/wrserver/public/interstitial.js +++ b/cmd/wrserver/public/interstitial.js @@ -1,4 +1,5 @@ -/** Copyright 2019 Google LLC +/** + Copyright 2023 Google LLC * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/cmd/wrserver/statik/statik.go b/cmd/wrserver/statik/statik.go index aeeb2bd..8f229fa 100644 --- a/cmd/wrserver/statik/statik.go +++ b/cmd/wrserver/statik/statik.go @@ -1,3 +1,16 @@ +// Copyright 2023 Google LLC +// +// 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 +// +// https://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. // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +34,7 @@ import ( "github.com/rakyll/statik/fs" ) + func init() { data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x0b\x8dmN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00 \x00interstitial.cssUT\x05\x00\x01\x87@\x89\\\xbcXm\x8f\xdb\xb8\x11\xfe\xee_1@p\xcd&\xb0\xbc\x92\xfc\xb2^-p\xe85wh\x0b\\\x83\xe2\xae\xed\xd7\x82\x96\xc66\x1b\x8a\x14(\xcak\xe7\xb0\xff\xbd\xa0(\xc9\xa4D\xd9JQ\xdc\x97dM\x91\xc3yyf\x9e\x19>~\x84O\xa2\xb8Hz8*\x88\xc3h\x05\xff8\"|:J\x91\xd3*\x87\x1f*u\x14\xb2\\\xc0\x0f\x8cA\xbd\xa9\x04\x89%\xca\x13f\x8b\x19\x00\xfc\xb3D\x10{PGZB)*\x99\"\xa4\"C\xa0%\x1c\xc4 %\xc7\x0cv\x17 \xf0\xa7_\x7f\x0cJua\x08\x8c\xa6\xc8K\x04u$\nR\xc2a\x87Z\xd2^T<\x03\xcaA\x1d\x11~\xfe\xeb\xa7\x9f>\xff\xfa\x13\xec)\xc3\x05||\x9c\xcd\x08\xfc6\x03H\x05\x132\x01y\xd8=\xac\x9e\xe7\xb0^\xcda\xbd\xf9\xf02{\x9b\xcdv\"\xbb\xd4{v$\xfdr\x90ZZ\xd0l\x7f=R\x85/7\x8e\xeb\xdb\xb9\n\xf6$\xa7\xec\x92\xc0\xfb\xbf ;\xa1\xa2)\x81\xcfX\xe1\xfb9\xbc\xff\xb9JiF\xe0\xcf\x92\xf0L/\x94\x84\x97A\x89\x92\xee\xbb\xd3%\xfd\x8a <\xad\xbf3\xeaTJ >\xa2\x90<\xec\xc8\xc3\xf2i\x0eO\x9b9G\x92\x89W\x88\xc30/!\xadv4\x0dv\xf8\x95\xa2|\x08\x17\xab9\x84s\x08\x17qkcU\xa2\x0cJd\x98\xaa\x04\xb8\xe0u\\\x82\\|\x0dF\xbe\x94#\x1f^q\xf7\x85*\xdf\xc7\xce\xfb I\x15=\xe1\xb7\x05AT\x8aQ\x8e\xb5\x07\xae\x92\x8e\x1a\xccFPgq\x02\xa1\x0e\x0b,\x8b\xb3\x11\x16\x1ac\xe7\xb0X\x1aL\xbe\xcbP\x11\xca\xca\x9b\xd8\xbd\xfa|\xb5.\xce\x10\xc2:\xd4~\xb6\x8f\x17 \x17\xea!\xd9SY\xaa@\xec\x03u)\xf0C-\xd4\x1c\x0d\x94(\x12\x88\xfb\xe7\x02/\x08\x13\xa0\xfc\x88\x92\xaa\x01\xe4n\xa4\x87\x81N\xeb\xfc\x1b \xa9\x97\x14\x9eU\x90a*$10\xa9x\x86R\xbb\xb5\xfbZ\x83h/d\x9e@U\x14(SR\xa2O\xf9\x11\xcf[&\xdc\xba\xecm6;F}\xef\xc7\xe1j\x0e\xcb\xcd\x1c\xa2\xf0C/\x0f\xa2\xc5\xc6\xa4A\xbd\xf6\x8a:U\xb4\xd92'L/k\xa9\xc1\xb1Y\x8e\x16\xb1\x934\xc1N(%\xf2\x04\xa2M\x13\x88c\xfcMw\xc77\xee~\x9b\xcd\x16G\x9aeh\xc2\x99\xd1\xb2`\xe4bA\xfe\xa8rV\x7f\xb2E\xc6\xba\x1a5.\xd2K\x01\xc9\xfeS\x95Z\xf70\xfc\xaeM<\xff\xd76\xfbn|mRpl\x87V\x99\xa6\xc3\"Hsr\xc0\x04*\xc9\x1e\x1e\x8bj\xc7h\xfa\xf8J$\xa7\xfc\xf0o%)\xe1\x07\x86\x8b\xf2t0%\xf1zLb\x81\x06\x84\xcd\x9f\xbd\xef\x8d\xc9\x8drm\x90\x9e\x9a\xc2\xd9A\x16BX\x85f\xed\x95f\xea\xd8n\xa9\xb5\xd5\xa5\xb2TTQ\xc2\x82WI40\xaf\xd0\xf3\x96]\xdb\xdb&|=\x8cl\xdc\xba\x1a\x85:KH\xa5\x84I\x95\x9c\x9c\x83F\x8fM\xe8\xea\xd5y\xf1\x1d\x13\x07Q\xeb\xd1\x8a]mm\xab:\xe0-\xcd\xea \xa5&/\x16\x10F\x0f<\x81\x9cf\x19C[\xf2\xd3\xba-\x15Zt\xb0c\"\xfd\xd2\x87j\xb4Y\xce\xa1\xfd\xa7\x0f\xd6\xc5\xb31\xabI~S\x80\xd6\x8d\xfe5 \x9a\xbbS4\xf4\xa3\xef\xca \xe5A\x8eeI\x0e\x08\xdfC\xe1\"\x99\xf2.g\x17\x9c\x9c\x1c\xff\xdben\x1d\xb5\xe1\xb2v% \xd9\xabfs\xca\x90H\x1d'u4U\x8d+\xe4*\x81\xf7\xef_\xec\xfb\x14\xd9\xb9N\xe9@[\xe6\x84\xb1\x80Q>\xf0\x89\xafkp\x19\xf4m6\xfbc\x8e\x19%\xf0`\x85\xf6I\x87\xd6T\xecq\x90Y\xa54\x84\xc8\xc0\xf8mD\xe0*\xee\x04\x9a:9\xd7\xa2{\x8a\x0f\xeavO\xe3\xb6|\xf5J\xce*\x0c\xcd\xaaS\xe6o\xd6m\xfd\xd9q\xa3\xd6|\x06\xe0\x10\xe0U`\\3E\xf3\xdfp\xf38\xdd\xb9H\x88\x1a\xbc9\xa7m\xd2\xb3\xa2]C\xfce \"nD\xf8A;f\xd6\xc4\x18\xae-G\xf4\xf2lP\xc1[\xc9}\xe4\xbb\xea.;\x8b\xdff\xb3\xc7\x8f\x1fg\xf0\x11\xfe&v\x94!\x94\x05\xa6tOS\xd0]6\xe5\x879\xec\x85\xd4\xa9_\x87;\x832\x95\x88\xbc\x84?\x00#\xf2\x80r\xa1\xcf~&'z\xa8i\xb3\x81Q D\"\x10\x9e\x1e\x85\xc4\x0c\x94\xa8\xdbqS_L\xa3\x8f\x8d\xa4\xfa\xfc\x8fM\xc4\xda\xa4\x96X0\x92bY\xefS\xa2h\x93O\xf7\xf5T\x95 ^\xb9>.\x18\xd3\xc9\xa7\xef\"Z\xce\xe3-\x8c\x13\x9e\x99\xe5\xae\xa4/7\xdd\xba\x90\x14\xb9j\x88\xbf\x10RIB\x95\xc1\x8a\x1f\x10N\xc3sE\xe4\xb6\x06\xe4\x15\x8b\x8b\x12S\xc13\"/\xee\xf1\x96\xf3\x9a\xa0\xa0n\xa7\xc2!\xacL\x07\xd0O_\xca[\xd3\xe2\x95k\xda\xc0\xe2Z\"\x809\xd4U\xfd0\xfa&\x87t\xfe\x98;\xe2\xba\xcb\"\x9f\x0e\xb60\xfb\xf2\xab\xcaWa\x96\x0ev\xb0l\x1d\x18\xe1Y\x99\x926\x81\xeb)\xcd\x03r\xbb=\xed\xc65\x80\x96\xd8\xc2\xf6\xa7\xdd{\x07\xb1\xee\xbe\xb5Z\xf6\x11\x86{5\x08o\xf7\xd35\xf3\xc5\xce\xd8\xc0\x9cl\xa7\x9c\xeb\xbal\x1d\xd0}\x10\xed\xf8\xb3\xa7g\xcc\xcc\xe2\xd7\x80\xf2\x0c\xcf D\x93\xca\x84O\x15\xa7\x8e\xe9\x98\x19\xc6ls\xc8\xa9/\x1d\xe7\xafB\x1f\xd4\xfe\x1fY4w\x02\xed\x83\xc7\x84\xf8\x83\x0f\x00.\x1b\x84u;\xd49\xe0\xcag\xe6/\x0f\xab\xd9\xc3\xfa/b'\x94\x08~\xc1C\xc5\x88\x9cw\xa3\xfb\x90\xef\x9e\x97K/\xdfm\xfa|\xb7ii\xe9\x0e\xe7\x8dU\xec\xf1nq\x18\xbem\x0b\xaa \xf4yKn\x1b\x87\xd6\x95\x03\xec\x8b\x82\xa4T]\x1a|\xbaS|\xf3\x0d\xe2\xf5\x94\x11\xdeQ\xad\x19J\x06h\xb5\x87\x15?\x0d\xb7\x1a\xf7\xf5k\x7f\x9fP\xee\x99\xcet#i\xa8\xb5C\x9c\xfej\xdf\xf7v4H\xfa^\xb9\xd6=vd\xc3\xac\x9d\xcd\xbaV\xa9\xd7ro\xad\x93\xd7ig8\x12\xc6\xce\xbe\xf1\xbap+\xc6]\xfb\xb4jG\x88V\xac\xd3v\xf8\n\x95DF\x14=\xe1\x1d\x1d\x8a\xa1\xe9\x8b\xe7\xce\xf4\xfed\x13\xf5|R\xfb\xd2v\x88\xaf~\xf5\x9bJ\x0f\x0c\xa3I/I\x0dO\xf7\x8b\x83C\xf0\xcd\x9e\xeap\xc0RaV\x97x\xf8\x1e\xdei\x95\xa4`\x0dX\xca\xb9\xbb\xcb\xbc\x86\x0e\xb7\x8d5\xd5\x8eI\x03\xca\xbf\xb2\xb7\xbfB\xba]\xcbm\xcep1\xb5Z\x8ft\x19\x1dg??O\xb9rX\xc1\xc6\xf2\xe6\x86q\xeb;,S\xcb\xed\x91\xc9\x18i\xf4]2\x9aV-\xd4\xef\xa6\x95\x8d\xd0\xcd\xea\x9e1\xdb\xc9\xdd\xd9\xffJ\xa8\xd6m\xcb\xe5\xf6.\xa3z \xb8\x93v\x8bo';\xef>\x08\xe2{~[\x87~\xbfE\xab)\xfd\xfa\xd4\xf0=o\x9c\x19\x08\xfe~\xd4\xb3\x84\x02S5\xf50\xe1i\xb8\x97OkoW\xbbY\xddk\xa9\xbd\xb8\x9df\xd1\xcd\xc9|\xf0n\xe4\xc9\xba~uo\xd8\xca\xe6\x12\xddO\xd5\xe3\xf2B\xec\xf7\xba@\x7fpB\xde\xda\xb3\x0d{}\xc6\xf6\xfe\xec\xec\xcc\xc9\xdb\xbb\x0c\xf9d\xcc\xb8\xc7\x84\xf1vb\xcav\x8c6\xe1\x84\x87\xb7\xa2E\xb8\xb65\x1a\xc5\xb7}\x81\x7fZ\x9b\x9e\x89\xfe\x81\xc9\x85V\xfc\xbc\xbd\x95\xc0\x9e~yB|\xd7\xfd\xf8\xae\xc3\x91\xc6\xc4\x81R8)\x12\xfe\xc9\xf6\x8eSM\x1f\x02\xbf\xabk=\x15\xfa\x86ko\xa1\xfe\x1b]\xd3\x82\xfb)\xbc\xed\x1d\xdb\x93\xd6\xc3\x17\x9e\x15\xf2\x0c\xeb7n!\x95\x0e\x8f(T@}\x99\x18\xfaj_g\xd9H\xf9\xdblG\x1cf\n\xd9\xb4\xf2k5\x9e\xf7m4H\xb1\x1e\xba\x07\xf3\xa9/\x98#L\xe6N\xa2>\x9a\xbeK\xb8v\xf1~\xf6\xfab\x19/[_LM\xbaM?\xe96\x13\xa7\x81\x1e\x85\xfd\x0b\xe5\x05j\x8a\x80\xbcy\xcd3\xafu\x0b\xf8,\xcc#\x03prZ8\xd1\xb5=1\xd2Z\x8ey\xa2s\xfd\xd2\xdf\x1f\x8e\xba\xfe\x9e\x0bM\xbfy\x0fN\xdd4\xb8g\xd88P\xff\x15dTbj\x14H\x05\xab\xf2f\xe6\xeb9\xcf\xf3`\xfc['#\x81\x08\"k\x08\x1e\x0c\x03\xbe\x91d\xd2A\x0f\xd2\xcd\xb9\xd09\xe7\x19\x85:a\xcd\xe4\xed\xbe7\x85\xee\xa2t\x86b\xff\x00\xe7y,\xf0\xbf\xfd\x8c\xc6w\xf2\x00pWG}\xf5\x7f\x03\x00\x00\xff\xffPK\x07\x08{\xdc\x9d\xdbg\x08\x00\x00E\"\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00J\x94mN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00 \x00interstitial.htmlUT\x05\x00\x01,M\x89\\t\x93\xc1\x92\xdb \x0c\x86\xefy\nU\xe7z=\xb9\xf5\x00>t\xfa\x06}\x02\x02J\xac.`\x06\x94d<;\xfb\xee\x1dC\xe28\x99]_,K\xbf> Y\xa8\x1fn\xb22'\x82Q\x82\x1fvjy\x81\xe3\xac\xd1KF\xf0&\x9e4R\xc4%D\xc6\x0d;\x00\x15H\x0c\xd8\xd1\xe4B\xa2\xf1,\xc7\xee\x17>\x02\xd1\x04\xd2xa\xba\xa6)\x0b\xee\xa0>v\x8aBQ4rda\xe3\xbbb\x8d'\xbd\xff \x81#\x87sx8\xae\xecd\xd4\x8e.l\xa9\xab\x1f\x8d.,\x9e\x86\xbfd\xcf\x99e\x06\xcay\xca\xaao\xde%\xee9\xbeC&\xaf\xb1\xc8\xec\xa9\x8cD\x820f:j\xec\xd3\xf9\xe0\xd9\xf6\x1c\x85r\x91\xda\xc2\x9b-\xa5\x91\x8b\xcd\x9c\x04J\xb6\xdf(\xff\x15\x1cT\xdfd\xc3N\xf5m\x14\xea0\xb9\x19\xd8i\\\x8c\x86r|\x01\xebM)\xcbI\x1f\x84\xee\x9aMJ\x94\xab\xe8&[\x12\x83\xe1\xd8\xddfs\x8b\xbd@\xec\x14\xb1J\xab5\xa8\xde\xf1\xe5I\xb8b\x02\x95bN\xb4b\x00\xd4\xb8\x1f>>\x84B\xf2F\x08pi\x9b\xe3 \xe1\xed\xf3S\xf5\xe3~\xa3LO\xc2;\xaa \xd3Z\xefQ|kn\xda\x8d\xe6\xf2rT\x00u8\x8bL\xb16\x9a2\x07\x93\xe7\xae\xb9p\xf8m\xec;\xc8\x04\xc5\x1cIf\xd57\xffW\x99\x8e\xc4\xb0/\xf7\xcc{\xc1\x12\x8c\xf7\xdd\xf2\xebq\xf8\xd3$\xcf\x94\xd7F7\xac\x152\xb2su\xc7\xbf\x1c\xc6\xaa\xde\x0ec\xc5\xde\x0c\xd5/;Pw\xa3^\xa4\xff\x01\x00\x00\xff\xffPK\x07\x08\xe9\x02\xe6\xcb\x89\x01\x00\x00Y\x03\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x0b\x8dmN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00 \x00interstitial.jsUT\x05\x00\x01\x87@\x89\\\x94UmO#G\x13\xfc\xbe\xbf\xa2\x8e\xe7\xa4\xb5y`\xcd\x11\x94HXV\xc2\xdb $\xe0\x94\xc0)\x1f\xa3\xf1N\xdb;bvf3\xd3k\xf0q\xfe\xef\xd1\xcc\xdaf\xfdF.\xdf`\xdc]\xdd]\xd5]\xdb\xeb\xe1\xc2VS\xa7\xc6\x05\xe3\xf8\xe8\xd3 \x1e\x0b\xc2E\xe1l\xa9\xea\x12g5\x17\xd6\xf9\x0cgZ#\x06y8\xf2\xe4&$\xb3\xa4\xd7\xc3WO\xb0#p\xa1<\xbc\xad]N\xc8\xad$(\x8f\xb1\x9d\x903$1\x9cB\xe0\xfc\xe1\xf2\xd0\xf3T\x13\xb4\xca\xc9x\x02\x17\x82\x91\x0b\x83!\x05\xa4\x91\xad\x8d\x842\xe0\x82p{squ\xffp\x85\x91\xd2\x94%Io\x7f?\xc1>\xce\xb4\x12\x1e#\xeb m^\x97d8\x1b\x13_i\n\x7f\x9eOod\x86\xcf\x11\x85\x9a'\x8f\xb2\xf6\x8c!\xe1\xfa\xf1\xeev\x1e\xe7\xb3\x00\xf5[%\x9c(\xf1\xea\xd9)3\x9eA\xc98\xf8\xcde3\x0d- \xc0\x16#ed\x93\xe4\x88kg\xf0\xda\x82\x9b\xc5\xbcQ\xbb,\xac\x83\xa9\xb5\x86\x1a\xc1Xn~\x0c\x00\xbddT\x9b\x9c\x955\xf8\xd8Q\xb2\x8b\xd7\x04\x98\x08\x07\xd2\x18\xec\x9a)\x04\xf6\x13`^\x9bt?\x99EFp/J\xf2\x95\xc8)\x0b\xd0\x01G\x19&\xe7Y\xb1\x12\x01q\xe5\xdf\xef\xdf\xf1:\xeb'K2\xff,\x88\x0brq\xd8J\x8c\xa3dy\xed\x1c\x19\xd6S\x0cI\x991&\x8a\x9eIB0\x04\xf6J;T\x9a\xf6\xe0sGd\xe0\xd57jX\xe1iEx\x1dZ\xabI\x98Y\xc3\xaeS\x13\xc1\x14gnw\x915 \xf7b\xf2\x17\x06\x18 \xed\xa9\xd5\xd2\x031\xea\n4 $\x16\xc2HM\xae\xd1\xfb\xeb\xcdR\xd3l\x13\xd4\x13\xd7\xd5\xd5$*>\xc0\x82\xe3N\xc3o\xaf\x17\x15\xda\x1b\x8a\xfc)\xa8\xe9\xc5\x88x\xba\x87a\xcdlM\x96\x00\x1f;i\xe5T)\xdc\xf4\xb0yL\xbb\x99\x902\x02\xde*\xcfd\xc8u\xd2\\\xab\xfc)=X\x87\x07\x9e\x95\x91\xf69+\x94g\xeb\xa6Y\xa8\xd3\x89\x8a\xcd\xba\xfd\xa4\xd5\xc0%\xb1P\xda\xafU\x96\xcd\xeb\x7f\xaa\x1c Z\x94\x0f\xba\x17JJ2\xf3\x02\x18\xb4p\xd3n\x96k\xe1}@\xcb\xd8\x8e\xc7\x9a:i\x13\x9e6\xed!\xacig\x87H\xdd\x18\x10\x1b-\x852\x87\xb95L\x86\xdfC=\xc0\x87\x95v\"\x15\x00iO?\x00\xe6\xa8\xb4\x93\xcd\x16\xb7\x11\xa5\x8c!\xf7H/\x8c\xc1\x1a\x01\xbf\"\x9d\xff\x99\xe2\x14\xe9\xb5\x92\x84\x05\x1f\xab\xc2\\\xc7%\x0b\x96\xa6\xbeQ\xb3xa\xc1\x16\x9anj\xd1D\xa6\x07+\xb7\x95Y\xf3G|\x8f\xb3n\xfd%lD\xfb\xfa>[\x07_\n\xad\x17\xe7\xd4p~\x10\xcf\xd1\x88\x89\x1a\x8b\xe8\x13\xcd\xb4\x1e\xc2\x11\x023\x12C\xd2\xf69\x86 9\x11&'\x19\xf0\x98^x\xcbe,\xcao\x9eE\\\x1b\xd2\xd5\x97\x9a\xc9\x9d\xdb\x97\xb6\x01\xfd]\x93\x9b>\x90\xa6\x9c\xad\xeb\xa4\xff[\xeeR\x7f\x9e\x18\xe4\xbbh\xd4{/oU\xe5e2I%~\x0f\xa1\x18 \xed\x94\xca\x1c>+\xc9\xc5)\x8eO\x8e\xaa\x97.\x84\x91\xe8\x94\xe2e\xf1|r\xbc|N\xf1\xff\xf9\x12\xa51\xa2\xa0\xf0M:\xc5/?\xfd\xfc\x96\xa9\xcc\xf2\xfd\xe4\xe8\xd3\xb6T\xeb\x14\x19\x8e\x0c\x9f\xa2\xb2\x8e\x9dP\xdc=X\xa9\xda\x82\xdcU\xb5\xd5\xd8J\xd5\xd6\x1c+\xa9o\x93\x9e\x1c/\xfbZmF\x0b#}.*\xea\xa6qG\x03as\xfa\xaf\xe3\x8e\x87eo\xc9\xd6:\x9d@\xb4P\xc6\xaf\x1dO\xf8\xc2\x17\x94?E\x1f\xcd\x0ba\x82\xd5\x9b\xb0c\xf0,\xb8\x8e\xfb\xfe\x8e\x05\xe0\xc3`q\x0e\xa5\xe0\xbc\xb8\x0b\xf2u\xdeD\xec6\xcf\xe4\x17\x86\xb4\xdb\xef?\xec\xf8\xe9\x07|h\x8e\x8d\xf6\xea\xbd\xebA+\xa4\xcd=\x08\xbb\xa8\xdbH\xdf\x96=\x8b\x1e\x16\xbb\\C\xff\x97\xe66=\xed\xddf\xb6\x87\xcf\x82o5\x16\xb2\xbc\xb7M{\xba\xfcr7\xaf\x7fk\x85$\xb9nT\xad/e\xb7\x9f\xfc\x13\x00\x00\xff\xffPK\x07\x08fg\xf4\x1a\xe6\x03\x00\x00\xfd \x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x8b\x8emN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00 \x00malware.tmplUT\x05\x00\x01WC\x89\\d\x91Ao\xd5@\x0c\x84\xef\xfc\n+\\@z$w\xd4W\xc4 \xce@\xc5\xd9\xddu\xb2\xab\xee\xda+\xdbQ\xfa\x14\xed\x7fGi(\x1cz\xb5\xec\xf1\xcc7\xfb\x1ei\xceL0$\xc2\x98y\x19z\xff\x95\x08,;\x01\x1e3\x08\xc2\x8e\x99\x0d*\x96\x0d\x95\xf6\x9d8\xf6\xfe\xee\xffi%3\\h\xe8\xfd\xab;\x86'R\x83\xb0\xaa\x12{\xb9\x810\xec\xfb\xf8\xa0e\xfc.\xe6\xbdC\xcdKr@w\xaa\xcd\xc1\x052\x9bc)\x10\x91\x17RY\x0d\x9a\xca\xa2X\xed8\xbe\xc9\xaa\x10\xa4\xb6\xd5I\xc1\x13:\x98\x13\x16\x10\x85H\x85\x9c\xce\x95\xcc\xb3hE\xcf\xc2\xf0a\x16\x05z\xc6\xda\n]\xa0%q\xb1\x0b44\xdbD\xa3]\xe0\xafe\xbb\x00r\x84\xa0\x14\xb3C@\x8d\xf6q|\x1b0\x92c.6\xf4\xfeMd)\x04\xbf\xe9\x11~d{\x02\xa5p\xa6\xbcCHJ\xf3uH\xee\xcd>O\xd3\xb6m\xe3\xf2\xb2=\x06\xa9\x93+\xb25T\xe2pSj\xa2>\x19\xce\xf4\xa8\xb2Y\xe6e\x8a\x19\x17\x16\xf3\x1c\xa6\xcc\x91\x9e\xc7\xe4\xb5|I\xe5J\xfc\xe9\xe1\xe7\xfbU\xcb\xf5\xa4\xd8\xfbp\x1f\xc9)8\xc5\xd7J\xee&\xbc\x7f\xc3y<\\\x1e=\xda \x0d\x95\x80\x0fB\xa5\xdc\xe0\xf8\xfd21\xa9\xe4\xb9\x92\x1d\xfcN\xd1-{zU\xfe\x07\xe3O\x00\x00\x00\xff\xffPK\x07\x08\xe5\xab\x14\xc9X\x01\x00\x00)\x02\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x8d\x8emN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00 \x00social_engineering.tmplUT\x05\x00\x01ZC\x89\\d\x91A\x8b\xd4L\x10\x86\xef\xdf\xaf(r\xfa\x841\xb9\xcb\xee\x8a \xe8Q\x94\xc5sM\xfaM\xd2L\xa7\xaa\xa9\xaa\xd98\x84\xfe\xef\x92\x11W\xd0[\xf3\xf6\xc3[bD\x8d\xfc\x02\xf2\x1c >~\xf6\x1d\x92Z\xfb\xef\x0f\xbf\xc2\x9dgt\xad}\x88\xe0\xf1\x02sR\xa1}\xef\x9f\xad\xf4\x9f\xd5\xa35Z\xf9Fay\xbc\xd0M\xaf\x94%\x94\x92f\x99\xc9uE,\xc7+\xb1\xcc0\xbd:\x95|\x01e\xf1\xe0R~1Sll 52\xbc\x80\xef\xe9M\xafF\x15\xe6*\\(\xcb\xa4\xb6rd\x15\xfa\x7fR#\xfc\xe0\xb5\x16\x9c\xa8\xb2\xfb\xa6\x96\xfcDuQ\x01\xc9u=\xc3\xfct\xd4\x8d\x86\x94\x83F\xb6\xe4o\xfa\x7f\xe5\x12\x82s\xf1\xae\xb5O\xaas\x01}\xc7\x99\xbef\xbf\x90a\x84D\xb9QB`\x0c$\xaaK\xf6\xbb\xc9\xdf\xf6==0-\x86\xe9\xb1[\"\xaa\xbf\x1b\x86m\xdb\xfa\xf9\xde\xd8\x8f\xba\x0ea,^\xd9 \xe3\xcdP\xd5bp\x9ep6\xdd<\xcb<\xbc_\xca#\xe4\xed\xf3\xb7\xee\xe9\xcb\xef)\xc7M\xfca\xe0'\xaa\x86\x80$\n\xa53Hc\x81\xd1\x86\xf3\x1d8\xc2\xd7\xc5\xbf\n\xfe\x0c\x00\x00\xff\xffPK\x07\x08\xa5\xae\x1a9>\x01\x00\x00\xee\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x8d\x8emN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00 \x00unwanted.tmplUT\x05\x00\x01[C\x89\\d\x91\xc1\x8e\xd40\x0c\x86\xef<\x85U. As_\xed.\xe2\x04g`\xc5\xd9\x93\xbaI4\x89]\xd9\x1e:\xa3*\xef\x8e\xda\x15\xcba\xae\xd1g\xfb\xff\xfel\xdbDsa\x82!\x13N\x85\xd3\xd0\xfb\xafL`\xc5 p\x7f\x83(\xecX\xd8 \xa3\xb6\xf9RaQI\x8a\xcd\xb6\x8dx\xea\xfd\xdd\xff\x1d\x8d\xcc0\xd1\xd0\xfbWw\x8cgR\x03a\xd8\xb6\xf1E\xeb\xf8]\xcc{\x87VRv@wj\x8b\x83\x0b\xb8\x96x\x86\x9b\\\xa0\xb0\x0b\x146\xc7Z\x0b\xa7\xb7K\xe0\x19\xfd\xb8\xbfc\n'\x95\xd5v\x80\xae\x0bi!\x8e\x04\x1ffQ\xa0+\xb6\xa5\xd2'8\xdd f\xe4\xb4C\xc7H\x96F\x0b&\x02Q\xb0,\xeb\xeb\xb4+\x02NG\xc8\xdd\xd8\x8e\x14\x7f\x8a\x15\xff8\xde\xebM\xe4X\xaa\x0d\xbd\x7f\x13I\x95\xe07\x9d\xe0G\xb13(Eb\xaf7xD\xc8J\xf3\xd3\x90\xdd\x17{\x08a]\xd71\x1d\xf4\x18\xa5\x05Wd[P\x89\xe3Mi\x11\xf5`8\xd3?\xa10\x15L,\xe6%\x86\xc2\x13]\xc7\xec\xad~\xc9\xf5\x89\xf8\xf3\xcb\xcf\xf7\x17\xadO\xfb\xe6\x87\x10^K\xed}x\x9e\xe5\xc2\xd3\xdd\xef<\x06|\xbe+\xffM\xeao\x00\x00\x00\xff\xffPK\x07\x08\xcar\xc9\xae:\x01\x00\x00\xf8\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x0b\x8dmN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00 \x00warning_triangle.svgUT\x05\x00\x01\x87@\x89\\\\\xce=j\xc40\x10\xc5\xf1~O1Lj\xaf\xc6\xcf\x03\x81`m\xb1\xa4H\x91\x1c\"\xb0\x8eF\xe0/b!\x19\x9d>8\xe0f\xcb\x1f\xfcy\xbc~\xcb\x81\xf6i\x9c7\xcf\x96\xd2\xfa\xe6\\)\xe5Z\xba\xeb\xf2\x1b\x1cD\xc4m90\x95\xf8H\xe6\x19\xba\xeeL6\xc4`\xe9T\x8eC\xb9/\xbbg!!(A\x99~\xe28z~y\xbf\xabv\xaf|\xbb\x10\x11\xf5\xebw2zx\xfe\x12\x12\x83f\xe8\x87\xd4\xb3\x9d\x97y`\xf7\\\xb6\x84\xd6\x80\xcf\x16\x04:P\xa7\x16Mg\x0dr\x03CF\x9d\xa4\xd1\x7f\xaa!k=&\xfa\xe3\xf2\xed\xf2\x17\x00\x00\xff\xffPK\x07\x08\xde\xf7\xb8\xd5\xa7\x00\x00\x00\xdb\x00\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x0b\x8dmN{\xdc\x9d\xdbg\x08\x00\x00E\"\x00\x00\x10\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x81\x00\x00\x00\x00interstitial.cssUT\x05\x00\x01\x87@\x89\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00J\x94mN\xe9\x02\xe6\xcb\x89\x01\x00\x00Y\x03\x00\x00\x11\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xae\x08\x00\x00interstitial.htmlUT\x05\x00\x01,M\x89\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x0b\x8dmNfg\xf4\x1a\xe6\x03\x00\x00\xfd \x00\x00\x0f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x81\x7f\n\x00\x00interstitial.jsUT\x05\x00\x01\x87@\x89\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x8b\x8emN\xe5\xab\x14\xc9X\x01\x00\x00)\x02\x00\x00\x0c\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xab\x0e\x00\x00malware.tmplUT\x05\x00\x01WC\x89\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x8d\x8emN\xa5\xae\x1a9>\x01\x00\x00\xee\x01\x00\x00\x17\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81F\x10\x00\x00social_engineering.tmplUT\x05\x00\x01ZC\x89\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x8d\x8emN\xcar\xc9\xae:\x01\x00\x00\xf8\x01\x00\x00\x0d\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd2\x11\x00\x00unwanted.tmplUT\x05\x00\x01[C\x89\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x0b\x8dmN\xde\xf7\xb8\xd5\xa7\x00\x00\x00\xdb\x00\x00\x00\x14\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81P\x13\x00\x00warning_triangle.svgUT\x05\x00\x01\x87@\x89\\PK\x05\x06\x00\x00\x00\x00\x07\x00\x07\x00\xf5\x01\x00\x00B\x14\x00\x00\x00\x00" fs.Register(data) diff --git a/database.go b/database.go index 58155e6..0aacf0c 100644 --- a/database.go +++ b/database.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,7 +26,6 @@ import ( "time" pb "github.com/google/webrisk/internal/webrisk_proto" - pt "github.com/golang/protobuf/ptypes" ) // jitter is the maximum amount of time that we expect an API list update to @@ -44,17 +43,17 @@ const ( // order to provide protection for the latest threats. // // The process for updating the database is as follows: -// * At startup, if a database file is provided, then load it. If loaded -// properly (not corrupted and not stale), then set tfu as the contents. -// Otherwise, pull a new threat list from the Web Risk API. -// * Periodically, synchronize the database with the Web Risk API. -// This uses the Version Token fields to update only parts of the threat list that have -// changed since the last sync. -// * Anytime tfu is updated, generate a new tfl. +// - At startup, if a database file is provided, then load it. If loaded +// properly (not corrupted and not stale), then set tfu as the contents. +// Otherwise, pull a new threat list from the Web Risk API. +// - Periodically, synchronize the database with the Web Risk API. +// This uses the Version Token fields to update only parts of the threat list that have +// changed since the last sync. +// - Anytime tfu is updated, generate a new tfl. // // The process for querying the database is as follows: -// * Check if the requested full hash matches any partial hash in tfl. -// If a match is found, return a set of ThreatTypes with a partial match. +// - Check if the requested full hash matches any partial hash in tfl. +// If a match is found, return a set of ThreatTypes with a partial match. type database struct { ml sync.RWMutex // Protects tfl, err, and last // threatsForLookup maps ThreatTypes to sets of partial hashes. @@ -228,7 +227,7 @@ func (db *database) Update(ctx context.Context, api api) (time.Duration, bool) { } resps = append(resps, resp) if resp.RecommendedNextDiff != nil { - ndiff, _ := pt.Timestamp(resp.RecommendedNextDiff) + ndiff := resp.RecommendedNextDiff.AsTime() serverMinWait := time.Duration(ndiff.Sub(time.Now())) if serverMinWait > nextUpdateWait { nextUpdateWait = serverMinWait diff --git a/database_test.go b/database_test.go index 83e3f09..bd9d8c2 100644 --- a/database_test.go +++ b/database_test.go @@ -1,10 +1,10 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // 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 // -// https://www.apache.org/licenses/LICENSE-2.0 +// https://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, @@ -29,7 +29,8 @@ import ( "testing" "time" - pt "github.com/golang/protobuf/ptypes" + timepb "google.golang.org/protobuf/types/known/timestamppb" + pb "github.com/google/webrisk/internal/webrisk_proto" ) @@ -291,7 +292,7 @@ func TestDatabaseUpdate(t *testing.T) { logger = log.New(ioutil.Discard, "", 0) ) - // Helper function to aid in the construction on responses. + // Helper function to aid in the construction of responses. newResp := func(td ThreatType, rtype int, dels []int32, adds []string, state string, chksum string) *pb.ComputeThreatListDiffResponse { resp := &pb.ComputeThreatListDiffResponse{ ResponseType: pb.ComputeThreatListDiffResponse_ResponseType(rtype), @@ -355,7 +356,7 @@ func TestDatabaseUpdate(t *testing.T) { now = now.Add(time.Hour) resp = newResp(ThreatTypeMalware, full, nil, []string{"aaaa", "0421e", "666666", "7777777", "88888888"}, "d1", "a3b93fac424834c2447e2dbe5db3ec8553519777523907ea310e207f556a7637") - ts, _ := pt.TimestampProto(time.Now().Add(2000 * time.Second)) + ts := timepb.New(time.Now().Add(2000 * time.Second)) resp.RecommendedNextDiff = ts delay, updated = db.Update(context.Background(), mockAPI) diff --git a/generate.sh b/generate.sh old mode 100755 new mode 100644 diff --git a/go.mod b/go.mod index 301226c..7fbe8fc 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,11 @@ module github.com/google/webrisk -go 1.20 +go 1.19 require ( - github.com/golang/protobuf v1.5.0 github.com/rakyll/statik v0.1.7 - golang.org/x/net v0.2.0 + golang.org/x/net v0.5.0 google.golang.org/protobuf v1.28.1 ) -require golang.org/x/text v0.4.0 // indirect +require golang.org/x/text v0.6.0 // indirect diff --git a/go.sum b/go.sum index d426f99..dd1e38f 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,12 @@ -github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= -golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= diff --git a/hash.go b/hash.go index 99ce180..06452e1 100644 --- a/hash.go +++ b/hash.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -65,10 +65,10 @@ func (p hashPrefixes) Sort() { sort.Sort(p) } // Validate checks that the list of hash prefixes is valid. It checks the // following parameters: -// * That each hash prefix is valid; that is, it has a length within -// minHashPrefixLength and maxHashPrefixLength. -// * That the list of prefixes is sorted. -// * That none of the hashes are prefixes of each other. +// - That each hash prefix is valid; that is, it has a length within +// minHashPrefixLength and maxHashPrefixLength. +// - That the list of prefixes is sorted. +// - That none of the hashes are prefixes of each other. func (p hashPrefixes) Validate() error { var hp hashPrefix // Previous hash for _, h := range p { @@ -258,6 +258,7 @@ func decodeRiceIntegers(rice *pb.RiceDeltaEncoding) ([]uint32, error) { // least-significant bits coming first in the bit stream. // // For more information, see the following: +// // https://en.wikipedia.org/wiki/Golomb_coding type riceDecoder struct { br *bitReader diff --git a/hash_test.go b/hash_test.go index 276cea0..9365541 100644 --- a/hash_test.go +++ b/hash_test.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,14 +17,14 @@ import ( "bytes" "encoding/gob" "encoding/hex" - "io/ioutil" + "os" "reflect" "runtime" "sync" "testing" + "google.golang.org/protobuf/proto" pb "github.com/google/webrisk/internal/webrisk_proto" - "github.com/golang/protobuf/proto" ) var ( @@ -32,15 +32,33 @@ var ( loadOnce sync.Once ) -func getTestHashes() [][]hashPrefix { +func getTestHashes(t *testing.T) [][]hashPrefix { loadOnce.Do(func() { - b, err := ioutil.ReadFile("testdata/hashes.gob") + t.Helper() + + b, err := os.ReadFile("testdata/hashes.gob") + if err != nil { + t.Fatalf("Error reading file %v - err: %v - result: %v", "testdata/hashes.gob", err, b) + } + r := gob.NewDecoder(bytes.NewReader(b)) + if err := r.Decode(&testHashesCached); err != nil { + t.Fatalf("Error decoding .gob: %v", err) + } + }) + return testHashesCached +} + +func getBenchmarkHashes(bnch *testing.B) [][]hashPrefix { + loadOnce.Do(func() { + bnch.Helper() + + b, err := os.ReadFile("testdata/hashes.gob") if err != nil { - panic(err) + bnch.Fatalf("Error reading file %v - err: %v - result: %v", "testdata/hashes.gob", err, b) } r := gob.NewDecoder(bytes.NewReader(b)) if err := r.Decode(&testHashesCached); err != nil { - panic(err) + bnch.Fatalf("Error decoding .gob: %v", err) } }) return testHashesCached @@ -104,7 +122,7 @@ func TestHashFromPattern(t *testing.T) { } func TestHashSet(t *testing.T) { - var testHashes = getTestHashes() + var testHashes = getTestHashes(t) type hashQuery struct { hash hashPrefix @@ -174,16 +192,16 @@ func TestHashSet(t *testing.T) { } func BenchmarkHashSet(b *testing.B) { - var testHashes = getTestHashes() + var benchmarkHashes = getBenchmarkHashes(b) var queries []hashPrefix - for _, h := range testHashes[1] { + for _, h := range benchmarkHashes[1] { queries = append(queries, "header"+h) queries = append(queries, h+"footer") } var hs hashSet - hs.Import(testHashes[1]) + hs.Import(benchmarkHashes[1]) b.ResetTimer() for i := 0; i < b.N; i++ { for _, h := range queries { @@ -193,7 +211,7 @@ func BenchmarkHashSet(b *testing.B) { } func BenchmarkHashSetMemory(b *testing.B) { - var testHashes = getTestHashes() + var benchmarkHashes = getBenchmarkHashes(b) var ms1, ms2 runtime.MemStats runtime.GC() @@ -204,12 +222,12 @@ func BenchmarkHashSetMemory(b *testing.B) { var hs hashSet for i := 0; i < b.N; i++ { hs = hashSet{} - hs.Import(testHashes[1]) + hs.Import(benchmarkHashes[1]) } runtime.GC() runtime.ReadMemStats(&ms2) - b.Logf("mem_alloc: %dB, hashes: %dx", ms2.Alloc-ms1.Alloc, len(testHashes[1])) + b.Logf("mem_alloc: %dB, hashes: %dx", ms2.Alloc-ms1.Alloc, len(benchmarkHashes[1])) } func TestDecodeHashes(t *testing.T) { diff --git a/internal/webrisk_proto/webrisk.pb.go b/internal/webrisk_proto/webrisk.pb.go index 4356f15..dad0f20 100644 --- a/internal/webrisk_proto/webrisk.pb.go +++ b/internal/webrisk_proto/webrisk.pb.go @@ -1,4 +1,17 @@ -// Copyright 2019 Google LLC. +// Copyright 2023 Google LLC +// +// 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 +// +// https://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. +// Copyright 2023 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,17 +29,18 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v3.12.4 +// protoc v3.21.12 // source: webrisk.proto package webrisk import ( - timestamp "github.com/golang/protobuf/ptypes/timestamp" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" ) const ( @@ -214,7 +228,7 @@ type ComputeThreatListDiffRequest struct { unknownFields protoimpl.UnknownFields // Required. The ThreatList to update. - ThreatType ThreatType `protobuf:"varint,1,opt,name=threat_type,json=threatType,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_type,omitempty"` + ThreatType ThreatType `protobuf:"varint,1,opt,name=threat_type,json=threatType,proto3,enum=google.cloud.webrisk.v1.container.ThreatType" json:"threat_type,omitempty"` // The current version token of the client for the requested list (the // client version that was received from the last successful diff). VersionToken []byte `protobuf:"bytes,2,opt,name=version_token,json=versionToken,proto3" json:"version_token,omitempty"` @@ -282,7 +296,7 @@ type ComputeThreatListDiffResponse struct { // The type of response. This may indicate that an action is required by the // client when the response is received. - ResponseType ComputeThreatListDiffResponse_ResponseType `protobuf:"varint,4,opt,name=response_type,json=responseType,proto3,enum=google.cloud.webrisk.v1.ComputeThreatListDiffResponse_ResponseType" json:"response_type,omitempty"` + ResponseType ComputeThreatListDiffResponse_ResponseType `protobuf:"varint,4,opt,name=response_type,json=responseType,proto3,enum=google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse_ResponseType" json:"response_type,omitempty"` // A set of entries to add to a local threat type's list. Additions *ThreatEntryAdditions `protobuf:"bytes,5,opt,name=additions,proto3" json:"additions,omitempty"` // A set of entries to remove from a local threat type's list. @@ -299,7 +313,7 @@ type ComputeThreatListDiffResponse struct { // request. Querying sooner is unlikely to produce a meaningful diff. // Waiting longer is acceptable considering the use case. // If this field is not set clients may update as soon as they want. - RecommendedNextDiff *timestamp.Timestamp `protobuf:"bytes,2,opt,name=recommended_next_diff,json=recommendedNextDiff,proto3" json:"recommended_next_diff,omitempty"` + RecommendedNextDiff *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=recommended_next_diff,json=recommendedNextDiff,proto3" json:"recommended_next_diff,omitempty"` } func (x *ComputeThreatListDiffResponse) Reset() { @@ -369,7 +383,7 @@ func (x *ComputeThreatListDiffResponse) GetChecksum() *ComputeThreatListDiffResp return nil } -func (x *ComputeThreatListDiffResponse) GetRecommendedNextDiff() *timestamp.Timestamp { +func (x *ComputeThreatListDiffResponse) GetRecommendedNextDiff() *timestamppb.Timestamp { if x != nil { return x.RecommendedNextDiff } @@ -385,7 +399,7 @@ type SearchUrisRequest struct { // The URI to be checked for matches. Uri string `protobuf:"bytes,1,opt,name=uri,proto3" json:"uri,omitempty"` // Required. The ThreatLists to search in. - ThreatTypes []ThreatType `protobuf:"varint,2,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` + ThreatTypes []ThreatType `protobuf:"varint,2,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.container.ThreatType" json:"threat_types,omitempty"` } func (x *SearchUrisRequest) Reset() { @@ -492,7 +506,7 @@ type SearchHashesRequest struct { // hash. For JSON requests, this field is base64-encoded. HashPrefix []byte `protobuf:"bytes,1,opt,name=hash_prefix,json=hashPrefix,proto3" json:"hash_prefix,omitempty"` // Required. The ThreatLists to search in. - ThreatTypes []ThreatType `protobuf:"varint,2,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` + ThreatTypes []ThreatType `protobuf:"varint,2,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.container.ThreatType" json:"threat_types,omitempty"` } func (x *SearchHashesRequest) Reset() { @@ -551,7 +565,7 @@ type SearchHashesResponse struct { Threats []*SearchHashesResponse_ThreatHash `protobuf:"bytes,1,rep,name=threats,proto3" json:"threats,omitempty"` // For requested entities that did not match the threat list, how long to // cache the response until. - NegativeExpireTime *timestamp.Timestamp `protobuf:"bytes,2,opt,name=negative_expire_time,json=negativeExpireTime,proto3" json:"negative_expire_time,omitempty"` + NegativeExpireTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=negative_expire_time,json=negativeExpireTime,proto3" json:"negative_expire_time,omitempty"` } func (x *SearchHashesResponse) Reset() { @@ -593,7 +607,7 @@ func (x *SearchHashesResponse) GetThreats() []*SearchHashesResponse_ThreatHash { return nil } -func (x *SearchHashesResponse) GetNegativeExpireTime() *timestamp.Timestamp { +func (x *SearchHashesResponse) GetNegativeExpireTime() *timestamppb.Timestamp { if x != nil { return x.NegativeExpireTime } @@ -937,7 +951,7 @@ type ComputeThreatListDiffRequest_Constraints struct { // 2**20. If zero, no database size limit is set. MaxDatabaseEntries int32 `protobuf:"varint,2,opt,name=max_database_entries,json=maxDatabaseEntries,proto3" json:"max_database_entries,omitempty"` // The compression types supported by the client. - SupportedCompressions []CompressionType `protobuf:"varint,3,rep,packed,name=supported_compressions,json=supportedCompressions,proto3,enum=google.cloud.webrisk.v1.CompressionType" json:"supported_compressions,omitempty"` + SupportedCompressions []CompressionType `protobuf:"varint,3,rep,packed,name=supported_compressions,json=supportedCompressions,proto3,enum=google.cloud.webrisk.v1.container.CompressionType" json:"supported_compressions,omitempty"` } func (x *ComputeThreatListDiffRequest_Constraints) Reset() { @@ -1050,10 +1064,10 @@ type SearchUrisResponse_ThreatUri struct { unknownFields protoimpl.UnknownFields // The ThreatList this threat belongs to. - ThreatTypes []ThreatType `protobuf:"varint,1,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` + ThreatTypes []ThreatType `protobuf:"varint,1,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.container.ThreatType" json:"threat_types,omitempty"` // The cache lifetime for the returned match. Clients must not cache this // response past this timestamp to avoid false positives. - ExpireTime *timestamp.Timestamp `protobuf:"bytes,2,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"` + ExpireTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"` } func (x *SearchUrisResponse_ThreatUri) Reset() { @@ -1095,7 +1109,7 @@ func (x *SearchUrisResponse_ThreatUri) GetThreatTypes() []ThreatType { return nil } -func (x *SearchUrisResponse_ThreatUri) GetExpireTime() *timestamp.Timestamp { +func (x *SearchUrisResponse_ThreatUri) GetExpireTime() *timestamppb.Timestamp { if x != nil { return x.ExpireTime } @@ -1110,13 +1124,13 @@ type SearchHashesResponse_ThreatHash struct { // The ThreatList this threat belongs to. // This must contain at least one entry. - ThreatTypes []ThreatType `protobuf:"varint,1,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` + ThreatTypes []ThreatType `protobuf:"varint,1,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.container.ThreatType" json:"threat_types,omitempty"` // A 32 byte SHA256 hash. This field is in binary format. For JSON // requests, hashes are base64-encoded. Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` // The cache lifetime for the returned match. Clients must not cache this // response past this timestamp to avoid false positives. - ExpireTime *timestamp.Timestamp `protobuf:"bytes,3,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"` + ExpireTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"` } func (x *SearchHashesResponse_ThreatHash) Reset() { @@ -1165,7 +1179,7 @@ func (x *SearchHashesResponse_ThreatHash) GetHash() []byte { return nil } -func (x *SearchHashesResponse_ThreatHash) GetExpireTime() *timestamp.Timestamp { +func (x *SearchHashesResponse_ThreatHash) GetExpireTime() *timestamppb.Timestamp { if x != nil { return x.ExpireTime } @@ -1176,62 +1190,67 @@ var File_webrisk_proto protoreflect.FileDescriptor var file_webrisk_proto_rawDesc = []byte{ 0x0a, 0x0d, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, - 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbb, 0x03, 0x0a, 0x1c, 0x43, 0x6f, - 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, - 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x44, 0x0a, 0x0b, 0x74, 0x68, - 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, - 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x63, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, - 0x69, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, - 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x0b, 0x63, - 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0xca, 0x01, 0x0a, 0x0b, 0x43, - 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, - 0x78, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x44, 0x69, 0x66, 0x66, 0x45, 0x6e, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x61, 0x74, 0x61, - 0x62, 0x61, 0x73, 0x65, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x12, 0x6d, 0x61, 0x78, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x45, - 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x5f, 0x0a, 0x16, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, - 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, - 0x52, 0x15, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x72, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe1, 0x04, 0x0a, 0x1d, 0x43, 0x6f, 0x6d, 0x70, - 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, - 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0d, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x43, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, - 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x4b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x41, 0x64, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x48, 0x0a, 0x08, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, - 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x72, - 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, - 0x52, 0x08, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6e, 0x65, - 0x77, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6e, 0x65, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x5b, 0x0a, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, - 0x75, 0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x21, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, + 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x22, 0xd9, 0x03, 0x0a, 0x1c, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, + 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x4e, 0x0a, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x68, + 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x6d, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, + 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4b, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, + 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, + 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x0b, 0x63, 0x6f, 0x6e, + 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0xd4, 0x01, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, + 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, + 0x64, 0x69, 0x66, 0x66, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x44, 0x69, 0x66, 0x66, 0x45, 0x6e, 0x74, 0x72, 0x69, + 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, + 0x73, 0x65, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x12, 0x6d, 0x61, 0x78, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x45, 0x6e, 0x74, + 0x72, 0x69, 0x65, 0x73, 0x12, 0x69, 0x0a, 0x16, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, + 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, + 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x15, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, + 0x89, 0x05, 0x0a, 0x1d, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, + 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x72, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, + 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, + 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x55, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, + 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x68, 0x72, + 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x52, 0x0a, 0x08, + 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, + 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x52, 0x08, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, + 0x12, 0x2a, 0x0a, 0x11, 0x6e, 0x65, 0x77, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6e, 0x65, 0x77, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x65, 0x0a, 0x08, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x49, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, + 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x52, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x4e, 0x0a, 0x15, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, @@ -1245,115 +1264,121 @@ var file_webrisk_proto_rawDesc = []byte{ 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x49, 0x46, 0x46, 0x10, 0x01, - 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x53, 0x45, 0x54, 0x10, 0x02, 0x22, 0x6d, 0x0a, 0x11, 0x53, + 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x53, 0x45, 0x54, 0x10, 0x02, 0x22, 0x77, 0x0a, 0x11, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x72, 0x69, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, - 0x72, 0x69, 0x12, 0x46, 0x0a, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x72, 0x69, 0x12, 0x50, 0x0a, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x68, 0x72, + 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x73, 0x22, 0x8a, 0x02, 0x0a, 0x12, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, + 0x72, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x06, 0x74, + 0x68, 0x72, 0x65, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, + 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, + 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x72, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x55, 0x72, 0x69, 0x52, 0x06, 0x74, 0x68, + 0x72, 0x65, 0x61, 0x74, 0x1a, 0x9a, 0x01, 0x0a, 0x09, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x55, + 0x72, 0x69, 0x12, 0x50, 0x0a, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, - 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0xf6, 0x01, 0x0a, 0x12, 0x53, - 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x72, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x4d, 0x0a, 0x06, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, - 0x63, 0x68, 0x55, 0x72, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, - 0x68, 0x72, 0x65, 0x61, 0x74, 0x55, 0x72, 0x69, 0x52, 0x06, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, - 0x1a, 0x90, 0x01, 0x0a, 0x09, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x55, 0x72, 0x69, 0x12, 0x46, - 0x0a, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, - 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x68, 0x72, + 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, 0x69, 0x6d, + 0x65, 0x22, 0x88, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x61, 0x73, 0x68, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x61, 0x73, + 0x68, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, + 0x68, 0x61, 0x73, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x50, 0x0a, 0x0c, 0x74, 0x68, + 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, + 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, + 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0xf4, 0x02, 0x0a, + 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x07, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, + 0x68, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x48, 0x61, 0x73, 0x68, 0x52, 0x07, 0x74, 0x68, 0x72, 0x65, + 0x61, 0x74, 0x73, 0x12, 0x4c, 0x0a, 0x14, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, + 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x12, 0x6e, + 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, 0x69, 0x6d, + 0x65, 0x1a, 0xaf, 0x01, 0x0a, 0x0a, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x48, 0x61, 0x73, 0x68, + 0x12, 0x50, 0x0a, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, - 0x69, 0x6d, 0x65, 0x22, 0x7e, 0x0a, 0x13, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x61, 0x73, - 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x61, - 0x73, 0x68, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x0a, 0x68, 0x61, 0x73, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x46, 0x0a, 0x0c, 0x74, - 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x72, 0x65, - 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x73, 0x22, 0xe0, 0x02, 0x0a, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x61, - 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x07, - 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, + 0x69, 0x6d, 0x65, 0x22, 0xba, 0x01, 0x0a, 0x14, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4b, 0x0a, 0x0a, + 0x72, 0x61, 0x77, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, + 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x61, 0x77, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x52, 0x09, + 0x72, 0x61, 0x77, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x55, 0x0a, 0x0b, 0x72, 0x69, 0x63, + 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, + 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x45, 0x6e, 0x63, 0x6f, + 0x64, 0x69, 0x6e, 0x67, 0x52, 0x0a, 0x72, 0x69, 0x63, 0x65, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, + 0x22, 0xbe, 0x01, 0x0a, 0x13, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0b, 0x72, 0x61, 0x77, 0x5f, + 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, - 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x61, - 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x68, 0x72, - 0x65, 0x61, 0x74, 0x48, 0x61, 0x73, 0x68, 0x52, 0x07, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x73, - 0x12, 0x4c, 0x0a, 0x14, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x65, 0x78, 0x70, - 0x69, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x12, 0x6e, 0x65, 0x67, 0x61, - 0x74, 0x69, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x1a, 0xa5, - 0x01, 0x0a, 0x0a, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x46, 0x0a, - 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, - 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, - 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, - 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x70, - 0x69, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, - 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0xa6, 0x01, 0x0a, 0x14, 0x54, 0x68, 0x72, 0x65, 0x61, - 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x41, 0x0a, 0x0a, 0x72, 0x61, 0x77, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, - 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x61, - 0x77, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x52, 0x09, 0x72, 0x61, 0x77, 0x48, 0x61, 0x73, 0x68, - 0x65, 0x73, 0x12, 0x4b, 0x0a, 0x0b, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x45, 0x6e, 0x63, 0x6f, 0x64, - 0x69, 0x6e, 0x67, 0x52, 0x0a, 0x72, 0x69, 0x63, 0x65, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, - 0xaa, 0x01, 0x0a, 0x13, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x44, 0x0a, 0x0b, 0x72, 0x61, 0x77, 0x5f, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, - 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x61, 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x52, 0x0a, 0x72, 0x61, 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x4d, 0x0a, - 0x0c, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, - 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x69, - 0x63, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, - 0x0b, 0x72, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x26, 0x0a, 0x0a, - 0x52, 0x61, 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x52, 0x07, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x09, 0x52, 0x61, 0x77, 0x48, 0x61, 0x73, 0x68, 0x65, - 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x73, 0x69, 0x7a, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x53, 0x69, - 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x61, 0x77, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x72, 0x61, 0x77, 0x48, 0x61, 0x73, 0x68, 0x65, - 0x73, 0x22, 0x9f, 0x01, 0x0a, 0x11, 0x52, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x45, - 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x72, 0x73, 0x74, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x66, 0x69, - 0x72, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x69, 0x63, 0x65, - 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x0d, 0x72, 0x69, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, - 0x1f, 0x0a, 0x0b, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x44, - 0x61, 0x74, 0x61, 0x2a, 0x8f, 0x01, 0x0a, 0x0a, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x54, 0x48, 0x52, 0x45, 0x41, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x2e, 0x52, 0x61, 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x52, 0x0a, 0x72, 0x61, + 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x57, 0x0a, 0x0c, 0x72, 0x69, 0x63, 0x65, + 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, + 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x45, 0x6e, 0x63, 0x6f, + 0x64, 0x69, 0x6e, 0x67, 0x52, 0x0b, 0x72, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, + 0x73, 0x22, 0x26, 0x0a, 0x0a, 0x52, 0x61, 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, + 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, + 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x09, 0x52, 0x61, 0x77, + 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x70, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x61, 0x77, 0x5f, 0x68, + 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x72, 0x61, 0x77, + 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, 0x9f, 0x01, 0x0a, 0x11, 0x52, 0x69, 0x63, 0x65, 0x44, + 0x65, 0x6c, 0x74, 0x61, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, 0x0b, + 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x25, 0x0a, + 0x0e, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x72, 0x69, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x65, 0x74, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, + 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x65, 0x6e, 0x63, + 0x6f, 0x64, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x2a, 0x8f, 0x01, 0x0a, 0x0a, 0x54, 0x68, 0x72, + 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x54, 0x48, 0x52, 0x45, 0x41, + 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4d, 0x41, 0x4c, 0x57, 0x41, 0x52, 0x45, 0x10, + 0x01, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x43, 0x49, 0x41, 0x4c, 0x5f, 0x45, 0x4e, 0x47, 0x49, + 0x4e, 0x45, 0x45, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x4e, 0x57, + 0x41, 0x4e, 0x54, 0x45, 0x44, 0x5f, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x10, 0x03, + 0x12, 0x28, 0x0a, 0x24, 0x53, 0x4f, 0x43, 0x49, 0x41, 0x4c, 0x5f, 0x45, 0x4e, 0x47, 0x49, 0x4e, + 0x45, 0x45, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x44, 0x45, 0x44, 0x5f, + 0x43, 0x4f, 0x56, 0x45, 0x52, 0x41, 0x47, 0x45, 0x10, 0x04, 0x2a, 0x46, 0x0a, 0x0f, 0x43, 0x6f, + 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, + 0x1c, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x0b, 0x0a, 0x07, 0x4d, 0x41, 0x4c, 0x57, 0x41, 0x52, 0x45, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, - 0x53, 0x4f, 0x43, 0x49, 0x41, 0x4c, 0x5f, 0x45, 0x4e, 0x47, 0x49, 0x4e, 0x45, 0x45, 0x52, 0x49, - 0x4e, 0x47, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x4e, 0x57, 0x41, 0x4e, 0x54, 0x45, 0x44, - 0x5f, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x10, 0x03, 0x12, 0x28, 0x0a, 0x24, 0x53, - 0x4f, 0x43, 0x49, 0x41, 0x4c, 0x5f, 0x45, 0x4e, 0x47, 0x49, 0x4e, 0x45, 0x45, 0x52, 0x49, 0x4e, - 0x47, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x44, 0x45, 0x44, 0x5f, 0x43, 0x4f, 0x56, 0x45, 0x52, - 0x41, 0x47, 0x45, 0x10, 0x04, 0x2a, 0x46, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x43, 0x4f, 0x4d, 0x50, - 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x52, 0x41, - 0x57, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x52, 0x49, 0x43, 0x45, 0x10, 0x02, 0x42, 0x1b, 0x5a, - 0x19, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2f, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x07, 0x0a, 0x03, 0x52, 0x41, 0x57, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x52, 0x49, 0x43, 0x45, + 0x10, 0x02, 0x42, 0x1b, 0x5a, 0x19, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1371,48 +1396,48 @@ func file_webrisk_proto_rawDescGZIP() []byte { var file_webrisk_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_webrisk_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_webrisk_proto_goTypes = []interface{}{ - (ThreatType)(0), // 0: google.cloud.webrisk.v1.ThreatType - (CompressionType)(0), // 1: google.cloud.webrisk.v1.CompressionType - (ComputeThreatListDiffResponse_ResponseType)(0), // 2: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.ResponseType - (*ComputeThreatListDiffRequest)(nil), // 3: google.cloud.webrisk.v1.ComputeThreatListDiffRequest - (*ComputeThreatListDiffResponse)(nil), // 4: google.cloud.webrisk.v1.ComputeThreatListDiffResponse - (*SearchUrisRequest)(nil), // 5: google.cloud.webrisk.v1.SearchUrisRequest - (*SearchUrisResponse)(nil), // 6: google.cloud.webrisk.v1.SearchUrisResponse - (*SearchHashesRequest)(nil), // 7: google.cloud.webrisk.v1.SearchHashesRequest - (*SearchHashesResponse)(nil), // 8: google.cloud.webrisk.v1.SearchHashesResponse - (*ThreatEntryAdditions)(nil), // 9: google.cloud.webrisk.v1.ThreatEntryAdditions - (*ThreatEntryRemovals)(nil), // 10: google.cloud.webrisk.v1.ThreatEntryRemovals - (*RawIndices)(nil), // 11: google.cloud.webrisk.v1.RawIndices - (*RawHashes)(nil), // 12: google.cloud.webrisk.v1.RawHashes - (*RiceDeltaEncoding)(nil), // 13: google.cloud.webrisk.v1.RiceDeltaEncoding - (*ComputeThreatListDiffRequest_Constraints)(nil), // 14: google.cloud.webrisk.v1.ComputeThreatListDiffRequest.Constraints - (*ComputeThreatListDiffResponse_Checksum)(nil), // 15: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.Checksum - (*SearchUrisResponse_ThreatUri)(nil), // 16: google.cloud.webrisk.v1.SearchUrisResponse.ThreatUri - (*SearchHashesResponse_ThreatHash)(nil), // 17: google.cloud.webrisk.v1.SearchHashesResponse.ThreatHash - (*timestamp.Timestamp)(nil), // 18: google.protobuf.Timestamp + (ThreatType)(0), // 0: google.cloud.webrisk.v1.container.ThreatType + (CompressionType)(0), // 1: google.cloud.webrisk.v1.container.CompressionType + (ComputeThreatListDiffResponse_ResponseType)(0), // 2: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.ResponseType + (*ComputeThreatListDiffRequest)(nil), // 3: google.cloud.webrisk.v1.container.ComputeThreatListDiffRequest + (*ComputeThreatListDiffResponse)(nil), // 4: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse + (*SearchUrisRequest)(nil), // 5: google.cloud.webrisk.v1.container.SearchUrisRequest + (*SearchUrisResponse)(nil), // 6: google.cloud.webrisk.v1.container.SearchUrisResponse + (*SearchHashesRequest)(nil), // 7: google.cloud.webrisk.v1.container.SearchHashesRequest + (*SearchHashesResponse)(nil), // 8: google.cloud.webrisk.v1.container.SearchHashesResponse + (*ThreatEntryAdditions)(nil), // 9: google.cloud.webrisk.v1.container.ThreatEntryAdditions + (*ThreatEntryRemovals)(nil), // 10: google.cloud.webrisk.v1.container.ThreatEntryRemovals + (*RawIndices)(nil), // 11: google.cloud.webrisk.v1.container.RawIndices + (*RawHashes)(nil), // 12: google.cloud.webrisk.v1.container.RawHashes + (*RiceDeltaEncoding)(nil), // 13: google.cloud.webrisk.v1.container.RiceDeltaEncoding + (*ComputeThreatListDiffRequest_Constraints)(nil), // 14: google.cloud.webrisk.v1.container.ComputeThreatListDiffRequest.Constraints + (*ComputeThreatListDiffResponse_Checksum)(nil), // 15: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.Checksum + (*SearchUrisResponse_ThreatUri)(nil), // 16: google.cloud.webrisk.v1.container.SearchUrisResponse.ThreatUri + (*SearchHashesResponse_ThreatHash)(nil), // 17: google.cloud.webrisk.v1.container.SearchHashesResponse.ThreatHash + (*timestamppb.Timestamp)(nil), // 18: google.protobuf.Timestamp } var file_webrisk_proto_depIdxs = []int32{ - 0, // 0: google.cloud.webrisk.v1.ComputeThreatListDiffRequest.threat_type:type_name -> google.cloud.webrisk.v1.ThreatType - 14, // 1: google.cloud.webrisk.v1.ComputeThreatListDiffRequest.constraints:type_name -> google.cloud.webrisk.v1.ComputeThreatListDiffRequest.Constraints - 2, // 2: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.response_type:type_name -> google.cloud.webrisk.v1.ComputeThreatListDiffResponse.ResponseType - 9, // 3: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.additions:type_name -> google.cloud.webrisk.v1.ThreatEntryAdditions - 10, // 4: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.removals:type_name -> google.cloud.webrisk.v1.ThreatEntryRemovals - 15, // 5: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.checksum:type_name -> google.cloud.webrisk.v1.ComputeThreatListDiffResponse.Checksum - 18, // 6: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.recommended_next_diff:type_name -> google.protobuf.Timestamp - 0, // 7: google.cloud.webrisk.v1.SearchUrisRequest.threat_types:type_name -> google.cloud.webrisk.v1.ThreatType - 16, // 8: google.cloud.webrisk.v1.SearchUrisResponse.threat:type_name -> google.cloud.webrisk.v1.SearchUrisResponse.ThreatUri - 0, // 9: google.cloud.webrisk.v1.SearchHashesRequest.threat_types:type_name -> google.cloud.webrisk.v1.ThreatType - 17, // 10: google.cloud.webrisk.v1.SearchHashesResponse.threats:type_name -> google.cloud.webrisk.v1.SearchHashesResponse.ThreatHash - 18, // 11: google.cloud.webrisk.v1.SearchHashesResponse.negative_expire_time:type_name -> google.protobuf.Timestamp - 12, // 12: google.cloud.webrisk.v1.ThreatEntryAdditions.raw_hashes:type_name -> google.cloud.webrisk.v1.RawHashes - 13, // 13: google.cloud.webrisk.v1.ThreatEntryAdditions.rice_hashes:type_name -> google.cloud.webrisk.v1.RiceDeltaEncoding - 11, // 14: google.cloud.webrisk.v1.ThreatEntryRemovals.raw_indices:type_name -> google.cloud.webrisk.v1.RawIndices - 13, // 15: google.cloud.webrisk.v1.ThreatEntryRemovals.rice_indices:type_name -> google.cloud.webrisk.v1.RiceDeltaEncoding - 1, // 16: google.cloud.webrisk.v1.ComputeThreatListDiffRequest.Constraints.supported_compressions:type_name -> google.cloud.webrisk.v1.CompressionType - 0, // 17: google.cloud.webrisk.v1.SearchUrisResponse.ThreatUri.threat_types:type_name -> google.cloud.webrisk.v1.ThreatType - 18, // 18: google.cloud.webrisk.v1.SearchUrisResponse.ThreatUri.expire_time:type_name -> google.protobuf.Timestamp - 0, // 19: google.cloud.webrisk.v1.SearchHashesResponse.ThreatHash.threat_types:type_name -> google.cloud.webrisk.v1.ThreatType - 18, // 20: google.cloud.webrisk.v1.SearchHashesResponse.ThreatHash.expire_time:type_name -> google.protobuf.Timestamp + 0, // 0: google.cloud.webrisk.v1.container.ComputeThreatListDiffRequest.threat_type:type_name -> google.cloud.webrisk.v1.container.ThreatType + 14, // 1: google.cloud.webrisk.v1.container.ComputeThreatListDiffRequest.constraints:type_name -> google.cloud.webrisk.v1.container.ComputeThreatListDiffRequest.Constraints + 2, // 2: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.response_type:type_name -> google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.ResponseType + 9, // 3: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.additions:type_name -> google.cloud.webrisk.v1.container.ThreatEntryAdditions + 10, // 4: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.removals:type_name -> google.cloud.webrisk.v1.container.ThreatEntryRemovals + 15, // 5: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.checksum:type_name -> google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.Checksum + 18, // 6: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.recommended_next_diff:type_name -> google.protobuf.Timestamp + 0, // 7: google.cloud.webrisk.v1.container.SearchUrisRequest.threat_types:type_name -> google.cloud.webrisk.v1.container.ThreatType + 16, // 8: google.cloud.webrisk.v1.container.SearchUrisResponse.threat:type_name -> google.cloud.webrisk.v1.container.SearchUrisResponse.ThreatUri + 0, // 9: google.cloud.webrisk.v1.container.SearchHashesRequest.threat_types:type_name -> google.cloud.webrisk.v1.container.ThreatType + 17, // 10: google.cloud.webrisk.v1.container.SearchHashesResponse.threats:type_name -> google.cloud.webrisk.v1.container.SearchHashesResponse.ThreatHash + 18, // 11: google.cloud.webrisk.v1.container.SearchHashesResponse.negative_expire_time:type_name -> google.protobuf.Timestamp + 12, // 12: google.cloud.webrisk.v1.container.ThreatEntryAdditions.raw_hashes:type_name -> google.cloud.webrisk.v1.container.RawHashes + 13, // 13: google.cloud.webrisk.v1.container.ThreatEntryAdditions.rice_hashes:type_name -> google.cloud.webrisk.v1.container.RiceDeltaEncoding + 11, // 14: google.cloud.webrisk.v1.container.ThreatEntryRemovals.raw_indices:type_name -> google.cloud.webrisk.v1.container.RawIndices + 13, // 15: google.cloud.webrisk.v1.container.ThreatEntryRemovals.rice_indices:type_name -> google.cloud.webrisk.v1.container.RiceDeltaEncoding + 1, // 16: google.cloud.webrisk.v1.container.ComputeThreatListDiffRequest.Constraints.supported_compressions:type_name -> google.cloud.webrisk.v1.container.CompressionType + 0, // 17: google.cloud.webrisk.v1.container.SearchUrisResponse.ThreatUri.threat_types:type_name -> google.cloud.webrisk.v1.container.ThreatType + 18, // 18: google.cloud.webrisk.v1.container.SearchUrisResponse.ThreatUri.expire_time:type_name -> google.protobuf.Timestamp + 0, // 19: google.cloud.webrisk.v1.container.SearchHashesResponse.ThreatHash.threat_types:type_name -> google.cloud.webrisk.v1.container.ThreatType + 18, // 20: google.cloud.webrisk.v1.container.SearchHashesResponse.ThreatHash.expire_time:type_name -> google.protobuf.Timestamp 21, // [21:21] is the sub-list for method output_type 21, // [21:21] is the sub-list for method input_type 21, // [21:21] is the sub-list for extension type_name diff --git a/internal/webrisk_proto/webrisk.proto b/internal/webrisk_proto/webrisk.proto index 6ca5548..e5127f9 100644 --- a/internal/webrisk_proto/webrisk.proto +++ b/internal/webrisk_proto/webrisk.proto @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC. +// Copyright 2023 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ syntax = "proto3"; -package google.cloud.webrisk.v1; +package google.cloud.webrisk.v1.container; import "google/protobuf/timestamp.proto"; diff --git a/urls.go b/urls.go index b1d4cb3..a4fb257 100644 --- a/urls.go +++ b/urls.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -39,14 +39,15 @@ import ( "errors" "fmt" "net" + + "golang.org/x/net/idna" + "net/url" "path" "regexp" "strconv" "strings" "unicode" - - "golang.org/x/net/idna" ) var ( @@ -142,6 +143,7 @@ func isUnicode(s string) bool { // split splits the string s around the delimiter c. // // Let string s be of the form: +// // "%s%s%s" % (t, c, u) // // Then split returns (t, u) if cutc is set, otherwise, it returns (t, c+u). @@ -274,15 +276,15 @@ func parseHost(hostish string) (host string, err error) { return "", err } // Then apply a to lower but only to ascii characters [a-z|A-Z]. - var temp_host bytes.Buffer + var tempHost bytes.Buffer for _, c := range []byte(host) { - if (c >= 0x41 && c <=0x5A) || (c >= 0x61 && c <= 0x7A) { - temp_host.WriteByte(byte(unicode.ToLower(rune(c)))) + if (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A) { + tempHost.WriteByte(byte(unicode.ToLower(rune(c)))) } else { - temp_host.WriteByte(c) + tempHost.WriteByte(c) } } - host = temp_host.String() + host = tempHost.String() // Then escape the result. host = escape(host) @@ -391,6 +393,7 @@ func parseIPAddress(iphostname string) string { // is usable as an IP address. // // For example: +// // s:"01234", n:2 => "2.156" // s:"0x10203040", n:4 => "16.32.48.64" func canonicalNum(s string, n int) string { diff --git a/urls_test.go b/urls_test.go index 145bde6..10007be 100644 --- a/urls_test.go +++ b/urls_test.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/webrisk_client.go b/webrisk_client.go index fef761f..f474639 100644 --- a/webrisk_client.go +++ b/webrisk_client.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,13 +11,7 @@ // 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 webrisk implements a client for the Web Risk API v4. -// API v4 emphasizes efficient usage of the network for bandwidth-constrained -// applications such as mobile devices. It achieves this by maintaining a small -// portion of the server state locally such that some queries can be answered -// immediately without any network requests. Thus, fewer API calls made, means -// less bandwidth is used. // // At a high-level, the implementation does the following: // @@ -83,13 +77,13 @@ const ( // DefaultServerURL is the default URL for the Web Risk API. DefaultServerURL = "webrisk.googleapis.com" - // DefaultUpdatePeriod is the default period for how often WebriskClient will + // DefaultUpdatePeriod is the default period for how often UpdateClient will // reload its blocklist database. DefaultUpdatePeriod = 30 * time.Minute - // DefaultID and DefaultVersion are the default client ID and Version - // strings to send with every API call. - DefaultID = "GoWebriskClient" + // DefaultID is the client ID sent with each API call. + DefaultID = "WebRiskContainer" + // DefaultVersion is the Version sent with each API call. DefaultVersion = "1.0.0" // DefaultRequestTimeout is the default amount of time a single @@ -111,20 +105,20 @@ func (tt ThreatType) String() string { return pb.ThreatType(tt).String() } // List of ThreatType constants. const ( - ThreatTypeUnspecified = ThreatType(pb.ThreatType_THREAT_TYPE_UNSPECIFIED) - ThreatTypeMalware = ThreatType(pb.ThreatType_MALWARE) - ThreatTypeSocialEngineering = ThreatType(pb.ThreatType_SOCIAL_ENGINEERING) - ThreatTypeUnwantedSoftware = ThreatType(pb.ThreatType_UNWANTED_SOFTWARE) + ThreatTypeUnspecified = ThreatType(pb.ThreatType_THREAT_TYPE_UNSPECIFIED) + ThreatTypeMalware = ThreatType(pb.ThreatType_MALWARE) + ThreatTypeSocialEngineering = ThreatType(pb.ThreatType_SOCIAL_ENGINEERING) + ThreatTypeUnwantedSoftware = ThreatType(pb.ThreatType_UNWANTED_SOFTWARE) ThreatTypeSocialEngineeringExtended = ThreatType(pb.ThreatType_SOCIAL_ENGINEERING_EXTENDED_COVERAGE) ) -// DefaultThreatLists is the default list of threat lists that WebriskClient -// will maintain. Do not modify this variable. +// DefaultThreatLists is the default list of threat lists that UpdateClient +// will maintain. If you modify this variable, you must refresh all saved database files. var DefaultThreatLists = []ThreatType{ ThreatTypeMalware, ThreatTypeSocialEngineering, - ThreatTypeSocialEngineeringExtended, ThreatTypeUnwantedSoftware, + ThreatTypeSocialEngineeringExtended, } // A URLThreat is a specialized ThreatType for the URL threat @@ -134,7 +128,7 @@ type URLThreat struct { ThreatType } -// Config sets up the WebriskClient object. +// Config sets up the UpdateClient object. type Config struct { // ServerURL is the URL for the Web Risk API server. // If empty, it defaults to DefaultServerURL. @@ -156,16 +150,16 @@ type Config struct { Version string // DBPath is a path to a persistent database file. - // If empty, WebriskClient operates in a non-persistent manner. + // If empty, UpdateClient operates in a non-persistent manner. // This means that blocklist results will not be cached beyond the lifetime - // of the WebriskClient object. + // of the UpdateClient object. DBPath string // UpdatePeriod determines how often we update the internal list database. // If zero value, it defaults to DefaultUpdatePeriod. UpdatePeriod time.Duration - // ThreatLists determines which threat lists that WebriskClient should + // ThreatLists determines which threat lists that UpdateClient should // subscribe to. The threats reported by LookupURLs will only be ones that // are specified by this list. // If empty, it defaults to DefaultThreatLists. @@ -174,7 +168,7 @@ type Config struct { // RequestTimeout determines the timeout value for the http client. RequestTimeout time.Duration - // Logger is an io.Writer that allows WebriskClient to write debug information + // Logger is an io.Writer that allows UpdateClient to write debug information // intended for human consumption. // If empty, no logs will be written. Logger io.Writer @@ -214,13 +208,13 @@ func (c Config) copy() Config { return c2 } -// WebriskClient is a client implementation of API v4. +// UpdateClient is a client implementation of API v4. // // It provides a set of lookup methods that allows the user to query whether // certain entries are considered a threat. The implementation manages all of // local database and caching that would normally be needed to interact // with the API server. -type WebriskClient struct { +type UpdateClient struct { stats Stats // Must be first for 64-bit alignment on non 64-bit systems. config Config api api @@ -235,7 +229,7 @@ type WebriskClient struct { done chan bool // Signals that the updater routine should stop } -// Stats records statistics regarding WebriskClient's operation. +// Stats records statistics regarding UpdateClient's operation. type Stats struct { QueriesByDatabase int64 // Number of queries satisfied by the database alone QueriesByCache int64 // Number of queries satisfied by the cache alone @@ -244,11 +238,11 @@ type Stats struct { DatabaseUpdateLag time.Duration // Duration since last *missed* update. 0 if next update is in the future. } -// NewWebriskClient creates a new WebriskClient. +// NewUpdateClient creates a new UpdateClient. // // The conf struct allows the user to configure many aspects of the -// WebriskClient's operation. -func NewWebriskClient(conf Config) (*WebriskClient, error) { +// UpdateClient's operation. +func NewUpdateClient(conf Config) (*UpdateClient, error) { conf = conf.copy() if !conf.setDefaults() { return nil, errors.New("webrisk: invalid configuration") @@ -265,7 +259,7 @@ func NewWebriskClient(conf Config) (*WebriskClient, error) { if conf.now == nil { conf.now = time.Now } - wr := &WebriskClient{ + wr := &UpdateClient{ config: conf, api: conf.api, c: cache{now: conf.now}, @@ -305,11 +299,11 @@ func NewWebriskClient(conf Config) (*WebriskClient, error) { return wr, nil } -// Status reports the status of WebriskClient. It returns some statistics +// Status reports the status of UpdateClient. It returns some statistics // regarding the operation, and an error representing the status of its // internal state. Most errors are transient and will recover themselves // after some period. -func (wr *WebriskClient) Status() (Stats, error) { +func (wr *UpdateClient) Status() (Stats, error) { stats := Stats{ QueriesByDatabase: atomic.LoadInt64(&wr.stats.QueriesByDatabase), QueriesByCache: atomic.LoadInt64(&wr.stats.QueriesByCache), @@ -322,8 +316,8 @@ func (wr *WebriskClient) Status() (Stats, error) { // WaitUntilReady blocks until the database is not in an error state. // Returns nil when the database is ready. Returns an error if the provided -// context is canceled or if the WebriskClient instance is Closed. -func (wr *WebriskClient) WaitUntilReady(ctx context.Context) error { +// context is canceled or if the UpdateClient instance is Closed. +func (wr *UpdateClient) WaitUntilReady(ctx context.Context) error { if atomic.LoadUint32(&wr.closed) == 1 { return errClosed } @@ -351,7 +345,7 @@ func (wr *WebriskClient) WaitUntilReady(ctx context.Context) error { // // If an error occurs, the caller should treat the threats list returned as a // best-effort response to the query. The results may be stale or be partial. -func (wr *WebriskClient) LookupURLs(urls []string) (threats [][]URLThreat, err error) { +func (wr *UpdateClient) LookupURLs(urls []string) (threats [][]URLThreat, err error) { threats, err = wr.LookupURLsContext(context.Background(), urls) return threats, err } @@ -361,7 +355,7 @@ func (wr *WebriskClient) LookupURLs(urls []string) (threats [][]URLThreat, err e // elapsed. It is safe to call this method concurrently. // // See LookupURLs for details on the returned results. -func (wr *WebriskClient) LookupURLsContext(ctx context.Context, urls []string) (threats [][]URLThreat, err error) { +func (wr *UpdateClient) LookupURLsContext(ctx context.Context, urls []string) (threats [][]URLThreat, err error) { ctx, cancel := context.WithTimeout(ctx, wr.config.RequestTimeout) defer cancel() @@ -487,13 +481,13 @@ func (wr *WebriskClient) LookupURLsContext(ctx context.Context, urls []string) ( } // TODO: Add other types of lookup when available. -// func (wr *WebriskClient) LookupBinaries(digests []string) (threats []BinaryThreat, err error) -// func (wr *WebriskClient) LookupAddresses(addrs []string) (threats [][]AddressThreat, err error) +// func (wr *UpdateClient) LookupBinaries(digests []string) (threats []BinaryThreat, err error) +// func (wr *UpdateClient) LookupAddresses(addrs []string) (threats [][]AddressThreat, err error) // updater is a blocking method that periodically updates the local database. // This should be run as a separate goroutine and will be automatically stopped // when wr.Close is called. -func (wr *WebriskClient) updater(delay time.Duration) { +func (wr *UpdateClient) updater(delay time.Duration) { for { wr.log.Printf("Next update in %v", delay) select { @@ -514,7 +508,7 @@ func (wr *WebriskClient) updater(delay time.Duration) { // Close cleans up all resources. // This method must not be called concurrently with other lookup methods. -func (wr *WebriskClient) Close() error { +func (wr *UpdateClient) Close() error { if atomic.LoadUint32(&wr.closed) == 0 { atomic.StoreUint32(&wr.closed, 1) close(wr.done) diff --git a/webrisk_client_system_test.go b/webrisk_client_system_test.go index e3dbd6d..2a74fbc 100644 --- a/webrisk_client_system_test.go +++ b/webrisk_client_system_test.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -103,7 +103,7 @@ func TestWebriskClient(t *testing.T) { t.Skip() } - sb, err := NewWebriskClient(Config{ + sb, err := NewUpdateClient(Config{ APIKey: apiKey, ID: "GoWebriskClientSystemTest", DBPath: "/tmp/webriskClient.db", From ddba9f58748a22611a0f089a79a91be735766b3c Mon Sep 17 00:00:00 2001 From: Web Risk Team Date: Thu, 26 Jan 2023 15:16:36 +0000 Subject: [PATCH 11/17] Internal change PiperOrigin-RevId: 504834508 --- Dockerfile | 11 +- LICENSE | 2 +- api.go | 29 +- api_test.go | 43 ++- cache.go | 12 +- cache_test.go | 10 +- cmd/wrlookup/main.go | 10 +- cmd/wrserver/main.go | 46 +-- cmd/wrserver/public/interstitial.js | 3 +- cmd/wrserver/statik/statik.go | 14 + database.go | 23 +- database_test.go | 11 +- generate.sh | 0 go.mod | 7 +- go.sum | 9 +- hash.go | 11 +- hash_test.go | 46 ++- internal/webrisk_proto/webrisk.pb.go | 459 ++++++++++++++------------- internal/webrisk_proto/webrisk.proto | 4 +- urls.go | 19 +- urls_test.go | 2 +- webrisk_client.go | 74 ++--- webrisk_client_system_test.go | 4 +- 23 files changed, 452 insertions(+), 397 deletions(-) mode change 100755 => 100644 generate.sh diff --git a/Dockerfile b/Dockerfile index d69047d..36c3a71 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,9 +8,10 @@ RUN go mod download && go mod verify COPY . . -# Uncomment the lines below to vet and test this container before building. -# RUN go vet -v -# RUN go test -v +# Analyze our Go code and run all tests. To speed up building, such as during +# development, consider commenting out these lines. +RUN go vet -v +RUN go test -v RUN CGO_ENABLED=0 go build -o /go/bin/wrserver cmd/wrserver/main.go @@ -19,5 +20,5 @@ FROM gcr.io/distroless/static-debian11 as wrserver COPY --from=build /go/bin/wrserver / # The APIKEY Environmental Variable should be passed in at runtime. Example: -# docker run -e APIKEY=XXXXXXXXXXXXXXXXXXXXX -p 8080:8080 -ENTRYPOINT [ "/wrserver"] +# docker run -e APIKEY=XXXXXXXXXXXXXXXXXXXXX -p 8080:8080 +ENTRYPOINT [ "/wrserver"] \ No newline at end of file diff --git a/LICENSE b/LICENSE index d645695..7a4a3ea 100644 --- a/LICENSE +++ b/LICENSE @@ -199,4 +199,4 @@ 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. + limitations under the License. \ No newline at end of file diff --git a/api.go b/api.go index e04193d..4c15ff3 100644 --- a/api.go +++ b/api.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -22,24 +22,24 @@ import ( "net/url" "strings" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" pb "github.com/google/webrisk/internal/webrisk_proto" - "github.com/golang/protobuf/proto" - "github.com/golang/protobuf/jsonpb" ) const ( - findHashPath = "v1/hashes:search" - fetchUpdatePath = "v1/threatLists:computeDiff" - threatTypeString = "threat_type" - versionTokenString = "version_token" + findHashPath = "v1/hashes:search" + fetchUpdatePath = "v1/threatLists:computeDiff" + threatTypeString = "threat_type" + versionTokenString = "version_token" supportedCompressionsString = "constraints.supported_compressions" - hashPrefixString = "hash_prefix" - threatTypesString = "threat_types" + hashPrefixString = "hash_prefix" + threatTypesString = "threat_types" ) // The api interface specifies wrappers around the Web Risk API. type api interface { - ListUpdate(ctx context.Context, threat_type pb.ThreatType, version_token []byte, + ListUpdate(ctx context.Context, threatType pb.ThreatType, versionToken []byte, compressionTypes []pb.CompressionType) (*pb.ComputeThreatListDiffResponse, error) HashLookup(ctx context.Context, hashPrefix []byte, threatTypes []pb.ThreatType) (*pb.SearchHashesResponse, error) @@ -67,11 +67,11 @@ func newNetAPI(root string, key string, proxy string) (*netAPI, error) { httpClient := &http.Client{} if proxy != "" { - proxyUrl, err := url.Parse(proxy) + proxyURL, err := url.Parse(proxy) if err != nil { return nil, err } - httpClient = &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyUrl)}} + httpClient = &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)}} } q := u.Query() @@ -84,6 +84,9 @@ func newNetAPI(root string, key string, proxy string) (*netAPI, error) { // response body payload as resp. func (a *netAPI) doRequest(ctx context.Context, urlString string, resp proto.Message) error { httpReq, err := http.NewRequest("GET", urlString, nil) + if err != nil { + return err + } httpReq.Header.Add("Content-Type", "application/json") httpReq.Header.Add("User-Agent", "Webrisk-Client/0.1.3") httpReq = httpReq.WithContext(ctx) @@ -99,7 +102,7 @@ func (a *netAPI) doRequest(ctx context.Context, urlString string, resp proto.Mes if err != nil { return err } - return jsonpb.UnmarshalString(string(body), resp) + return protojson.Unmarshal(body, resp) } // ListUpdate issues a ComputeThreatListDiff API call and returns the response. diff --git a/api_test.go b/api_test.go index c7fedf8..8450793 100644 --- a/api_test.go +++ b/api_test.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,9 +21,9 @@ import ( "reflect" "testing" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" pb "github.com/google/webrisk/internal/webrisk_proto" - "github.com/golang/protobuf/jsonpb" - "github.com/golang/protobuf/proto" ) type mockAPI struct { @@ -51,47 +51,46 @@ func TestNetAPI(t *testing.T) { var gotResp, wantResp proto.Message responseMisformatter := "" ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - var p string + var p []byte var err error - marshaler := jsonpb.Marshaler{} for key, value := range r.URL.Query() { - if (key == "threat_type") { - if (len(value) == 0) { + if key == "threat_type" { + if len(value) == 0 { t.Fatalf("missing value for key: %v", key) } gotReqThreatType = pb.ThreatType(pb.ThreatType_value[value[0]]) - } else if (key == "constraints.supported_compressions") { - if (len(value) == 0) { + } else if key == "constraints.supported_compressions" { + if len(value) == 0 { t.Fatalf("missing value for key: %v", key) } for _, comp := range value { gotReqCompressionTypes = append(gotReqCompressionTypes, pb.CompressionType(pb.CompressionType_value[comp])) } - } else if (key == "hash_prefix") { - if (len(value) == 0) { + } else if key == "hash_prefix" { + if len(value) == 0 { t.Fatalf("missing value for key: %v", key) } gotReqHashPrefix, err = base64.StdEncoding.DecodeString(value[0]) - if (err != nil) { + if err != nil { t.Fatalf("unexpected hash prefix decoding error for: %v", value[0]) } - } else if (key == "threat_types") { - if (len(value) == 0) { + } else if key == "threat_types" { + if len(value) == 0 { t.Fatalf("missing value for key: %v", key) } for _, threat := range value { gotReqThreatTypes = append(gotReqThreatTypes, pb.ThreatType(pb.ThreatType_value[threat])) } - } else if (key != "key") { + } else if key != "key" { t.Fatalf("unexpected request param error for key: %v", key) } } - if p, err = marshaler.MarshalToString(wantResp); err != nil { - t.Fatalf("unexpected jsonpb MarshalToString error: %v", err) + if p, err = protojson.Marshal(wantResp); err != nil { + t.Fatalf("unexpected json MarshalToString error: %v", err) } - if _, err := w.Write([]byte(responseMisformatter + p)); err != nil { + if _, err := w.Write([]byte(responseMisformatter + string(p))); err != nil { t.Fatalf("unexpected ResponseWriter.Write error: %v", err) } })) @@ -113,8 +112,8 @@ func TestNetAPI(t *testing.T) { RawIndices: &pb.RawIndices{Indices: []int32{1, 2, 3}}, }, } - resp1, err := api.ListUpdate(context.Background(), wantReqThreatType, []byte {}, - wantReqCompressionTypes) + resp1, err := api.ListUpdate(context.Background(), wantReqThreatType, []byte{}, + wantReqCompressionTypes) gotResp = resp1 if err != nil { t.Errorf("unexpected ListUpdate error: %v", err) @@ -127,7 +126,7 @@ func TestNetAPI(t *testing.T) { t.Errorf("mismatching ListUpdate requests for compression types:\ngot %+v\nwant %+v", gotReqCompressionTypes, wantReqCompressionTypes) } - if !reflect.DeepEqual(gotResp, wantResp) { + if !proto.Equal(gotResp, wantResp) { t.Errorf("mismatching ListUpdate responses:\ngot %+v\nwant %+v", gotResp, wantResp) } @@ -151,7 +150,7 @@ func TestNetAPI(t *testing.T) { t.Errorf("mismatching HashLookup requests for threat types:\ngot %+v\nwant %+v", gotReqThreatTypes, wantReqThreatTypes) } - if !reflect.DeepEqual(gotResp, wantResp) { + if !proto.Equal(gotResp, wantResp) { t.Errorf("mismatching HashLookup responses:\ngot %+v\nwant %+v", gotResp, wantResp) } diff --git a/cache.go b/cache.go index 3c4cca5..acf3a0b 100644 --- a/cache.go +++ b/cache.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,12 +14,10 @@ package webrisk import ( - "fmt" "sync" "time" pb "github.com/google/webrisk/internal/webrisk_proto" - pt "github.com/golang/protobuf/ptypes" ) type cacheResult int @@ -85,17 +83,13 @@ func (c *cache) Update(req *pb.SearchHashesRequest, resp *pb.SearchHashesRespons c.pttls[fullHash] = make(map[ThreatType]time.Time) } for _, tt := range threat.ThreatTypes { - var err error - c.pttls[fullHash][ThreatType(tt)], err = pt.Timestamp(threat.ExpireTime) - if err != nil { - return fmt.Errorf("pt.Timestamp: %v", err) - } + c.pttls[fullHash][ThreatType(tt)] = threat.ExpireTime.AsTime() } } // Insert negative TTLs for partial hashes. if resp.GetNegativeExpireTime() != nil { - nttl, _ := pt.Timestamp(resp.GetNegativeExpireTime()) + nttl := resp.GetNegativeExpireTime().AsTime() partialHash := hashPrefix(req.HashPrefix) c.nttls[partialHash] = nttl } diff --git a/cache_test.go b/cache_test.go index 5aea45c..5fa13a4 100644 --- a/cache_test.go +++ b/cache_test.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,8 +18,9 @@ import ( "testing" "time" + timepb "google.golang.org/protobuf/types/known/timestamppb" + pb "github.com/google/webrisk/internal/webrisk_proto" - pt "github.com/golang/protobuf/ptypes" ) func TestCacheLookup(t *testing.T) { @@ -164,8 +165,9 @@ func TestCacheLookup(t *testing.T) { func TestCacheUpdate(t *testing.T) { now := time.Unix(1451436338, 951473000) mockNow := func() time.Time { return now } - ts, _ := pt.TimestampProto(now.Add(1000 * time.Second)) - tft, _ := pt.Timestamp(ts) + + ts := timepb.New(now.Add(1000 * time.Second)) + tft := ts.AsTime() vectors := []struct { req *pb.SearchHashesRequest diff --git a/cmd/wrlookup/main.go b/cmd/wrlookup/main.go index b2c0eb5..92e7fe4 100644 --- a/cmd/wrlookup/main.go +++ b/cmd/wrlookup/main.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,7 +11,6 @@ // 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. - // Command wrlookup is a tool for looking up URLs via the command-line. // // The tool reads one URL per line from STDIN and checks every URL against @@ -19,9 +18,11 @@ // If an error occurred, debug information may be printed to STDERR. // // To build the tool: +// // $ go get github.com/google/webrisk/cmd/wrlookup // // Example usage: +// // $ wrlookup -apikey $APIKEY // https://google.com // Safe URL: https://google.com @@ -33,8 +34,9 @@ import ( "bufio" "flag" "fmt" - "github.com/google/webrisk" "os" + + "github.com/google/webrisk" ) var ( @@ -77,7 +79,7 @@ func main() { fmt.Fprintln(os.Stderr, "No -apikey specified") os.Exit(codeInvalid) } - sb, err := webrisk.NewWebriskClient(webrisk.Config{ + sb, err := webrisk.NewUpdateClient(webrisk.Config{ APIKey: *apiKeyFlag, DBPath: *databaseFlag, Logger: os.Stderr, diff --git a/cmd/wrserver/main.go b/cmd/wrserver/main.go index 191bc04..55f5ba6 100644 --- a/cmd/wrserver/main.go +++ b/cmd/wrserver/main.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,7 +11,6 @@ // 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. - // Command wrserver is an application for serving URL lookups via a simple API. // // In order to abstract away the complexities of the Web Risk API v4, the @@ -189,7 +188,6 @@ package main import ( - "bytes" "encoding/json" "errors" "flag" @@ -200,13 +198,12 @@ import ( "net/url" "os" - "github.com/google/webrisk" - pb "github.com/google/webrisk/internal/webrisk_proto" - - "github.com/golang/protobuf/jsonpb" - "github.com/golang/protobuf/proto" - _ "github.com/google/webrisk/cmd/wrserver/statik" + "google.golang.org/protobuf/encoding/protojson" + "google.golang.org/protobuf/proto" "github.com/rakyll/statik/fs" + _ "github.com/google/webrisk/cmd/wrserver/statik" + pb "github.com/google/webrisk/internal/webrisk_proto" + "github.com/google/webrisk" ) const ( @@ -228,9 +225,10 @@ var ( ) var threatTemplate = map[webrisk.ThreatType]string{ - webrisk.ThreatTypeMalware: "/malware.tmpl", - webrisk.ThreatTypeUnwantedSoftware: "/unwanted.tmpl", - webrisk.ThreatTypeSocialEngineering: "/social_engineering.tmpl", + webrisk.ThreatTypeMalware: "/malware.tmpl", + webrisk.ThreatTypeUnwantedSoftware: "/unwanted.tmpl", + webrisk.ThreatTypeSocialEngineering: "/social_engineering.tmpl", + webrisk.ThreatTypeSocialEngineeringExtended: "/social_engineering.tmpl", } const usage = `wrserver: starts a Web Risk API proxy server. @@ -265,7 +263,11 @@ func unmarshal(req *http.Request, pbReq proto.Message) (string, error) { switch req.Header.Get("Content-Type") { case mimeJSON: - if err := jsonpb.Unmarshal(req.Body, pbReq); err != nil { + body, err := ioutil.ReadAll(req.Body) + if err != nil { + return mime, err + } + if err := protojson.Unmarshal(body, pbReq); err != nil { return mime, err } case mimeProto: @@ -293,12 +295,11 @@ func marshal(resp http.ResponseWriter, pbResp proto.Message, mime string) error return err } case mimeJSON: - var m jsonpb.Marshaler - var b bytes.Buffer - if err := m.Marshal(&b, pbResp); err != nil { + b, err := protojson.Marshal(pbResp) + if err != nil { return err } - if _, err := resp.Write(b.Bytes()); err != nil { + if _, err := resp.Write(b); err != nil { return err } default: @@ -308,7 +309,7 @@ func marshal(resp http.ResponseWriter, pbResp proto.Message, mime string) error } // serveStatus writes a simple JSON with server status information to resp. -func serveStatus(resp http.ResponseWriter, req *http.Request, sb *webrisk.WebriskClient) { +func serveStatus(resp http.ResponseWriter, req *http.Request, sb *webrisk.UpdateClient) { stats, sbErr := sb.Status() errStr := "" if sbErr != nil { @@ -330,7 +331,7 @@ func serveStatus(resp http.ResponseWriter, req *http.Request, sb *webrisk.Webris // API endpoint. This allows clients to look up whether a given URL is safe. // Unlike the official API, it does not require an API key. // It supports both JSON and ProtoBuf. -func serveLookups(resp http.ResponseWriter, req *http.Request, sb *webrisk.WebriskClient) { +func serveLookups(resp http.ResponseWriter, req *http.Request, sb *webrisk.UpdateClient) { if req.Method != "POST" { http.Error(resp, "invalid method", http.StatusBadRequest) return @@ -400,7 +401,7 @@ func parseTemplates(fs http.FileSystem, t *template.Template, paths ...string) ( // serveRedirector implements a basic HTTP redirector that will filter out // redirect URLs that are unsafe according to the Web Risk API. -func serveRedirector(resp http.ResponseWriter, req *http.Request, sb *webrisk.WebriskClient, fs http.FileSystem) { +func serveRedirector(resp http.ResponseWriter, req *http.Request, sb *webrisk.UpdateClient, fs http.FileSystem) { rawURL := req.URL.Query().Get("url") if rawURL == "" || req.URL.Path != "/r" { http.NotFound(resp, req) @@ -429,7 +430,7 @@ func serveRedirector(resp http.ResponseWriter, req *http.Request, sb *webrisk.We http.Error(resp, err.Error(), http.StatusInternalServerError) return } - err = t.Execute(resp, map[string]interface{}{ + err = t.Execute(resp, map[string]any{ "Threat": threat, "Url": parsedURL}) if err != nil { @@ -438,7 +439,6 @@ func serveRedirector(resp http.ResponseWriter, req *http.Request, sb *webrisk.We return } } - http.Error(resp, err.Error(), http.StatusInternalServerError) } func main() { @@ -457,7 +457,7 @@ func main() { DBPath: *databaseFlag, Logger: os.Stderr, } - sb, err := webrisk.NewWebriskClient(conf) + sb, err := webrisk.NewUpdateClient(conf) if err != nil { fmt.Fprintln(os.Stderr, "Unable to initialize Web Risk client: ", err) os.Exit(1) diff --git a/cmd/wrserver/public/interstitial.js b/cmd/wrserver/public/interstitial.js index 77612f9..ea60b4a 100644 --- a/cmd/wrserver/public/interstitial.js +++ b/cmd/wrserver/public/interstitial.js @@ -1,4 +1,5 @@ -/** Copyright 2019 Google LLC +/** + Copyright 2023 Google LLC * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/cmd/wrserver/statik/statik.go b/cmd/wrserver/statik/statik.go index aeeb2bd..8f229fa 100644 --- a/cmd/wrserver/statik/statik.go +++ b/cmd/wrserver/statik/statik.go @@ -1,3 +1,16 @@ +// Copyright 2023 Google LLC +// +// 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 +// +// https://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. // Copyright 2019 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); @@ -21,6 +34,7 @@ import ( "github.com/rakyll/statik/fs" ) + func init() { data := "PK\x03\x04\x14\x00\x08\x00\x08\x00\x0b\x8dmN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00 \x00interstitial.cssUT\x05\x00\x01\x87@\x89\\\xbcXm\x8f\xdb\xb8\x11\xfe\xee_1@p\xcd&\xb0\xbc\x92\xfc\xb2^-p\xe85wh\x0b\\\x83\xe2\xae\xed\xd7\x82\x96\xc66\x1b\x8a\x14(\xcak\xe7\xb0\xff\xbd\xa0(\xc9\xa4D\xd9JQ\xdc\x97dM\x91\xc3yyf\x9e\x19>~\x84O\xa2\xb8Hz8*\x88\xc3h\x05\xff8\"|:J\x91\xd3*\x87\x1f*u\x14\xb2\\\xc0\x0f\x8cA\xbd\xa9\x04\x89%\xca\x13f\x8b\x19\x00\xfc\xb3D\x10{PGZB)*\x99\"\xa4\"C\xa0%\x1c\xc4 %\xc7\x0cv\x17 \xf0\xa7_\x7f\x0cJua\x08\x8c\xa6\xc8K\x04u$\nR\xc2a\x87Z\xd2^T<\x03\xcaA\x1d\x11~\xfe\xeb\xa7\x9f>\xff\xfa\x13\xec)\xc3\x05||\x9c\xcd\x08\xfc6\x03H\x05\x132\x01y\xd8=\xac\x9e\xe7\xb0^\xcda\xbd\xf9\xf02{\x9b\xcdv\"\xbb\xd4{v$\xfdr\x90ZZ\xd0l\x7f=R\x85/7\x8e\xeb\xdb\xb9\n\xf6$\xa7\xec\x92\xc0\xfb\xbf ;\xa1\xa2)\x81\xcfX\xe1\xfb9\xbc\xff\xb9JiF\xe0\xcf\x92\xf0L/\x94\x84\x97A\x89\x92\xee\xbb\xd3%\xfd\x8a <\xad\xbf3\xeaTJ >\xa2\x90<\xec\xc8\xc3\xf2i\x0eO\x9b9G\x92\x89W\x88\xc30/!\xadv4\x0dv\xf8\x95\xa2|\x08\x17\xab9\x84s\x08\x17qkcU\xa2\x0cJd\x98\xaa\x04\xb8\xe0u\\\x82\\|\x0dF\xbe\x94#\x1f^q\xf7\x85*\xdf\xc7\xce\xfb I\x15=\xe1\xb7\x05AT\x8aQ\x8e\xb5\x07\xae\x92\x8e\x1a\xccFPgq\x02\xa1\x0e\x0b,\x8b\xb3\x11\x16\x1ac\xe7\xb0X\x1aL\xbe\xcbP\x11\xca\xca\x9b\xd8\xbd\xfa|\xb5.\xce\x10\xc2:\xd4~\xb6\x8f\x17 \x17\xea!\xd9SY\xaa@\xec\x03u)\xf0C-\xd4\x1c\x0d\x94(\x12\x88\xfb\xe7\x02/\x08\x13\xa0\xfc\x88\x92\xaa\x01\xe4n\xa4\x87\x81N\xeb\xfc\x1b \xa9\x97\x14\x9eU\x90a*$10\xa9x\x86R\xbb\xb5\xfbZ\x83h/d\x9e@U\x14(SR\xa2O\xf9\x11\xcf[&\xdc\xba\xecm6;F}\xef\xc7\xe1j\x0e\xcb\xcd\x1c\xa2\xf0C/\x0f\xa2\xc5\xc6\xa4A\xbd\xf6\x8a:U\xb4\xd92'L/k\xa9\xc1\xb1Y\x8e\x16\xb1\x934\xc1N(%\xf2\x04\xa2M\x13\x88c\xfcMw\xc77\xee~\x9b\xcd\x16G\x9aeh\xc2\x99\xd1\xb2`\xe4bA\xfe\xa8rV\x7f\xb2E\xc6\xba\x1a5.\xd2K\x01\xc9\xfeS\x95Z\xf70\xfc\xaeM<\xff\xd76\xfbn|mRpl\x87V\x99\xa6\xc3\"Hsr\xc0\x04*\xc9\x1e\x1e\x8bj\xc7h\xfa\xf8J$\xa7\xfc\xf0o%)\xe1\x07\x86\x8b\xf2t0%\xf1zLb\x81\x06\x84\xcd\x9f\xbd\xef\x8d\xc9\x8drm\x90\x9e\x9a\xc2\xd9A\x16BX\x85f\xed\x95f\xea\xd8n\xa9\xb5\xd5\xa5\xb2TTQ\xc2\x82WI40\xaf\xd0\xf3\x96]\xdb\xdb&|=\x8cl\xdc\xba\x1a\x85:KH\xa5\x84I\x95\x9c\x9c\x83F\x8fM\xe8\xea\xd5y\xf1\x1d\x13\x07Q\xeb\xd1\x8a]mm\xab:\xe0-\xcd\xea \xa5&/\x16\x10F\x0f<\x81\x9cf\x19C[\xf2\xd3\xba-\x15Zt\xb0c\"\xfd\xd2\x87j\xb4Y\xce\xa1\xfd\xa7\x0f\xd6\xc5\xb31\xabI~S\x80\xd6\x8d\xfe5 \x9a\xbbS4\xf4\xa3\xef\xca \xe5A\x8eeI\x0e\x08\xdfC\xe1\"\x99\xf2.g\x17\x9c\x9c\x1c\xff\xdben\x1d\xb5\xe1\xb2v% \xd9\xabfs\xca\x90H\x1d'u4U\x8d+\xe4*\x81\xf7\xef_\xec\xfb\x14\xd9\xb9N\xe9@[\xe6\x84\xb1\x80Q>\xf0\x89\xafkp\x19\xf4m6\xfbc\x8e\x19%\xf0`\x85\xf6I\x87\xd6T\xecq\x90Y\xa54\x84\xc8\xc0\xf8mD\xe0*\xee\x04\x9a:9\xd7\xa2{\x8a\x0f\xeavO\xe3\xb6|\xf5J\xce*\x0c\xcd\xaaS\xe6o\xd6m\xfd\xd9q\xa3\xd6|\x06\xe0\x10\xe0U`\\3E\xf3\xdfp\xf38\xdd\xb9H\x88\x1a\xbc9\xa7m\xd2\xb3\xa2]C\xfce \"nD\xf8A;f\xd6\xc4\x18\xae-G\xf4\xf2lP\xc1[\xc9}\xe4\xbb\xea.;\x8b\xdff\xb3\xc7\x8f\x1fg\xf0\x11\xfe&v\x94!\x94\x05\xa6tOS\xd0]6\xe5\x879\xec\x85\xd4\xa9_\x87;\x832\x95\x88\xbc\x84?\x00#\xf2\x80r\xa1\xcf~&'z\xa8i\xb3\x81Q D\"\x10\x9e\x1e\x85\xc4\x0c\x94\xa8\xdbqS_L\xa3\x8f\x8d\xa4\xfa\xfc\x8fM\xc4\xda\xa4\x96X0\x92bY\xefS\xa2h\x93O\xf7\xf5T\x95 ^\xb9>.\x18\xd3\xc9\xa7\xef\"Z\xce\xe3-\x8c\x13\x9e\x99\xe5\xae\xa4/7\xdd\xba\x90\x14\xb9j\x88\xbf\x10RIB\x95\xc1\x8a\x1f\x10N\xc3sE\xe4\xb6\x06\xe4\x15\x8b\x8b\x12S\xc13\"/\xee\xf1\x96\xf3\x9a\xa0\xa0n\xa7\xc2!\xacL\x07\xd0O_\xca[\xd3\xe2\x95k\xda\xc0\xe2Z\"\x809\xd4U\xfd0\xfa&\x87t\xfe\x98;\xe2\xba\xcb\"\x9f\x0e\xb60\xfb\xf2\xab\xcaWa\x96\x0ev\xb0l\x1d\x18\xe1Y\x99\x926\x81\xeb)\xcd\x03r\xbb=\xed\xc65\x80\x96\xd8\xc2\xf6\xa7\xdd{\x07\xb1\xee\xbe\xb5Z\xf6\x11\x86{5\x08o\xf7\xd35\xf3\xc5\xce\xd8\xc0\x9cl\xa7\x9c\xeb\xbal\x1d\xd0}\x10\xed\xf8\xb3\xa7g\xcc\xcc\xe2\xd7\x80\xf2\x0c\xcf D\x93\xca\x84O\x15\xa7\x8e\xe9\x98\x19\xc6ls\xc8\xa9/\x1d\xe7\xafB\x1f\xd4\xfe\x1fY4w\x02\xed\x83\xc7\x84\xf8\x83\x0f\x00.\x1b\x84u;\xd49\xe0\xcag\xe6/\x0f\xab\xd9\xc3\xfa/b'\x94\x08~\xc1C\xc5\x88\x9cw\xa3\xfb\x90\xef\x9e\x97K/\xdfm\xfa|\xb7ii\xe9\x0e\xe7\x8dU\xec\xf1nq\x18\xbem\x0b\xaa \xf4yKn\x1b\x87\xd6\x95\x03\xec\x8b\x82\xa4T]\x1a|\xbaS|\xf3\x0d\xe2\xf5\x94\x11\xdeQ\xad\x19J\x06h\xb5\x87\x15?\x0d\xb7\x1a\xf7\xf5k\x7f\x9fP\xee\x99\xcet#i\xa8\xb5C\x9c\xfej\xdf\xf7v4H\xfa^\xb9\xd6=vd\xc3\xac\x9d\xcd\xbaV\xa9\xd7ro\xad\x93\xd7ig8\x12\xc6\xce\xbe\xf1\xbap+\xc6]\xfb\xb4jG\x88V\xac\xd3v\xf8\n\x95DF\x14=\xe1\x1d\x1d\x8a\xa1\xe9\x8b\xe7\xce\xf4\xfed\x13\xf5|R\xfb\xd2v\x88\xaf~\xf5\x9bJ\x0f\x0c\xa3I/I\x0dO\xf7\x8b\x83C\xf0\xcd\x9e\xeap\xc0RaV\x97x\xf8\x1e\xdei\x95\xa4`\x0dX\xca\xb9\xbb\xcb\xbc\x86\x0e\xb7\x8d5\xd5\x8eI\x03\xca\xbf\xb2\xb7\xbfB\xba]\xcbm\xcep1\xb5Z\x8ft\x19\x1dg??O\xb9rX\xc1\xc6\xf2\xe6\x86q\xeb;,S\xcb\xed\x91\xc9\x18i\xf4]2\x9aV-\xd4\xef\xa6\x95\x8d\xd0\xcd\xea\x9e1\xdb\xc9\xdd\xd9\xffJ\xa8\xd6m\xcb\xe5\xf6.\xa3z \xb8\x93v\x8bo';\xef>\x08\xe2{~[\x87~\xbfE\xab)\xfd\xfa\xd4\xf0=o\x9c\x19\x08\xfe~\xd4\xb3\x84\x02S5\xf50\xe1i\xb8\x97OkoW\xbbY\xddk\xa9\xbd\xb8\x9df\xd1\xcd\xc9|\xf0n\xe4\xc9\xba~uo\xd8\xca\xe6\x12\xddO\xd5\xe3\xf2B\xec\xf7\xba@\x7fpB\xde\xda\xb3\x0d{}\xc6\xf6\xfe\xec\xec\xcc\xc9\xdb\xbb\x0c\xf9d\xcc\xb8\xc7\x84\xf1vb\xcav\x8c6\xe1\x84\x87\xb7\xa2E\xb8\xb65\x1a\xc5\xb7}\x81\x7fZ\x9b\x9e\x89\xfe\x81\xc9\x85V\xfc\xbc\xbd\x95\xc0\x9e~yB|\xd7\xfd\xf8\xae\xc3\x91\xc6\xc4\x81R8)\x12\xfe\xc9\xf6\x8eSM\x1f\x02\xbf\xabk=\x15\xfa\x86ko\xa1\xfe\x1b]\xd3\x82\xfb)\xbc\xed\x1d\xdb\x93\xd6\xc3\x17\x9e\x15\xf2\x0c\xeb7n!\x95\x0e\x8f(T@}\x99\x18\xfaj_g\xd9H\xf9\xdblG\x1cf\n\xd9\xb4\xf2k5\x9e\xf7m4H\xb1\x1e\xba\x07\xf3\xa9/\x98#L\xe6N\xa2>\x9a\xbeK\xb8v\xf1~\xf6\xfab\x19/[_LM\xbaM?\xe96\x13\xa7\x81\x1e\x85\xfd\x0b\xe5\x05j\x8a\x80\xbcy\xcd3\xafu\x0b\xf8,\xcc#\x03prZ8\xd1\xb5=1\xd2Z\x8ey\xa2s\xfd\xd2\xdf\x1f\x8e\xba\xfe\x9e\x0bM\xbfy\x0fN\xdd4\xb8g\xd88P\xff\x15dTbj\x14H\x05\xab\xf2f\xe6\xeb9\xcf\xf3`\xfc['#\x81\x08\"k\x08\x1e\x0c\x03\xbe\x91d\xd2A\x0f\xd2\xcd\xb9\xd09\xe7\x19\x85:a\xcd\xe4\xed\xbe7\x85\xee\xa2t\x86b\xff\x00\xe7y,\xf0\xbf\xfd\x8c\xc6w\xf2\x00pWG}\xf5\x7f\x03\x00\x00\xff\xffPK\x07\x08{\xdc\x9d\xdbg\x08\x00\x00E\"\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00J\x94mN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x11\x00 \x00interstitial.htmlUT\x05\x00\x01,M\x89\\t\x93\xc1\x92\xdb \x0c\x86\xefy\nU\xe7z=\xb9\xf5\x00>t\xfa\x06}\x02\x02J\xac.`\x06\x94d<;\xfb\xee\x1dC\xe28\x99]_,K\xbf> Y\xa8\x1fn\xb22'\x82Q\x82\x1fvjy\x81\xe3\xac\xd1KF\xf0&\x9e4R\xc4%D\xc6\x0d;\x00\x15H\x0c\xd8\xd1\xe4B\xa2\xf1,\xc7\xee\x17>\x02\xd1\x04\xd2xa\xba\xa6)\x0b\xee\xa0>v\x8aBQ4rda\xe3\xbbb\x8d'\xbd\xff \x81#\x87sx8\xae\xecd\xd4\x8e.l\xa9\xab\x1f\x8d.,\x9e\x86\xbfd\xcf\x99e\x06\xcay\xca\xaao\xde%\xee9\xbeC&\xaf\xb1\xc8\xec\xa9\x8cD\x820f:j\xec\xd3\xf9\xe0\xd9\xf6\x1c\x85r\x91\xda\xc2\x9b-\xa5\x91\x8b\xcd\x9c\x04J\xb6\xdf(\xff\x15\x1cT\xdfd\xc3N\xf5m\x14\xea0\xb9\x19\xd8i\\\x8c\x86r|\x01\xebM)\xcbI\x1f\x84\xee\x9aMJ\x94\xab\xe8&[\x12\x83\xe1\xd8\xddfs\x8b\xbd@\xec\x14\xb1J\xab5\xa8\xde\xf1\xe5I\xb8b\x02\x95bN\xb4b\x00\xd4\xb8\x1f>>\x84B\xf2F\x08pi\x9b\xe3 \xe1\xed\xf3S\xf5\xe3~\xa3LO\xc2;\xaa \xd3Z\xefQ|kn\xda\x8d\xe6\xf2rT\x00u8\x8bL\xb16\x9a2\x07\x93\xe7\xae\xb9p\xf8m\xec;\xc8\x04\xc5\x1cIf\xd57\xffW\x99\x8e\xc4\xb0/\xf7\xcc{\xc1\x12\x8c\xf7\xdd\xf2\xebq\xf8\xd3$\xcf\x94\xd7F7\xac\x152\xb2su\xc7\xbf\x1c\xc6\xaa\xde\x0ec\xc5\xde\x0c\xd5/;Pw\xa3^\xa4\xff\x01\x00\x00\xff\xffPK\x07\x08\xe9\x02\xe6\xcb\x89\x01\x00\x00Y\x03\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x0b\x8dmN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0f\x00 \x00interstitial.jsUT\x05\x00\x01\x87@\x89\\\x94UmO#G\x13\xfc\xbe\xbf\xa2\x8e\xe7\xa4\xb5y`\xcd\x11\x94HXV\xc2\xdb $\xe0\x94\xc0)\x1f\xa3\xf1N\xdb;bvf3\xd3k\xf0q\xfe\xef\xd1\xcc\xdaf\xfdF.\xdf`\xdc]\xdd]\xd5]\xdb\xeb\xe1\xc2VS\xa7\xc6\x05\xe3\xf8\xe8\xd3 \x1e\x0b\xc2E\xe1l\xa9\xea\x12g5\x17\xd6\xf9\x0cgZ#\x06y8\xf2\xe4&$\xb3\xa4\xd7\xc3WO\xb0#p\xa1<\xbc\xad]N\xc8\xad$(\x8f\xb1\x9d\x903$1\x9cB\xe0\xfc\xe1\xf2\xd0\xf3T\x13\xb4\xca\xc9x\x02\x17\x82\x91\x0b\x83!\x05\xa4\x91\xad\x8d\x842\xe0\x82p{squ\xffp\x85\x91\xd2\x94%Io\x7f?\xc1>\xce\xb4\x12\x1e#\xeb m^\x97d8\x1b\x13_i\n\x7f\x9eOod\x86\xcf\x11\x85\x9a'\x8f\xb2\xf6\x8c!\xe1\xfa\xf1\xeev\x1e\xe7\xb3\x00\xf5[%\x9c(\xf1\xea\xd9)3\x9eA\xc98\xf8\xcde3\x0d- \xc0\x16#ed\x93\xe4\x88kg\xf0\xda\x82\x9b\xc5\xbcQ\xbb,\xac\x83\xa9\xb5\x86\x1a\xc1Xn~\x0c\x00\xbddT\x9b\x9c\x955\xf8\xd8Q\xb2\x8b\xd7\x04\x98\x08\x07\xd2\x18\xec\x9a)\x04\xf6\x13`^\x9bt?\x99EFp/J\xf2\x95\xc8)\x0b\xd0\x01G\x19&\xe7Y\xb1\x12\x01q\xe5\xdf\xef\xdf\xf1:\xeb'K2\xff,\x88\x0brq\xd8J\x8c\xa3dy\xed\x1c\x19\xd6S\x0cI\x991&\x8a\x9eIB0\x04\xf6J;T\x9a\xf6\xe0sGd\xe0\xd57jX\xe1iEx\x1dZ\xabI\x98Y\xc3\xaeS\x13\xc1\x14gnw\x915 \xf7b\xf2\x17\x06\x18 \xed\xa9\xd5\xd2\x031\xea\n4 $\x16\xc2HM\xae\xd1\xfb\xeb\xcdR\xd3l\x13\xd4\x13\xd7\xd5\xd5$*>\xc0\x82\xe3N\xc3o\xaf\x17\x15\xda\x1b\x8a\xfc)\xa8\xe9\xc5\x88x\xba\x87a\xcdlM\x96\x00\x1f;i\xe5T)\xdc\xf4\xb0yL\xbb\x99\x902\x02\xde*\xcfd\xc8u\xd2\\\xab\xfc)=X\x87\x07\x9e\x95\x91\xf69+\x94g\xeb\xa6Y\xa8\xd3\x89\x8a\xcd\xba\xfd\xa4\xd5\xc0%\xb1P\xda\xafU\x96\xcd\xeb\x7f\xaa\x1c Z\x94\x0f\xba\x17JJ2\xf3\x02\x18\xb4p\xd3n\x96k\xe1}@\xcb\xd8\x8e\xc7\x9a:i\x13\x9e6\xed!\xacig\x87H\xdd\x18\x10\x1b-\x852\x87\xb95L\x86\xdfC=\xc0\x87\x95v\"\x15\x00iO?\x00\xe6\xa8\xb4\x93\xcd\x16\xb7\x11\xa5\x8c!\xf7H/\x8c\xc1\x1a\x01\xbf\"\x9d\xff\x99\xe2\x14\xe9\xb5\x92\x84\x05\x1f\xab\xc2\\\xc7%\x0b\x96\xa6\xbeQ\xb3xa\xc1\x16\x9anj\xd1D\xa6\x07+\xb7\x95Y\xf3G|\x8f\xb3n\xfd%lD\xfb\xfa>[\x07_\n\xad\x17\xe7\xd4p~\x10\xcf\xd1\x88\x89\x1a\x8b\xe8\x13\xcd\xb4\x1e\xc2\x11\x023\x12C\xd2\xf69\x86 9\x11&'\x19\xf0\x98^x\xcbe,\xcao\x9eE\\\x1b\xd2\xd5\x97\x9a\xc9\x9d\xdb\x97\xb6\x01\xfd]\x93\x9b>\x90\xa6\x9c\xad\xeb\xa4\xff[\xeeR\x7f\x9e\x18\xe4\xbbh\xd4{/oU\xe5e2I%~\x0f\xa1\x18 \xed\x94\xca\x1c>+\xc9\xc5)\x8eO\x8e\xaa\x97.\x84\x91\xe8\x94\xe2e\xf1|r\xbc|N\xf1\xff\xf9\x12\xa51\xa2\xa0\xf0M:\xc5/?\xfd\xfc\x96\xa9\xcc\xf2\xfd\xe4\xe8\xd3\xb6T\xeb\x14\x19\x8e\x0c\x9f\xa2\xb2\x8e\x9dP\xdc=X\xa9\xda\x82\xdcU\xb5\xd5\xd8J\xd5\xd6\x1c+\xa9o\x93\x9e\x1c/\xfbZmF\x0b#}.*\xea\xa6qG\x03as\xfa\xaf\xe3\x8e\x87eo\xc9\xd6:\x9d@\xb4P\xc6\xaf\x1dO\xf8\xc2\x17\x94?E\x1f\xcd\x0ba\x82\xd5\x9b\xb0c\xf0,\xb8\x8e\xfb\xfe\x8e\x05\xe0\xc3`q\x0e\xa5\xe0\xbc\xb8\x0b\xf2u\xdeD\xec6\xcf\xe4\x17\x86\xb4\xdb\xef?\xec\xf8\xe9\x07|h\x8e\x8d\xf6\xea\xbd\xebA+\xa4\xcd=\x08\xbb\xa8\xdbH\xdf\x96=\x8b\x1e\x16\xbb\\C\xff\x97\xe66=\xed\xddf\xb6\x87\xcf\x82o5\x16\xb2\xbc\xb7M{\xba\xfcr7\xaf\x7fk\x85$\xb9nT\xad/e\xb7\x9f\xfc\x13\x00\x00\xff\xffPK\x07\x08fg\xf4\x1a\xe6\x03\x00\x00\xfd \x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x8b\x8emN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0c\x00 \x00malware.tmplUT\x05\x00\x01WC\x89\\d\x91Ao\xd5@\x0c\x84\xef\xfc\n+\\@z$w\xd4W\xc4 \xce@\xc5\xd9\xddu\xb2\xab\xee\xda+\xdbQ\xfa\x14\xed\x7fGi(\x1cz\xb5\xec\xf1\xcc7\xfb\x1ei\xceL0$\xc2\x98y\x19z\xff\x95\x08,;\x01\x1e3\x08\xc2\x8e\x99\x0d*\x96\x0d\x95\xf6\x9d8\xf6\xfe\xee\xffi%3\\h\xe8\xfd\xab;\x86'R\x83\xb0\xaa\x12{\xb9\x810\xec\xfb\xf8\xa0e\xfc.\xe6\xbdC\xcdKr@w\xaa\xcd\xc1\x052\x9bc)\x10\x91\x17RY\x0d\x9a\xca\xa2X\xed8\xbe\xc9\xaa\x10\xa4\xb6\xd5I\xc1\x13:\x98\x13\x16\x10\x85H\x85\x9c\xce\x95\xcc\xb3hE\xcf\xc2\xf0a\x16\x05z\xc6\xda\n]\xa0%q\xb1\x0b44\xdbD\xa3]\xe0\xafe\xbb\x00r\x84\xa0\x14\xb3C@\x8d\xf6q|\x1b0\x92c.6\xf4\xfeMd)\x04\xbf\xe9\x11~d{\x02\xa5p\xa6\xbcCHJ\xf3uH\xee\xcd>O\xd3\xb6m\xe3\xf2\xb2=\x06\xa9\x93+\xb25T\xe2pSj\xa2>\x19\xce\xf4\xa8\xb2Y\xe6e\x8a\x19\x17\x16\xf3\x1c\xa6\xcc\x91\x9e\xc7\xe4\xb5|I\xe5J\xfc\xe9\xe1\xe7\xfbU\xcb\xf5\xa4\xd8\xfbp\x1f\xc9)8\xc5\xd7J\xee&\xbc\x7f\xc3y<\\\x1e=\xda \x0d\x95\x80\x0fB\xa5\xdc\xe0\xf8\xfd21\xa9\xe4\xb9\x92\x1d\xfcN\xd1-{zU\xfe\x07\xe3O\x00\x00\x00\xff\xffPK\x07\x08\xe5\xab\x14\xc9X\x01\x00\x00)\x02\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x8d\x8emN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x17\x00 \x00social_engineering.tmplUT\x05\x00\x01ZC\x89\\d\x91A\x8b\xd4L\x10\x86\xef\xdf\xaf(r\xfa\x841\xb9\xcb\xee\x8a \xe8Q\x94\xc5sM\xfaM\xd2L\xa7\xaa\xa9\xaa\xd98\x84\xfe\xef\x92\x11W\xd0[\xf3\xf6\xc3[bD\x8d\xfc\x02\xf2\x1c >~\xf6\x1d\x92Z\xfb\xef\x0f\xbf\xc2\x9dgt\xad}\x88\xe0\xf1\x02sR\xa1}\xef\x9f\xad\xf4\x9f\xd5\xa35Z\xf9Fay\xbc\xd0M\xaf\x94%\x94\x92f\x99\xc9uE,\xc7+\xb1\xcc0\xbd:\x95|\x01e\xf1\xe0R~1Sll 52\xbc\x80\xef\xe9M\xafF\x15\xe6*\\(\xcb\xa4\xb6rd\x15\xfa\x7fR#\xfc\xe0\xb5\x16\x9c\xa8\xb2\xfb\xa6\x96\xfcDuQ\x01\xc9u=\xc3\xfct\xd4\x8d\x86\x94\x83F\xb6\xe4o\xfa\x7f\xe5\x12\x82s\xf1\xae\xb5O\xaas\x01}\xc7\x99\xbef\xbf\x90a\x84D\xb9QB`\x0c$\xaaK\xf6\xbb\xc9\xdf\xf6==0-\x86\xe9\xb1[\"\xaa\xbf\x1b\x86m\xdb\xfa\xf9\xde\xd8\x8f\xba\x0ea,^\xd9 \xe3\xcdP\xd5bp\x9ep6\xdd<\xcb<\xbc_\xca#\xe4\xed\xf3\xb7\xee\xe9\xcb\xef)\xc7M\xfca\xe0'\xaa\x86\x80$\n\xa53Hc\x81\xd1\x86\xf3\x1d8\xc2\xd7\xc5\xbf\n\xfe\x0c\x00\x00\xff\xffPK\x07\x08\xa5\xae\x1a9>\x01\x00\x00\xee\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x8d\x8emN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0d\x00 \x00unwanted.tmplUT\x05\x00\x01[C\x89\\d\x91\xc1\x8e\xd40\x0c\x86\xef<\x85U. As_\xed.\xe2\x04g`\xc5\xd9\x93\xbaI4\x89]\xd9\x1e:\xa3*\xef\x8e\xda\x15\xcba\xae\xd1g\xfb\xff\xfel\xdbDsa\x82!\x13N\x85\xd3\xd0\xfb\xafL`\xc5 p\x7f\x83(\xecX\xd8 \xa3\xb6\xf9RaQI\x8a\xcd\xb6\x8dx\xea\xfd\xdd\xff\x1d\x8d\xcc0\xd1\xd0\xfbWw\x8cgR\x03a\xd8\xb6\xf1E\xeb\xf8]\xcc{\x87VRv@wj\x8b\x83\x0b\xb8\x96x\x86\x9b\\\xa0\xb0\x0b\x146\xc7Z\x0b\xa7\xb7K\xe0\x19\xfd\xb8\xbfc\n'\x95\xd5v\x80\xae\x0bi!\x8e\x04\x1ffQ\xa0+\xb6\xa5\xd2'8\xdd f\xe4\xb4C\xc7H\x96F\x0b&\x02Q\xb0,\xeb\xeb\xb4+\x02NG\xc8\xdd\xd8\x8e\x14\x7f\x8a\x15\xff8\xde\xebM\xe4X\xaa\x0d\xbd\x7f\x13I\x95\xe07\x9d\xe0G\xb13(Eb\xaf7xD\xc8J\xf3\xd3\x90\xdd\x17{\x08a]\xd71\x1d\xf4\x18\xa5\x05Wd[P\x89\xe3Mi\x11\xf5`8\xd3?\xa10\x15L,\xe6%\x86\xc2\x13]\xc7\xec\xad~\xc9\xf5\x89\xf8\xf3\xcb\xcf\xf7\x17\xadO\xfb\xe6\x87\x10^K\xed}x\x9e\xe5\xc2\xd3\xdd\xef<\x06|\xbe+\xffM\xeao\x00\x00\x00\xff\xffPK\x07\x08\xcar\xc9\xae:\x01\x00\x00\xf8\x01\x00\x00PK\x03\x04\x14\x00\x08\x00\x08\x00\x0b\x8dmN\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00 \x00warning_triangle.svgUT\x05\x00\x01\x87@\x89\\\\\xce=j\xc40\x10\xc5\xf1~O1Lj\xaf\xc6\xcf\x03\x81`m\xb1\xa4H\x91\x1c\"\xb0\x8eF\xe0/b!\x19\x9d>8\xe0f\xcb\x1f\xfcy\xbc~\xcb\x81\xf6i\x9c7\xcf\x96\xd2\xfa\xe6\\)\xe5Z\xba\xeb\xf2\x1b\x1cD\xc4m90\x95\xf8H\xe6\x19\xba\xeeL6\xc4`\xe9T\x8eC\xb9/\xbbg!!(A\x99~\xe28z~y\xbf\xabv\xaf|\xbb\x10\x11\xf5\xebw2zx\xfe\x12\x12\x83f\xe8\x87\xd4\xb3\x9d\x97y`\xf7\\\xb6\x84\xd6\x80\xcf\x16\x04:P\xa7\x16Mg\x0dr\x03CF\x9d\xa4\xd1\x7f\xaa!k=&\xfa\xe3\xf2\xed\xf2\x17\x00\x00\xff\xffPK\x07\x08\xde\xf7\xb8\xd5\xa7\x00\x00\x00\xdb\x00\x00\x00PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x0b\x8dmN{\xdc\x9d\xdbg\x08\x00\x00E\"\x00\x00\x10\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x81\x00\x00\x00\x00interstitial.cssUT\x05\x00\x01\x87@\x89\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00J\x94mN\xe9\x02\xe6\xcb\x89\x01\x00\x00Y\x03\x00\x00\x11\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xae\x08\x00\x00interstitial.htmlUT\x05\x00\x01,M\x89\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x0b\x8dmNfg\xf4\x1a\xe6\x03\x00\x00\xfd \x00\x00\x0f\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xe8\x81\x7f\n\x00\x00interstitial.jsUT\x05\x00\x01\x87@\x89\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x8b\x8emN\xe5\xab\x14\xc9X\x01\x00\x00)\x02\x00\x00\x0c\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xab\x0e\x00\x00malware.tmplUT\x05\x00\x01WC\x89\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x8d\x8emN\xa5\xae\x1a9>\x01\x00\x00\xee\x01\x00\x00\x17\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81F\x10\x00\x00social_engineering.tmplUT\x05\x00\x01ZC\x89\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x8d\x8emN\xcar\xc9\xae:\x01\x00\x00\xf8\x01\x00\x00\x0d\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81\xd2\x11\x00\x00unwanted.tmplUT\x05\x00\x01[C\x89\\PK\x01\x02\x14\x03\x14\x00\x08\x00\x08\x00\x0b\x8dmN\xde\xf7\xb8\xd5\xa7\x00\x00\x00\xdb\x00\x00\x00\x14\x00 \x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0\x81P\x13\x00\x00warning_triangle.svgUT\x05\x00\x01\x87@\x89\\PK\x05\x06\x00\x00\x00\x00\x07\x00\x07\x00\xf5\x01\x00\x00B\x14\x00\x00\x00\x00" fs.Register(data) diff --git a/database.go b/database.go index 58155e6..0aacf0c 100644 --- a/database.go +++ b/database.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -26,7 +26,6 @@ import ( "time" pb "github.com/google/webrisk/internal/webrisk_proto" - pt "github.com/golang/protobuf/ptypes" ) // jitter is the maximum amount of time that we expect an API list update to @@ -44,17 +43,17 @@ const ( // order to provide protection for the latest threats. // // The process for updating the database is as follows: -// * At startup, if a database file is provided, then load it. If loaded -// properly (not corrupted and not stale), then set tfu as the contents. -// Otherwise, pull a new threat list from the Web Risk API. -// * Periodically, synchronize the database with the Web Risk API. -// This uses the Version Token fields to update only parts of the threat list that have -// changed since the last sync. -// * Anytime tfu is updated, generate a new tfl. +// - At startup, if a database file is provided, then load it. If loaded +// properly (not corrupted and not stale), then set tfu as the contents. +// Otherwise, pull a new threat list from the Web Risk API. +// - Periodically, synchronize the database with the Web Risk API. +// This uses the Version Token fields to update only parts of the threat list that have +// changed since the last sync. +// - Anytime tfu is updated, generate a new tfl. // // The process for querying the database is as follows: -// * Check if the requested full hash matches any partial hash in tfl. -// If a match is found, return a set of ThreatTypes with a partial match. +// - Check if the requested full hash matches any partial hash in tfl. +// If a match is found, return a set of ThreatTypes with a partial match. type database struct { ml sync.RWMutex // Protects tfl, err, and last // threatsForLookup maps ThreatTypes to sets of partial hashes. @@ -228,7 +227,7 @@ func (db *database) Update(ctx context.Context, api api) (time.Duration, bool) { } resps = append(resps, resp) if resp.RecommendedNextDiff != nil { - ndiff, _ := pt.Timestamp(resp.RecommendedNextDiff) + ndiff := resp.RecommendedNextDiff.AsTime() serverMinWait := time.Duration(ndiff.Sub(time.Now())) if serverMinWait > nextUpdateWait { nextUpdateWait = serverMinWait diff --git a/database_test.go b/database_test.go index 83e3f09..bd9d8c2 100644 --- a/database_test.go +++ b/database_test.go @@ -1,10 +1,10 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // 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 // -// https://www.apache.org/licenses/LICENSE-2.0 +// https://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, @@ -29,7 +29,8 @@ import ( "testing" "time" - pt "github.com/golang/protobuf/ptypes" + timepb "google.golang.org/protobuf/types/known/timestamppb" + pb "github.com/google/webrisk/internal/webrisk_proto" ) @@ -291,7 +292,7 @@ func TestDatabaseUpdate(t *testing.T) { logger = log.New(ioutil.Discard, "", 0) ) - // Helper function to aid in the construction on responses. + // Helper function to aid in the construction of responses. newResp := func(td ThreatType, rtype int, dels []int32, adds []string, state string, chksum string) *pb.ComputeThreatListDiffResponse { resp := &pb.ComputeThreatListDiffResponse{ ResponseType: pb.ComputeThreatListDiffResponse_ResponseType(rtype), @@ -355,7 +356,7 @@ func TestDatabaseUpdate(t *testing.T) { now = now.Add(time.Hour) resp = newResp(ThreatTypeMalware, full, nil, []string{"aaaa", "0421e", "666666", "7777777", "88888888"}, "d1", "a3b93fac424834c2447e2dbe5db3ec8553519777523907ea310e207f556a7637") - ts, _ := pt.TimestampProto(time.Now().Add(2000 * time.Second)) + ts := timepb.New(time.Now().Add(2000 * time.Second)) resp.RecommendedNextDiff = ts delay, updated = db.Update(context.Background(), mockAPI) diff --git a/generate.sh b/generate.sh old mode 100755 new mode 100644 diff --git a/go.mod b/go.mod index 301226c..7fbe8fc 100644 --- a/go.mod +++ b/go.mod @@ -1,12 +1,11 @@ module github.com/google/webrisk -go 1.20 +go 1.19 require ( - github.com/golang/protobuf v1.5.0 github.com/rakyll/statik v0.1.7 - golang.org/x/net v0.2.0 + golang.org/x/net v0.5.0 google.golang.org/protobuf v1.28.1 ) -require golang.org/x/text v0.4.0 // indirect +require golang.org/x/text v0.6.0 // indirect diff --git a/go.sum b/go.sum index d426f99..dd1e38f 100644 --- a/go.sum +++ b/go.sum @@ -1,13 +1,12 @@ -github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/rakyll/statik v0.1.7 h1:OF3QCZUuyPxuGEP7B4ypUa7sB/iHtqOTDYZXGM8KOdQ= github.com/rakyll/statik v0.1.7/go.mod h1:AlZONWzMtEnMs7W4e/1LURLiI49pIMmp6V9Unghqrcc= -golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= +golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= diff --git a/hash.go b/hash.go index 99ce180..06452e1 100644 --- a/hash.go +++ b/hash.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -65,10 +65,10 @@ func (p hashPrefixes) Sort() { sort.Sort(p) } // Validate checks that the list of hash prefixes is valid. It checks the // following parameters: -// * That each hash prefix is valid; that is, it has a length within -// minHashPrefixLength and maxHashPrefixLength. -// * That the list of prefixes is sorted. -// * That none of the hashes are prefixes of each other. +// - That each hash prefix is valid; that is, it has a length within +// minHashPrefixLength and maxHashPrefixLength. +// - That the list of prefixes is sorted. +// - That none of the hashes are prefixes of each other. func (p hashPrefixes) Validate() error { var hp hashPrefix // Previous hash for _, h := range p { @@ -258,6 +258,7 @@ func decodeRiceIntegers(rice *pb.RiceDeltaEncoding) ([]uint32, error) { // least-significant bits coming first in the bit stream. // // For more information, see the following: +// // https://en.wikipedia.org/wiki/Golomb_coding type riceDecoder struct { br *bitReader diff --git a/hash_test.go b/hash_test.go index 276cea0..9365541 100644 --- a/hash_test.go +++ b/hash_test.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -17,14 +17,14 @@ import ( "bytes" "encoding/gob" "encoding/hex" - "io/ioutil" + "os" "reflect" "runtime" "sync" "testing" + "google.golang.org/protobuf/proto" pb "github.com/google/webrisk/internal/webrisk_proto" - "github.com/golang/protobuf/proto" ) var ( @@ -32,15 +32,33 @@ var ( loadOnce sync.Once ) -func getTestHashes() [][]hashPrefix { +func getTestHashes(t *testing.T) [][]hashPrefix { loadOnce.Do(func() { - b, err := ioutil.ReadFile("testdata/hashes.gob") + t.Helper() + + b, err := os.ReadFile("testdata/hashes.gob") + if err != nil { + t.Fatalf("Error reading file %v - err: %v - result: %v", "testdata/hashes.gob", err, b) + } + r := gob.NewDecoder(bytes.NewReader(b)) + if err := r.Decode(&testHashesCached); err != nil { + t.Fatalf("Error decoding .gob: %v", err) + } + }) + return testHashesCached +} + +func getBenchmarkHashes(bnch *testing.B) [][]hashPrefix { + loadOnce.Do(func() { + bnch.Helper() + + b, err := os.ReadFile("testdata/hashes.gob") if err != nil { - panic(err) + bnch.Fatalf("Error reading file %v - err: %v - result: %v", "testdata/hashes.gob", err, b) } r := gob.NewDecoder(bytes.NewReader(b)) if err := r.Decode(&testHashesCached); err != nil { - panic(err) + bnch.Fatalf("Error decoding .gob: %v", err) } }) return testHashesCached @@ -104,7 +122,7 @@ func TestHashFromPattern(t *testing.T) { } func TestHashSet(t *testing.T) { - var testHashes = getTestHashes() + var testHashes = getTestHashes(t) type hashQuery struct { hash hashPrefix @@ -174,16 +192,16 @@ func TestHashSet(t *testing.T) { } func BenchmarkHashSet(b *testing.B) { - var testHashes = getTestHashes() + var benchmarkHashes = getBenchmarkHashes(b) var queries []hashPrefix - for _, h := range testHashes[1] { + for _, h := range benchmarkHashes[1] { queries = append(queries, "header"+h) queries = append(queries, h+"footer") } var hs hashSet - hs.Import(testHashes[1]) + hs.Import(benchmarkHashes[1]) b.ResetTimer() for i := 0; i < b.N; i++ { for _, h := range queries { @@ -193,7 +211,7 @@ func BenchmarkHashSet(b *testing.B) { } func BenchmarkHashSetMemory(b *testing.B) { - var testHashes = getTestHashes() + var benchmarkHashes = getBenchmarkHashes(b) var ms1, ms2 runtime.MemStats runtime.GC() @@ -204,12 +222,12 @@ func BenchmarkHashSetMemory(b *testing.B) { var hs hashSet for i := 0; i < b.N; i++ { hs = hashSet{} - hs.Import(testHashes[1]) + hs.Import(benchmarkHashes[1]) } runtime.GC() runtime.ReadMemStats(&ms2) - b.Logf("mem_alloc: %dB, hashes: %dx", ms2.Alloc-ms1.Alloc, len(testHashes[1])) + b.Logf("mem_alloc: %dB, hashes: %dx", ms2.Alloc-ms1.Alloc, len(benchmarkHashes[1])) } func TestDecodeHashes(t *testing.T) { diff --git a/internal/webrisk_proto/webrisk.pb.go b/internal/webrisk_proto/webrisk.pb.go index 4356f15..dad0f20 100644 --- a/internal/webrisk_proto/webrisk.pb.go +++ b/internal/webrisk_proto/webrisk.pb.go @@ -1,4 +1,17 @@ -// Copyright 2019 Google LLC. +// Copyright 2023 Google LLC +// +// 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 +// +// https://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. +// Copyright 2023 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,17 +29,18 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.28.1 -// protoc v3.12.4 +// protoc v3.21.12 // source: webrisk.proto package webrisk import ( - timestamp "github.com/golang/protobuf/ptypes/timestamp" - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" reflect "reflect" sync "sync" + + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + timestamppb "google.golang.org/protobuf/types/known/timestamppb" ) const ( @@ -214,7 +228,7 @@ type ComputeThreatListDiffRequest struct { unknownFields protoimpl.UnknownFields // Required. The ThreatList to update. - ThreatType ThreatType `protobuf:"varint,1,opt,name=threat_type,json=threatType,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_type,omitempty"` + ThreatType ThreatType `protobuf:"varint,1,opt,name=threat_type,json=threatType,proto3,enum=google.cloud.webrisk.v1.container.ThreatType" json:"threat_type,omitempty"` // The current version token of the client for the requested list (the // client version that was received from the last successful diff). VersionToken []byte `protobuf:"bytes,2,opt,name=version_token,json=versionToken,proto3" json:"version_token,omitempty"` @@ -282,7 +296,7 @@ type ComputeThreatListDiffResponse struct { // The type of response. This may indicate that an action is required by the // client when the response is received. - ResponseType ComputeThreatListDiffResponse_ResponseType `protobuf:"varint,4,opt,name=response_type,json=responseType,proto3,enum=google.cloud.webrisk.v1.ComputeThreatListDiffResponse_ResponseType" json:"response_type,omitempty"` + ResponseType ComputeThreatListDiffResponse_ResponseType `protobuf:"varint,4,opt,name=response_type,json=responseType,proto3,enum=google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse_ResponseType" json:"response_type,omitempty"` // A set of entries to add to a local threat type's list. Additions *ThreatEntryAdditions `protobuf:"bytes,5,opt,name=additions,proto3" json:"additions,omitempty"` // A set of entries to remove from a local threat type's list. @@ -299,7 +313,7 @@ type ComputeThreatListDiffResponse struct { // request. Querying sooner is unlikely to produce a meaningful diff. // Waiting longer is acceptable considering the use case. // If this field is not set clients may update as soon as they want. - RecommendedNextDiff *timestamp.Timestamp `protobuf:"bytes,2,opt,name=recommended_next_diff,json=recommendedNextDiff,proto3" json:"recommended_next_diff,omitempty"` + RecommendedNextDiff *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=recommended_next_diff,json=recommendedNextDiff,proto3" json:"recommended_next_diff,omitempty"` } func (x *ComputeThreatListDiffResponse) Reset() { @@ -369,7 +383,7 @@ func (x *ComputeThreatListDiffResponse) GetChecksum() *ComputeThreatListDiffResp return nil } -func (x *ComputeThreatListDiffResponse) GetRecommendedNextDiff() *timestamp.Timestamp { +func (x *ComputeThreatListDiffResponse) GetRecommendedNextDiff() *timestamppb.Timestamp { if x != nil { return x.RecommendedNextDiff } @@ -385,7 +399,7 @@ type SearchUrisRequest struct { // The URI to be checked for matches. Uri string `protobuf:"bytes,1,opt,name=uri,proto3" json:"uri,omitempty"` // Required. The ThreatLists to search in. - ThreatTypes []ThreatType `protobuf:"varint,2,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` + ThreatTypes []ThreatType `protobuf:"varint,2,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.container.ThreatType" json:"threat_types,omitempty"` } func (x *SearchUrisRequest) Reset() { @@ -492,7 +506,7 @@ type SearchHashesRequest struct { // hash. For JSON requests, this field is base64-encoded. HashPrefix []byte `protobuf:"bytes,1,opt,name=hash_prefix,json=hashPrefix,proto3" json:"hash_prefix,omitempty"` // Required. The ThreatLists to search in. - ThreatTypes []ThreatType `protobuf:"varint,2,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` + ThreatTypes []ThreatType `protobuf:"varint,2,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.container.ThreatType" json:"threat_types,omitempty"` } func (x *SearchHashesRequest) Reset() { @@ -551,7 +565,7 @@ type SearchHashesResponse struct { Threats []*SearchHashesResponse_ThreatHash `protobuf:"bytes,1,rep,name=threats,proto3" json:"threats,omitempty"` // For requested entities that did not match the threat list, how long to // cache the response until. - NegativeExpireTime *timestamp.Timestamp `protobuf:"bytes,2,opt,name=negative_expire_time,json=negativeExpireTime,proto3" json:"negative_expire_time,omitempty"` + NegativeExpireTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=negative_expire_time,json=negativeExpireTime,proto3" json:"negative_expire_time,omitempty"` } func (x *SearchHashesResponse) Reset() { @@ -593,7 +607,7 @@ func (x *SearchHashesResponse) GetThreats() []*SearchHashesResponse_ThreatHash { return nil } -func (x *SearchHashesResponse) GetNegativeExpireTime() *timestamp.Timestamp { +func (x *SearchHashesResponse) GetNegativeExpireTime() *timestamppb.Timestamp { if x != nil { return x.NegativeExpireTime } @@ -937,7 +951,7 @@ type ComputeThreatListDiffRequest_Constraints struct { // 2**20. If zero, no database size limit is set. MaxDatabaseEntries int32 `protobuf:"varint,2,opt,name=max_database_entries,json=maxDatabaseEntries,proto3" json:"max_database_entries,omitempty"` // The compression types supported by the client. - SupportedCompressions []CompressionType `protobuf:"varint,3,rep,packed,name=supported_compressions,json=supportedCompressions,proto3,enum=google.cloud.webrisk.v1.CompressionType" json:"supported_compressions,omitempty"` + SupportedCompressions []CompressionType `protobuf:"varint,3,rep,packed,name=supported_compressions,json=supportedCompressions,proto3,enum=google.cloud.webrisk.v1.container.CompressionType" json:"supported_compressions,omitempty"` } func (x *ComputeThreatListDiffRequest_Constraints) Reset() { @@ -1050,10 +1064,10 @@ type SearchUrisResponse_ThreatUri struct { unknownFields protoimpl.UnknownFields // The ThreatList this threat belongs to. - ThreatTypes []ThreatType `protobuf:"varint,1,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` + ThreatTypes []ThreatType `protobuf:"varint,1,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.container.ThreatType" json:"threat_types,omitempty"` // The cache lifetime for the returned match. Clients must not cache this // response past this timestamp to avoid false positives. - ExpireTime *timestamp.Timestamp `protobuf:"bytes,2,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"` + ExpireTime *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"` } func (x *SearchUrisResponse_ThreatUri) Reset() { @@ -1095,7 +1109,7 @@ func (x *SearchUrisResponse_ThreatUri) GetThreatTypes() []ThreatType { return nil } -func (x *SearchUrisResponse_ThreatUri) GetExpireTime() *timestamp.Timestamp { +func (x *SearchUrisResponse_ThreatUri) GetExpireTime() *timestamppb.Timestamp { if x != nil { return x.ExpireTime } @@ -1110,13 +1124,13 @@ type SearchHashesResponse_ThreatHash struct { // The ThreatList this threat belongs to. // This must contain at least one entry. - ThreatTypes []ThreatType `protobuf:"varint,1,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.ThreatType" json:"threat_types,omitempty"` + ThreatTypes []ThreatType `protobuf:"varint,1,rep,packed,name=threat_types,json=threatTypes,proto3,enum=google.cloud.webrisk.v1.container.ThreatType" json:"threat_types,omitempty"` // A 32 byte SHA256 hash. This field is in binary format. For JSON // requests, hashes are base64-encoded. Hash []byte `protobuf:"bytes,2,opt,name=hash,proto3" json:"hash,omitempty"` // The cache lifetime for the returned match. Clients must not cache this // response past this timestamp to avoid false positives. - ExpireTime *timestamp.Timestamp `protobuf:"bytes,3,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"` + ExpireTime *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=expire_time,json=expireTime,proto3" json:"expire_time,omitempty"` } func (x *SearchHashesResponse_ThreatHash) Reset() { @@ -1165,7 +1179,7 @@ func (x *SearchHashesResponse_ThreatHash) GetHash() []byte { return nil } -func (x *SearchHashesResponse_ThreatHash) GetExpireTime() *timestamp.Timestamp { +func (x *SearchHashesResponse_ThreatHash) GetExpireTime() *timestamppb.Timestamp { if x != nil { return x.ExpireTime } @@ -1176,62 +1190,67 @@ var File_webrisk_proto protoreflect.FileDescriptor var file_webrisk_proto_rawDesc = []byte{ 0x0a, 0x0d, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, - 0x17, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, - 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xbb, 0x03, 0x0a, 0x1c, 0x43, 0x6f, - 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, - 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x44, 0x0a, 0x0b, 0x74, 0x68, - 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, - 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, - 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, - 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, - 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, - 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, - 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x63, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, - 0x69, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x41, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, - 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, - 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x2e, 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x0b, 0x63, - 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0xca, 0x01, 0x0a, 0x0b, 0x43, - 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, - 0x78, 0x5f, 0x64, 0x69, 0x66, 0x66, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x44, 0x69, 0x66, 0x66, 0x45, 0x6e, 0x74, - 0x72, 0x69, 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x61, 0x74, 0x61, - 0x62, 0x61, 0x73, 0x65, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x12, 0x6d, 0x61, 0x78, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x45, - 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x12, 0x5f, 0x0a, 0x16, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, - 0x74, 0x65, 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x03, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, - 0x52, 0x15, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x72, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe1, 0x04, 0x0a, 0x1d, 0x43, 0x6f, 0x6d, 0x70, - 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, - 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x68, 0x0a, 0x0d, 0x72, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x43, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, - 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, - 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x54, - 0x79, 0x70, 0x65, 0x12, 0x4b, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, - 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x41, 0x64, 0x64, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x48, 0x0a, 0x08, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, - 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x72, - 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, - 0x52, 0x08, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x6e, 0x65, - 0x77, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6e, 0x65, 0x77, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x5b, 0x0a, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, - 0x75, 0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x21, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, + 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x22, 0xd9, 0x03, 0x0a, 0x1c, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, + 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x4e, 0x0a, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, + 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, + 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x68, + 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x6d, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, + 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x4b, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, + 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, + 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x43, 0x6f, 0x6e, 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x52, 0x0b, 0x63, 0x6f, 0x6e, + 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0xd4, 0x01, 0x0a, 0x0b, 0x43, 0x6f, 0x6e, + 0x73, 0x74, 0x72, 0x61, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, + 0x64, 0x69, 0x66, 0x66, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0e, 0x6d, 0x61, 0x78, 0x44, 0x69, 0x66, 0x66, 0x45, 0x6e, 0x74, 0x72, 0x69, + 0x65, 0x73, 0x12, 0x30, 0x0a, 0x14, 0x6d, 0x61, 0x78, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, + 0x73, 0x65, 0x5f, 0x65, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x12, 0x6d, 0x61, 0x78, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x45, 0x6e, 0x74, + 0x72, 0x69, 0x65, 0x73, 0x12, 0x69, 0x0a, 0x16, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, 0x74, 0x65, + 0x64, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, + 0x20, 0x03, 0x28, 0x0e, 0x32, 0x32, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, + 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, + 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x15, 0x73, 0x75, 0x70, 0x70, 0x6f, 0x72, + 0x74, 0x65, 0x64, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x22, + 0x89, 0x05, 0x0a, 0x1d, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, + 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x72, 0x0a, 0x0d, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x4d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, + 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, + 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0c, 0x72, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x55, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x37, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, + 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x68, 0x72, + 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x52, 0x09, 0x61, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x52, 0x0a, 0x08, + 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x36, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, + 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, + 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x52, 0x08, 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, + 0x12, 0x2a, 0x0a, 0x11, 0x6e, 0x65, 0x77, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0f, 0x6e, 0x65, 0x77, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x65, 0x0a, 0x08, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x49, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, + 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x65, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x66, 0x66, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x52, 0x08, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x73, 0x75, 0x6d, 0x12, 0x4e, 0x0a, 0x15, 0x72, 0x65, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, @@ -1245,115 +1264,121 @@ var file_webrisk_proto_rawDesc = []byte{ 0x6e, 0x73, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x19, 0x52, 0x45, 0x53, 0x50, 0x4f, 0x4e, 0x53, 0x45, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x49, 0x46, 0x46, 0x10, 0x01, - 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x53, 0x45, 0x54, 0x10, 0x02, 0x22, 0x6d, 0x0a, 0x11, 0x53, + 0x12, 0x09, 0x0a, 0x05, 0x52, 0x45, 0x53, 0x45, 0x54, 0x10, 0x02, 0x22, 0x77, 0x0a, 0x11, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x72, 0x69, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, - 0x72, 0x69, 0x12, 0x46, 0x0a, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x72, 0x69, 0x12, 0x50, 0x0a, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, + 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x68, 0x72, + 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x73, 0x22, 0x8a, 0x02, 0x0a, 0x12, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, + 0x72, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x57, 0x0a, 0x06, 0x74, + 0x68, 0x72, 0x65, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x3f, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, + 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, + 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x72, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x55, 0x72, 0x69, 0x52, 0x06, 0x74, 0x68, + 0x72, 0x65, 0x61, 0x74, 0x1a, 0x9a, 0x01, 0x0a, 0x09, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x55, + 0x72, 0x69, 0x12, 0x50, 0x0a, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, - 0x76, 0x31, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, - 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0xf6, 0x01, 0x0a, 0x12, 0x53, - 0x65, 0x61, 0x72, 0x63, 0x68, 0x55, 0x72, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x4d, 0x0a, 0x06, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x35, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, - 0x63, 0x68, 0x55, 0x72, 0x69, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, - 0x68, 0x72, 0x65, 0x61, 0x74, 0x55, 0x72, 0x69, 0x52, 0x06, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, - 0x1a, 0x90, 0x01, 0x0a, 0x09, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x55, 0x72, 0x69, 0x12, 0x46, - 0x0a, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, - 0x20, 0x03, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, - 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, - 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x68, 0x72, + 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x73, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, 0x69, 0x6d, + 0x65, 0x22, 0x88, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x61, 0x73, 0x68, + 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x61, 0x73, + 0x68, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, + 0x68, 0x61, 0x73, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x50, 0x0a, 0x0c, 0x74, 0x68, + 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, + 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, + 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, + 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x73, 0x22, 0xf4, 0x02, 0x0a, + 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x5c, 0x0a, 0x07, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, + 0x68, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, + 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x48, 0x61, 0x73, 0x68, 0x52, 0x07, 0x74, 0x68, 0x72, 0x65, + 0x61, 0x74, 0x73, 0x12, 0x4c, 0x0a, 0x14, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, + 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x12, 0x6e, + 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, 0x69, 0x6d, + 0x65, 0x1a, 0xaf, 0x01, 0x0a, 0x0a, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x48, 0x61, 0x73, 0x68, + 0x12, 0x50, 0x0a, 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, + 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x54, 0x68, 0x72, 0x65, 0x61, + 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, + 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, + 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, - 0x69, 0x6d, 0x65, 0x22, 0x7e, 0x0a, 0x13, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x61, 0x73, - 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x68, 0x61, - 0x73, 0x68, 0x5f, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, - 0x0a, 0x68, 0x61, 0x73, 0x68, 0x50, 0x72, 0x65, 0x66, 0x69, 0x78, 0x12, 0x46, 0x0a, 0x0c, 0x74, - 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, - 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, 0x72, 0x65, - 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x73, 0x22, 0xe0, 0x02, 0x0a, 0x14, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x61, - 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x52, 0x0a, 0x07, - 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38, 0x2e, + 0x69, 0x6d, 0x65, 0x22, 0xba, 0x01, 0x0a, 0x14, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x4b, 0x0a, 0x0a, + 0x72, 0x61, 0x77, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x2c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, + 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, + 0x69, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x61, 0x77, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x52, 0x09, + 0x72, 0x61, 0x77, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x55, 0x0a, 0x0b, 0x72, 0x69, 0x63, + 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, + 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x45, 0x6e, 0x63, 0x6f, + 0x64, 0x69, 0x6e, 0x67, 0x52, 0x0a, 0x72, 0x69, 0x63, 0x65, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, + 0x22, 0xbe, 0x01, 0x0a, 0x13, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x4e, 0x0a, 0x0b, 0x72, 0x61, 0x77, 0x5f, + 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, - 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x48, 0x61, - 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x54, 0x68, 0x72, - 0x65, 0x61, 0x74, 0x48, 0x61, 0x73, 0x68, 0x52, 0x07, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x73, - 0x12, 0x4c, 0x0a, 0x14, 0x6e, 0x65, 0x67, 0x61, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x65, 0x78, 0x70, - 0x69, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x12, 0x6e, 0x65, 0x67, 0x61, - 0x74, 0x69, 0x76, 0x65, 0x45, 0x78, 0x70, 0x69, 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x1a, 0xa5, - 0x01, 0x0a, 0x0a, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x48, 0x61, 0x73, 0x68, 0x12, 0x46, 0x0a, - 0x0c, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0e, 0x32, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, - 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x68, - 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0b, 0x74, 0x68, 0x72, 0x65, 0x61, 0x74, - 0x54, 0x79, 0x70, 0x65, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x3b, 0x0a, 0x0b, 0x65, 0x78, 0x70, - 0x69, 0x72, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x65, 0x78, 0x70, 0x69, - 0x72, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x22, 0xa6, 0x01, 0x0a, 0x14, 0x54, 0x68, 0x72, 0x65, 0x61, - 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x41, 0x64, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x41, 0x0a, 0x0a, 0x72, 0x61, 0x77, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x01, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, - 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x61, - 0x77, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x52, 0x09, 0x72, 0x61, 0x77, 0x48, 0x61, 0x73, 0x68, - 0x65, 0x73, 0x12, 0x4b, 0x0a, 0x0b, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, - 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, - 0x31, 0x2e, 0x52, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x45, 0x6e, 0x63, 0x6f, 0x64, - 0x69, 0x6e, 0x67, 0x52, 0x0a, 0x72, 0x69, 0x63, 0x65, 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, - 0xaa, 0x01, 0x0a, 0x13, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x61, 0x6c, 0x73, 0x12, 0x44, 0x0a, 0x0b, 0x72, 0x61, 0x77, 0x5f, 0x69, - 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, - 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x61, 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, - 0x73, 0x52, 0x0a, 0x72, 0x61, 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x4d, 0x0a, - 0x0c, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, - 0x75, 0x64, 0x2e, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x69, - 0x63, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x52, - 0x0b, 0x72, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x26, 0x0a, 0x0a, - 0x52, 0x61, 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, - 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, 0x52, 0x07, 0x69, 0x6e, 0x64, - 0x69, 0x63, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x09, 0x52, 0x61, 0x77, 0x48, 0x61, 0x73, 0x68, 0x65, - 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x5f, 0x73, 0x69, 0x7a, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, 0x53, 0x69, - 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x61, 0x77, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x65, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x72, 0x61, 0x77, 0x48, 0x61, 0x73, 0x68, 0x65, - 0x73, 0x22, 0x9f, 0x01, 0x0a, 0x11, 0x52, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x45, - 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x72, 0x73, 0x74, - 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x66, 0x69, - 0x72, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x69, 0x63, 0x65, - 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x0d, 0x72, 0x69, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, - 0x1f, 0x0a, 0x0b, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x43, 0x6f, 0x75, 0x6e, 0x74, - 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x5f, 0x64, 0x61, 0x74, 0x61, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, 0x44, - 0x61, 0x74, 0x61, 0x2a, 0x8f, 0x01, 0x0a, 0x0a, 0x54, 0x68, 0x72, 0x65, 0x61, 0x74, 0x54, 0x79, - 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x54, 0x48, 0x52, 0x45, 0x41, 0x54, 0x5f, 0x54, 0x59, 0x50, + 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x2e, 0x52, 0x61, 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x52, 0x0a, 0x72, 0x61, + 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, 0x57, 0x0a, 0x0c, 0x72, 0x69, 0x63, 0x65, + 0x5f, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x34, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x77, 0x65, + 0x62, 0x72, 0x69, 0x73, 0x6b, 0x2e, 0x76, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, + 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x65, 0x44, 0x65, 0x6c, 0x74, 0x61, 0x45, 0x6e, 0x63, 0x6f, + 0x64, 0x69, 0x6e, 0x67, 0x52, 0x0b, 0x72, 0x69, 0x63, 0x65, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, + 0x73, 0x22, 0x26, 0x0a, 0x0a, 0x52, 0x61, 0x77, 0x49, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x12, + 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x05, + 0x52, 0x07, 0x69, 0x6e, 0x64, 0x69, 0x63, 0x65, 0x73, 0x22, 0x4b, 0x0a, 0x09, 0x52, 0x61, 0x77, + 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x66, 0x69, 0x78, + 0x5f, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x70, 0x72, 0x65, + 0x66, 0x69, 0x78, 0x53, 0x69, 0x7a, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x61, 0x77, 0x5f, 0x68, + 0x61, 0x73, 0x68, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x72, 0x61, 0x77, + 0x48, 0x61, 0x73, 0x68, 0x65, 0x73, 0x22, 0x9f, 0x01, 0x0a, 0x11, 0x52, 0x69, 0x63, 0x65, 0x44, + 0x65, 0x6c, 0x74, 0x61, 0x45, 0x6e, 0x63, 0x6f, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, 0x0b, + 0x66, 0x69, 0x72, 0x73, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0a, 0x66, 0x69, 0x72, 0x73, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x25, 0x0a, + 0x0e, 0x72, 0x69, 0x63, 0x65, 0x5f, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x72, 0x69, 0x63, 0x65, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x65, 0x74, 0x65, 0x72, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x6e, 0x74, 0x72, 0x79, 0x5f, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x65, 0x6e, 0x74, 0x72, 0x79, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x6e, 0x63, 0x6f, 0x64, 0x65, 0x64, + 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0b, 0x65, 0x6e, 0x63, + 0x6f, 0x64, 0x65, 0x64, 0x44, 0x61, 0x74, 0x61, 0x2a, 0x8f, 0x01, 0x0a, 0x0a, 0x54, 0x68, 0x72, + 0x65, 0x61, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x54, 0x48, 0x52, 0x45, 0x41, + 0x54, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, + 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x4d, 0x41, 0x4c, 0x57, 0x41, 0x52, 0x45, 0x10, + 0x01, 0x12, 0x16, 0x0a, 0x12, 0x53, 0x4f, 0x43, 0x49, 0x41, 0x4c, 0x5f, 0x45, 0x4e, 0x47, 0x49, + 0x4e, 0x45, 0x45, 0x52, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x4e, 0x57, + 0x41, 0x4e, 0x54, 0x45, 0x44, 0x5f, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x10, 0x03, + 0x12, 0x28, 0x0a, 0x24, 0x53, 0x4f, 0x43, 0x49, 0x41, 0x4c, 0x5f, 0x45, 0x4e, 0x47, 0x49, 0x4e, + 0x45, 0x45, 0x52, 0x49, 0x4e, 0x47, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x44, 0x45, 0x44, 0x5f, + 0x43, 0x4f, 0x56, 0x45, 0x52, 0x41, 0x47, 0x45, 0x10, 0x04, 0x2a, 0x46, 0x0a, 0x0f, 0x43, 0x6f, + 0x6d, 0x70, 0x72, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, + 0x1c, 0x43, 0x4f, 0x4d, 0x50, 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x0b, 0x0a, 0x07, 0x4d, 0x41, 0x4c, 0x57, 0x41, 0x52, 0x45, 0x10, 0x01, 0x12, 0x16, 0x0a, 0x12, - 0x53, 0x4f, 0x43, 0x49, 0x41, 0x4c, 0x5f, 0x45, 0x4e, 0x47, 0x49, 0x4e, 0x45, 0x45, 0x52, 0x49, - 0x4e, 0x47, 0x10, 0x02, 0x12, 0x15, 0x0a, 0x11, 0x55, 0x4e, 0x57, 0x41, 0x4e, 0x54, 0x45, 0x44, - 0x5f, 0x53, 0x4f, 0x46, 0x54, 0x57, 0x41, 0x52, 0x45, 0x10, 0x03, 0x12, 0x28, 0x0a, 0x24, 0x53, - 0x4f, 0x43, 0x49, 0x41, 0x4c, 0x5f, 0x45, 0x4e, 0x47, 0x49, 0x4e, 0x45, 0x45, 0x52, 0x49, 0x4e, - 0x47, 0x5f, 0x45, 0x58, 0x54, 0x45, 0x4e, 0x44, 0x45, 0x44, 0x5f, 0x43, 0x4f, 0x56, 0x45, 0x52, - 0x41, 0x47, 0x45, 0x10, 0x04, 0x2a, 0x46, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x70, 0x72, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x43, 0x4f, 0x4d, 0x50, - 0x52, 0x45, 0x53, 0x53, 0x49, 0x4f, 0x4e, 0x5f, 0x54, 0x59, 0x50, 0x45, 0x5f, 0x55, 0x4e, 0x53, - 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x52, 0x41, - 0x57, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x52, 0x49, 0x43, 0x45, 0x10, 0x02, 0x42, 0x1b, 0x5a, - 0x19, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2f, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x07, 0x0a, 0x03, 0x52, 0x41, 0x57, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x52, 0x49, 0x43, 0x45, + 0x10, 0x02, 0x42, 0x1b, 0x5a, 0x19, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x77, 0x65, 0x62, 0x72, 0x69, 0x73, 0x6b, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1371,48 +1396,48 @@ func file_webrisk_proto_rawDescGZIP() []byte { var file_webrisk_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_webrisk_proto_msgTypes = make([]protoimpl.MessageInfo, 15) var file_webrisk_proto_goTypes = []interface{}{ - (ThreatType)(0), // 0: google.cloud.webrisk.v1.ThreatType - (CompressionType)(0), // 1: google.cloud.webrisk.v1.CompressionType - (ComputeThreatListDiffResponse_ResponseType)(0), // 2: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.ResponseType - (*ComputeThreatListDiffRequest)(nil), // 3: google.cloud.webrisk.v1.ComputeThreatListDiffRequest - (*ComputeThreatListDiffResponse)(nil), // 4: google.cloud.webrisk.v1.ComputeThreatListDiffResponse - (*SearchUrisRequest)(nil), // 5: google.cloud.webrisk.v1.SearchUrisRequest - (*SearchUrisResponse)(nil), // 6: google.cloud.webrisk.v1.SearchUrisResponse - (*SearchHashesRequest)(nil), // 7: google.cloud.webrisk.v1.SearchHashesRequest - (*SearchHashesResponse)(nil), // 8: google.cloud.webrisk.v1.SearchHashesResponse - (*ThreatEntryAdditions)(nil), // 9: google.cloud.webrisk.v1.ThreatEntryAdditions - (*ThreatEntryRemovals)(nil), // 10: google.cloud.webrisk.v1.ThreatEntryRemovals - (*RawIndices)(nil), // 11: google.cloud.webrisk.v1.RawIndices - (*RawHashes)(nil), // 12: google.cloud.webrisk.v1.RawHashes - (*RiceDeltaEncoding)(nil), // 13: google.cloud.webrisk.v1.RiceDeltaEncoding - (*ComputeThreatListDiffRequest_Constraints)(nil), // 14: google.cloud.webrisk.v1.ComputeThreatListDiffRequest.Constraints - (*ComputeThreatListDiffResponse_Checksum)(nil), // 15: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.Checksum - (*SearchUrisResponse_ThreatUri)(nil), // 16: google.cloud.webrisk.v1.SearchUrisResponse.ThreatUri - (*SearchHashesResponse_ThreatHash)(nil), // 17: google.cloud.webrisk.v1.SearchHashesResponse.ThreatHash - (*timestamp.Timestamp)(nil), // 18: google.protobuf.Timestamp + (ThreatType)(0), // 0: google.cloud.webrisk.v1.container.ThreatType + (CompressionType)(0), // 1: google.cloud.webrisk.v1.container.CompressionType + (ComputeThreatListDiffResponse_ResponseType)(0), // 2: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.ResponseType + (*ComputeThreatListDiffRequest)(nil), // 3: google.cloud.webrisk.v1.container.ComputeThreatListDiffRequest + (*ComputeThreatListDiffResponse)(nil), // 4: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse + (*SearchUrisRequest)(nil), // 5: google.cloud.webrisk.v1.container.SearchUrisRequest + (*SearchUrisResponse)(nil), // 6: google.cloud.webrisk.v1.container.SearchUrisResponse + (*SearchHashesRequest)(nil), // 7: google.cloud.webrisk.v1.container.SearchHashesRequest + (*SearchHashesResponse)(nil), // 8: google.cloud.webrisk.v1.container.SearchHashesResponse + (*ThreatEntryAdditions)(nil), // 9: google.cloud.webrisk.v1.container.ThreatEntryAdditions + (*ThreatEntryRemovals)(nil), // 10: google.cloud.webrisk.v1.container.ThreatEntryRemovals + (*RawIndices)(nil), // 11: google.cloud.webrisk.v1.container.RawIndices + (*RawHashes)(nil), // 12: google.cloud.webrisk.v1.container.RawHashes + (*RiceDeltaEncoding)(nil), // 13: google.cloud.webrisk.v1.container.RiceDeltaEncoding + (*ComputeThreatListDiffRequest_Constraints)(nil), // 14: google.cloud.webrisk.v1.container.ComputeThreatListDiffRequest.Constraints + (*ComputeThreatListDiffResponse_Checksum)(nil), // 15: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.Checksum + (*SearchUrisResponse_ThreatUri)(nil), // 16: google.cloud.webrisk.v1.container.SearchUrisResponse.ThreatUri + (*SearchHashesResponse_ThreatHash)(nil), // 17: google.cloud.webrisk.v1.container.SearchHashesResponse.ThreatHash + (*timestamppb.Timestamp)(nil), // 18: google.protobuf.Timestamp } var file_webrisk_proto_depIdxs = []int32{ - 0, // 0: google.cloud.webrisk.v1.ComputeThreatListDiffRequest.threat_type:type_name -> google.cloud.webrisk.v1.ThreatType - 14, // 1: google.cloud.webrisk.v1.ComputeThreatListDiffRequest.constraints:type_name -> google.cloud.webrisk.v1.ComputeThreatListDiffRequest.Constraints - 2, // 2: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.response_type:type_name -> google.cloud.webrisk.v1.ComputeThreatListDiffResponse.ResponseType - 9, // 3: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.additions:type_name -> google.cloud.webrisk.v1.ThreatEntryAdditions - 10, // 4: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.removals:type_name -> google.cloud.webrisk.v1.ThreatEntryRemovals - 15, // 5: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.checksum:type_name -> google.cloud.webrisk.v1.ComputeThreatListDiffResponse.Checksum - 18, // 6: google.cloud.webrisk.v1.ComputeThreatListDiffResponse.recommended_next_diff:type_name -> google.protobuf.Timestamp - 0, // 7: google.cloud.webrisk.v1.SearchUrisRequest.threat_types:type_name -> google.cloud.webrisk.v1.ThreatType - 16, // 8: google.cloud.webrisk.v1.SearchUrisResponse.threat:type_name -> google.cloud.webrisk.v1.SearchUrisResponse.ThreatUri - 0, // 9: google.cloud.webrisk.v1.SearchHashesRequest.threat_types:type_name -> google.cloud.webrisk.v1.ThreatType - 17, // 10: google.cloud.webrisk.v1.SearchHashesResponse.threats:type_name -> google.cloud.webrisk.v1.SearchHashesResponse.ThreatHash - 18, // 11: google.cloud.webrisk.v1.SearchHashesResponse.negative_expire_time:type_name -> google.protobuf.Timestamp - 12, // 12: google.cloud.webrisk.v1.ThreatEntryAdditions.raw_hashes:type_name -> google.cloud.webrisk.v1.RawHashes - 13, // 13: google.cloud.webrisk.v1.ThreatEntryAdditions.rice_hashes:type_name -> google.cloud.webrisk.v1.RiceDeltaEncoding - 11, // 14: google.cloud.webrisk.v1.ThreatEntryRemovals.raw_indices:type_name -> google.cloud.webrisk.v1.RawIndices - 13, // 15: google.cloud.webrisk.v1.ThreatEntryRemovals.rice_indices:type_name -> google.cloud.webrisk.v1.RiceDeltaEncoding - 1, // 16: google.cloud.webrisk.v1.ComputeThreatListDiffRequest.Constraints.supported_compressions:type_name -> google.cloud.webrisk.v1.CompressionType - 0, // 17: google.cloud.webrisk.v1.SearchUrisResponse.ThreatUri.threat_types:type_name -> google.cloud.webrisk.v1.ThreatType - 18, // 18: google.cloud.webrisk.v1.SearchUrisResponse.ThreatUri.expire_time:type_name -> google.protobuf.Timestamp - 0, // 19: google.cloud.webrisk.v1.SearchHashesResponse.ThreatHash.threat_types:type_name -> google.cloud.webrisk.v1.ThreatType - 18, // 20: google.cloud.webrisk.v1.SearchHashesResponse.ThreatHash.expire_time:type_name -> google.protobuf.Timestamp + 0, // 0: google.cloud.webrisk.v1.container.ComputeThreatListDiffRequest.threat_type:type_name -> google.cloud.webrisk.v1.container.ThreatType + 14, // 1: google.cloud.webrisk.v1.container.ComputeThreatListDiffRequest.constraints:type_name -> google.cloud.webrisk.v1.container.ComputeThreatListDiffRequest.Constraints + 2, // 2: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.response_type:type_name -> google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.ResponseType + 9, // 3: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.additions:type_name -> google.cloud.webrisk.v1.container.ThreatEntryAdditions + 10, // 4: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.removals:type_name -> google.cloud.webrisk.v1.container.ThreatEntryRemovals + 15, // 5: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.checksum:type_name -> google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.Checksum + 18, // 6: google.cloud.webrisk.v1.container.ComputeThreatListDiffResponse.recommended_next_diff:type_name -> google.protobuf.Timestamp + 0, // 7: google.cloud.webrisk.v1.container.SearchUrisRequest.threat_types:type_name -> google.cloud.webrisk.v1.container.ThreatType + 16, // 8: google.cloud.webrisk.v1.container.SearchUrisResponse.threat:type_name -> google.cloud.webrisk.v1.container.SearchUrisResponse.ThreatUri + 0, // 9: google.cloud.webrisk.v1.container.SearchHashesRequest.threat_types:type_name -> google.cloud.webrisk.v1.container.ThreatType + 17, // 10: google.cloud.webrisk.v1.container.SearchHashesResponse.threats:type_name -> google.cloud.webrisk.v1.container.SearchHashesResponse.ThreatHash + 18, // 11: google.cloud.webrisk.v1.container.SearchHashesResponse.negative_expire_time:type_name -> google.protobuf.Timestamp + 12, // 12: google.cloud.webrisk.v1.container.ThreatEntryAdditions.raw_hashes:type_name -> google.cloud.webrisk.v1.container.RawHashes + 13, // 13: google.cloud.webrisk.v1.container.ThreatEntryAdditions.rice_hashes:type_name -> google.cloud.webrisk.v1.container.RiceDeltaEncoding + 11, // 14: google.cloud.webrisk.v1.container.ThreatEntryRemovals.raw_indices:type_name -> google.cloud.webrisk.v1.container.RawIndices + 13, // 15: google.cloud.webrisk.v1.container.ThreatEntryRemovals.rice_indices:type_name -> google.cloud.webrisk.v1.container.RiceDeltaEncoding + 1, // 16: google.cloud.webrisk.v1.container.ComputeThreatListDiffRequest.Constraints.supported_compressions:type_name -> google.cloud.webrisk.v1.container.CompressionType + 0, // 17: google.cloud.webrisk.v1.container.SearchUrisResponse.ThreatUri.threat_types:type_name -> google.cloud.webrisk.v1.container.ThreatType + 18, // 18: google.cloud.webrisk.v1.container.SearchUrisResponse.ThreatUri.expire_time:type_name -> google.protobuf.Timestamp + 0, // 19: google.cloud.webrisk.v1.container.SearchHashesResponse.ThreatHash.threat_types:type_name -> google.cloud.webrisk.v1.container.ThreatType + 18, // 20: google.cloud.webrisk.v1.container.SearchHashesResponse.ThreatHash.expire_time:type_name -> google.protobuf.Timestamp 21, // [21:21] is the sub-list for method output_type 21, // [21:21] is the sub-list for method input_type 21, // [21:21] is the sub-list for extension type_name diff --git a/internal/webrisk_proto/webrisk.proto b/internal/webrisk_proto/webrisk.proto index 6ca5548..e5127f9 100644 --- a/internal/webrisk_proto/webrisk.proto +++ b/internal/webrisk_proto/webrisk.proto @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC. +// Copyright 2023 Google LLC. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,7 +15,7 @@ syntax = "proto3"; -package google.cloud.webrisk.v1; +package google.cloud.webrisk.v1.container; import "google/protobuf/timestamp.proto"; diff --git a/urls.go b/urls.go index b1d4cb3..a4fb257 100644 --- a/urls.go +++ b/urls.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -39,14 +39,15 @@ import ( "errors" "fmt" "net" + + "golang.org/x/net/idna" + "net/url" "path" "regexp" "strconv" "strings" "unicode" - - "golang.org/x/net/idna" ) var ( @@ -142,6 +143,7 @@ func isUnicode(s string) bool { // split splits the string s around the delimiter c. // // Let string s be of the form: +// // "%s%s%s" % (t, c, u) // // Then split returns (t, u) if cutc is set, otherwise, it returns (t, c+u). @@ -274,15 +276,15 @@ func parseHost(hostish string) (host string, err error) { return "", err } // Then apply a to lower but only to ascii characters [a-z|A-Z]. - var temp_host bytes.Buffer + var tempHost bytes.Buffer for _, c := range []byte(host) { - if (c >= 0x41 && c <=0x5A) || (c >= 0x61 && c <= 0x7A) { - temp_host.WriteByte(byte(unicode.ToLower(rune(c)))) + if (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A) { + tempHost.WriteByte(byte(unicode.ToLower(rune(c)))) } else { - temp_host.WriteByte(c) + tempHost.WriteByte(c) } } - host = temp_host.String() + host = tempHost.String() // Then escape the result. host = escape(host) @@ -391,6 +393,7 @@ func parseIPAddress(iphostname string) string { // is usable as an IP address. // // For example: +// // s:"01234", n:2 => "2.156" // s:"0x10203040", n:4 => "16.32.48.64" func canonicalNum(s string, n int) string { diff --git a/urls_test.go b/urls_test.go index 145bde6..10007be 100644 --- a/urls_test.go +++ b/urls_test.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/webrisk_client.go b/webrisk_client.go index fef761f..f474639 100644 --- a/webrisk_client.go +++ b/webrisk_client.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -11,13 +11,7 @@ // 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 webrisk implements a client for the Web Risk API v4. -// API v4 emphasizes efficient usage of the network for bandwidth-constrained -// applications such as mobile devices. It achieves this by maintaining a small -// portion of the server state locally such that some queries can be answered -// immediately without any network requests. Thus, fewer API calls made, means -// less bandwidth is used. // // At a high-level, the implementation does the following: // @@ -83,13 +77,13 @@ const ( // DefaultServerURL is the default URL for the Web Risk API. DefaultServerURL = "webrisk.googleapis.com" - // DefaultUpdatePeriod is the default period for how often WebriskClient will + // DefaultUpdatePeriod is the default period for how often UpdateClient will // reload its blocklist database. DefaultUpdatePeriod = 30 * time.Minute - // DefaultID and DefaultVersion are the default client ID and Version - // strings to send with every API call. - DefaultID = "GoWebriskClient" + // DefaultID is the client ID sent with each API call. + DefaultID = "WebRiskContainer" + // DefaultVersion is the Version sent with each API call. DefaultVersion = "1.0.0" // DefaultRequestTimeout is the default amount of time a single @@ -111,20 +105,20 @@ func (tt ThreatType) String() string { return pb.ThreatType(tt).String() } // List of ThreatType constants. const ( - ThreatTypeUnspecified = ThreatType(pb.ThreatType_THREAT_TYPE_UNSPECIFIED) - ThreatTypeMalware = ThreatType(pb.ThreatType_MALWARE) - ThreatTypeSocialEngineering = ThreatType(pb.ThreatType_SOCIAL_ENGINEERING) - ThreatTypeUnwantedSoftware = ThreatType(pb.ThreatType_UNWANTED_SOFTWARE) + ThreatTypeUnspecified = ThreatType(pb.ThreatType_THREAT_TYPE_UNSPECIFIED) + ThreatTypeMalware = ThreatType(pb.ThreatType_MALWARE) + ThreatTypeSocialEngineering = ThreatType(pb.ThreatType_SOCIAL_ENGINEERING) + ThreatTypeUnwantedSoftware = ThreatType(pb.ThreatType_UNWANTED_SOFTWARE) ThreatTypeSocialEngineeringExtended = ThreatType(pb.ThreatType_SOCIAL_ENGINEERING_EXTENDED_COVERAGE) ) -// DefaultThreatLists is the default list of threat lists that WebriskClient -// will maintain. Do not modify this variable. +// DefaultThreatLists is the default list of threat lists that UpdateClient +// will maintain. If you modify this variable, you must refresh all saved database files. var DefaultThreatLists = []ThreatType{ ThreatTypeMalware, ThreatTypeSocialEngineering, - ThreatTypeSocialEngineeringExtended, ThreatTypeUnwantedSoftware, + ThreatTypeSocialEngineeringExtended, } // A URLThreat is a specialized ThreatType for the URL threat @@ -134,7 +128,7 @@ type URLThreat struct { ThreatType } -// Config sets up the WebriskClient object. +// Config sets up the UpdateClient object. type Config struct { // ServerURL is the URL for the Web Risk API server. // If empty, it defaults to DefaultServerURL. @@ -156,16 +150,16 @@ type Config struct { Version string // DBPath is a path to a persistent database file. - // If empty, WebriskClient operates in a non-persistent manner. + // If empty, UpdateClient operates in a non-persistent manner. // This means that blocklist results will not be cached beyond the lifetime - // of the WebriskClient object. + // of the UpdateClient object. DBPath string // UpdatePeriod determines how often we update the internal list database. // If zero value, it defaults to DefaultUpdatePeriod. UpdatePeriod time.Duration - // ThreatLists determines which threat lists that WebriskClient should + // ThreatLists determines which threat lists that UpdateClient should // subscribe to. The threats reported by LookupURLs will only be ones that // are specified by this list. // If empty, it defaults to DefaultThreatLists. @@ -174,7 +168,7 @@ type Config struct { // RequestTimeout determines the timeout value for the http client. RequestTimeout time.Duration - // Logger is an io.Writer that allows WebriskClient to write debug information + // Logger is an io.Writer that allows UpdateClient to write debug information // intended for human consumption. // If empty, no logs will be written. Logger io.Writer @@ -214,13 +208,13 @@ func (c Config) copy() Config { return c2 } -// WebriskClient is a client implementation of API v4. +// UpdateClient is a client implementation of API v4. // // It provides a set of lookup methods that allows the user to query whether // certain entries are considered a threat. The implementation manages all of // local database and caching that would normally be needed to interact // with the API server. -type WebriskClient struct { +type UpdateClient struct { stats Stats // Must be first for 64-bit alignment on non 64-bit systems. config Config api api @@ -235,7 +229,7 @@ type WebriskClient struct { done chan bool // Signals that the updater routine should stop } -// Stats records statistics regarding WebriskClient's operation. +// Stats records statistics regarding UpdateClient's operation. type Stats struct { QueriesByDatabase int64 // Number of queries satisfied by the database alone QueriesByCache int64 // Number of queries satisfied by the cache alone @@ -244,11 +238,11 @@ type Stats struct { DatabaseUpdateLag time.Duration // Duration since last *missed* update. 0 if next update is in the future. } -// NewWebriskClient creates a new WebriskClient. +// NewUpdateClient creates a new UpdateClient. // // The conf struct allows the user to configure many aspects of the -// WebriskClient's operation. -func NewWebriskClient(conf Config) (*WebriskClient, error) { +// UpdateClient's operation. +func NewUpdateClient(conf Config) (*UpdateClient, error) { conf = conf.copy() if !conf.setDefaults() { return nil, errors.New("webrisk: invalid configuration") @@ -265,7 +259,7 @@ func NewWebriskClient(conf Config) (*WebriskClient, error) { if conf.now == nil { conf.now = time.Now } - wr := &WebriskClient{ + wr := &UpdateClient{ config: conf, api: conf.api, c: cache{now: conf.now}, @@ -305,11 +299,11 @@ func NewWebriskClient(conf Config) (*WebriskClient, error) { return wr, nil } -// Status reports the status of WebriskClient. It returns some statistics +// Status reports the status of UpdateClient. It returns some statistics // regarding the operation, and an error representing the status of its // internal state. Most errors are transient and will recover themselves // after some period. -func (wr *WebriskClient) Status() (Stats, error) { +func (wr *UpdateClient) Status() (Stats, error) { stats := Stats{ QueriesByDatabase: atomic.LoadInt64(&wr.stats.QueriesByDatabase), QueriesByCache: atomic.LoadInt64(&wr.stats.QueriesByCache), @@ -322,8 +316,8 @@ func (wr *WebriskClient) Status() (Stats, error) { // WaitUntilReady blocks until the database is not in an error state. // Returns nil when the database is ready. Returns an error if the provided -// context is canceled or if the WebriskClient instance is Closed. -func (wr *WebriskClient) WaitUntilReady(ctx context.Context) error { +// context is canceled or if the UpdateClient instance is Closed. +func (wr *UpdateClient) WaitUntilReady(ctx context.Context) error { if atomic.LoadUint32(&wr.closed) == 1 { return errClosed } @@ -351,7 +345,7 @@ func (wr *WebriskClient) WaitUntilReady(ctx context.Context) error { // // If an error occurs, the caller should treat the threats list returned as a // best-effort response to the query. The results may be stale or be partial. -func (wr *WebriskClient) LookupURLs(urls []string) (threats [][]URLThreat, err error) { +func (wr *UpdateClient) LookupURLs(urls []string) (threats [][]URLThreat, err error) { threats, err = wr.LookupURLsContext(context.Background(), urls) return threats, err } @@ -361,7 +355,7 @@ func (wr *WebriskClient) LookupURLs(urls []string) (threats [][]URLThreat, err e // elapsed. It is safe to call this method concurrently. // // See LookupURLs for details on the returned results. -func (wr *WebriskClient) LookupURLsContext(ctx context.Context, urls []string) (threats [][]URLThreat, err error) { +func (wr *UpdateClient) LookupURLsContext(ctx context.Context, urls []string) (threats [][]URLThreat, err error) { ctx, cancel := context.WithTimeout(ctx, wr.config.RequestTimeout) defer cancel() @@ -487,13 +481,13 @@ func (wr *WebriskClient) LookupURLsContext(ctx context.Context, urls []string) ( } // TODO: Add other types of lookup when available. -// func (wr *WebriskClient) LookupBinaries(digests []string) (threats []BinaryThreat, err error) -// func (wr *WebriskClient) LookupAddresses(addrs []string) (threats [][]AddressThreat, err error) +// func (wr *UpdateClient) LookupBinaries(digests []string) (threats []BinaryThreat, err error) +// func (wr *UpdateClient) LookupAddresses(addrs []string) (threats [][]AddressThreat, err error) // updater is a blocking method that periodically updates the local database. // This should be run as a separate goroutine and will be automatically stopped // when wr.Close is called. -func (wr *WebriskClient) updater(delay time.Duration) { +func (wr *UpdateClient) updater(delay time.Duration) { for { wr.log.Printf("Next update in %v", delay) select { @@ -514,7 +508,7 @@ func (wr *WebriskClient) updater(delay time.Duration) { // Close cleans up all resources. // This method must not be called concurrently with other lookup methods. -func (wr *WebriskClient) Close() error { +func (wr *UpdateClient) Close() error { if atomic.LoadUint32(&wr.closed) == 0 { atomic.StoreUint32(&wr.closed, 1) close(wr.done) diff --git a/webrisk_client_system_test.go b/webrisk_client_system_test.go index e3dbd6d..2a74fbc 100644 --- a/webrisk_client_system_test.go +++ b/webrisk_client_system_test.go @@ -1,4 +1,4 @@ -// Copyright 2019 Google LLC +// Copyright 2023 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -103,7 +103,7 @@ func TestWebriskClient(t *testing.T) { t.Skip() } - sb, err := NewWebriskClient(Config{ + sb, err := NewUpdateClient(Config{ APIKey: apiKey, ID: "GoWebriskClientSystemTest", DBPath: "/tmp/webriskClient.db", From ef4e6cd29623cb863628d7a5f14c96c2a03bbb05 Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Fri, 27 Jan 2023 20:47:47 +0000 Subject: [PATCH 12/17] Internal change PiperOrigin-RevId: 505187398 --- README.md | 175 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 134 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index d06dfdd..3a62b3e 100644 --- a/README.md +++ b/README.md @@ -10,83 +10,176 @@ program is a command line service that can also be used to check URLs. This **README.md** is a quickstart guide on how to build, deploy, and use the WebRisk Go package. It can be used out-of-the-box. The GoDoc and API -documentation provide more details on fine tuning the parameters if desired. +documentation in the .go source files provide more details on fine tuning the +parameters if desired. +This client implements the [Update API](https://cloud.google.com/web-risk/docs/update-api), +and includes a simplified Dockerfile. It is not necessary to run as a container +to test the client or new blocklist. -# How to Build +This container branch also includes support for the +`SOCIAL_ENGINEERING_EXTENDED_COVERAGE` blocklist. -To download and install from the source, run the following command: +# Enable Web Risk + +To begin using Web Risk, you will need a GCP Account and a project to work in. + +1. Enable the Web Risk API (requires Billing). + +2. Generate an API Key. + +# Docker Container App Quickstart + +We have included a Dockerfile to accelerate and simplify onboarding. This +container wraps the `wrserver` binary detailed below. + +If you haven't already, you must install [Docker](https://www.docker.com/). + +## Clone and Build Container + +Building the container is straightforward. + +``` +# clone this repo into a local directory & switch to the container branch +> git clone -b container https://github.com/google/webrisk && cd webrisk + +# build the a docker container +> docker build -t wr-container . +``` + +## Run Container + +We supply the `APIKEY` as an environmental variable to the container at runtime +so that the API Key is not revealed as part of the docker file or in `docker ps`. +This example also provides a port binding. + +``` +> docker run -e APIKEY=XXXXXXXXXXXXXXXXXXXXXXX -p 8080:8080 wr-container +``` + +`wrserver` defaults to port 8080, but you can bind any port on the host machine. +See the [Docker documentation](https://docs.docker.com/config/containers/container-networking/) +for details. + +# Go Binary Quickstart | `wrlookup` example + +The Go Client can be compiled and run directly without Docker. In this example +we will use that to run the `wrlookup` binary that takes URLs from `STDIN` and +outputs to `STDOUT`. + +Before compiling from source you should [install Go](https://go.dev/doc/install) +and have some familiarity with Go development. See [here](https://go.dev/doc/tutorial/getting-started) +for a good place to get started. + +## Clone Source & Install Dependencies + +To download and install this branch from the source, run the following command: ``` -go get github.com/google/webrisk +# clone this repo into a local directory & switch to the container branch +> git clone -b container https://github.com/google/webrisk && cd webrisk + +# install dependencies +.../webrisk> go install ``` -The programs below execute from your `$GOPATH/bin` folder. -Add that to your `$PATH` for convenience: +## Build and Execute `wrlookup` + +After installing dependencies, you can build and run `wrlookup` ``` -export PATH=$PATH:$GOPATH/bin +# builds a wrlookup binary in the current directory +.../webrisk> go build -o wrlookup cmd/wrlookup/main.go + + +# run the binary and supply an API Key +.../webrisk> ./wrlookup -apikey=XXXXXXXXXXXXXXXXXXXXXXX ``` -The program expects an API key as a parameter, export it with the following -command for later use: +You should see some output similar to below as `wrlookup` starts up. ``` -export APIKEY=Your Api Key +webrisk: 2023/01/27 19:36:46 database.go:110: no database file specified +webrisk: 2023/01/27 19:36:53 database.go:384: database is now healthy +webrisk: 2023/01/27 19:36:53 webrisk_client.go:492: Next update in 30m29s ``` -# Proxy Server +`wrlookup` will take any URLs from `STDIN`. Test your configuration with a sample: -The `wrserver` server binary runs a WebRisk API lookup proxy that allows -users to check URLs via a simple JSON API. +``` +http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/ #input +Unsafe URL: [MALWARE] # output +``` + +An incorrect API Key or other auth error might result in an error as below: -1. Once the Go environment is setup, run the following command with your API key: +``` +webrisk: 2023/01/27 19:36:13 database.go:217: ListUpdate failure (1): webrisk: unexpected server response code: 400 +``` + +# Using `wrserver` + +`wrserver` runs a WebRisk API lookup proxy that allows users to check URLs via +a simple JSON API. This local API will use the API key supplied by the Docker +container or the command line that runs the binary. + +1. Start the `wrserver` by either running the container or binary. ``` - go get github.com/google/webrisk/cmd/wrserver - wrserver -apikey $APIKEY + # run in docker + > docker run -e APIKEY=XXXXXXXXXXXXXXXXXXXXXXX -p 8080:8080 + + # run from CLI, compile as above but use `wrserver` in place of `wrlookup` + > ./wrserver -apikey=XXXXXXXXXXXXXXXXXXXXXXX ``` - With the default settings this will start a local server at **127.0.0.1:8080**. + With the default settings this will start a local server at **0.0.0.0:8080**. + +2. `wrserver` serves a URL redirector listening on `/r` which will show an interstitial for anything marked unsafe. -2. The server also uses an URL redirector (listening on `/r`) to show an interstitial for anything marked unsafe. -If the URL is safe, the client is automatically redirected to the target. Else, an interstitial warning page is shown as recommended by Web Risk. -Try these URLs: + If the URL is safe, the client is automatically redirected to the target. + Otherwise an interstitial warning page is shown as recommended by Web Risk. + Try these URLs: ``` - 127.0.0.1:8080/r?url=http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/ - 127.0.0.1:8080/r?url=http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/SOCIAL_ENGINEERING/URL/ - 127.0.0.1:8080/r?url=http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/UNWANTED_SOFTWARE/URL/ - 127.0.0.1:8080/r?url=http://www.google.com/ + 0.0.0.0:8080/r?url=http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/ + 0.0.0.0:8080/r?url=http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/SOCIAL_ENGINEERING/URL/ + 0.0.0.0:8080/r?url=http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/UNWANTED_SOFTWARE/URL/ + 0.0.0.0:8080/r?url=http://www.google.com/ ``` -3. The server also has a lightweight implementation of the API v4 threatMatches endpoint. -To use the local proxy server to check a URL, send a POST request to `127.0.0.1:8080/v1beta1/uris:search` with the following JSON body: +3. The server also has a lightweight implementation of a [Web Risk Lookup API](https://cloud.google.com/web-risk/docs/lookup-api)-like endpoint at `v1/uris:search`. +To use the local endpoint to check a URL, send a POST request to `0.0.0.0:8080/v1/uris:search` with the a JSON body similar to the following. ```json { - "uri":"http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/", - "threatTypes":[ - "MALWARE" - ] - } + "uri":"http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/", + "threatTypes":[ + "MALWARE" + ] + } ``` -# Command-Line Lookup +4. Test with the following cURL command: -The `wrlookup` command-line binary is another example of how the Go Safe -Browsing library can be used to protect users from unsafe URLs. This -command-line tool filters unsafe URLs piped via STDIN. Example usage: + ``` + > curl -X POST 0.0.0.0:8080/v1/uris:search \ + -H 'Content-Type: application/json' \ + -d '{"uri":"http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/", "threatTypes":["MALWARE"]}' + ``` -``` -$ go get github.com/google/webrisk/cmd/wrlookup -$ echo "http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/" | wrlookup -apikey=$APIKEY -``` +There are two significant differences between this local endpoint and the +public `v1/uris:search` endpoint: + + - The public endpoint accepts `GET` requests instead of `POST` requests. + - The local `wrserver` endpoint uses the privacy-preserving and lower latency + [Update API](https://cloud.google.com/web-risk/docs/update-api) making it better + suited for higher-demand use cases. -# WebRisk System Test +## WebRisk System Test To perform an end-to-end test on the package with the WebRisk backend, -run the following command after exporting your API key: +run the following command after exporting your API key as $APIKEY: ``` go test github.com/google/webrisk -v -run TestWebriskClient From 69192101f00530e4b09017e4218196e095d8e9b9 Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Wed, 1 Mar 2023 09:45:29 -0800 Subject: [PATCH 13/17] Internal change PiperOrigin-RevId: 513262544 --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3a62b3e..23c223d 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Reference Implementation for the Usage of Google Cloud WebRisk APIs (Beta) The `webrisk` Go package can be used with the -[Google Cloud WebRisk APIs (Beta)](https://cloud.google.com/web-risk/) +[Google Cloud WebRisk APIs](https://cloud.google.com/web-risk/) to access the Google Cloud WebRisk lists of unsafe web resources. Inside the `cmd` sub-directory, you can find two programs: `wrlookup` and `wrserver`. The `wrserver` program creates a proxy local server to check URLs and a URL @@ -154,9 +154,7 @@ To use the local endpoint to check a URL, send a POST request to `0.0.0.0:8080/v ```json { "uri":"http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/", - "threatTypes":[ - "MALWARE" - ] + "threatTypes":["MALWARE"] } ``` From ff08494a683e284f4318b3ee95abd9e654d13980 Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Thu, 2 Mar 2023 11:19:47 -0800 Subject: [PATCH 14/17] Adds simple Github action to build a Docker image. Dockerfile runs all Go tests as part of the build step. PiperOrigin-RevId: 513590782 --- .github/workflows/docker_build.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 .github/workflows/docker_build.yml diff --git a/.github/workflows/docker_build.yml b/.github/workflows/docker_build.yml new file mode 100644 index 0000000..3dd6f4b --- /dev/null +++ b/.github/workflows/docker_build.yml @@ -0,0 +1,13 @@ +name: Docker build + +on: [push] + +jobs: + build: + # we are using ubuntu as it ships with docker pre-installed + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + # Our Dockerfile runs all of our Go Tests + - name: Build and Test Docker Image + run: docker build --tag wr-container . From 997df2fa16adf8a4c2afdc3b61f25773285c8c5d Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Wed, 8 Mar 2023 08:11:23 -0800 Subject: [PATCH 15/17] Adds new Github Action workflow `go-test-build` to test & build all Go code outside of Docker. Renames Docker workflow `job_id` from `build` to `docker-build`. PiperOrigin-RevId: 515040713 --- .github/workflows/docker_build.yml | 2 +- .github/workflows/go_tests.yml | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/go_tests.yml diff --git a/.github/workflows/docker_build.yml b/.github/workflows/docker_build.yml index 3dd6f4b..abc6899 100644 --- a/.github/workflows/docker_build.yml +++ b/.github/workflows/docker_build.yml @@ -3,7 +3,7 @@ name: Docker build on: [push] jobs: - build: + docker-build: # we are using ubuntu as it ships with docker pre-installed runs-on: ubuntu-latest steps: diff --git a/.github/workflows/go_tests.yml b/.github/workflows/go_tests.yml new file mode 100644 index 0000000..68d4365 --- /dev/null +++ b/.github/workflows/go_tests.yml @@ -0,0 +1,26 @@ +name: Go Test & Build + +on: [push] + +jobs: + go-test-build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Set up Go + uses: actions/setup-go@v3 + with: + go-version: 1.19 + + - name: Install Dependencies + run: go install ./ + + - name: Run Go Tests + run: go test -v ./ + + - name: Build wrlookup + run: go build -v -o wrlookup ./cmd/wrlookup/main.go + + - name: Build wrserver + run: go build -v -o wrserver ./cmd/wrserver/main.go From 5b0948ae4a6f8a641453261fbaf30267001e81af Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Fri, 10 Mar 2023 08:35:33 -0800 Subject: [PATCH 16/17] Rewrites README for Container App. PiperOrigin-RevId: 515645104 --- README.md | 228 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 149 insertions(+), 79 deletions(-) diff --git a/README.md b/README.md index 23c223d..49eb0cc 100644 --- a/README.md +++ b/README.md @@ -1,50 +1,72 @@ -# Reference Implementation for the Usage of Google Cloud WebRisk APIs (Beta) +# Web Risk Client App | Container & Go -The `webrisk` Go package can be used with the -[Google Cloud WebRisk APIs](https://cloud.google.com/web-risk/) -to access the Google Cloud WebRisk lists of unsafe web resources. Inside the -`cmd` sub-directory, you can find two programs: `wrlookup` and `wrserver`. The -`wrserver` program creates a proxy local server to check URLs and a URL -redirector to redirect users to a warning page for unsafe URLs. The `wrlookup` -program is a command line service that can also be used to check URLs. +[Web Risk](https://cloud.google.com/web-risk) is the enterprise version of +Google's [Safe Browsing API](https://safebrowsing.google.com/) that protects 5 +Billion devices globally from dangerous URLs including phishing, malware, +unwanted software, and social engineering. -This **README.md** is a quickstart guide on how to build, deploy, and use the -WebRisk Go package. It can be used out-of-the-box. The GoDoc and API -documentation in the .go source files provide more details on fine tuning the -parameters if desired. +This client implements the Web Risk [Update API](https://cloud.google.com/web-risk/docs/update-api), +which allows for URLs to be checked for badness via privacy-preserving and +low-latency API. It works out-of-the-box via either Docker or Go. -This client implements the [Update API](https://cloud.google.com/web-risk/docs/update-api), -and includes a simplified Dockerfile. It is not necessary to run as a container -to test the client or new blocklist. +This README provides a quickstart guide to running a client either with Docker +or as Go binaries. It also serves as a reference implementation of the API. The +GoDoc and API documentation in the `.go` source files provide more details on +fine-tuning the parameters if desired. -This container branch also includes support for the -`SOCIAL_ENGINEERING_EXTENDED_COVERAGE` blocklist. +Supported clients: + +- `wrserver` runs a thin HTTP client that can query URLs via a POST request or +a redirection endpoint that diverts bad URLs to a warning page. This is the +client wrapped by Docker. +- `wrlookup` is a command line service that takes URLs from `STDIN` and outputs results to `STDOUT`. It can +accept multiple URLs at a time on separate lines. + +Supported blocklists: + + - `MALWARE` + - `UNWANTED_SOFTWARE` + - `SOCIAL_ENGINEERING` + - [`SOCIAL_ENGINEERING_EXTENDED_COVERAGE`](https://cloud.google.com/web-risk/docs/extended-coverage) + +The client is originally forked from the [Safebrowsing Go Client](https://github.com/google/safebrowsing). # Enable Web Risk -To begin using Web Risk, you will need a GCP Account and a project to work in. +To begin using Web Risk, you will need a [GCP](https://cloud.google.com/) +Account and a project to work in. -1. Enable the Web Risk API (requires Billing). +1. Enable the [Web Risk API](https://console.cloud.google.com/marketplace/product/google/webrisk.googleapis.com). -2. Generate an API Key. +2. [Create an API Key](https://console.cloud.google.com/apis/credentials). -# Docker Container App Quickstart +3. [Enable Billing](https://console.cloud.google.com/billing) for your account +and make sure it's linked to your project. -We have included a Dockerfile to accelerate and simplify onboarding. This -container wraps the `wrserver` binary detailed below. +# Install Docker and/or Go + +To use the Container App, you will need [Docker](https://www.docker.com/). To +compile binaries from source or run tests install [Go](https://go.dev/). -If you haven't already, you must install [Docker](https://www.docker.com/). +# Docker Quickstart (recommended) + +We have included a Dockerfile to accelerate and simplify onboarding. This +container wraps the `wrserver` binary detailed [below](#using-wrserver). ## Clone and Build Container Building the container is straightforward. +First, clone this repo into a local directory & switch to the container branch + +``` +git clone -b container https://github.com/google/webrisk && cd webrisk ``` -# clone this repo into a local directory & switch to the container branch -> git clone -b container https://github.com/google/webrisk && cd webrisk -# build the a docker container -> docker build -t wr-container . +Build the container. This will run all tests before compiling `wrserver` into +a distroless container. +``` +docker build -tag wr-container . ``` ## Run Container @@ -54,13 +76,16 @@ so that the API Key is not revealed as part of the docker file or in `docker ps` This example also provides a port binding. ``` -> docker run -e APIKEY=XXXXXXXXXXXXXXXXXXXXXXX -p 8080:8080 wr-container +docker run -e APIKEY=XXXXXXXXXXXXXXXXXXXXXXX -p 8080:8080 wr-container ``` `wrserver` defaults to port 8080, but you can bind any port on the host machine. See the [Docker documentation](https://docs.docker.com/config/containers/container-networking/) for details. +See [Using `wrserver`](#using-wrserver) below for how to query URLs or use the +redirection endpoint. + # Go Binary Quickstart | `wrlookup` example The Go Client can be compiled and run directly without Docker. In this example @@ -73,14 +98,19 @@ for a good place to get started. ## Clone Source & Install Dependencies -To download and install this branch from the source, run the following command: +To download and install this branch from the source, run the following commands. + +First clone this repo into a local directory, switch to the container branch, +and switch to the webrisk directory. ``` -# clone this repo into a local directory & switch to the container branch -> git clone -b container https://github.com/google/webrisk && cd webrisk +git clone -b container https://github.com/google/webrisk && cd webrisk +``` + +Next, install dependencies. -# install dependencies -.../webrisk> go install +``` +go install . ``` ## Build and Execute `wrlookup` @@ -88,12 +118,13 @@ To download and install this branch from the source, run the following command: After installing dependencies, you can build and run `wrlookup` ``` -# builds a wrlookup binary in the current directory -.../webrisk> go build -o wrlookup cmd/wrlookup/main.go +go build -o wrlookup cmd/wrlookup/main.go +``` +Run the binary and supply an API key. -# run the binary and supply an API Key -.../webrisk> ./wrlookup -apikey=XXXXXXXXXXXXXXXXXXXXXXX +``` +./wrlookup -apikey=XXXXXXXXXXXXXXXXXXXXXXX ``` You should see some output similar to below as `wrlookup` starts up. @@ -107,14 +138,8 @@ webrisk: 2023/01/27 19:36:53 webrisk_client.go:492: Next update in 30m29s `wrlookup` will take any URLs from `STDIN`. Test your configuration with a sample: ``` -http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/ #input -Unsafe URL: [MALWARE] # output -``` - -An incorrect API Key or other auth error might result in an error as below: - -``` -webrisk: 2023/01/27 19:36:13 database.go:217: ListUpdate failure (1): webrisk: unexpected server response code: 400 +http://testsafebrowsing.appspot.com/s/social_engineering_extended_coverage.html #input +Unsafe URL: [SOCIAL_ENGINEERING_EXTENDED_COVERAGE] # output ``` # Using `wrserver` @@ -123,57 +148,102 @@ webrisk: 2023/01/27 19:36:13 database.go:217: ListUpdate failure (1): webrisk: u a simple JSON API. This local API will use the API key supplied by the Docker container or the command line that runs the binary. -1. Start the `wrserver` by either running the container or binary. +First start the `wrserver` by either running the container or binary. + +To run in Docker: + +``` +docker run -e APIKEY=XXXXXXXXXXXXXXXXXXXXXXX -p 8080:8080 +``` - ``` - # run in docker - > docker run -e APIKEY=XXXXXXXXXXXXXXXXXXXXXXX -p 8080:8080 +To run from a CLI, compile as [`wrlookup`](#build-and-execute-wrlookup) above +and run: - # run from CLI, compile as above but use `wrserver` in place of `wrlookup` - > ./wrserver -apikey=XXXXXXXXXXXXXXXXXXXXXXX - ``` +``` +./wrserver -apikey=XXXXXXXXXXXXXXXXXXXXXXX +``` - With the default settings this will start a local server at **0.0.0.0:8080**. +With the default settings this will start a local server at **0.0.0.0:8080**. -2. `wrserver` serves a URL redirector listening on `/r` which will show an interstitial for anything marked unsafe. +The server has a lightweight implementation of a +[Web Risk Lookup API](https://cloud.google.com/web-risk/docs/lookup-api)-like +endpoint at `v1/uris:search`. To use the local endpoint to check a URL, send a +POST request to `0.0.0.0:8080/v1/uris:search` with the a JSON body similar to +the following. - If the URL is safe, the client is automatically redirected to the target. - Otherwise an interstitial warning page is shown as recommended by Web Risk. - Try these URLs: +```json +{ + "uri":"http://testsafebrowsing.appspot.com/s/social_engineering_extended_coverage.html", + "threatTypes":["MALWARE","SOCIAL_ENGINEERING","SOCIAL_ENGINEERING_EXTENDED_COVERAGE"] +} +``` - ``` - 0.0.0.0:8080/r?url=http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/ - 0.0.0.0:8080/r?url=http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/SOCIAL_ENGINEERING/URL/ - 0.0.0.0:8080/r?url=http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/UNWANTED_SOFTWARE/URL/ - 0.0.0.0:8080/r?url=http://www.google.com/ - ``` +A sample cURL command: -3. The server also has a lightweight implementation of a [Web Risk Lookup API](https://cloud.google.com/web-risk/docs/lookup-api)-like endpoint at `v1/uris:search`. -To use the local endpoint to check a URL, send a POST request to `0.0.0.0:8080/v1/uris:search` with the a JSON body similar to the following. +``` +curl -H 'Content-Type: application/json' \ + -d '{"uri":"http://testsafebrowsing.appspot.com/s/social_engineering_extended_coverage.html","threatTypes":["MALWARE","SOCIAL_ENGINEERING","SOCIAL_ENGINEERING_EXTENDED_COVERAGE"]}' \ + -X POST '0.0.0.0:8080/v1/uris:search' +``` - ```json - { - "uri":"http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/", - "threatTypes":["MALWARE"] - } - ``` +See [Sample URLs](#sample-urls) below to test the different blocklists. -4. Test with the following cURL command: +`wrserver` also serves a URL redirector listening on `/r?url=...` which will +show an interstitial for anything marked unsafe. - ``` - > curl -X POST 0.0.0.0:8080/v1/uris:search \ - -H 'Content-Type: application/json' \ - -d '{"uri":"http://testsafebrowsing.appspot.com/apiv4/ANY_PLATFORM/MALWARE/URL/", "threatTypes":["MALWARE"]}' - ``` +If the URL is safe, the client is automatically redirected to the target. +Otherwise an interstitial warning page is shown as recommended by Web Risk. + +Try some sample URLs: + +``` +http://0.0.0.0:8080/r?url=https://testsafebrowsing.appspot.com/s/social_engineering_extended_coverage.html +http://0.0.0.0:8080/r?url=https://testsafebrowsing.appspot.com/s/malware.html +http://0.0.0.0:8080/r?url=https://www.google.com/ +``` + +### Differences from Web Risk Lookup API There are two significant differences between this local endpoint and the -public `v1/uris:search` endpoint: +public [`v1/uris:search` endpoint](https://cloud.google.com/web-risk/docs/lookup-api): - The public endpoint accepts `GET` requests instead of `POST` requests. - The local `wrserver` endpoint uses the privacy-preserving and lower latency [Update API](https://cloud.google.com/web-risk/docs/update-api) making it better suited for higher-demand use cases. +# Sample URLs + +For testing the blocklists, you can use the following URLs: + +- Phishing / Social Engineering: https://testsafebrowsing.appspot.com/s/phishing.html +- Malware: https://testsafebrowsing.appspot.com/s/malware.html +- Unwanted Software: https://testsafebrowsing.appspot.com/s/unwanted.html +- Social Engineering Extended Coverage: https://testsafebrowsing.appspot.com/s/social_engineering_extended_coverage.html + +# Troubleshooting + +## 4XX Errors + +If you start the client without proper credentials or project set up, you will +see an error similar to what is shown below on startup: + +``` +webrisk: 2023/01/27 19:36:13 database.go:217: ListUpdate failure (1): webrisk: unexpected server response code: 400 +``` + +For 400 errors, this usually means the API key is incorrect or was not supplied +correctly. + +For 403 errors, this could mean the Web Risk API is not enabled for your project +**or** your project does not have Billing enabled. + +# About the Social Engineering Extended Coverage List + +This is a newer blocklist that includes a greater range of risky URLs that +are not included in the Safebrowsing blocklists shipped to most browsers. +The extended coverage list offers significantly more coverage, but may have +a higher number of false positives. For more details, see [here](https://cloud.google.com/web-risk/docs/extended-coverage). ## WebRisk System Test To perform an end-to-end test on the package with the WebRisk backend, From 8bb8e7f872f9952876af570179b39f2aea7f3e4a Mon Sep 17 00:00:00 2001 From: Rim Vilgalys Date: Mon, 13 Mar 2023 08:31:36 -0700 Subject: [PATCH 17/17] Updates to README before merging branch back to master. PiperOrigin-RevId: 516218879 --- README.md | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 49eb0cc..ec682a3 100644 --- a/README.md +++ b/README.md @@ -57,16 +57,16 @@ container wraps the `wrserver` binary detailed [below](#using-wrserver). Building the container is straightforward. -First, clone this repo into a local directory & switch to the container branch +First, clone this repo into a local directory. ``` -git clone -b container https://github.com/google/webrisk && cd webrisk +git clone https://github.com/google/webrisk && cd webrisk ``` Build the container. This will run all tests before compiling `wrserver` into a distroless container. ``` -docker build -tag wr-container . +docker build --tag wr-container . ``` ## Run Container @@ -100,11 +100,11 @@ for a good place to get started. To download and install this branch from the source, run the following commands. -First clone this repo into a local directory, switch to the container branch, -and switch to the webrisk directory. +First clone this repo into a local directory and switch to the webrisk +directory. ``` -git clone -b container https://github.com/google/webrisk && cd webrisk +git clone https://github.com/google/webrisk && cd webrisk ``` Next, install dependencies. @@ -173,8 +173,7 @@ the following. ```json { - "uri":"http://testsafebrowsing.appspot.com/s/social_engineering_extended_coverage.html", - "threatTypes":["MALWARE","SOCIAL_ENGINEERING","SOCIAL_ENGINEERING_EXTENDED_COVERAGE"] + "uri":"http://testsafebrowsing.appspot.com/s/social_engineering_extended_coverage.html" } ``` @@ -182,7 +181,7 @@ A sample cURL command: ``` curl -H 'Content-Type: application/json' \ - -d '{"uri":"http://testsafebrowsing.appspot.com/s/social_engineering_extended_coverage.html","threatTypes":["MALWARE","SOCIAL_ENGINEERING","SOCIAL_ENGINEERING_EXTENDED_COVERAGE"]}' \ + -d '{"uri":"http://testsafebrowsing.appspot.com/s/social_engineering_extended_coverage.html"}' \ -X POST '0.0.0.0:8080/v1/uris:search' ```