mirror of
https://github.com/go-gost/x.git
synced 2026-10-20 08:18:33 +00:00
Extracts the verified mTLS peer certificate (CN, SANs, SHA-256 fingerprint) from the TLS connection in the HTTP handler after the handshake completes, stores it in the request context, and forwards it to both gRPC and HTTP auth plugins via new AuthenticateRequest fields (client_cn, client_san, client_cert_fingerprint).
88 lines
1.8 KiB
Go
88 lines
1.8 KiB
Go
package auth
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
|
|
"github.com/go-gost/core/auth"
|
|
"github.com/go-gost/core/logger"
|
|
"github.com/go-gost/plugin/auth/proto"
|
|
xctx "github.com/go-gost/x/ctx"
|
|
"github.com/go-gost/x/internal/plugin"
|
|
"google.golang.org/grpc"
|
|
)
|
|
|
|
type grpcPlugin struct {
|
|
conn grpc.ClientConnInterface
|
|
client proto.AuthenticatorClient
|
|
log logger.Logger
|
|
}
|
|
|
|
// NewGRPCPlugin creates an Authenticator plugin based on gRPC.
|
|
func NewGRPCPlugin(name string, addr string, opts ...plugin.Option) auth.Authenticator {
|
|
var options plugin.Options
|
|
for _, opt := range opts {
|
|
opt(&options)
|
|
}
|
|
|
|
log := logger.Default().WithFields(map[string]any{
|
|
"kind": "auther",
|
|
"auther": name,
|
|
})
|
|
conn, err := plugin.NewGRPCConn(addr, &options)
|
|
if err != nil {
|
|
log.Error(err)
|
|
}
|
|
|
|
p := &grpcPlugin{
|
|
conn: conn,
|
|
log: log,
|
|
}
|
|
|
|
if conn != nil {
|
|
p.client = proto.NewAuthenticatorClient(conn)
|
|
}
|
|
return p
|
|
}
|
|
|
|
// Authenticate checks the validity of the provided user-password pair.
|
|
func (p *grpcPlugin) Authenticate(ctx context.Context, user, password string, opts ...auth.Option) (string, bool) {
|
|
if p.client == nil {
|
|
return "", false
|
|
}
|
|
|
|
var options auth.Options
|
|
for _, opt := range opts {
|
|
opt(&options)
|
|
}
|
|
|
|
var clientAddr string
|
|
if v := xctx.SrcAddrFromContext(ctx); v != nil {
|
|
clientAddr = v.String()
|
|
}
|
|
req := &proto.AuthenticateRequest{
|
|
Service: options.Service,
|
|
Username: user,
|
|
Password: password,
|
|
Client: clientAddr,
|
|
}
|
|
if v := xctx.PeerCertFromContext(ctx); v != nil {
|
|
req.ClientCn = v.CN
|
|
req.ClientSan = v.SANs
|
|
req.ClientCertFingerprint = v.Fingerprint
|
|
}
|
|
r, err := p.client.Authenticate(ctx, req)
|
|
if err != nil {
|
|
p.log.Error(err)
|
|
return "", false
|
|
}
|
|
return r.Id, r.Ok
|
|
}
|
|
|
|
func (p *grpcPlugin) Close() error {
|
|
if closer, ok := p.conn.(io.Closer); ok {
|
|
return closer.Close()
|
|
}
|
|
return nil
|
|
}
|