Files

64 lines
2.2 KiB
Go

package agentsvc
import (
"context"
"crypto/x509"
"net/http"
"time"
"gitea.mynodes.xyz/ilker/llmgw/internal/tlsconf"
)
// peerKey carries the verified client identity through to the stream handler.
//
// connect's BidiStream exposes the peer's address but not its certificate, so
// the identity is lifted out of the TLS state by middleware and put on the
// context before the connect handler ever sees the request.
type peerKey struct{}
// PeerIdentity is who the other end proved itself to be.
type PeerIdentity struct {
// CommonName is the certificate's subject CN, which is the node id a node
// is allowed to claim.
CommonName string
// Verified is false when the connection carried no client certificate,
// which only happens when TLS is switched off.
Verified bool
// IssuedAt is when the certificate was issued, for revocation: one issued
// for a node before it was removed is refused.
IssuedAt time.Time
}
// WithPeerIdentity records a verified identity on the context.
func WithPeerIdentity(ctx context.Context, id PeerIdentity) context.Context {
return context.WithValue(ctx, peerKey{}, id)
}
// peerFrom reads the identity a request was authenticated with.
func peerFrom(ctx context.Context) PeerIdentity {
id, _ := ctx.Value(peerKey{}).(PeerIdentity)
return id
}
// AuthMiddleware lifts the client certificate's common name onto the request
// context.
//
// The certificate chain has already been verified by the TLS handshake — this
// only makes the result reachable from the handler. Without a certificate the
// identity is marked unverified and the handler decides what to do, which keeps
// the insecure development path working without a second code path through the
// service itself.
func AuthMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
var id PeerIdentity
if r.TLS != nil && len(r.TLS.PeerCertificates) > 0 {
id = identityOf(r.TLS.PeerCertificates[0])
}
next.ServeHTTP(w, r.WithContext(WithPeerIdentity(r.Context(), id)))
})
}
func identityOf(cert *x509.Certificate) PeerIdentity {
return PeerIdentity{CommonName: cert.Subject.CommonName, Verified: true, IssuedAt: tlsconf.IssuedAt(cert)}
}