diff --git a/client/internal/config.go b/client/internal/config.go index c50260707cd..082424c1ae2 100644 --- a/client/internal/config.go +++ b/client/internal/config.go @@ -110,7 +110,7 @@ func GetConfig(managementURL string, configPath string, preSharedKey string) (*C // generateKey generates a new Wireguard private key func generateKey() string { - key, err := wgtypes.GenerateKey() + key, err := wgtypes.GeneratePrivateKey() if err != nil { panic(err) } diff --git a/management/proto/management.pb.go b/management/proto/management.pb.go index eb006dd6b30..a527a10b2e5 100644 --- a/management/proto/management.pb.go +++ b/management/proto/management.pb.go @@ -85,6 +85,8 @@ type EncryptedMessage struct { WgPubKey string `protobuf:"bytes,1,opt,name=wgPubKey,proto3" json:"wgPubKey,omitempty"` // encrypted message Body Body []byte `protobuf:"bytes,2,opt,name=body,proto3" json:"body,omitempty"` + // Version of the Wiretrustee Management Service protocol + Version int32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"` } func (x *EncryptedMessage) Reset() { @@ -133,6 +135,13 @@ func (x *EncryptedMessage) GetBody() []byte { return nil } +func (x *EncryptedMessage) GetVersion() int32 { + if x != nil { + return x.Version + } + return 0 +} + type SyncRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -178,11 +187,15 @@ type SyncResponse struct { unknownFields protoimpl.UnknownFields // Global config - WiretrusteeConfig *WiretrusteeConfig `protobuf:"bytes,1,opt,name=wiretrusteeConfig,proto3" json:"wiretrusteeConfig,omitempty"` - PeerConfig *PeerConfig `protobuf:"bytes,2,opt,name=peerConfig,proto3" json:"peerConfig,omitempty"` - RemotePeers []*RemotePeerConfig `protobuf:"bytes,3,rep,name=remotePeers,proto3" json:"remotePeers,omitempty"` + WiretrusteeConfig *WiretrusteeConfig `protobuf:"bytes,1,opt,name=wiretrusteeConfig,proto3" json:"wiretrusteeConfig,omitempty"` + // Deprecated. Use NetworkMap.PeerConfig + PeerConfig *PeerConfig `protobuf:"bytes,2,opt,name=peerConfig,proto3" json:"peerConfig,omitempty"` + // Deprecated. Use NetworkMap.RemotePeerConfig + RemotePeers []*RemotePeerConfig `protobuf:"bytes,3,rep,name=remotePeers,proto3" json:"remotePeers,omitempty"` // Indicates whether remotePeers array is empty or not to bypass protobuf null and empty array equality. - RemotePeersIsEmpty bool `protobuf:"varint,4,opt,name=remotePeersIsEmpty,proto3" json:"remotePeersIsEmpty,omitempty"` + // Deprecated. Use NetworkMap.remotePeersIsEmpty + RemotePeersIsEmpty bool `protobuf:"varint,4,opt,name=remotePeersIsEmpty,proto3" json:"remotePeersIsEmpty,omitempty"` + NetworkMap *NetworkMap `protobuf:"bytes,5,opt,name=NetworkMap,proto3" json:"NetworkMap,omitempty"` } func (x *SyncResponse) Reset() { @@ -245,6 +258,13 @@ func (x *SyncResponse) GetRemotePeersIsEmpty() bool { return false } +func (x *SyncResponse) GetNetworkMap() *NetworkMap { + if x != nil { + return x.NetworkMap + } + return nil +} + type LoginRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -464,6 +484,8 @@ type ServerKeyResponse struct { Key string `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` // Key expiration timestamp after which the key should be fetched again by the client ExpiresAt *timestamp.Timestamp `protobuf:"bytes,2,opt,name=expiresAt,proto3" json:"expiresAt,omitempty"` + // Version of the Wiretrustee Management Service protocol + Version int32 `protobuf:"varint,3,opt,name=version,proto3" json:"version,omitempty"` } func (x *ServerKeyResponse) Reset() { @@ -512,6 +534,13 @@ func (x *ServerKeyResponse) GetExpiresAt() *timestamp.Timestamp { return nil } +func (x *ServerKeyResponse) GetVersion() int32 { + if x != nil { + return x.Version + } + return 0 +} + type Empty struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -798,6 +827,84 @@ func (x *PeerConfig) GetDns() string { return "" } +// NetworkMap represents a network state of the peer with the corresponding configuration parameters to establish peer-to-peer connections +type NetworkMap struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // Serial is an ID of the network state to be used by clients to order updates. + // The larger the Serial the newer the configuration. + // E.g. the client app should keep track of this id locally and discard all the configurations with a lower value + Serial uint64 `protobuf:"varint,1,opt,name=Serial,proto3" json:"Serial,omitempty"` + // PeerConfig represents configuration of a peer + PeerConfig *PeerConfig `protobuf:"bytes,2,opt,name=peerConfig,proto3" json:"peerConfig,omitempty"` + // RemotePeerConfig represents a list of remote peers that the receiver can connect to + RemotePeers []*RemotePeerConfig `protobuf:"bytes,3,rep,name=remotePeers,proto3" json:"remotePeers,omitempty"` + // Indicates whether remotePeers array is empty or not to bypass protobuf null and empty array equality. + RemotePeersIsEmpty bool `protobuf:"varint,4,opt,name=remotePeersIsEmpty,proto3" json:"remotePeersIsEmpty,omitempty"` +} + +func (x *NetworkMap) Reset() { + *x = NetworkMap{} + if protoimpl.UnsafeEnabled { + mi := &file_management_proto_msgTypes[12] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetworkMap) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetworkMap) ProtoMessage() {} + +func (x *NetworkMap) ProtoReflect() protoreflect.Message { + mi := &file_management_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 NetworkMap.ProtoReflect.Descriptor instead. +func (*NetworkMap) Descriptor() ([]byte, []int) { + return file_management_proto_rawDescGZIP(), []int{12} +} + +func (x *NetworkMap) GetSerial() uint64 { + if x != nil { + return x.Serial + } + return 0 +} + +func (x *NetworkMap) GetPeerConfig() *PeerConfig { + if x != nil { + return x.PeerConfig + } + return nil +} + +func (x *NetworkMap) GetRemotePeers() []*RemotePeerConfig { + if x != nil { + return x.RemotePeers + } + return nil +} + +func (x *NetworkMap) GetRemotePeersIsEmpty() bool { + if x != nil { + return x.RemotePeersIsEmpty + } + return false +} + // RemotePeerConfig represents a configuration of a remote peer. // The properties are used to configure Wireguard Peers sections type RemotePeerConfig struct { @@ -814,7 +921,7 @@ type RemotePeerConfig struct { func (x *RemotePeerConfig) Reset() { *x = RemotePeerConfig{} if protoimpl.UnsafeEnabled { - mi := &file_management_proto_msgTypes[12] + mi := &file_management_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -827,7 +934,7 @@ func (x *RemotePeerConfig) String() string { func (*RemotePeerConfig) ProtoMessage() {} func (x *RemotePeerConfig) ProtoReflect() protoreflect.Message { - mi := &file_management_proto_msgTypes[12] + mi := &file_management_proto_msgTypes[13] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -840,7 +947,7 @@ func (x *RemotePeerConfig) ProtoReflect() protoreflect.Message { // Deprecated: Use RemotePeerConfig.ProtoReflect.Descriptor instead. func (*RemotePeerConfig) Descriptor() ([]byte, []int) { - return file_management_proto_rawDescGZIP(), []int{12} + return file_management_proto_rawDescGZIP(), []int{13} } func (x *RemotePeerConfig) GetWgPubKey() string { @@ -864,12 +971,52 @@ var file_management_proto_rawDesc = []byte{ 0x74, 0x6f, 0x12, 0x0a, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 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, - 0x42, 0x0a, 0x10, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, + 0x5c, 0x0a, 0x10, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x67, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x67, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x62, - 0x6f, 0x64, 0x79, 0x22, 0x0d, 0x0a, 0x0b, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x22, 0x83, 0x02, 0x0a, 0x0c, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6f, 0x64, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x0d, 0x0a, + 0x0b, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xbb, 0x02, 0x0a, + 0x0c, 0x53, 0x79, 0x6e, 0x63, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, + 0x11, 0x77, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x57, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, + 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x77, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, + 0x73, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x0a, 0x70, 0x65, + 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, + 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x65, 0x65, 0x72, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x3e, 0x0a, 0x0b, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, + 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, + 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, + 0x73, 0x49, 0x73, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, + 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x49, 0x73, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x12, 0x36, 0x0a, 0x0a, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4d, 0x61, 0x70, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4d, 0x61, 0x70, 0x52, 0x0a, + 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4d, 0x61, 0x70, 0x22, 0x5a, 0x0a, 0x0c, 0x4c, 0x6f, + 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, + 0x74, 0x75, 0x70, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, + 0x74, 0x75, 0x70, 0x4b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4d, 0x65, 0x74, 0x61, + 0x52, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x22, 0xc8, 0x01, 0x0a, 0x0e, 0x50, 0x65, 0x65, 0x72, 0x53, + 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, + 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, + 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x6f, 0x4f, 0x53, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x67, 0x6f, 0x4f, 0x53, 0x12, 0x16, 0x0a, 0x06, 0x6b, 0x65, 0x72, + 0x6e, 0x65, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6b, 0x65, 0x72, 0x6e, 0x65, + 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x63, 0x6f, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x4f, 0x53, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x4f, + 0x53, 0x12, 0x2e, 0x0a, 0x12, 0x77, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x77, + 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x22, 0x94, 0x01, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4b, 0x0a, 0x11, 0x77, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x57, 0x69, 0x72, 0x65, @@ -878,104 +1025,84 @@ var file_management_proto_rawDesc = []byte{ 0x12, 0x36, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x65, - 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3e, 0x0a, 0x0b, 0x72, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1c, 0x2e, - 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x6d, 0x6f, 0x74, - 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x72, 0x65, 0x6d, - 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x72, 0x65, 0x6d, 0x6f, - 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x49, 0x73, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, - 0x73, 0x49, 0x73, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x5a, 0x0a, 0x0c, 0x4c, 0x6f, 0x67, 0x69, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x73, 0x65, 0x74, 0x75, - 0x70, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73, 0x65, 0x74, 0x75, - 0x70, 0x4b, 0x65, 0x79, 0x12, 0x2e, 0x0a, 0x04, 0x6d, 0x65, 0x74, 0x61, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, - 0x50, 0x65, 0x65, 0x72, 0x53, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x52, 0x04, - 0x6d, 0x65, 0x74, 0x61, 0x22, 0xc8, 0x01, 0x0a, 0x0e, 0x50, 0x65, 0x65, 0x72, 0x53, 0x79, 0x73, - 0x74, 0x65, 0x6d, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1a, 0x0a, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x68, 0x6f, 0x73, 0x74, 0x6e, - 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x67, 0x6f, 0x4f, 0x53, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x67, 0x6f, 0x4f, 0x53, 0x12, 0x16, 0x0a, 0x06, 0x6b, 0x65, 0x72, 0x6e, 0x65, - 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x6c, 0x12, - 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, - 0x6f, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, - 0x0e, 0x0a, 0x02, 0x4f, 0x53, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x4f, 0x53, 0x12, - 0x2e, 0x0a, 0x12, 0x77, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x56, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x77, 0x69, 0x72, - 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, - 0x94, 0x01, 0x0a, 0x0d, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x4b, 0x0a, 0x11, 0x77, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x6d, - 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x57, 0x69, 0x72, 0x65, 0x74, 0x72, - 0x75, 0x73, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x11, 0x77, 0x69, 0x72, - 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, - 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, - 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x70, 0x65, 0x65, 0x72, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x5f, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6b, - 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x38, 0x0a, - 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x65, 0x78, - 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x22, 0xa8, 0x01, 0x0a, 0x11, 0x57, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2c, 0x0a, 0x05, 0x73, 0x74, 0x75, 0x6e, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x73, - 0x74, 0x75, 0x6e, 0x73, 0x12, 0x35, 0x0a, 0x05, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, - 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x06, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x52, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x22, 0x98, 0x01, 0x0a, 0x0a, - 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, - 0x69, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x3b, 0x0a, 0x08, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, - 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x6f, 0x73, 0x74, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, - 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x3b, 0x0a, 0x08, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x00, 0x12, 0x07, - 0x0a, 0x03, 0x54, 0x43, 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, - 0x02, 0x12, 0x09, 0x0a, 0x05, 0x48, 0x54, 0x54, 0x50, 0x53, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, - 0x44, 0x54, 0x4c, 0x53, 0x10, 0x04, 0x22, 0x7d, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, - 0x74, 0x65, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, - 0x0a, 0x68, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x79, 0x0a, 0x11, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x10, 0x0a, + 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, + 0x38, 0x0a, 0x09, 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, + 0x65, 0x78, 0x70, 0x69, 0x72, 0x65, 0x73, 0x41, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x22, 0x07, 0x0a, 0x05, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0xa8, 0x01, 0x0a, + 0x11, 0x57, 0x69, 0x72, 0x65, 0x74, 0x72, 0x75, 0x73, 0x74, 0x65, 0x65, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x12, 0x2c, 0x0a, 0x05, 0x73, 0x74, 0x75, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x48, - 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x68, 0x6f, 0x73, 0x74, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, - 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, - 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x38, 0x0a, 0x0a, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x10, 0x0a, - 0x03, 0x64, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x6e, 0x73, 0x22, - 0x4e, 0x0a, 0x10, 0x52, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x12, 0x1a, 0x0a, 0x08, 0x77, 0x67, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x67, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, - 0x1e, 0x0a, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x49, 0x70, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x49, 0x70, 0x73, 0x32, - 0x9b, 0x02, 0x0a, 0x11, 0x4d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x45, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x1c, - 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, - 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, - 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x04, - 0x53, 0x79, 0x6e, 0x63, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, - 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x22, 0x00, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x4b, 0x65, 0x79, 0x12, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1d, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x09, 0x69, 0x73, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x79, 0x12, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x08, 0x5a, - 0x06, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x05, 0x73, 0x74, 0x75, 0x6e, 0x73, + 0x12, 0x35, 0x0a, 0x05, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1f, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x72, 0x6f, + 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x52, 0x05, 0x74, 0x75, 0x72, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x06, 0x73, 0x69, 0x67, 0x6e, 0x61, + 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x06, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x22, 0x98, 0x01, 0x0a, 0x0a, 0x48, 0x6f, 0x73, 0x74, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x10, 0x0a, 0x03, 0x75, 0x72, 0x69, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x75, 0x72, 0x69, 0x12, 0x3b, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x6d, 0x61, 0x6e, + 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x22, 0x3b, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, + 0x6c, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, + 0x50, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x54, 0x54, 0x50, 0x10, 0x02, 0x12, 0x09, 0x0a, + 0x05, 0x48, 0x54, 0x54, 0x50, 0x53, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x54, 0x4c, 0x53, + 0x10, 0x04, 0x22, 0x7d, 0x0a, 0x13, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x65, 0x64, 0x48, + 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x36, 0x0a, 0x0a, 0x68, 0x6f, 0x73, + 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, + 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x48, 0x6f, 0x73, 0x74, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, 0x68, 0x6f, 0x73, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, + 0x64, 0x22, 0x38, 0x0a, 0x0a, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, + 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x64, 0x6e, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x64, 0x6e, 0x73, 0x22, 0xcc, 0x01, 0x0a, 0x0a, + 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x4d, 0x61, 0x70, 0x12, 0x16, 0x0a, 0x06, 0x53, 0x65, + 0x72, 0x69, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x53, 0x65, 0x72, 0x69, + 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x0a, 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0a, + 0x70, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3e, 0x0a, 0x0b, 0x72, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x6d, + 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x72, + 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x12, 0x2e, 0x0a, 0x12, 0x72, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x73, 0x49, 0x73, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, + 0x65, 0x72, 0x73, 0x49, 0x73, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x4e, 0x0a, 0x10, 0x52, 0x65, + 0x6d, 0x6f, 0x74, 0x65, 0x50, 0x65, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x1a, + 0x0a, 0x08, 0x77, 0x67, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x77, 0x67, 0x50, 0x75, 0x62, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x49, 0x70, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0a, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x65, 0x64, 0x49, 0x70, 0x73, 0x32, 0x9b, 0x02, 0x0a, 0x11, 0x4d, + 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x12, 0x45, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, + 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x04, 0x53, 0x79, 0x6e, 0x63, 0x12, + 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, + 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, + 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, + 0x42, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x12, + 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x1d, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x12, 0x33, 0x0a, 0x09, 0x69, 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, + 0x12, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x08, 0x5a, 0x06, 0x2f, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -991,7 +1118,7 @@ func file_management_proto_rawDescGZIP() []byte { } var file_management_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_management_proto_msgTypes = make([]protoimpl.MessageInfo, 13) +var file_management_proto_msgTypes = make([]protoimpl.MessageInfo, 14) var file_management_proto_goTypes = []interface{}{ (HostConfig_Protocol)(0), // 0: management.HostConfig.Protocol (*EncryptedMessage)(nil), // 1: management.EncryptedMessage @@ -1006,35 +1133,39 @@ var file_management_proto_goTypes = []interface{}{ (*HostConfig)(nil), // 10: management.HostConfig (*ProtectedHostConfig)(nil), // 11: management.ProtectedHostConfig (*PeerConfig)(nil), // 12: management.PeerConfig - (*RemotePeerConfig)(nil), // 13: management.RemotePeerConfig - (*timestamp.Timestamp)(nil), // 14: google.protobuf.Timestamp + (*NetworkMap)(nil), // 13: management.NetworkMap + (*RemotePeerConfig)(nil), // 14: management.RemotePeerConfig + (*timestamp.Timestamp)(nil), // 15: google.protobuf.Timestamp } var file_management_proto_depIdxs = []int32{ 9, // 0: management.SyncResponse.wiretrusteeConfig:type_name -> management.WiretrusteeConfig 12, // 1: management.SyncResponse.peerConfig:type_name -> management.PeerConfig - 13, // 2: management.SyncResponse.remotePeers:type_name -> management.RemotePeerConfig - 5, // 3: management.LoginRequest.meta:type_name -> management.PeerSystemMeta - 9, // 4: management.LoginResponse.wiretrusteeConfig:type_name -> management.WiretrusteeConfig - 12, // 5: management.LoginResponse.peerConfig:type_name -> management.PeerConfig - 14, // 6: management.ServerKeyResponse.expiresAt:type_name -> google.protobuf.Timestamp - 10, // 7: management.WiretrusteeConfig.stuns:type_name -> management.HostConfig - 11, // 8: management.WiretrusteeConfig.turns:type_name -> management.ProtectedHostConfig - 10, // 9: management.WiretrusteeConfig.signal:type_name -> management.HostConfig - 0, // 10: management.HostConfig.protocol:type_name -> management.HostConfig.Protocol - 10, // 11: management.ProtectedHostConfig.hostConfig:type_name -> management.HostConfig - 1, // 12: management.ManagementService.Login:input_type -> management.EncryptedMessage - 1, // 13: management.ManagementService.Sync:input_type -> management.EncryptedMessage - 8, // 14: management.ManagementService.GetServerKey:input_type -> management.Empty - 8, // 15: management.ManagementService.isHealthy:input_type -> management.Empty - 1, // 16: management.ManagementService.Login:output_type -> management.EncryptedMessage - 1, // 17: management.ManagementService.Sync:output_type -> management.EncryptedMessage - 7, // 18: management.ManagementService.GetServerKey:output_type -> management.ServerKeyResponse - 8, // 19: management.ManagementService.isHealthy:output_type -> management.Empty - 16, // [16:20] is the sub-list for method output_type - 12, // [12:16] is the sub-list for method input_type - 12, // [12:12] is the sub-list for extension type_name - 12, // [12:12] is the sub-list for extension extendee - 0, // [0:12] is the sub-list for field type_name + 14, // 2: management.SyncResponse.remotePeers:type_name -> management.RemotePeerConfig + 13, // 3: management.SyncResponse.NetworkMap:type_name -> management.NetworkMap + 5, // 4: management.LoginRequest.meta:type_name -> management.PeerSystemMeta + 9, // 5: management.LoginResponse.wiretrusteeConfig:type_name -> management.WiretrusteeConfig + 12, // 6: management.LoginResponse.peerConfig:type_name -> management.PeerConfig + 15, // 7: management.ServerKeyResponse.expiresAt:type_name -> google.protobuf.Timestamp + 10, // 8: management.WiretrusteeConfig.stuns:type_name -> management.HostConfig + 11, // 9: management.WiretrusteeConfig.turns:type_name -> management.ProtectedHostConfig + 10, // 10: management.WiretrusteeConfig.signal:type_name -> management.HostConfig + 0, // 11: management.HostConfig.protocol:type_name -> management.HostConfig.Protocol + 10, // 12: management.ProtectedHostConfig.hostConfig:type_name -> management.HostConfig + 12, // 13: management.NetworkMap.peerConfig:type_name -> management.PeerConfig + 14, // 14: management.NetworkMap.remotePeers:type_name -> management.RemotePeerConfig + 1, // 15: management.ManagementService.Login:input_type -> management.EncryptedMessage + 1, // 16: management.ManagementService.Sync:input_type -> management.EncryptedMessage + 8, // 17: management.ManagementService.GetServerKey:input_type -> management.Empty + 8, // 18: management.ManagementService.isHealthy:input_type -> management.Empty + 1, // 19: management.ManagementService.Login:output_type -> management.EncryptedMessage + 1, // 20: management.ManagementService.Sync:output_type -> management.EncryptedMessage + 7, // 21: management.ManagementService.GetServerKey:output_type -> management.ServerKeyResponse + 8, // 22: management.ManagementService.isHealthy:output_type -> management.Empty + 19, // [19:23] is the sub-list for method output_type + 15, // [15:19] is the sub-list for method input_type + 15, // [15:15] is the sub-list for extension type_name + 15, // [15:15] is the sub-list for extension extendee + 0, // [0:15] is the sub-list for field type_name } func init() { file_management_proto_init() } @@ -1188,6 +1319,18 @@ func file_management_proto_init() { } } file_management_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetworkMap); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_management_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*RemotePeerConfig); i { case 0: return &v.state @@ -1206,7 +1349,7 @@ func file_management_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_management_proto_rawDesc, NumEnums: 1, - NumMessages: 13, + NumMessages: 14, NumExtensions: 0, NumServices: 1, }, diff --git a/management/proto/management.proto b/management/proto/management.proto index cc80c9580d4..bf3454199b6 100644 --- a/management/proto/management.proto +++ b/management/proto/management.proto @@ -30,20 +30,29 @@ message EncryptedMessage { // encrypted message Body bytes body = 2; + // Version of the Wiretrustee Management Service protocol + int32 version = 3; } message SyncRequest {} // SyncResponse represents a state that should be applied to the local peer (e.g. Wiretrustee servers config as well as local peer and remote peers configs) message SyncResponse { + // Global config WiretrusteeConfig wiretrusteeConfig = 1; + // Deprecated. Use NetworkMap.PeerConfig PeerConfig peerConfig = 2; + // Deprecated. Use NetworkMap.RemotePeerConfig repeated RemotePeerConfig remotePeers = 3; + // Indicates whether remotePeers array is empty or not to bypass protobuf null and empty array equality. + // Deprecated. Use NetworkMap.remotePeersIsEmpty bool remotePeersIsEmpty = 4; + + NetworkMap NetworkMap = 5; } message LoginRequest { @@ -76,6 +85,8 @@ message ServerKeyResponse { string key = 1; // Key expiration timestamp after which the key should be fetched again by the client google.protobuf.Timestamp expiresAt = 2; + // Version of the Wiretrustee Management Service protocol + int32 version = 3; } message Empty {} @@ -122,6 +133,24 @@ message PeerConfig { string dns = 2; } +// NetworkMap represents a network state of the peer with the corresponding configuration parameters to establish peer-to-peer connections +message NetworkMap { + // Serial is an ID of the network state to be used by clients to order updates. + // The larger the Serial the newer the configuration. + // E.g. the client app should keep track of this id locally and discard all the configurations with a lower value + uint64 Serial = 1; + + // PeerConfig represents configuration of a peer + PeerConfig peerConfig = 2; + + // RemotePeerConfig represents a list of remote peers that the receiver can connect to + repeated RemotePeerConfig remotePeers = 3; + + // Indicates whether remotePeers array is empty or not to bypass protobuf null and empty array equality. + bool remotePeersIsEmpty = 4; + +} + // RemotePeerConfig represents a configuration of a remote peer. // The properties are used to configure Wireguard Peers sections message RemotePeerConfig { diff --git a/management/server/account_test.go b/management/server/account_test.go index 4c6e6e2a6b1..240960c38db 100644 --- a/management/server/account_test.go +++ b/management/server/account_test.go @@ -163,7 +163,7 @@ func TestAccountManager_AddPeer(t *testing.T) { return } - key, err := wgtypes.GenerateKey() + key, err := wgtypes.GeneratePrivateKey() if err != nil { t.Fatal(err) return @@ -171,7 +171,7 @@ func TestAccountManager_AddPeer(t *testing.T) { expectedPeerKey := key.PublicKey().String() expectedPeerIP := "100.64.0.1" - peer, err := manager.AddPeer(setupKey.Key, Peer{ + peer, err := manager.AddPeer(setupKey.Key, &Peer{ Key: expectedPeerKey, Meta: PeerSystemMeta{}, Name: expectedPeerKey, @@ -226,7 +226,7 @@ func TestAccountManager_DeletePeer(t *testing.T) { peerKey := key.PublicKey().String() - _, err = manager.AddPeer(setupKey.Key, Peer{ + _, err = manager.AddPeer(setupKey.Key, &Peer{ Key: peerKey, Meta: PeerSystemMeta{}, Name: peerKey, diff --git a/management/server/grpcserver.go b/management/server/grpcserver.go index 9cd1b2c6c99..4e2ebcfc511 100644 --- a/management/server/grpcserver.go +++ b/management/server/grpcserver.go @@ -141,7 +141,7 @@ func (s *Server) registerPeer(peerKey wgtypes.Key, req *proto.LoginRequest) (*Pe if meta == nil { return nil, status.Errorf(codes.InvalidArgument, "peer meta data was not provided") } - peer, err := s.accountManager.AddPeer(req.GetSetupKey(), Peer{ + peer, err := s.accountManager.AddPeer(req.GetSetupKey(), &Peer{ Key: peerKey.String(), Name: meta.GetHostname(), Meta: PeerSystemMeta{ @@ -158,21 +158,22 @@ func (s *Server) registerPeer(peerKey wgtypes.Key, req *proto.LoginRequest) (*Pe return nil, status.Errorf(codes.NotFound, "provided setup key doesn't exists") } - peers, err := s.accountManager.GetPeersForAPeer(peer.Key) + //todo move to AccountManager the code below + networkMap, err := s.accountManager.GetNetworkMap(peer.Key) if err != nil { return nil, status.Error(codes.Internal, "internal server error") } // notify other peers of our registration - for _, remotePeer := range peers { + for _, remotePeer := range networkMap.Peers { // exclude notified peer and add ourselves peersToSend := []*Peer{peer} - for _, p := range peers { + for _, p := range networkMap.Peers { if remotePeer.Key != p.Key { peersToSend = append(peersToSend, p) } } - update := toSyncResponse(s.config, peer, peersToSend, nil) + update := toSyncResponse(s.config, peer, peersToSend, nil, networkMap.Network.Serial()) err = s.peersUpdateManager.SendUpdate(remotePeer.Key, &UpdateMessage{Update: update}) if err != nil { // todo rethink if we should keep this return @@ -317,7 +318,7 @@ func toRemotePeerConfig(peers []*Peer) []*proto.RemotePeerConfig { } -func toSyncResponse(config *Config, peer *Peer, peers []*Peer, turnCredentials *TURNCredentials) *proto.SyncResponse { +func toSyncResponse(config *Config, peer *Peer, peers []*Peer, turnCredentials *TURNCredentials, serial uint64) *proto.SyncResponse { wtConfig := toWiretrusteeConfig(config, turnCredentials) @@ -330,6 +331,12 @@ func toSyncResponse(config *Config, peer *Peer, peers []*Peer, turnCredentials * PeerConfig: pConfig, RemotePeers: remotePeers, RemotePeersIsEmpty: len(remotePeers) == 0, + NetworkMap: &proto.NetworkMap{ + Serial: serial, + PeerConfig: pConfig, + RemotePeers: remotePeers, + RemotePeersIsEmpty: len(remotePeers) == 0, + }, } } @@ -341,7 +348,7 @@ func (s *Server) IsHealthy(ctx context.Context, req *proto.Empty) (*proto.Empty, // sendInitialSync sends initial proto.SyncResponse to the peer requesting synchronization func (s *Server) sendInitialSync(peerKey wgtypes.Key, peer *Peer, srv proto.ManagementService_SyncServer) error { - peers, err := s.accountManager.GetPeersForAPeer(peer.Key) + networkMap, err := s.accountManager.GetNetworkMap(peer.Key) if err != nil { log.Warnf("error getting a list of peers for a peer %s", peer.Key) return err @@ -355,7 +362,7 @@ func (s *Server) sendInitialSync(peerKey wgtypes.Key, peer *Peer, srv proto.Mana } else { turnCredentials = nil } - plainResp := toSyncResponse(s.config, peer, peers, turnCredentials) + plainResp := toSyncResponse(s.config, peer, networkMap.Peers, turnCredentials, networkMap.Network.Serial()) encryptedResp, err := encryption.EncryptMessage(peerKey, s.wgKey, plainResp) if err != nil { diff --git a/management/server/management_proto_test.go b/management/server/management_proto_test.go new file mode 100644 index 00000000000..4253e2ddb6e --- /dev/null +++ b/management/server/management_proto_test.go @@ -0,0 +1,348 @@ +package server + +import ( + "context" + "fmt" + log "github.com/sirupsen/logrus" + "github.com/wiretrustee/wiretrustee/encryption" + mgmtProto "github.com/wiretrustee/wiretrustee/management/proto" + "github.com/wiretrustee/wiretrustee/util" + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/keepalive" + "net" + "os" + "path/filepath" + "runtime" + "testing" + "time" +) + +var ( + kaep = keepalive.EnforcementPolicy{ + MinTime: 15 * time.Second, + PermitWithoutStream: true, + } + + kasp = keepalive.ServerParameters{ + MaxConnectionIdle: 15 * time.Second, + MaxConnectionAgeGrace: 5 * time.Second, + Time: 5 * time.Second, + Timeout: 2 * time.Second, + } +) + +const ( + TestValidSetupKey = "A2C8E62B-38F5-4553-B31E-DD66C696CEBB" +) + +// registerPeers registers peersNum peers on the management service and returns their Wireguard keys +func registerPeers(peersNum int, client mgmtProto.ManagementServiceClient) ([]*wgtypes.Key, error) { + + var peers = []*wgtypes.Key{} + for i := 0; i < peersNum; i++ { + key, err := wgtypes.GeneratePrivateKey() + if err != nil { + return nil, err + } + + _, err = loginPeerWithValidSetupKey(key, client) + if err != nil { + return nil, err + } + + peers = append(peers, &key) + } + + return peers, nil +} + +// getServerKey gets Management Service Wireguard public key +func getServerKey(client mgmtProto.ManagementServiceClient) (*wgtypes.Key, error) { + + keyResp, err := client.GetServerKey(context.TODO(), &mgmtProto.Empty{}) + if err != nil { + return nil, err + } + + serverKey, err := wgtypes.ParseKey(keyResp.Key) + if err != nil { + return nil, err + } + + return &serverKey, nil +} + +func Test_SyncProtocol(t *testing.T) { + + dir := t.TempDir() + err := util.CopyFileContents("testdata/store.json", filepath.Join(dir, "store.json")) + if err != nil { + t.Fatal(err) + } + defer func() { + os.Remove(filepath.Join(dir, "store.json")) //nolint + }() + + mgmtServer, err := startManagement(33071, &Config{ + Stuns: []*Host{{ + Proto: "udp", + URI: "stun:stun.wiretrustee.com:3468", + }}, + TURNConfig: &TURNConfig{ + TimeBasedCredentials: false, + CredentialsTTL: util.Duration{}, + Secret: "whatever", + Turns: []*Host{{ + Proto: "udp", + URI: "turn:stun.wiretrustee.com:3468", + }}, + }, + Signal: &Host{ + Proto: "http", + URI: "signal.wiretrustee.com:10000", + }, + Datadir: dir, + HttpConfig: nil, + }) + if err != nil { + t.Fatal(err) + return + } + defer mgmtServer.Stop() + + client, clientConn, err := createRawClient("localhost:33071") + if err != nil { + t.Fatal(err) + return + } + + defer clientConn.Close() + + peers, err := registerPeers(2, client) + if err != nil { + t.Fatal(err) + return + } + + serverKey, err := getServerKey(client) + if err != nil { + t.Fatal(err) + return + } + + // take the first registered peer as a base for the test + key := *peers[0] + + message, err := encryption.EncryptMessage(*serverKey, key, &mgmtProto.SyncRequest{}) + if err != nil { + t.Fatal(err) + return + } + + if err != nil { + t.Fatal(err) + return + } + + sync, err := client.Sync(context.TODO(), &mgmtProto.EncryptedMessage{ + WgPubKey: key.PublicKey().String(), + Body: message, + }) + if err != nil { + t.Fatal(err) + return + } + + resp := &mgmtProto.EncryptedMessage{} + err = sync.RecvMsg(resp) + if err != nil { + t.Fatal(err) + return + } + + syncResp := &mgmtProto.SyncResponse{} + err = encryption.DecryptMessage(*serverKey, key, resp.Body, syncResp) + if err != nil { + t.Fatal(err) + return + } + + wiretrusteeConfig := syncResp.GetWiretrusteeConfig() + if wiretrusteeConfig == nil { + t.Fatal("expecting SyncResponse to have non-nil WiretrusteeConfig") + } + + if wiretrusteeConfig.GetSignal() == nil { + t.Fatal("expecting SyncResponse to have WiretrusteeConfig with non-nil Signal config") + } + + expectedSignalConfig := &mgmtProto.HostConfig{ + Uri: "signal.wiretrustee.com:10000", + Protocol: mgmtProto.HostConfig_HTTP, + } + + if wiretrusteeConfig.GetSignal().GetUri() != expectedSignalConfig.GetUri() { + t.Fatalf("expecting SyncResponse to have WiretrusteeConfig with expected Signal URI: %v, actual: %v", + expectedSignalConfig.GetUri(), + wiretrusteeConfig.GetSignal().GetUri()) + } + + if wiretrusteeConfig.GetSignal().GetProtocol() != expectedSignalConfig.GetProtocol() { + t.Fatalf("expecting SyncResponse to have WiretrusteeConfig with expected Signal Protocol: %v, actual: %v", + expectedSignalConfig.GetProtocol().String(), + wiretrusteeConfig.GetSignal().GetProtocol()) + } + + expectedStunsConfig := &mgmtProto.HostConfig{ + Uri: "stun:stun.wiretrustee.com:3468", + Protocol: mgmtProto.HostConfig_UDP, + } + + if wiretrusteeConfig.GetStuns()[0].GetUri() != expectedStunsConfig.GetUri() { + t.Fatalf("expecting SyncResponse to have WiretrusteeConfig with expected STUN URI: %v, actual: %v", + expectedStunsConfig.GetUri(), + wiretrusteeConfig.GetStuns()[0].GetUri()) + } + + if wiretrusteeConfig.GetStuns()[0].GetProtocol() != expectedStunsConfig.GetProtocol() { + t.Fatalf("expecting SyncResponse to have WiretrusteeConfig with expected STUN Protocol: %v, actual: %v", + expectedStunsConfig.GetProtocol(), + wiretrusteeConfig.GetStuns()[0].GetProtocol()) + } + + expectedTRUNHost := &mgmtProto.HostConfig{ + Uri: "turn:stun.wiretrustee.com:3468", + Protocol: mgmtProto.HostConfig_UDP, + } + + if wiretrusteeConfig.GetTurns()[0].GetHostConfig().GetUri() != expectedTRUNHost.GetUri() { + t.Fatalf("expecting SyncResponse to have WiretrusteeConfig with expected TURN URI: %v, actual: %v", + expectedTRUNHost.GetUri(), + wiretrusteeConfig.GetTurns()[0].GetHostConfig().GetUri()) + } + + if wiretrusteeConfig.GetTurns()[0].GetHostConfig().GetProtocol() != expectedTRUNHost.GetProtocol() { + t.Fatalf("expecting SyncResponse to have WiretrusteeConfig with expected TURN Protocol: %v, actual: %v", + expectedTRUNHost.GetProtocol().String(), + wiretrusteeConfig.GetTurns()[0].GetHostConfig().GetProtocol()) + } + + // ensure backward compatibility + + if syncResp.GetRemotePeers() == nil { + t.Fatal("expecting SyncResponse to have non-nil RemotePeers for backward compatibility") + } + + if syncResp.GetPeerConfig() == nil { + t.Fatal("expecting SyncResponse to have non-nil PeerConfig for backward compatibility") + } + + // new field - NetworkMap + networkMap := syncResp.GetNetworkMap() + if networkMap == nil { + t.Fatal("expecting SyncResponse to have non-nil NetworkMap") + } + + if len(networkMap.GetRemotePeers()) != 1 { + t.Fatal("expecting SyncResponse to have NetworkMap with 1 remote peer") + } + + if networkMap.GetPeerConfig() == nil { + t.Fatal("expecting SyncResponse to have NetworkMap with a non-nil PeerConfig") + } + + if networkMap.GetPeerConfig().GetAddress() != "100.64.0.1/24" { + t.Fatal("expecting SyncResponse to have NetworkMap with a PeerConfig having valid Address") + } + + if networkMap.GetSerial() <= 0 { + t.Fatalf("expecting SyncResponse to have NetworkMap with a positive Network Serial, actual %d", networkMap.GetSerial()) + } +} + +func loginPeerWithValidSetupKey(key wgtypes.Key, client mgmtProto.ManagementServiceClient) (*mgmtProto.LoginResponse, error) { + + serverKey, err := getServerKey(client) + if err != nil { + return nil, err + } + + meta := &mgmtProto.PeerSystemMeta{ + Hostname: key.PublicKey().String(), + GoOS: runtime.GOOS, + OS: runtime.GOOS, + Core: "core", + Platform: "platform", + Kernel: "kernel", + WiretrusteeVersion: "", + } + message, err := encryption.EncryptMessage(*serverKey, key, &mgmtProto.LoginRequest{SetupKey: TestValidSetupKey, Meta: meta}) + if err != nil { + return nil, err + } + + resp, err := client.Login(context.TODO(), &mgmtProto.EncryptedMessage{ + WgPubKey: key.PublicKey().String(), + Body: message, + }) + if err != nil { + return nil, err + } + + loginResp := &mgmtProto.LoginResponse{} + err = encryption.DecryptMessage(*serverKey, key, resp.Body, loginResp) + if err != nil { + return nil, err + } + + return loginResp, nil + +} + +func startManagement(port int, config *Config) (*grpc.Server, error) { + + lis, err := net.Listen("tcp", fmt.Sprintf("localhost:%d", port)) + if err != nil { + return nil, err + } + s := grpc.NewServer(grpc.KeepaliveEnforcementPolicy(kaep), grpc.KeepaliveParams(kasp)) + store, err := NewStore(config.Datadir) + if err != nil { + return nil, err + } + peersUpdateManager := NewPeersUpdateManager() + accountManager := NewManager(store, peersUpdateManager) + turnManager := NewTimeBasedAuthSecretsManager(peersUpdateManager, config.TURNConfig) + mgmtServer, err := NewServer(config, accountManager, peersUpdateManager, turnManager) + if err != nil { + return nil, err + } + mgmtProto.RegisterManagementServiceServer(s, mgmtServer) + go func() { + if err = s.Serve(lis); err != nil { + log.Fatalf("failed to serve: %v", err) + } + }() + + return s, nil +} + +func createRawClient(addr string) (mgmtProto.ManagementServiceClient, *grpc.ClientConn, error) { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + conn, err := grpc.DialContext(ctx, addr, + grpc.WithTransportCredentials(insecure.NewCredentials()), + grpc.WithBlock(), + grpc.WithKeepaliveParams(keepalive.ClientParameters{ + Time: 10 * time.Second, + Timeout: 2 * time.Second, + })) + if err != nil { + return nil, nil, err + } + + return mgmtProto.NewManagementServiceClient(conn), conn, nil +} diff --git a/management/server/network.go b/management/server/network.go index 8590212d858..b495d2858d6 100644 --- a/management/server/network.go +++ b/management/server/network.go @@ -13,6 +13,11 @@ var ( upperIPv6 = []byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff} ) +type NetworkMap struct { + Peers []*Peer + Network *Network +} + type Network struct { Id string Net net.IPNet diff --git a/management/server/peer.go b/management/server/peer.go index 7213786c9c5..59daa63d61f 100644 --- a/management/server/peer.go +++ b/management/server/peer.go @@ -137,8 +137,15 @@ func (am *AccountManager) DeletePeer(accountId string, peerKey string) (*Peer, e err = am.peersUpdateManager.SendUpdate(peerKey, &UpdateMessage{ Update: &proto.SyncResponse{ + // fill those field for backward compatibility RemotePeers: []*proto.RemotePeerConfig{}, RemotePeersIsEmpty: true, + // new field + NetworkMap: &proto.NetworkMap{ + Serial: account.Network.Serial(), + RemotePeers: []*proto.RemotePeerConfig{}, + RemotePeersIsEmpty: true, + }, }}) if err != nil { return nil, err @@ -161,8 +168,15 @@ func (am *AccountManager) DeletePeer(accountId string, peerKey string) (*Peer, e err = am.peersUpdateManager.SendUpdate(p.Key, &UpdateMessage{ Update: &proto.SyncResponse{ + // fill those field for backward compatibility RemotePeers: update, RemotePeersIsEmpty: len(update) == 0, + // new field + NetworkMap: &proto.NetworkMap{ + Serial: account.Network.Serial(), + RemotePeers: update, + RemotePeersIsEmpty: len(update) == 0, + }, }}) if err != nil { return nil, err @@ -192,9 +206,8 @@ func (am *AccountManager) GetPeerByIP(accountId string, peerIP string) (*Peer, e return nil, status.Errorf(codes.NotFound, "peer with IP %s not found", peerIP) } -// GetPeersForAPeer returns a list of peers available for a given peer (key) -// Effectively all the peers of the original peer's account except for the peer itself -func (am *AccountManager) GetPeersForAPeer(peerKey string) ([]*Peer, error) { +// GetNetworkMap returns Network map for a given peer (omits original peer from the Peers result) +func (am *AccountManager) GetNetworkMap(peerKey string) (*NetworkMap, error) { am.mux.Lock() defer am.mux.Unlock() @@ -205,12 +218,16 @@ func (am *AccountManager) GetPeersForAPeer(peerKey string) ([]*Peer, error) { var res []*Peer for _, peer := range account.Peers { + // exclude original peer if peer.Key != peerKey { - res = append(res, peer) + res = append(res, peer.Copy()) } } - return res, nil + return &NetworkMap{ + Peers: res, + Network: account.Network.Copy(), + }, err } // AddPeer adds a new peer to the Store. @@ -218,7 +235,7 @@ func (am *AccountManager) GetPeersForAPeer(peerKey string) ([]*Peer, error) { // will be returned, meaning the key is invalid // Each new Peer will be assigned a new next net.IP from the Account.Network and Account.Network.LastIP will be updated (IP's are not reused). // The peer property is just a placeholder for the Peer properties to pass further -func (am *AccountManager) AddPeer(setupKey string, peer Peer) (*Peer, error) { +func (am *AccountManager) AddPeer(setupKey string, peer *Peer) (*Peer, error) { am.mux.Lock() defer am.mux.Unlock() diff --git a/management/server/peer_test.go b/management/server/peer_test.go new file mode 100644 index 00000000000..e70b691b23a --- /dev/null +++ b/management/server/peer_test.go @@ -0,0 +1,76 @@ +package server + +import ( + "golang.zx2c4.com/wireguard/wgctrl/wgtypes" + "testing" +) + +func TestAccountManager_GetNetworkMap(t *testing.T) { + manager, err := createManager(t) + if err != nil { + t.Fatal(err) + return + } + + expectedId := "test_account" + userId := "account_creator" + account, err := manager.AddAccount(expectedId, userId) + if err != nil { + t.Fatal(err) + } + + var setupKey *SetupKey + for _, key := range account.SetupKeys { + if key.Type == SetupKeyReusable { + setupKey = key + } + } + + peerKey1, err := wgtypes.GeneratePrivateKey() + if err != nil { + t.Fatal(err) + return + } + + _, err = manager.AddPeer(setupKey.Key, &Peer{ + Key: peerKey1.PublicKey().String(), + Meta: PeerSystemMeta{}, + Name: "test-peer-2", + }) + + if err != nil { + t.Errorf("expecting peer to be added, got failure %v", err) + return + } + + peerKey2, err := wgtypes.GeneratePrivateKey() + if err != nil { + t.Fatal(err) + return + } + _, err = manager.AddPeer(setupKey.Key, &Peer{ + Key: peerKey2.PublicKey().String(), + Meta: PeerSystemMeta{}, + Name: "test-peer-2", + }) + + if err != nil { + t.Errorf("expecting peer to be added, got failure %v", err) + return + } + + networkMap, err := manager.GetNetworkMap(peerKey1.PublicKey().String()) + if err != nil { + t.Fatal(err) + return + } + + if len(networkMap.Peers) != 1 { + t.Errorf("expecting Account NetworkMap to have 1 peers, got %v", len(networkMap.Peers)) + } + + if networkMap.Peers[0].Key != peerKey2.PublicKey().String() { + t.Errorf("expecting Account NetworkMap to have peer with a key %s, got %s", peerKey2.PublicKey().String(), networkMap.Peers[0].Key) + } + +}