mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-02 04:51:29 +02:00
115 lines
3.4 KiB
Go
115 lines
3.4 KiB
Go
//go:build linux || darwin || freebsd
|
|
|
|
package ipcauth
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/credentials/insecure"
|
|
"google.golang.org/grpc/health"
|
|
healthpb "google.golang.org/grpc/health/grpc_health_v1"
|
|
)
|
|
|
|
// TestPeerIdentity_MatchesCurrentProcess connects to a real Unix socket and
|
|
// verifies the extracted UID/GID match the running process (both ends are us).
|
|
func TestPeerIdentity_MatchesCurrentProcess(t *testing.T) {
|
|
sock := filepath.Join(t.TempDir(), "peer.sock")
|
|
ln, err := net.Listen("unix", sock)
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { _ = ln.Close() })
|
|
|
|
type result struct {
|
|
id Identity
|
|
err error
|
|
}
|
|
done := make(chan result, 1)
|
|
go func() {
|
|
c, aerr := ln.Accept()
|
|
if aerr != nil {
|
|
done <- result{err: aerr}
|
|
return
|
|
}
|
|
defer func() { _ = c.Close() }()
|
|
id, ierr := PeerIdentity(c)
|
|
done <- result{id: id, err: ierr}
|
|
}()
|
|
|
|
client, err := net.Dial("unix", sock)
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { _ = client.Close() })
|
|
|
|
res := <-done
|
|
require.NoError(t, res.err)
|
|
assert.Equal(t, uint32(os.Getuid()), res.id.UID, "UID should match current process")
|
|
assert.Equal(t, uint32(os.Getgid()), res.id.GID, "primary GID should match current process")
|
|
}
|
|
|
|
// TestPeerIdentity_NonUnixConn rejects non-Unix connections (fail closed).
|
|
func TestPeerIdentity_NonUnixConn(t *testing.T) {
|
|
ln, err := net.Listen("tcp", "127.0.0.1:0")
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { _ = ln.Close() })
|
|
|
|
done := make(chan error, 1)
|
|
go func() {
|
|
c, aerr := ln.Accept()
|
|
if aerr != nil {
|
|
done <- aerr
|
|
return
|
|
}
|
|
defer func() { _ = c.Close() }()
|
|
_, ierr := PeerIdentity(c)
|
|
done <- ierr
|
|
}()
|
|
|
|
client, err := net.Dial("tcp", ln.Addr().String())
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { _ = client.Close() })
|
|
|
|
assert.Error(t, <-done, "PeerIdentity must reject a non-Unix connection")
|
|
}
|
|
|
|
// TestGRPCRoundTrip_ServerCredsClientInsecure proves the transport contract end
|
|
// to end: a gRPC server using the peercred transport credentials still serves a
|
|
// plain insecure client (the CLI never changed), and the caller's kernel
|
|
// identity reaches the handler via IdentityFromContext.
|
|
func TestGRPCRoundTrip_ServerCredsClientInsecure(t *testing.T) {
|
|
sock := filepath.Join(t.TempDir(), "rt.sock")
|
|
ln, err := net.Listen("unix", sock)
|
|
require.NoError(t, err)
|
|
|
|
var gotUID uint32
|
|
var gotOK bool
|
|
srv := grpc.NewServer(
|
|
grpc.Creds(NewTransportCredentials()),
|
|
grpc.UnaryInterceptor(func(ctx context.Context, req any, _ *grpc.UnaryServerInfo, h grpc.UnaryHandler) (any, error) {
|
|
id, ok := IdentityFromContext(ctx)
|
|
gotUID, gotOK = id.UID, ok
|
|
return h(ctx, req)
|
|
}),
|
|
)
|
|
healthpb.RegisterHealthServer(srv, health.NewServer())
|
|
go func() { _ = srv.Serve(ln) }()
|
|
t.Cleanup(srv.Stop)
|
|
|
|
conn, err := grpc.NewClient("unix://"+sock, grpc.WithTransportCredentials(insecure.NewCredentials()))
|
|
require.NoError(t, err)
|
|
t.Cleanup(func() { _ = conn.Close() })
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
_, err = healthpb.NewHealthClient(conn).Check(ctx, &healthpb.HealthCheckRequest{})
|
|
require.NoError(t, err, "insecure client must reach the peercred server")
|
|
|
|
assert.True(t, gotOK, "handler must see a peer identity")
|
|
assert.Equal(t, uint32(os.Getuid()), gotUID, "handler must see the caller's UID")
|
|
}
|