Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
64 lines
2.2 KiB
Go
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)}
|
|
}
|