github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/integration/suites/broker_auth/broker_auth_test.go (about) 1 package broker_auth 2 3 import ( 4 "context" 5 "crypto/ed25519" 6 "crypto/rsa" 7 "crypto/tls" 8 "encoding/hex" 9 "os" 10 "strings" 11 "sync" 12 "testing" 13 "time" 14 15 "github.com/choria-io/go-choria/broker/network" 16 "github.com/choria-io/go-choria/choria" 17 "github.com/choria-io/go-choria/integration/testbroker" 18 "github.com/choria-io/go-choria/integration/testutil" 19 "github.com/choria-io/tokens" 20 "github.com/nats-io/nats.go" 21 . "github.com/onsi/ginkgo/v2" 22 . "github.com/onsi/gomega" 23 "github.com/onsi/gomega/gbytes" 24 "github.com/sirupsen/logrus" 25 ) 26 27 // TestBrokerAuthentication is a number of tests that essentially test out broker.ChoriaAuth class 28 // by starting a broker with a specific configuration file and then using the nats.go client to attempt 29 // to connect to it, bypass restrictions and more 30 func TestBrokerAuthentication(t *testing.T) { 31 RegisterFailHandler(Fail) 32 RunSpecs(t, "Integration/Broker Authentication") 33 } 34 35 var _ = Describe("Authentication", func() { 36 var ( 37 ctx context.Context 38 cancel context.CancelFunc 39 wg sync.WaitGroup 40 logger *logrus.Logger 41 logbuff *gbytes.Buffer 42 ) 43 44 BeforeEach(func() { 45 ctx, cancel = context.WithTimeout(context.Background(), 45*time.Second) 46 DeferCleanup(func() { 47 cancel() 48 Eventually(logbuff, 5).Should(gbytes.Say("Choria Network Broker shut down")) 49 }) 50 51 logbuff, logger = testutil.GbytesLogger(logrus.DebugLevel) 52 }) 53 54 Describe("JWT Auth", func() { 55 var ( 56 edPrivateKey ed25519.PrivateKey 57 edPublicKey ed25519.PublicKey 58 nodeSignerPK *rsa.PrivateKey 59 clientSignerPK *rsa.PrivateKey 60 ) 61 62 BeforeEach(func() { 63 _, err := testbroker.StartNetworkBrokerWithConfigFile(ctx, &wg, "testdata/anontls.conf", logger) 64 Expect(err).ToNot(HaveOccurred()) 65 66 Eventually(logbuff, 1).Should(gbytes.Say("Server is ready")) 67 68 Expect(logbuff.Contents()).To(ContainSubstring("Allowing unverified TLS connections for AAA signed clients")) 69 Expect(logbuff.Contents()).To(ContainSubstring("Allowing unverified TLS connections for Provisioner signed servers")) 70 Expect(logbuff.Contents()).To(ContainSubstring("TLS required for client connections")) 71 72 edPublicKey, edPrivateKey, err = choria.Ed25519KeyPair() 73 Expect(err).ToNot(HaveOccurred()) 74 75 nodeSignerPK, err = testutil.LoadRSAKey("../../ca/node-signer-key.pem") 76 Expect(err).ToNot(HaveOccurred()) 77 clientSignerPK, err = testutil.LoadRSAKey("../../ca/client-signer-key.pem") 78 Expect(err).ToNot(HaveOccurred()) 79 }) 80 81 Describe("JWT Token Servers", func() { 82 It("Should fail for invalid server tokens", func() { 83 // signing the server jwt with the client signer which will yield an invalid connection 84 jwt, err := testutil.CreateSignedServerJWT(clientSignerPK, edPublicKey, map[string]any{ 85 "purpose": tokens.ServerPurpose, 86 "public_key": hex.EncodeToString(edPublicKey), 87 "collectives": []string{"c1"}, 88 }) 89 Expect(err).ToNot(HaveOccurred()) 90 91 _, err = nats.Connect("nats://localhost:4222", 92 nats.Secure(&tls.Config{InsecureSkipVerify: true}), 93 nats.Token(jwt), 94 nats.UserJWT(func() (string, error) { 95 return jwt, nil 96 }, func(n []byte) ([]byte, error) { 97 return choria.Ed25519Sign(edPrivateKey, n) 98 }), 99 ) 100 Expect(err).To(MatchError("nats: Authorization Violation")) 101 Eventually(logbuff, 5).Should(gbytes.Say("Performing JWT based authentication verification")) 102 Eventually(logbuff, 1).Should(gbytes.Say("could not parse server id token: crypto/rsa: verification error")) 103 Eventually(logbuff, 1).Should(gbytes.Say("invalid nonce signature or jwt token")) 104 Eventually(logbuff, 1).ShouldNot(gbytes.Say("Registering user")) 105 }) 106 107 It("Should fail for invalid nonce signatures", func() { 108 jwt, err := testutil.CreateSignedServerJWT(nodeSignerPK, edPublicKey, map[string]any{ 109 "purpose": tokens.ServerPurpose, 110 "public_key": hex.EncodeToString(edPublicKey), 111 "collectives": []string{"c1"}, 112 }) 113 Expect(err).ToNot(HaveOccurred()) 114 115 _, err = nats.Connect("nats://localhost:4222", 116 nats.Secure(&tls.Config{InsecureSkipVerify: true}), 117 nats.Token(jwt), 118 nats.UserJWT(func() (string, error) { 119 return jwt, nil 120 }, func(n []byte) ([]byte, error) { 121 // we create an invalid nonce signature so this must fail 122 return []byte("invalid signature"), nil 123 }), 124 ) 125 Expect(err).To(MatchError("nats: Authorization Violation")) 126 Eventually(logbuff, 5).Should(gbytes.Say("Performing JWT based authentication verification")) 127 Eventually(logbuff, 1).Should(gbytes.Say("nonce signature verification failed: nonce signature did not verify using pub key in the jwt")) 128 Eventually(logbuff, 1).ShouldNot(gbytes.Say("Registering user")) 129 }) 130 131 It("Should accept valid servers and set permissions", func() { 132 jwt, err := testutil.CreateSignedServerJWT(nodeSignerPK, edPublicKey, map[string]any{ 133 "purpose": tokens.ServerPurpose, 134 "public_key": hex.EncodeToString(edPublicKey), 135 "collectives": []string{"c1"}, 136 }) 137 Expect(err).ToNot(HaveOccurred()) 138 139 clBuffer, clLogger := testutil.GbytesLogger(logrus.DebugLevel) 140 141 nc, err := nats.Connect("nats://localhost:4222", 142 nats.ErrorHandler(func(_ *nats.Conn, _ *nats.Subscription, err error) { 143 clLogger.Errorf(strings.ReplaceAll(err.Error(), `"`, ``)) 144 }), 145 nats.Secure(&tls.Config{InsecureSkipVerify: true}), 146 nats.Token(jwt), 147 nats.UserJWT(func() (string, error) { 148 return jwt, nil 149 }, func(n []byte) ([]byte, error) { 150 return choria.Ed25519Sign(edPrivateKey, n) 151 }), 152 ) 153 Expect(err).ToNot(HaveOccurred()) 154 defer nc.Close() 155 156 Eventually(logbuff, 5).Should(gbytes.Say("Performing JWT based authentication verification")) 157 Eventually(logbuff, 1).Should(gbytes.Say("Successfully verified nonce signature")) 158 Eventually(logbuff, 1).Should(gbytes.Say("Extracted remote identity ginkgo.example.net from JWT token")) 159 Eventually(logbuff, 1).Should(gbytes.Say("Setting server permissions based on token claims")) 160 Eventually(logbuff, 1).Should(gbytes.Say("Registering user 'ginkgo.example.net' in account 'choria'")) 161 162 Expect(nc.ConnectedUrl()).To(Equal("nats://localhost:4222")) 163 Expect(nc.Publish("choria.lifecycle.x", []byte("x"))).ToNot(HaveOccurred()) 164 Expect(nc.Publish("choria.machine.transition", []byte("x"))).ToNot(HaveOccurred()) 165 Expect(nc.Publish("choria.machine.watcher.x", []byte("x"))).ToNot(HaveOccurred()) 166 167 // should not allow submission by default 168 Expect(nc.Publish("c1.submission.in.x", []byte("x"))).ToNot(HaveOccurred()) 169 Eventually(clBuffer, 1).Should(gbytes.Say(`Permissions Violation for Publish to c1.submission.in.x`)) 170 171 // should only allow us to sub to our id 172 _, err = nc.Subscribe("c1.node.other.node", func(m *nats.Msg) {}) 173 Expect(err).ToNot(HaveOccurred()) 174 Eventually(clBuffer, 1).Should(gbytes.Say("Permissions Violation for Subscription to c1.node.other.node")) 175 176 _, err = nc.Subscribe("c1.node.ginkgo.example.net", func(m *nats.Msg) {}) 177 Expect(err).ToNot(HaveOccurred()) 178 Eventually(clBuffer, 1).ShouldNot(gbytes.Say("Permissions Violation for Subscription")) 179 180 // should not allow sub collective escape 181 _, err = nc.Subscribe("other.node.ginkgo.example.net", func(m *nats.Msg) {}) 182 Expect(err).ToNot(HaveOccurred()) 183 Eventually(clBuffer, 1).Should(gbytes.Say("Permissions Violation for Subscription to other.node.ginkgo.example.net")) 184 185 }) 186 }) 187 188 Describe("JWT Token Clients", func() { 189 It("Should fail for invalid client tokens", func() { 190 // signing the client jwt with the server signer which will yield an invalid connection 191 jwt, err := testutil.CreateSignedServerJWT(nodeSignerPK, edPublicKey, map[string]any{ 192 "purpose": tokens.ClientIDPurpose, 193 "callerid": "up=ginkgo", 194 "public_key": hex.EncodeToString(edPublicKey), 195 }) 196 Expect(err).ToNot(HaveOccurred()) 197 198 _, err = nats.Connect("nats://localhost:4222", 199 nats.Secure(&tls.Config{InsecureSkipVerify: true}), 200 nats.Token(jwt), 201 nats.UserJWT(func() (string, error) { 202 return jwt, nil 203 }, func(n []byte) ([]byte, error) { 204 return choria.Ed25519Sign(edPrivateKey, n) 205 }), 206 ) 207 Expect(err).To(MatchError("nats: Authorization Violation")) 208 Eventually(logbuff, 5).Should(gbytes.Say("Performing JWT based authentication verification")) 209 Eventually(logbuff, 1).Should(gbytes.Say("could not parse client id token: crypto/rsa: verification error")) 210 Eventually(logbuff, 1).Should(gbytes.Say("invalid nonce signature or jwt token")) 211 Eventually(logbuff, 1).ShouldNot(gbytes.Say("Registering user")) 212 }) 213 214 It("Should fail for invalid nonce signatures", func() { 215 jwt, err := testutil.CreateSignedServerJWT(clientSignerPK, edPublicKey, map[string]any{ 216 "purpose": tokens.ClientIDPurpose, 217 "callerid": "up=ginkgo", 218 "public_key": hex.EncodeToString(edPublicKey), 219 }) 220 Expect(err).ToNot(HaveOccurred()) 221 222 _, err = nats.Connect("nats://localhost:4222", 223 nats.Secure(&tls.Config{InsecureSkipVerify: true}), 224 nats.Token(jwt), 225 nats.UserJWT(func() (string, error) { 226 return jwt, nil 227 }, func(n []byte) ([]byte, error) { 228 // we create an invalid nonce signature so this must fail 229 return []byte("invalid signature"), nil 230 }), 231 ) 232 Expect(err).To(MatchError("nats: Authorization Violation")) 233 234 Eventually(logbuff, 5).Should(gbytes.Say("Performing JWT based authentication verification")) 235 Eventually(logbuff, 1).Should(gbytes.Say("nonce signature verification failed: nonce signature did not verify using pub key in the jwt")) 236 Eventually(logbuff, 1).ShouldNot(gbytes.Say("Registering user")) 237 }) 238 239 It("Should require a caller id claim", func() { 240 jwt, err := testutil.CreateSignedServerJWT(clientSignerPK, edPublicKey, map[string]any{ 241 "purpose": tokens.ClientIDPurpose, 242 "public_key": hex.EncodeToString(edPublicKey), 243 }) 244 Expect(err).ToNot(HaveOccurred()) 245 246 _, err = nats.Connect("nats://localhost:4222", 247 nats.Secure(&tls.Config{InsecureSkipVerify: true}), 248 nats.Token(jwt), 249 nats.UserJWT(func() (string, error) { 250 return jwt, nil 251 }, func(n []byte) ([]byte, error) { 252 return choria.Ed25519Sign(edPrivateKey, n) 253 }), 254 ) 255 Expect(err).To(MatchError("nats: Authorization Violation")) 256 257 Eventually(logbuff, 5).Should(gbytes.Say("Performing JWT based authentication verification")) 258 Eventually(logbuff, 1).Should(gbytes.Say("no callerid in claims")) 259 Eventually(logbuff, 1).ShouldNot(gbytes.Say("Registering user")) 260 }) 261 262 It("Should accept valid clients and set permissions", func() { 263 jwt, err := testutil.CreateSignedServerJWT(clientSignerPK, edPublicKey, map[string]any{ 264 "purpose": tokens.ClientIDPurpose, 265 "callerid": "up=ginkgo", 266 "public_key": hex.EncodeToString(edPublicKey), 267 }) 268 Expect(err).ToNot(HaveOccurred()) 269 270 clBuffer, clLogger := testutil.GbytesLogger(logrus.DebugLevel) 271 272 nc, err := nats.Connect("nats://localhost:4222", 273 nats.ErrorHandler(func(_ *nats.Conn, _ *nats.Subscription, err error) { 274 clLogger.Errorf(strings.ReplaceAll(err.Error(), `"`, ``)) 275 }), 276 nats.Secure(&tls.Config{InsecureSkipVerify: true}), 277 nats.Token(jwt), 278 nats.UserJWT(func() (string, error) { 279 return jwt, nil 280 }, func(n []byte) ([]byte, error) { 281 return choria.Ed25519Sign(edPrivateKey, n) 282 }), 283 ) 284 Expect(err).ToNot(HaveOccurred()) 285 defer nc.Close() 286 287 Eventually(logbuff, 5).Should(gbytes.Say("Performing JWT based authentication verification")) 288 Eventually(logbuff, 1).Should(gbytes.Say("Successfully verified nonce signature")) 289 Eventually(logbuff, 1).Should(gbytes.Say("Extracted caller id up=ginkgo from JWT token")) 290 Eventually(logbuff, 1).Should(gbytes.Say("Creating ACLs for a private reply subject on \\*.reply.e33bf0376d4accbb4a8fd24b2f840b2e.>")) 291 Eventually(logbuff, 1).Should(gbytes.Say("Registering user 'up=ginkgo' in account 'choria'")) 292 293 // should only access its own replies 294 _, err = nc.Subscribe("c1.reply.xxxx.>", func(_ *nats.Msg) {}) 295 Expect(err).ToNot(HaveOccurred()) 296 Eventually(logbuff, 1).Should(gbytes.Say("Subscription Violation - User .+up=ginkgo.+, Subject .+c1.reply.xxxx.>")) 297 Eventually(clBuffer, 1).Should(gbytes.Say("Permissions Violation for Subscription to c1.reply.xxxx.>")) 298 299 _, err = nc.Subscribe("c1.reply.e33bf0376d4accbb4a8fd24b2f840b2e.>", func(_ *nats.Msg) {}) 300 Expect(err).ToNot(HaveOccurred()) 301 Eventually(logbuff, 1).ShouldNot(gbytes.Say("c1.reply.e33bf0376d4accbb4a8fd24b2f840b2e")) 302 Eventually(clBuffer, 1).ShouldNot(gbytes.Say("c1.reply.e33bf0376d4accbb4a8fd24b2f840b2e")) 303 304 // should not be able to be a node 305 _, err = nc.Subscribe("c1.node.other.node", func(m *nats.Msg) {}) 306 Expect(err).ToNot(HaveOccurred()) 307 Eventually(clBuffer, 1).Should(gbytes.Say("Permissions Violation for Subscription to c1.node.other.node")) 308 309 }) 310 }) 311 }) 312 313 Describe("In-process connections", func() { 314 var broker *network.Server 315 var err error 316 317 Describe("mTLS Broker", func() { 318 BeforeEach(func() { 319 broker, err = testbroker.StartNetworkBrokerWithConfigFile(ctx, &wg, "testdata/mtls.conf", logger) 320 Expect(err).ToNot(HaveOccurred()) 321 Eventually(logbuff, 1).Should(gbytes.Say("TLS required for client connections")) 322 Eventually(logbuff, 1).Should(gbytes.Say("Server is ready")) 323 }) 324 325 It("Should allow in process connections to the choria account", func() { 326 _, err = nats.Connect("nats://localhost:4222", nats.InProcessServer(broker), nats.Secure(&tls.Config{InsecureSkipVerify: true})) 327 Expect(err).ToNot(HaveOccurred()) 328 Expect(logbuff.Contents()).To(ContainSubstring("Allowing pipe connection without any limitations")) 329 Expect(logbuff.Contents()).To(ContainSubstring("Registering user '' in account 'choria'")) 330 }) 331 332 It("Should allow in process connections to the system account", func() { 333 _, err = nats.Connect("nats://localhost:4222", nats.UserInfo("system", "system"), nats.InProcessServer(broker), nats.Secure(&tls.Config{InsecureSkipVerify: true})) 334 Expect(err).ToNot(HaveOccurred()) 335 Expect(logbuff.Contents()).To(ContainSubstring("Registering user 'system' in account 'system'")) 336 }) 337 }) 338 339 Describe("JWT Broker", func() { 340 BeforeEach(func() { 341 broker, err = testbroker.StartNetworkBrokerWithConfigFile(ctx, &wg, "testdata/anontls.conf", logger) 342 Expect(err).ToNot(HaveOccurred()) 343 344 Eventually(logbuff, 1).Should(gbytes.Say("Server is ready")) 345 Expect(logbuff.Contents()).To(ContainSubstring("Allowing unverified TLS connections for AAA signed clients")) 346 Expect(logbuff.Contents()).To(ContainSubstring("Allowing unverified TLS connections for Provisioner signed servers")) 347 Expect(logbuff.Contents()).To(ContainSubstring("TLS required for client connections")) 348 }) 349 350 It("Should allow in process connections to the choria account", func() { 351 _, err = nats.Connect("nats://localhost:4222", nats.InProcessServer(broker), nats.Secure(&tls.Config{InsecureSkipVerify: true})) 352 Expect(err).ToNot(HaveOccurred()) 353 Expect(logbuff.Contents()).To(ContainSubstring("Allowing pipe connection without any limitations")) 354 Expect(logbuff.Contents()).To(ContainSubstring("Registering user '' in account 'choria'")) 355 }) 356 357 It("Should allow in process connections to the system account", func() { 358 _, err = nats.Connect("nats://localhost:4222", nats.UserInfo("system", "systemS3cret"), nats.InProcessServer(broker), nats.Secure(&tls.Config{InsecureSkipVerify: true})) 359 Expect(err).ToNot(HaveOccurred()) 360 Expect(logbuff.Contents()).To(ContainSubstring("Registering user 'system' in account 'system'")) 361 }) 362 }) 363 }) 364 365 Describe("mTLS Connections", FlakeAttempts(5), func() { 366 BeforeEach(func() { 367 _, err := testbroker.StartNetworkBrokerWithConfigFile(ctx, &wg, "testdata/mtls.conf", logger) 368 Expect(err).ToNot(HaveOccurred()) 369 370 Eventually(logbuff, 2).Should(gbytes.Say("TLS required for client connections")) 371 Eventually(logbuff, 1).Should(gbytes.Say("Server is ready")) 372 }) 373 374 It("Should reject unverified TLS connections", func() { 375 _, err := nats.Connect("nats://localhost:4222", 376 nats.Secure(&tls.Config{InsecureSkipVerify: true}), 377 ) 378 Expect(err).To(MatchError("nats: Authorization Violation")) 379 Eventually(logbuff, 2).Should(gbytes.Say("Rejecting unverified connection without token")) 380 Expect(logbuff).ToNot(gbytes.Say("Registering user")) 381 }) 382 383 It("Should be rejected using the certs from an unknown CA", func() { 384 nc, err := nats.Connect("tls://localhost:4222", 385 nats.ClientCert(testutil.CertPath("two", "rip.mcollective"), testutil.KeyPath("two", "rip.mcollective")), 386 nats.RootCAs(testutil.CertPath("one", "ca")), 387 ) 388 Eventually(logbuff, 5).Should(gbytes.Say("failed to verify.+certificate: x509: certificate signed by unknown authority")) 389 Expect(err).To(Or(MatchError("remote error: tls: bad certificate"), MatchError("remote error: tls: unknown certificate authority"))) 390 Expect(nc).To(BeNil()) 391 Expect(logbuff).ToNot(gbytes.Say("Registering user")) 392 }) 393 394 It("Should allow connections using the right CA and valid keys", func() { 395 nc, err := nats.Connect("tls://localhost:4222", 396 nats.ClientCert(testutil.CertPath("one", "rip.mcollective"), testutil.KeyPath("one", "rip.mcollective")), 397 nats.RootCAs(testutil.CertPath("one", "ca")), 398 ) 399 Expect(err).ToNot(HaveOccurred()) 400 defer nc.Close() 401 402 Eventually(logbuff, 1).Should(gbytes.Say("Registering user '' in account 'choria'")) 403 Expect(nc.ConnectedUrl()).To(Equal("tls://localhost:4222")) 404 }) 405 }) 406 407 Describe("System Account Connections", func() { 408 BeforeEach(func() { 409 _, err := testbroker.StartNetworkBrokerWithConfigFile(ctx, &wg, "testdata/provisioning.conf", logger) 410 Expect(err).ToNot(HaveOccurred()) 411 Eventually(logbuff, 1).Should(gbytes.Say("Allowing unverified TLS connections for provisioning purposes")) 412 Eventually(logbuff, 2).Should(gbytes.Say("TLS required for client connections")) 413 Eventually(logbuff, 1).Should(gbytes.Say("Server is ready")) 414 }) 415 416 It("Should prevent the system user from connecting without full TLS", func() { 417 _, err := nats.Connect("nats://localhost:4222", 418 nats.UserInfo("system", "systemS3cret"), 419 nats.Secure(&tls.Config{InsecureSkipVerify: true})) 420 Expect(err).To(MatchError("nats: Authorization Violation")) 421 Expect(logbuff).To(gbytes.Say("Handling unverified TLS system user failed, denying: no JWT token received")) 422 Expect(logbuff).ToNot(gbytes.Say("Registering user")) 423 }) 424 425 It("Should verify credentials", func() { 426 _, err := nats.Connect("nats://localhost:4222", 427 nats.UserInfo("system", "s3cret"), 428 nats.ClientCert(testutil.CertPath("one", "rip.mcollective"), testutil.KeyPath("one", "rip.mcollective")), 429 nats.RootCAs(testutil.CertPath("one", "ca"))) 430 Expect(err).To(MatchError("nats: Authorization Violation")) 431 Expect(logbuff).To(gbytes.Say("Handling system user failed, denying: invalid system credentials")) 432 Expect(logbuff).ToNot(gbytes.Say("Registering user")) 433 }) 434 435 It("Should register correct connections", func() { 436 nc, err := nats.Connect("nats://localhost:4222", 437 nats.UserInfo("system", "systemS3cret"), 438 nats.ClientCert(testutil.CertPath("one", "rip.mcollective"), testutil.KeyPath("one", "rip.mcollective")), 439 nats.RootCAs(testutil.CertPath("one", "ca"))) 440 Expect(err).ToNot(HaveOccurred()) 441 Expect(nc.ConnectedUrl()).To(Equal("nats://localhost:4222")) 442 Expect(logbuff).To(gbytes.Say("Registering user 'system' in account 'system'")) 443 }) 444 }) 445 446 Describe("Provisioning Mode Server Connections", func() { 447 var ( 448 jwt []byte 449 invalidJwt []byte 450 ) 451 452 BeforeEach(func() { 453 _, err := testbroker.StartNetworkBrokerWithConfigFile(ctx, &wg, "testdata/provisioning.conf", logger) 454 Expect(err).ToNot(HaveOccurred()) 455 Eventually(logbuff, 1).Should(gbytes.Say("Allowing unverified TLS connections for provisioning purposes")) 456 Eventually(logbuff, 2).Should(gbytes.Say("TLS required for client connections")) 457 Eventually(logbuff, 1).Should(gbytes.Say("Server is ready")) 458 459 invalidJwt, err = os.ReadFile("../../ca/invalid-provisioning.jwt") 460 Expect(err).ToNot(HaveOccurred()) 461 462 jwt, err = os.ReadFile("../../ca/provisioning.jwt") 463 Expect(err).ToNot(HaveOccurred()) 464 }) 465 466 It("Should fail without a token", func() { 467 _, err := nats.Connect("nats://localhost:4222", 468 nats.Secure(&tls.Config{InsecureSkipVerify: true}), 469 ) 470 Expect(err).To(MatchError("nats: Authorization Violation")) 471 Expect(logbuff).To(gbytes.Say("Rejecting unverified connection without token")) 472 Expect(logbuff).To(gbytes.Say("unverified connection without JWT token")) 473 Expect(logbuff).To(gbytes.Say("provisioning requires a token")) 474 Expect(logbuff).ToNot(gbytes.Say("Registering user")) 475 }) 476 477 It("Should verify the token", func() { 478 _, err := nats.Connect("nats://localhost:4222", 479 nats.Secure(&tls.Config{InsecureSkipVerify: true}), 480 nats.Token(string(invalidJwt)), 481 ) 482 Expect(err).To(MatchError("nats: Authorization Violation")) 483 484 Expect(logbuff).To(gbytes.Say("Performing JWT based authentication verification")) 485 Expect(logbuff).To(gbytes.Say("could not parse provisioner token: crypto/rsa: verification error")) 486 Expect(logbuff).ToNot(gbytes.Say("Registering user")) 487 }) 488 489 It("Should accept correctly configured servers", func() { 490 nc, err := nats.Connect("nats://localhost:4222", 491 nats.Secure(&tls.Config{InsecureSkipVerify: true}), 492 nats.Token(string(jwt)), 493 ) 494 Expect(err).ToNot(HaveOccurred()) 495 496 Expect(nc.ConnectedUrl()).To(Equal("nats://localhost:4222")) 497 Expect(logbuff).To(gbytes.Say("Performing JWT based authentication verification")) 498 Expect(logbuff).To(gbytes.Say("Allowing a provisioning server from using unverified TLS connection from")) 499 Expect(logbuff).To(gbytes.Say("Registering user '' in account 'provisioning'")) 500 Expect(logbuff).ToNot(gbytes.Say("in account 'choria'")) 501 }) 502 }) 503 504 Describe("Server Provisioner connections", func() { 505 It("Should deny the provisioner user over unverified tls", func() { 506 _, err := testbroker.StartNetworkBrokerWithConfigFile(ctx, &wg, "testdata/provisioning.conf", logger) 507 Expect(err).ToNot(HaveOccurred()) 508 Eventually(logbuff, 1).Should(gbytes.Say("Server is ready")) 509 510 _, err = nats.Connect("nats://localhost:4222", 511 nats.Secure(&tls.Config{InsecureSkipVerify: true}), 512 nats.UserInfo("provisioner", "s3cret"), 513 ) 514 515 Expect(err).To(MatchError("nats: Authorization Violation")) 516 Expect(logbuff).To(gbytes.Say("provisioning user is only allowed over verified TLS connections")) 517 Expect(logbuff).ToNot(gbytes.Say("Registering user")) 518 }) 519 520 It("Should only accept provisioning connections when configured", func() { 521 _, err := testbroker.StartNetworkBrokerWithConfigFile(ctx, &wg, "testdata/mtls.conf", logger) 522 Expect(err).ToNot(HaveOccurred()) 523 Eventually(logbuff, 1).Should(gbytes.Say("Server is ready")) 524 525 _, err = nats.Connect("tls://localhost:4222", 526 nats.UserInfo("provisioner", "s3cret"), 527 nats.ClientCert(testutil.CertPath("one", "rip.mcollective"), testutil.KeyPath("one", "rip.mcollective")), 528 nats.RootCAs(testutil.CertPath("one", "ca")), 529 ) 530 Expect(err).To(MatchError("nats: Authorization Violation")) 531 Eventually(logbuff, 1).Should(gbytes.Say("provisioning user password not enabled")) 532 Expect(logbuff).ToNot(gbytes.Say("Registering user")) 533 }) 534 535 It("Should require a password on the connection", func() { 536 _, err := testbroker.StartNetworkBrokerWithConfigFile(ctx, &wg, "testdata/provisioning.conf", logger) 537 Expect(err).ToNot(HaveOccurred()) 538 Eventually(logbuff, 1).Should(gbytes.Say("Server is ready")) 539 540 _, err = nats.Connect("tls://localhost:4222", 541 nats.UserInfo("provisioner", ""), 542 nats.ClientCert(testutil.CertPath("one", "rip.mcollective"), testutil.KeyPath("one", "rip.mcollective")), 543 nats.RootCAs(testutil.CertPath("one", "ca")), 544 ) 545 Expect(err).To(MatchError("nats: Authorization Violation")) 546 Expect(string(logbuff.Contents())).To(MatchRegexp("Handling provisioning user connection failed, denying.+: password required")) 547 }) 548 549 It("Should register the connection into the provisioning account", func() { 550 _, err := testbroker.StartNetworkBrokerWithConfigFile(ctx, &wg, "testdata/provisioning.conf", logger) 551 Expect(err).ToNot(HaveOccurred()) 552 Eventually(logbuff, 1).Should(gbytes.Say("Allowing unverified TLS connections for provisioning purposes")) 553 Eventually(logbuff, 1).Should(gbytes.Say("TLS required for client connections")) 554 Eventually(logbuff, 1).Should(gbytes.Say("Server is ready")) 555 556 nc, err := nats.Connect("tls://localhost:4222", 557 nats.UserInfo("provisioner", "s3cret"), 558 nats.ClientCert(testutil.CertPath("one", "rip.mcollective"), testutil.KeyPath("one", "rip.mcollective")), 559 nats.RootCAs(testutil.CertPath("one", "ca")), 560 ) 561 Expect(err).ToNot(HaveOccurred()) 562 Expect(nc.ConnectedUrl()).To(Equal("tls://localhost:4222")) 563 Expect(logbuff).To(gbytes.Say(`Registering user 'provisioner' in account 'provisioning'`)) 564 }) 565 }) 566 })