feat(creds): retrieve peer credentials when using unix socket

Signed-off-by: Adphi <philippe.adrien.nousse@gmail.com>
This commit is contained in:
2025-11-23 12:42:01 +01:00
parent 4b64efb327
commit 6829ab5bbc
4 changed files with 75 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
package peercreds
import (
"context"
"errors"
"net"
"github.com/tailscale/peercred"
"google.golang.org/grpc/credentials"
)
var _ credentials.TransportCredentials = (*peerCreds)(nil)
var common = credentials.CommonAuthInfo{SecurityLevel: credentials.PrivacyAndIntegrity}
func New() credentials.TransportCredentials {
return &peerCreds{info: credentials.ProtocolInfo{
SecurityProtocol: "peercred",
ProtocolVersion: "0.1",
}}
}
type peerCreds struct {
info credentials.ProtocolInfo
}
// AuthInfo well attach to the gRPC peer
type AuthInfo struct {
credentials.CommonAuthInfo
Creds *peercred.Creds
}
func (AuthInfo) AuthType() string { return "peercred" }
func (t *peerCreds) ClientHandshake(_ context.Context, _ string, conn net.Conn) (net.Conn, credentials.AuthInfo, error) {
return t.handshakeConn(conn)
}
func (t *peerCreds) ServerHandshake(conn net.Conn) (net.Conn, credentials.AuthInfo, error) {
return t.handshakeConn(conn)
}
func (t *peerCreds) Info() credentials.ProtocolInfo {
return t.info
}
func (t *peerCreds) Clone() credentials.TransportCredentials {
return &peerCreds{info: t.info}
}
func (t *peerCreds) OverrideServerName(name string) error {
t.info.ServerName = name
return nil
}
func (t *peerCreds) handshakeConn(conn net.Conn) (net.Conn, credentials.AuthInfo, error) {
if conn.RemoteAddr().Network() != "unix" {
return nil, nil, errors.New("peercred only works with unix domain sockets")
}
creds, err := peercred.Get(conn)
if err != nil {
if errors.Is(err, peercred.ErrNotImplemented) {
return nil, nil, errors.New("peercred not implemented on this OS")
}
return nil, nil, err
}
return conn, AuthInfo{Creds: creds, CommonAuthInfo: common}, nil
}