Files
netbird/shared/management/proto/proxy_service_grpc.pb.go
Maycon Santos 7aebdd69dd [management, client, proxy] add expose NetBird-only services over tunnel peers (#6226)
Adds a new "private" service mode for the reverse proxy: services reachable exclusively over the embedded WireGuard tunnel, gated by per-peer group membership instead of operator auth schemes.

Wire contract
- ProxyMapping.private (field 13): the proxy MUST call ValidateTunnelPeer and fail closed; operator schemes are bypassed.
- ProxyCapabilities.private (4) + supports_private_service (5): capability gate. Management never streams private mappings to proxies that don't claim the capability; the broadcast path applies the same filter via filterMappingsForProxy.
- ValidateTunnelPeer RPC: resolves an inbound tunnel IP to a peer, checks the peer's groups against service.AccessGroups, and mints a session JWT on success. checkPeerGroupAccess fails closed when a private service has empty AccessGroups.
- ValidateSession/ValidateTunnelPeer responses now carry peer_group_ids + peer_group_names so the proxy can authorise policy-aware middlewares without an extra management round-trip.
- ProxyInboundListener + SendStatusUpdate.inbound_listener: per-account inbound listener state surfaced to dashboards.
- PathTargetOptions.direct_upstream (11): bypass the embedded NetBird client and dial the target via the proxy host's network stack for upstreams reachable without WireGuard.

Data model
- Service.Private (bool) + Service.AccessGroups ([]string, JSON- serialised). Validate() rejects bearer auth on private services. Copy() deep-copies AccessGroups. pgx getServices loads the columns.
- DomainConfig.Private threaded into the proxy auth middleware. Request handler routes private services through forwardWithTunnelPeer and returns 403 on validation failure.
- Account-level SynthesizePrivateServiceZones (synthetic DNS) and injectPrivateServicePolicies (synthetic ACL) gate on len(svc.AccessGroups) > 0.

Proxy
- /netbird proxy --private (embedded mode) flag; Config.Private in proxy/lifecycle.go.
- Per-account inbound listener (proxy/inbound.go) binding HTTP/HTTPS on the embedded NetBird client's WireGuard tunnel netstack.
- proxy/internal/auth/tunnel_cache: ValidateTunnelPeer response cache with single-flight de-duplication and per-account eviction.
- Local peerstore short-circuit: when the inbound IP isn't in the account roster, deny fast without an RPC.
- proxy/server.go reports SupportsPrivateService=true and redacts the full ProxyMapping JSON from info logs (auth_token + header-auth hashed values now only at debug level).

Identity forwarding
- ValidateSessionJWT returns user_id, email, method, groups, group_names. sessionkey.Claims carries Email + Groups + GroupNames so the proxy can stamp identity onto upstream requests without an extra management round-trip on every cookie-bearing request.
- CapturedData carries userEmail / userGroups / userGroupNames; the proxy stamps X-NetBird-User and X-NetBird-Groups on r.Out from the authenticated identity (strips client-supplied values first to prevent spoofing).
- AccessLog.UserGroups: access-log enrichment captures the user's group memberships at write time so the dashboard can render group context without reverse-resolving stale memberships.

OpenAPI/dashboard surface
- ReverseProxyService gains private + access_groups; ReverseProxyCluster gains private + supports_private. ReverseProxyTarget target_type enum gains "cluster". ServiceTargetOptions gains direct_upstream. ProxyAccessLog gains user_groups.
2026-05-25 17:41:50 +02:00

482 lines
19 KiB
Go

// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
package proto
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
// ProxyServiceClient is the client API for ProxyService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type ProxyServiceClient interface {
GetMappingUpdate(ctx context.Context, in *GetMappingUpdateRequest, opts ...grpc.CallOption) (ProxyService_GetMappingUpdateClient, error)
// SyncMappings is a bidirectional stream that replaces GetMappingUpdate for
// new proxies. The proxy sends an initial SyncMappingsRequest to start the
// stream and then sends an ack after each batch is fully processed.
// Management waits for the ack before sending the next batch, providing
// application-level back-pressure during large initial syncs.
// Old proxies continue using GetMappingUpdate; old management servers
// return Unimplemented for this RPC and proxies fall back.
SyncMappings(ctx context.Context, opts ...grpc.CallOption) (ProxyService_SyncMappingsClient, error)
SendAccessLog(ctx context.Context, in *SendAccessLogRequest, opts ...grpc.CallOption) (*SendAccessLogResponse, error)
Authenticate(ctx context.Context, in *AuthenticateRequest, opts ...grpc.CallOption) (*AuthenticateResponse, error)
SendStatusUpdate(ctx context.Context, in *SendStatusUpdateRequest, opts ...grpc.CallOption) (*SendStatusUpdateResponse, error)
CreateProxyPeer(ctx context.Context, in *CreateProxyPeerRequest, opts ...grpc.CallOption) (*CreateProxyPeerResponse, error)
GetOIDCURL(ctx context.Context, in *GetOIDCURLRequest, opts ...grpc.CallOption) (*GetOIDCURLResponse, error)
// ValidateSession validates a session token and checks user access permissions.
// Called by the proxy after receiving a session token from OIDC callback.
ValidateSession(ctx context.Context, in *ValidateSessionRequest, opts ...grpc.CallOption) (*ValidateSessionResponse, error)
// ValidateTunnelPeer resolves an inbound peer by its WireGuard tunnel IP and
// checks the resolved user's access against the service's access_groups.
// Acts as a fast-path equivalent of OIDC for requests originating on the
// netbird mesh: when the source IP maps to a known peer in the calling
// account and that peer is in the service's access_groups, the proxy can
// issue a session cookie without redirecting through the OIDC flow.
// Mirrors ValidateSession's response shape.
ValidateTunnelPeer(ctx context.Context, in *ValidateTunnelPeerRequest, opts ...grpc.CallOption) (*ValidateTunnelPeerResponse, error)
}
type proxyServiceClient struct {
cc grpc.ClientConnInterface
}
func NewProxyServiceClient(cc grpc.ClientConnInterface) ProxyServiceClient {
return &proxyServiceClient{cc}
}
func (c *proxyServiceClient) GetMappingUpdate(ctx context.Context, in *GetMappingUpdateRequest, opts ...grpc.CallOption) (ProxyService_GetMappingUpdateClient, error) {
stream, err := c.cc.NewStream(ctx, &ProxyService_ServiceDesc.Streams[0], "/management.ProxyService/GetMappingUpdate", opts...)
if err != nil {
return nil, err
}
x := &proxyServiceGetMappingUpdateClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type ProxyService_GetMappingUpdateClient interface {
Recv() (*GetMappingUpdateResponse, error)
grpc.ClientStream
}
type proxyServiceGetMappingUpdateClient struct {
grpc.ClientStream
}
func (x *proxyServiceGetMappingUpdateClient) Recv() (*GetMappingUpdateResponse, error) {
m := new(GetMappingUpdateResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *proxyServiceClient) SyncMappings(ctx context.Context, opts ...grpc.CallOption) (ProxyService_SyncMappingsClient, error) {
stream, err := c.cc.NewStream(ctx, &ProxyService_ServiceDesc.Streams[1], "/management.ProxyService/SyncMappings", opts...)
if err != nil {
return nil, err
}
x := &proxyServiceSyncMappingsClient{stream}
return x, nil
}
type ProxyService_SyncMappingsClient interface {
Send(*SyncMappingsRequest) error
Recv() (*SyncMappingsResponse, error)
grpc.ClientStream
}
type proxyServiceSyncMappingsClient struct {
grpc.ClientStream
}
func (x *proxyServiceSyncMappingsClient) Send(m *SyncMappingsRequest) error {
return x.ClientStream.SendMsg(m)
}
func (x *proxyServiceSyncMappingsClient) Recv() (*SyncMappingsResponse, error) {
m := new(SyncMappingsResponse)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *proxyServiceClient) SendAccessLog(ctx context.Context, in *SendAccessLogRequest, opts ...grpc.CallOption) (*SendAccessLogResponse, error) {
out := new(SendAccessLogResponse)
err := c.cc.Invoke(ctx, "/management.ProxyService/SendAccessLog", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *proxyServiceClient) Authenticate(ctx context.Context, in *AuthenticateRequest, opts ...grpc.CallOption) (*AuthenticateResponse, error) {
out := new(AuthenticateResponse)
err := c.cc.Invoke(ctx, "/management.ProxyService/Authenticate", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *proxyServiceClient) SendStatusUpdate(ctx context.Context, in *SendStatusUpdateRequest, opts ...grpc.CallOption) (*SendStatusUpdateResponse, error) {
out := new(SendStatusUpdateResponse)
err := c.cc.Invoke(ctx, "/management.ProxyService/SendStatusUpdate", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *proxyServiceClient) CreateProxyPeer(ctx context.Context, in *CreateProxyPeerRequest, opts ...grpc.CallOption) (*CreateProxyPeerResponse, error) {
out := new(CreateProxyPeerResponse)
err := c.cc.Invoke(ctx, "/management.ProxyService/CreateProxyPeer", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *proxyServiceClient) GetOIDCURL(ctx context.Context, in *GetOIDCURLRequest, opts ...grpc.CallOption) (*GetOIDCURLResponse, error) {
out := new(GetOIDCURLResponse)
err := c.cc.Invoke(ctx, "/management.ProxyService/GetOIDCURL", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *proxyServiceClient) ValidateSession(ctx context.Context, in *ValidateSessionRequest, opts ...grpc.CallOption) (*ValidateSessionResponse, error) {
out := new(ValidateSessionResponse)
err := c.cc.Invoke(ctx, "/management.ProxyService/ValidateSession", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *proxyServiceClient) ValidateTunnelPeer(ctx context.Context, in *ValidateTunnelPeerRequest, opts ...grpc.CallOption) (*ValidateTunnelPeerResponse, error) {
out := new(ValidateTunnelPeerResponse)
err := c.cc.Invoke(ctx, "/management.ProxyService/ValidateTunnelPeer", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// ProxyServiceServer is the server API for ProxyService service.
// All implementations must embed UnimplementedProxyServiceServer
// for forward compatibility
type ProxyServiceServer interface {
GetMappingUpdate(*GetMappingUpdateRequest, ProxyService_GetMappingUpdateServer) error
// SyncMappings is a bidirectional stream that replaces GetMappingUpdate for
// new proxies. The proxy sends an initial SyncMappingsRequest to start the
// stream and then sends an ack after each batch is fully processed.
// Management waits for the ack before sending the next batch, providing
// application-level back-pressure during large initial syncs.
// Old proxies continue using GetMappingUpdate; old management servers
// return Unimplemented for this RPC and proxies fall back.
SyncMappings(ProxyService_SyncMappingsServer) error
SendAccessLog(context.Context, *SendAccessLogRequest) (*SendAccessLogResponse, error)
Authenticate(context.Context, *AuthenticateRequest) (*AuthenticateResponse, error)
SendStatusUpdate(context.Context, *SendStatusUpdateRequest) (*SendStatusUpdateResponse, error)
CreateProxyPeer(context.Context, *CreateProxyPeerRequest) (*CreateProxyPeerResponse, error)
GetOIDCURL(context.Context, *GetOIDCURLRequest) (*GetOIDCURLResponse, error)
// ValidateSession validates a session token and checks user access permissions.
// Called by the proxy after receiving a session token from OIDC callback.
ValidateSession(context.Context, *ValidateSessionRequest) (*ValidateSessionResponse, error)
// ValidateTunnelPeer resolves an inbound peer by its WireGuard tunnel IP and
// checks the resolved user's access against the service's access_groups.
// Acts as a fast-path equivalent of OIDC for requests originating on the
// netbird mesh: when the source IP maps to a known peer in the calling
// account and that peer is in the service's access_groups, the proxy can
// issue a session cookie without redirecting through the OIDC flow.
// Mirrors ValidateSession's response shape.
ValidateTunnelPeer(context.Context, *ValidateTunnelPeerRequest) (*ValidateTunnelPeerResponse, error)
mustEmbedUnimplementedProxyServiceServer()
}
// UnimplementedProxyServiceServer must be embedded to have forward compatible implementations.
type UnimplementedProxyServiceServer struct {
}
func (UnimplementedProxyServiceServer) GetMappingUpdate(*GetMappingUpdateRequest, ProxyService_GetMappingUpdateServer) error {
return status.Errorf(codes.Unimplemented, "method GetMappingUpdate not implemented")
}
func (UnimplementedProxyServiceServer) SyncMappings(ProxyService_SyncMappingsServer) error {
return status.Errorf(codes.Unimplemented, "method SyncMappings not implemented")
}
func (UnimplementedProxyServiceServer) SendAccessLog(context.Context, *SendAccessLogRequest) (*SendAccessLogResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SendAccessLog not implemented")
}
func (UnimplementedProxyServiceServer) Authenticate(context.Context, *AuthenticateRequest) (*AuthenticateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method Authenticate not implemented")
}
func (UnimplementedProxyServiceServer) SendStatusUpdate(context.Context, *SendStatusUpdateRequest) (*SendStatusUpdateResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method SendStatusUpdate not implemented")
}
func (UnimplementedProxyServiceServer) CreateProxyPeer(context.Context, *CreateProxyPeerRequest) (*CreateProxyPeerResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method CreateProxyPeer not implemented")
}
func (UnimplementedProxyServiceServer) GetOIDCURL(context.Context, *GetOIDCURLRequest) (*GetOIDCURLResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetOIDCURL not implemented")
}
func (UnimplementedProxyServiceServer) ValidateSession(context.Context, *ValidateSessionRequest) (*ValidateSessionResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ValidateSession not implemented")
}
func (UnimplementedProxyServiceServer) ValidateTunnelPeer(context.Context, *ValidateTunnelPeerRequest) (*ValidateTunnelPeerResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ValidateTunnelPeer not implemented")
}
func (UnimplementedProxyServiceServer) mustEmbedUnimplementedProxyServiceServer() {}
// UnsafeProxyServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to ProxyServiceServer will
// result in compilation errors.
type UnsafeProxyServiceServer interface {
mustEmbedUnimplementedProxyServiceServer()
}
func RegisterProxyServiceServer(s grpc.ServiceRegistrar, srv ProxyServiceServer) {
s.RegisterService(&ProxyService_ServiceDesc, srv)
}
func _ProxyService_GetMappingUpdate_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(GetMappingUpdateRequest)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(ProxyServiceServer).GetMappingUpdate(m, &proxyServiceGetMappingUpdateServer{stream})
}
type ProxyService_GetMappingUpdateServer interface {
Send(*GetMappingUpdateResponse) error
grpc.ServerStream
}
type proxyServiceGetMappingUpdateServer struct {
grpc.ServerStream
}
func (x *proxyServiceGetMappingUpdateServer) Send(m *GetMappingUpdateResponse) error {
return x.ServerStream.SendMsg(m)
}
func _ProxyService_SyncMappings_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(ProxyServiceServer).SyncMappings(&proxyServiceSyncMappingsServer{stream})
}
type ProxyService_SyncMappingsServer interface {
Send(*SyncMappingsResponse) error
Recv() (*SyncMappingsRequest, error)
grpc.ServerStream
}
type proxyServiceSyncMappingsServer struct {
grpc.ServerStream
}
func (x *proxyServiceSyncMappingsServer) Send(m *SyncMappingsResponse) error {
return x.ServerStream.SendMsg(m)
}
func (x *proxyServiceSyncMappingsServer) Recv() (*SyncMappingsRequest, error) {
m := new(SyncMappingsRequest)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func _ProxyService_SendAccessLog_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SendAccessLogRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProxyServiceServer).SendAccessLog(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/management.ProxyService/SendAccessLog",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProxyServiceServer).SendAccessLog(ctx, req.(*SendAccessLogRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ProxyService_Authenticate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(AuthenticateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProxyServiceServer).Authenticate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/management.ProxyService/Authenticate",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProxyServiceServer).Authenticate(ctx, req.(*AuthenticateRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ProxyService_SendStatusUpdate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(SendStatusUpdateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProxyServiceServer).SendStatusUpdate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/management.ProxyService/SendStatusUpdate",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProxyServiceServer).SendStatusUpdate(ctx, req.(*SendStatusUpdateRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ProxyService_CreateProxyPeer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(CreateProxyPeerRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProxyServiceServer).CreateProxyPeer(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/management.ProxyService/CreateProxyPeer",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProxyServiceServer).CreateProxyPeer(ctx, req.(*CreateProxyPeerRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ProxyService_GetOIDCURL_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetOIDCURLRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProxyServiceServer).GetOIDCURL(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/management.ProxyService/GetOIDCURL",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProxyServiceServer).GetOIDCURL(ctx, req.(*GetOIDCURLRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ProxyService_ValidateSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ValidateSessionRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProxyServiceServer).ValidateSession(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/management.ProxyService/ValidateSession",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProxyServiceServer).ValidateSession(ctx, req.(*ValidateSessionRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ProxyService_ValidateTunnelPeer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ValidateTunnelPeerRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ProxyServiceServer).ValidateTunnelPeer(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/management.ProxyService/ValidateTunnelPeer",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ProxyServiceServer).ValidateTunnelPeer(ctx, req.(*ValidateTunnelPeerRequest))
}
return interceptor(ctx, in, info, handler)
}
// ProxyService_ServiceDesc is the grpc.ServiceDesc for ProxyService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var ProxyService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "management.ProxyService",
HandlerType: (*ProxyServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "SendAccessLog",
Handler: _ProxyService_SendAccessLog_Handler,
},
{
MethodName: "Authenticate",
Handler: _ProxyService_Authenticate_Handler,
},
{
MethodName: "SendStatusUpdate",
Handler: _ProxyService_SendStatusUpdate_Handler,
},
{
MethodName: "CreateProxyPeer",
Handler: _ProxyService_CreateProxyPeer_Handler,
},
{
MethodName: "GetOIDCURL",
Handler: _ProxyService_GetOIDCURL_Handler,
},
{
MethodName: "ValidateSession",
Handler: _ProxyService_ValidateSession_Handler,
},
{
MethodName: "ValidateTunnelPeer",
Handler: _ProxyService_ValidateTunnelPeer_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "GetMappingUpdate",
Handler: _ProxyService_GetMappingUpdate_Handler,
ServerStreams: true,
},
{
StreamName: "SyncMappings",
Handler: _ProxyService_SyncMappings_Handler,
ServerStreams: true,
ClientStreams: true,
},
},
Metadata: "proxy_service.proto",
}