import { SC , startServer , stopServer } from './helpers/nats_server_control' ; import test from 'ava' ; import { join } from 'path' ; import { Client , connect } from '../src/nats' ; import { Lock } from './helpers/latch' ; import { readFileSync } from 'fs' ; import { ErrorCode , NatsError } from "../src/error" ; let serverCert = join ( __dirname , '../../test/helpers/certs/server.pem' ) ; let serverKey = join ( __dirname , '../../test/helpers/certs/key.pem' ) ; let caCert = join ( __dirname , '../../test/helpers/certs/ca.pem' ) ; let clientCert = join ( __dirname , '../../test/helpers/certs/client-cert.pem' ) ; let clientKey = join ( __dirname , '../../test/helpers/certs/client-key.pem' ) ; test . before ( async ( t ) => { let server = await startServer ( ) ; let tls = await startServer ( [ '--tlscert' , serverCert , '--tlskey' , serverKey ] ) ; let tlsverify = await startServer ( [ '--tlsverify' , '--tlscert' , serverCert , '--tlskey' , serverKey , '--tlscacert' , caCert ] ) ; t . context = { server : server , tls : tls , tlsverify : tlsverify , cacert : readFileSync ( caCert ) , clientcert : readFileSync ( clientCert ) , clientkey : readFileSync ( clientKey ) } ; } ) ; test . after . always ( ( t ) => { let sc = t . context as SC ; stopServer ( sc . server ) ; stopServer ( sc . tls ) ; stopServer ( sc . tlsverify ) ; } ) ; test ( 'error if server does not support TLS' , async ( t ) => { t . plan ( 2 ) ; let lock = new Lock ( ) ; let sc = t . context as SC ; let nc = await connect ( { url : sc . server . nats , tls : true } ) ; nc . on ( 'error' , ( err ) => { t . truthy ( err ) ; t . regex ( err . message , /Server does not support a secure/ ) ; nc . close ( ) ; lock . unlock ( ) ; } ) ; return lock . latch ; } ) ; test ( 'error if server requires TLS' , async ( t ) => { t . plan ( 2 ) ; let lock = new Lock ( ) ; let sc = t . context as SC ; let nc = await connect ( { url : sc . tls . nats , tls : false } ) ; nc . on ( 'error' , ( err ) => { t . truthy ( err ) ; t . regex ( err . message , /Server requires a secure/ ) ; nc . close ( ) ; lock . unlock ( ) ; } ) ; return lock . latch ; } ) ; test ( 'no error if server requires TLS - but tls is undefined' , async ( t ) => { t . plan ( 2 ) ; let lock = new Lock ( ) ; let sc = t . context as SC ; let nc = await connect ( { url : sc . tls . nats } ) ; nc . on ( 'error' , ( err ) => { t . truthy ( err ) ; t . regex ( err . message , /unable to verify the first certificate/ ) ; lock . unlock ( ) ; } ) ; return lock . latch ; } ) ; test ( 'reject without proper CA' , async ( t ) => { t . plan ( 2 ) ; let lock = new Lock ( ) ; let sc = t . context as SC ; let nc = await connect ( { url : sc . tls . nats , tls : true } ) ; nc . on ( 'error' , ( err ) => { t . truthy ( err ) ; t . regex ( err . message , /unable to verify the first certificate/ ) ; nc . close ( ) ; lock . unlock ( ) ; } ) ; return lock . latch ; } ) ; test ( 'connect if authorized is overridden' , async ( t ) => { t . plan ( 2 ) ; let lock = new Lock ( ) ; let sc = t . context as SC ; let nc = await connect ( { url : sc . tls . nats , tls : { rejectUnauthorized : false } } ) ; nc . on ( 'connect' , ( c ) => { t . is ( c , nc ) ; t . false ( nc . protocolHandler . transport . isAuthorized ( ) ) ; nc . close ( ) ; lock . unlock ( ) ; } ) ; return lock . latch ; } ) ; test ( 'connect with proper ca and be authorized' , async ( t ) => { t . plan ( 2 ) ; let lock = new Lock ( ) ; let sc = t . context as SC ; let nc = await connect ( { url : sc . tls . nats , tls : { ca : [ sc . cacert ] } } ) ; nc . on ( 'connect' , ( c ) => { t . is ( c , nc ) ; t . true ( nc . protocolHandler . transport . isAuthorized ( ) ) ; nc . close ( ) ; lock . unlock ( ) ; } ) ; return lock . latch ; } ) ; test ( 'reject without proper cert if required by server' , async ( t ) => { t . plan ( 2 ) ; let lock = new Lock ( ) ; let sc = t . context as SC ; let nc = await connect ( { url : sc . tlsverify . nats , tls : true } ) ; nc . on ( 'error' , ( err ) => { t . truthy ( err ) ; t . regex ( err . message , /Server requires a client certificate/ ) ; nc . close ( ) ; lock . unlock ( ) ; } ) ; return lock . latch ; } ) ; test ( 'authorized with proper cert' , async ( t ) => { t . plan ( 2 ) ; let lock = new Lock ( ) ; let sc = t . context as SC ; let nc = await connect ( { url : sc . tls . nats , tls : { ca : [ sc . cacert ] } , key : [ sc . clientkey ] , cert : [ sc . clientcert ] } ) ; nc . on ( 'connect' , ( c ) => { t . is ( c , nc ) ; t . true ( nc . protocolHandler . transport . isAuthorized ( ) ) ; nc . close ( ) ; lock . unlock ( ) ; } ) ; return lock . latch ; } ) ; test ( 'handle openssl error' , async ( t ) => { t . plan ( 3 ) ; let lock = new Lock ( ) ; let sc = t . context as SC ; const nc = await connect ( { url : sc . tls . nats , tls : { key : sc . clientkey , cert : sc . cacert , ca : sc . clientcert } } ) ; nc . on ( 'error' , ( err ) => { t . is ( err . code , ErrorCode . CONN_ERR ) ; const nerr = err . chainedError as NatsError ; t . is ( nerr . code , ErrorCode . SSL_ERR ) ; t . truthy ( nerr . chainedError ) ; lock . unlock ( ) ; } ) ; return lock . latch ; } ) ;