mirror of
https://github.com/netbirdio/netbird.git
synced 2026-05-20 07:39:56 +00:00
add SSO session extend flow (management)
Adds the management-server half of the SSO session-extension feature: - New ExtendAuthSession gRPC RPC that refreshes a peer's session expiry using a fresh JWT, validated through the same pipeline as Login but without tearing down the tunnel or redoing the NetworkMap sync. - Per-peer SessionExpiresAt timestamp on every LoginResponse and SyncResponse so connected clients learn the deadline on the existing long-lived stream, and admin-side changes (toggling expiration, changing the expiration window) reach every peer within seconds. - SessionExpiresAt(...) helper on Peer that derives the absolute UTC deadline from LastLogin + the account-level PeerLoginExpiration setting, returning zero when the peer is not SSO-tracked or expiration is disabled. The matching client-side consumer of these fields lands separately.
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -52,6 +52,14 @@ service ManagementService {
|
||||
// Executes a job on a target peer (e.g., debug bundle)
|
||||
rpc Job(stream EncryptedMessage) returns (stream EncryptedMessage) {}
|
||||
|
||||
// ExtendAuthSession refreshes the peer's session expiry deadline using a fresh JWT.
|
||||
// Same JWT validation pipeline as Login (including jwt.UserID == peer.UserID check),
|
||||
// but does not redo the network-map sync. Only valid for SSO-registered peers where
|
||||
// login expiration is enabled. The tunnel remains up.
|
||||
// EncryptedMessage of the request has a body of ExtendAuthSessionRequest.
|
||||
// EncryptedMessage of the response has a body of ExtendAuthSessionResponse.
|
||||
rpc ExtendAuthSession(EncryptedMessage) returns (EncryptedMessage) {}
|
||||
|
||||
// CreateExpose creates a temporary reverse proxy service for a peer
|
||||
rpc CreateExpose(EncryptedMessage) returns (EncryptedMessage) {}
|
||||
|
||||
@@ -133,6 +141,12 @@ message SyncResponse {
|
||||
|
||||
// Posture checks to be evaluated by client
|
||||
repeated Checks Checks = 6;
|
||||
|
||||
// Absolute UTC instant at which the peer's SSO session expires.
|
||||
// Unset when the peer is not SSO-registered or login expiration is disabled.
|
||||
// Carried on every Sync snapshot so admin-side changes propagate live without
|
||||
// a client reconnect.
|
||||
google.protobuf.Timestamp sessionExpiresAt = 7;
|
||||
}
|
||||
|
||||
message SyncMetaRequest {
|
||||
@@ -244,6 +258,26 @@ message LoginResponse {
|
||||
PeerConfig peerConfig = 2;
|
||||
// Posture checks to be evaluated by client
|
||||
repeated Checks Checks = 3;
|
||||
|
||||
// Absolute UTC instant at which the peer's SSO session expires.
|
||||
// Unset when the peer is not SSO-registered or login expiration is disabled.
|
||||
google.protobuf.Timestamp sessionExpiresAt = 4;
|
||||
}
|
||||
|
||||
// ExtendAuthSessionRequest carries a fresh JWT to refresh the peer's session deadline.
|
||||
// The encrypted body of an EncryptedMessage with this payload is sent to the
|
||||
// ExtendAuthSession RPC.
|
||||
message ExtendAuthSessionRequest {
|
||||
// SSO token (must be a fresh, valid JWT for the peer's owning user)
|
||||
string jwtToken = 1;
|
||||
// Meta data of the peer (used for IdP user info refresh consistent with Login)
|
||||
PeerSystemMeta meta = 2;
|
||||
}
|
||||
|
||||
// ExtendAuthSessionResponse contains the refreshed session deadline.
|
||||
message ExtendAuthSessionResponse {
|
||||
// Absolute UTC instant at which the peer's SSO session now expires.
|
||||
google.protobuf.Timestamp sessionExpiresAt = 1;
|
||||
}
|
||||
|
||||
message ServerKeyResponse {
|
||||
|
||||
@@ -52,6 +52,13 @@ type ManagementServiceClient interface {
|
||||
Logout(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*Empty, error)
|
||||
// Executes a job on a target peer (e.g., debug bundle)
|
||||
Job(ctx context.Context, opts ...grpc.CallOption) (ManagementService_JobClient, error)
|
||||
// ExtendAuthSession refreshes the peer's session expiry deadline using a fresh JWT.
|
||||
// Same JWT validation pipeline as Login (including jwt.UserID == peer.UserID check),
|
||||
// but does not redo the network-map sync. Only valid for SSO-registered peers where
|
||||
// login expiration is enabled. The tunnel remains up.
|
||||
// EncryptedMessage of the request has a body of ExtendAuthSessionRequest.
|
||||
// EncryptedMessage of the response has a body of ExtendAuthSessionResponse.
|
||||
ExtendAuthSession(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error)
|
||||
// CreateExpose creates a temporary reverse proxy service for a peer
|
||||
CreateExpose(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error)
|
||||
// RenewExpose extends the TTL of an active expose session
|
||||
@@ -194,6 +201,15 @@ func (x *managementServiceJobClient) Recv() (*EncryptedMessage, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (c *managementServiceClient) ExtendAuthSession(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error) {
|
||||
out := new(EncryptedMessage)
|
||||
err := c.cc.Invoke(ctx, "/management.ManagementService/ExtendAuthSession", in, out, opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *managementServiceClient) CreateExpose(ctx context.Context, in *EncryptedMessage, opts ...grpc.CallOption) (*EncryptedMessage, error) {
|
||||
out := new(EncryptedMessage)
|
||||
err := c.cc.Invoke(ctx, "/management.ManagementService/CreateExpose", in, out, opts...)
|
||||
@@ -259,6 +275,13 @@ type ManagementServiceServer interface {
|
||||
Logout(context.Context, *EncryptedMessage) (*Empty, error)
|
||||
// Executes a job on a target peer (e.g., debug bundle)
|
||||
Job(ManagementService_JobServer) error
|
||||
// ExtendAuthSession refreshes the peer's session expiry deadline using a fresh JWT.
|
||||
// Same JWT validation pipeline as Login (including jwt.UserID == peer.UserID check),
|
||||
// but does not redo the network-map sync. Only valid for SSO-registered peers where
|
||||
// login expiration is enabled. The tunnel remains up.
|
||||
// EncryptedMessage of the request has a body of ExtendAuthSessionRequest.
|
||||
// EncryptedMessage of the response has a body of ExtendAuthSessionResponse.
|
||||
ExtendAuthSession(context.Context, *EncryptedMessage) (*EncryptedMessage, error)
|
||||
// CreateExpose creates a temporary reverse proxy service for a peer
|
||||
CreateExpose(context.Context, *EncryptedMessage) (*EncryptedMessage, error)
|
||||
// RenewExpose extends the TTL of an active expose session
|
||||
@@ -299,6 +322,9 @@ func (UnimplementedManagementServiceServer) Logout(context.Context, *EncryptedMe
|
||||
func (UnimplementedManagementServiceServer) Job(ManagementService_JobServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method Job not implemented")
|
||||
}
|
||||
func (UnimplementedManagementServiceServer) ExtendAuthSession(context.Context, *EncryptedMessage) (*EncryptedMessage, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method ExtendAuthSession not implemented")
|
||||
}
|
||||
func (UnimplementedManagementServiceServer) CreateExpose(context.Context, *EncryptedMessage) (*EncryptedMessage, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method CreateExpose not implemented")
|
||||
}
|
||||
@@ -494,6 +520,24 @@ func (x *managementServiceJobServer) Recv() (*EncryptedMessage, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func _ManagementService_ExtendAuthSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(EncryptedMessage)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(ManagementServiceServer).ExtendAuthSession(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: "/management.ManagementService/ExtendAuthSession",
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(ManagementServiceServer).ExtendAuthSession(ctx, req.(*EncryptedMessage))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
func _ManagementService_CreateExpose_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(EncryptedMessage)
|
||||
if err := dec(in); err != nil {
|
||||
@@ -583,6 +627,10 @@ var ManagementService_ServiceDesc = grpc.ServiceDesc{
|
||||
MethodName: "Logout",
|
||||
Handler: _ManagementService_Logout_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "ExtendAuthSession",
|
||||
Handler: _ManagementService_ExtendAuthSession_Handler,
|
||||
},
|
||||
{
|
||||
MethodName: "CreateExpose",
|
||||
Handler: _ManagementService_CreateExpose_Handler,
|
||||
|
||||
Reference in New Issue
Block a user