AuthCallout request should include TLS data when client is NATS WS client

This commit is contained in:
Todd Beets
2023-09-15 12:36:34 -07:00
parent 8f84ea4224
commit 75d2ddb26b
2 changed files with 101 additions and 3 deletions

View File

@@ -152,6 +152,23 @@ func (at *authTest) Connect(clientOptions ...nats.Option) *nats.Conn {
return conn
}
func (at *authTest) WSNewClient(clientOptions ...nats.Option) (*nats.Conn, error) {
pi := at.srv.PortsInfo(10 * time.Millisecond)
require_False(at.t, pi == nil)
conn, err := nats.Connect(strings.Replace(pi.WebSocket[0], "127.0.0.1", "localhost", 1), clientOptions...)
if err != nil {
return nil, err
}
at.clients = append(at.clients, conn)
return conn, nil
}
func (at *authTest) WSConnect(clientOptions ...nats.Option) *nats.Conn {
conn, err := at.WSNewClient(clientOptions...)
require_NoError(at.t, err)
return conn
}
func (at *authTest) RequireConnectError(clientOptions ...nats.Option) {
_, err := at.NewClient(clientOptions...)
require_Error(at.t, err)
@@ -1423,3 +1440,82 @@ func TestAuthCalloutOperator_AnyAccount(t *testing.T) {
userInfo = response.Data.(*UserInfo)
require_Equal(t, userInfo.Account, bpk)
}
func TestAuthCalloutWSClientTLSCerts(t *testing.T) {
conf := `
server_name: T
listen: "localhost:-1"
tls {
cert_file = "../test/configs/certs/tlsauth/server.pem"
key_file = "../test/configs/certs/tlsauth/server-key.pem"
ca_file = "../test/configs/certs/tlsauth/ca.pem"
verify = true
}
websocket: {
listen: "localhost:-1"
tls {
cert_file = "../test/configs/certs/tlsauth/server.pem"
key_file = "../test/configs/certs/tlsauth/server-key.pem"
ca_file = "../test/configs/certs/tlsauth/ca.pem"
verify = true
}
}
accounts {
AUTH { users [ {user: "auth", password: "pwd"} ] }
FOO {}
}
authorization {
timeout: 1s
auth_callout {
# Needs to be a public account nkey, will work for both server config and operator mode.
issuer: "ABJHLOVMPA4CI6R5KLNGOB4GSLNIY7IOUPAJC4YFNDLQVIOBYQGUWVLA"
account: AUTH
auth_users: [ auth ]
}
}
`
handler := func(m *nats.Msg) {
user, si, ci, _, ctls := decodeAuthRequest(t, m.Data)
require_True(t, si.Name == "T")
require_True(t, ci.Host == "127.0.0.1")
require_True(t, ctls != nil)
// Zero since we are verified and will be under verified chains.
require_True(t, len(ctls.Certs) == 0)
require_True(t, len(ctls.VerifiedChains) == 1)
// Since we have a CA.
require_True(t, len(ctls.VerifiedChains[0]) == 2)
blk, _ := pem.Decode([]byte(ctls.VerifiedChains[0][0]))
cert, err := x509.ParseCertificate(blk.Bytes)
require_NoError(t, err)
if strings.HasPrefix(cert.Subject.String(), "CN=example.com") {
// Override blank name here, server will substitute.
ujwt := createAuthUser(t, user, "dlc", "FOO", "", nil, 0, nil)
m.Respond(serviceResponse(t, user, si.ID, ujwt, "", 0))
}
}
ac := NewAuthTest(t, conf, handler,
nats.UserInfo("auth", "pwd"),
nats.ClientCert("../test/configs/certs/tlsauth/client2.pem", "../test/configs/certs/tlsauth/client2-key.pem"),
nats.RootCAs("../test/configs/certs/tlsauth/ca.pem"))
defer ac.Cleanup()
// Will use client cert to determine user.
nc := ac.WSConnect(
nats.ClientCert("../test/configs/certs/tlsauth/client2.pem", "../test/configs/certs/tlsauth/client2-key.pem"),
nats.RootCAs("../test/configs/certs/tlsauth/ca.pem"),
)
resp, err := nc.Request(userDirectInfoSubj, nil, time.Second)
require_NoError(t, err)
response := ServerAPIResponse{Data: &UserInfo{}}
err = json.Unmarshal(resp.Data, &response)
require_NoError(t, err)
userInfo := response.Data.(*UserInfo)
require_True(t, userInfo.UserID == "dlc")
require_True(t, userInfo.Account == "FOO")
}

View File

@@ -1234,12 +1234,14 @@ func (s *Server) createWSClient(conn net.Conn, ws *websocket) *client {
return nil
}
s.clients[c.cid] = c
// Websocket clients do TLS in the websocket http server.
// So no TLS here...
s.mu.Unlock()
c.mu.Lock()
// Websocket clients do TLS in the websocket http server.
// So no TLS initiation here...
if _, ok := conn.(*tls.Conn); ok {
c.flags.set(handshakeComplete)
}
if c.isClosed() {
c.mu.Unlock()