Peer management login (#83)

* feature: replace RegisterPeer with Login method that does both - registration and login

* test: add management login test

* feature: add WiretrusteeConfig to the Login response to configure peer global config

* feature: add client peer login support

* fix: missing parts

* chore: update go deps

* feature: support Management Service gRPC endpoints [CLIENT]

* feature: finalize client sync with management

* fix: management store peer key lower case restore

* fix: management returns peer ip without a mask

* refactor: remove cmd pkg

* fix: invalid tun interface name on mac

* fix: timeout when calling management client

* fix: tests and lint errors

* fix: golang-test workflow

* fix: client service tests

* fix: iface build

* feature: detect management scheme on startup

* chore: better logs for management

* fix: goreleaser

* fix: lint errors

* fix: signal TLS

* fix: direct Wireguard connection

* chore: verbose logging on direct connection
This commit is contained in:
Mikhail Bragin
2021-08-15 16:56:26 +02:00
committed by GitHub
parent 80de6a75d5
commit 877ad97a96
34 changed files with 1139 additions and 783 deletions
+75 -15
View File
@@ -77,7 +77,7 @@ func (s *Server) Sync(req *proto.EncryptedMessage, srv proto.ManagementService_S
peer, err := s.accountManager.GetPeer(peerKey.String())
if err != nil {
return status.Errorf(codes.Unauthenticated, "provided peer with the key wgPubKey %s is not registered", peerKey.String())
return status.Errorf(codes.PermissionDenied, "provided peer with the key wgPubKey %s is not registered", peerKey.String())
}
syncReq := &proto.SyncRequest{}
@@ -126,23 +126,18 @@ func (s *Server) Sync(req *proto.EncryptedMessage, srv proto.ManagementService_S
}
}
// RegisterPeer adds a peer to the Store. Returns 404 in case the provided setup key doesn't exist
func (s *Server) RegisterPeer(ctx context.Context, req *proto.RegisterPeerRequest) (*proto.RegisterPeerResponse, error) {
log.Debugf("RegisterPeer request from peer %s", req.Key)
func (s *Server) registerPeer(peerKey wgtypes.Key, setupKey string) (*server.Peer, error) {
s.channelsMux.Lock()
defer s.channelsMux.Unlock()
peer, err := s.accountManager.AddPeer(req.SetupKey, req.Key)
peer, err := s.accountManager.AddPeer(setupKey, peerKey.String())
if err != nil {
return &proto.RegisterPeerResponse{}, status.Errorf(codes.NotFound, "provided setup key doesn't exists")
return nil, status.Errorf(codes.NotFound, "provided setup key doesn't exists")
}
peers, err := s.accountManager.GetPeersForAPeer(peer.Key)
if err != nil {
//todo return a proper error
return nil, err
return nil, status.Error(codes.Internal, "internal server error")
}
// notify other peers of our registration
@@ -160,7 +155,63 @@ func (s *Server) RegisterPeer(ctx context.Context, req *proto.RegisterPeerReques
}
}
return &proto.RegisterPeerResponse{}, nil
return peer, nil
}
// Login endpoint first checks whether peer is registered under any account
// In case it is, the login is successful
// In case it isn't, the endpoint checks whether setup key is provided within the request and tries to register a peer.
// In case of the successful registration login is also successful
func (s *Server) Login(ctx context.Context, req *proto.EncryptedMessage) (*proto.EncryptedMessage, error) {
log.Debugf("Login request from peer %s", req.WgPubKey)
peerKey, err := wgtypes.ParseKey(req.GetWgPubKey())
if err != nil {
log.Warnf("error while parsing peer's Wireguard public key %s on Sync request.", req.WgPubKey)
return nil, status.Errorf(codes.InvalidArgument, "provided wgPubKey %s is invalid", req.WgPubKey)
}
peer, err := s.accountManager.GetPeer(peerKey.String())
if err != nil {
if errStatus, ok := status.FromError(err); ok && errStatus.Code() == codes.NotFound {
//peer doesn't exist -> check if setup key was provided
loginReq := &proto.LoginRequest{}
err = encryption.DecryptMessage(peerKey, s.wgKey, req.Body, loginReq)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid request message")
}
if loginReq.GetSetupKey() == "" {
//absent setup key -> permission denied
return nil, status.Errorf(codes.PermissionDenied, "provided peer with the key wgPubKey %s is not registered", peerKey.String())
}
//setup key is present -> try normal registration flow
peer, err = s.registerPeer(peerKey, loginReq.GetSetupKey())
if err != nil {
return nil, err
}
} else {
return nil, status.Error(codes.Internal, "internal server error")
}
}
// if peer has reached this point then it has logged in
loginResp := &proto.LoginResponse{
WiretrusteeConfig: toWiretrusteeConfig(s.config),
PeerConfig: toPeerConfig(peer),
}
encryptedResp, err := encryption.EncryptMessage(peerKey, s.wgKey, loginResp)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed logging in peer")
}
return &proto.EncryptedMessage{
WgPubKey: s.wgKey.PublicKey().String(),
Body: encryptedResp,
}, nil
}
func toResponseProto(configProto server.Protocol) proto.HostConfig_Protocol {
@@ -181,7 +232,7 @@ func toResponseProto(configProto server.Protocol) proto.HostConfig_Protocol {
}
}
func toSyncResponse(config *server.Config, peer *server.Peer, peers []*server.Peer) *proto.SyncResponse {
func toWiretrusteeConfig(config *server.Config) *proto.WiretrusteeConfig {
var stuns []*proto.HostConfig
for _, stun := range config.Stuns {
@@ -202,7 +253,7 @@ func toSyncResponse(config *server.Config, peer *server.Peer, peers []*server.Pe
})
}
wtConfig := &proto.WiretrusteeConfig{
return &proto.WiretrusteeConfig{
Stuns: stuns,
Turns: turns,
Signal: &proto.HostConfig{
@@ -210,10 +261,19 @@ func toSyncResponse(config *server.Config, peer *server.Peer, peers []*server.Pe
Protocol: toResponseProto(config.Signal.Proto),
},
}
}
pConfig := &proto.PeerConfig{
Address: peer.IP.String(),
func toPeerConfig(peer *server.Peer) *proto.PeerConfig {
return &proto.PeerConfig{
Address: peer.IP.String() + "/24", //todo make it explicit
}
}
func toSyncResponse(config *server.Config, peer *server.Peer, peers []*server.Peer) *proto.SyncResponse {
wtConfig := toWiretrusteeConfig(config)
pConfig := toPeerConfig(peer)
remotePeers := make([]*proto.RemotePeerConfig, 0, len(peers))
for _, rPeer := range peers {