github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/providers/security/filesec/file_security_test.go (about) 1 // Copyright (c) 2020-2022, R.I. Pienaar and the Choria Project contributors 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 package filesec 6 7 import ( 8 "crypto/tls" 9 "encoding/base64" 10 "encoding/pem" 11 "fmt" 12 "io" 13 "os" 14 "path/filepath" 15 "testing" 16 17 "github.com/choria-io/go-choria/build" 18 "github.com/choria-io/go-choria/inter" 19 "github.com/choria-io/go-choria/tlssetup" 20 21 "github.com/choria-io/go-choria/config" 22 . "github.com/onsi/ginkgo/v2" 23 . "github.com/onsi/gomega" 24 "github.com/sirupsen/logrus" 25 ) 26 27 func TestFileSecurity(t *testing.T) { 28 RegisterFailHandler(Fail) 29 RunSpecs(t, "Providers/Security/File") 30 } 31 32 func setTLS(c *Config, parent string, id string, privateExtension string) { 33 if privateExtension == "" { 34 privateExtension = "pem" 35 } 36 c.Certificate = filepath.Join(parent, "certs", fmt.Sprintf("%s.pem", id)) 37 c.CA = filepath.Join(parent, "certs", "ca.pem") 38 c.Key = filepath.Join(parent, "private_keys", fmt.Sprintf("%s.%s", id, privateExtension)) 39 c.AllowList = []string{"\\.mcollective$"} 40 c.PrivilegedUsers = []string{"\\.privileged.mcollective$"} 41 c.DisableTLSVerify = false 42 c.Identity = id 43 44 useFakeUID = true 45 fakeUID = 500 46 } 47 48 var _ = Describe("FileSecurity", func() { 49 var cfg *Config 50 var err error 51 var prov *FileSecurity 52 var l *logrus.Logger 53 54 var goodStub string 55 var nonexistingStub string 56 57 BeforeEach(func() { 58 os.Setenv("MCOLLECTIVE_CERTNAME", "rip.mcollective") 59 60 goodStub = filepath.Join("..", "testdata", "good") 61 nonexistingStub = filepath.Join("..", "testdata", "nonexisting") 62 63 cfg = &Config{} 64 setTLS(cfg, goodStub, "rip.mcollective", "") 65 66 l = logrus.New() 67 68 l.Out = io.Discard 69 70 prov, err = New(WithConfig(cfg), WithLog(l.WithFields(logrus.Fields{}))) 71 Expect(err).ToNot(HaveOccurred()) 72 }) 73 74 It("Should implement the provider interface", func() { 75 f := func(p inter.SecurityProvider) {} 76 f(prov) 77 Expect(prov.Provider()).To(Equal("file")) 78 }) 79 80 Describe("WithChoriaConfig", func() { 81 BeforeEach(func() { 82 os.Unsetenv("MCOLLECTIVE_CERTNAME") 83 }) 84 85 It("Should support OverrideCertname", func() { 86 c, err := config.NewDefaultConfig() 87 Expect(err).ToNot(HaveOccurred()) 88 c.OverrideCertname = "override.choria" 89 prov, err := New(WithChoriaConfig(&build.Info{}, c), WithLog(l.WithFields(logrus.Fields{}))) 90 Expect(err).ToNot(HaveOccurred()) 91 92 Expect(prov.conf.Identity).To(Equal("override.choria")) 93 }) 94 95 It("Should support MCOLLECTIVE_CERTNAME", func() { 96 os.Setenv("MCOLLECTIVE_CERTNAME", "bob.mcollective") 97 c, err := config.NewDefaultConfig() 98 Expect(err).ToNot(HaveOccurred()) 99 prov, err := New(WithChoriaConfig(&build.Info{}, c), WithLog(l.WithFields(logrus.Fields{}))) 100 Expect(err).ToNot(HaveOccurred()) 101 102 Expect(prov.conf.Identity).To(Equal("bob.mcollective")) 103 }) 104 105 It("Should copy all the relevant settings", func() { 106 c, err := config.NewDefaultConfig() 107 Expect(err).ToNot(HaveOccurred()) 108 109 fakeUID = 0 110 c.Choria.FileSecurityCA = "stub/ca.pem" 111 c.Choria.FileSecurityCertificate = "stub/cert.pem" 112 c.Choria.FileSecurityKey = "stub/key.pem" 113 c.DisableTLSVerify = true 114 c.Identity = "test.identity" 115 116 prov, err := New(WithChoriaConfig(&build.Info{}, c), WithLog(l.WithFields(logrus.Fields{}))) 117 Expect(err).ToNot(HaveOccurred()) 118 119 Expect(prov.conf.AllowList).To(Equal([]string{"\\.mcollective$", "\\.choria$"})) 120 Expect(prov.conf.PrivilegedUsers).To(Equal([]string{"\\.privileged.mcollective$", "\\.privileged.choria$"})) 121 Expect(prov.conf.CA).To(Equal("stub/ca.pem")) 122 Expect(prov.conf.Certificate).To(Equal("stub/cert.pem")) 123 Expect(prov.conf.Key).To(Equal("stub/key.pem")) 124 Expect(prov.conf.DisableTLSVerify).To(BeTrue()) 125 Expect(prov.conf.Identity).To(Equal("test.identity")) 126 }) 127 128 It("Should support override certname", func() { 129 c, err := config.NewDefaultConfig() 130 Expect(err).ToNot(HaveOccurred()) 131 132 c.Choria.FileSecurityCA = "stub/ca.pem" 133 c.Choria.FileSecurityCertificate = "stub/cert.pem" 134 c.Choria.FileSecurityKey = "stub/key.pem" 135 c.DisableTLSVerify = true 136 c.Identity = "test.identity" 137 c.OverrideCertname = "bob.identity" 138 139 prov, err := New(WithChoriaConfig(&build.Info{}, c), WithLog(l.WithFields(logrus.Fields{}))) 140 Expect(err).ToNot(HaveOccurred()) 141 142 Expect(prov.conf.Identity).To(Equal("bob.identity")) 143 }) 144 145 It("Should support root and windows", func() { 146 c, err := config.NewDefaultConfig() 147 Expect(err).ToNot(HaveOccurred()) 148 149 c.Choria.FileSecurityCA = "stub/ca.pem" 150 c.Choria.FileSecurityCertificate = "stub/cert.pem" 151 c.Choria.FileSecurityKey = "stub/key.pem" 152 c.DisableTLSVerify = true 153 c.Identity = "test.identity" 154 155 useFakeOS = true 156 defer func() { useFakeOS = false }() 157 fakeOS = "windows" 158 Expect(runtimeOs()).To(Equal("windows")) 159 160 prov, err = New(WithChoriaConfig(&build.Info{}, c), WithLog(l.WithFields(logrus.Fields{}))) 161 Expect(err).ToNot(HaveOccurred()) 162 163 Expect(prov.conf.Identity).To(Equal("test.identity")) 164 }) 165 }) 166 167 Describe("Validate", func() { 168 It("Should handle missing files", func() { 169 setTLS(cfg, nonexistingStub, "test.mcollective", "") 170 prov, err = New(WithConfig(cfg), WithLog(l.WithFields(logrus.Fields{}))) 171 Expect(err).ToNot(HaveOccurred()) 172 173 errs, ok := prov.Validate() 174 175 Expect(ok).To(BeFalse()) 176 Expect(errs).To(HaveLen(3)) 177 Expect(errs[0]).To(Equal(fmt.Sprintf("public certificate %s does not exist", cfg.Certificate))) 178 Expect(errs[1]).To(Equal(fmt.Sprintf("private key %s does not exist", cfg.Key))) 179 Expect(errs[2]).To(Equal(fmt.Sprintf("CA %s does not exist", cfg.CA))) 180 }) 181 182 It("Should accept valid directories", func() { 183 setTLS(cfg, goodStub, "rip.mcollective", "") 184 185 errs, ok := prov.Validate() 186 Expect(errs).To(BeEmpty()) 187 Expect(ok).To(BeTrue()) 188 }) 189 }) 190 191 Describe("Identity", func() { 192 It("Should return the identity", func() { 193 cfg.Identity = "bob.choria" 194 Expect(prov.Identity()).To(Equal("bob.choria")) 195 }) 196 }) 197 198 Describe("CallerName", func() { 199 It("Should return the right caller name", func() { 200 cfg.Identity = "test.choria" 201 Expect(prov.CallerName()).To(Equal("choria=test.choria")) 202 }) 203 }) 204 205 Describe("CallerIdentity", func() { 206 It("Should return the right caller ident", func() { 207 Expect(prov.CallerIdentity("choria=test.choria")).To(Equal("test.choria")) 208 Expect(prov.CallerIdentity("foo=test1.choria")).To(Equal("test1.choria")) 209 }) 210 211 It("Should handle invalid caller ident", func() { 212 _, err := prov.CallerIdentity("test.choria") 213 Expect(err).To(MatchError("could not find a valid caller identity name in test.choria")) 214 215 _, err = prov.CallerIdentity("fooBar=test.choria") 216 Expect(err).To(MatchError("could not find a valid caller identity name in fooBar=test.choria")) 217 }) 218 }) 219 220 Describe("SignBytes", func() { 221 It("Should produce the right signature", func() { 222 sig, err := prov.SignBytes([]byte("too many secrets")) 223 Expect(err).ToNot(HaveOccurred()) 224 Expect(base64.StdEncoding.EncodeToString(sig)).To(Equal("kh5PlHXcht+FeyPdlNdpYjsW4AtOp9lRo6z3NWMcjxZq15mknzXOjkbYT1J4pp627tnlzbSC0dohP7YffGfNv5zJotx8QaIrVm2akSpWjf+M2xBf5V72f3Prn/f4dzZTP6EClM8L6SWxjQHiDamMGyT+6ZCja7Ld9TmgZV5Mx9t66pDu0OgZdi6k45/SRpLdNISnhGWpRQ5KIXgaf9gNqABNPtTstPS9i9PYNYQP6sucZPAzRa9zeyZXlKkxuBLqk4cdMUD9LgtGTy7BaAV/ZG1fzGyybw1swDAMp6x06428R+TCOaystOEbaSTqR1D1/qTDu0xUpA/izN0ZSW1g5f8K2xxv5NHoFbUyWCPGRozbrBc83uJMxhOgkeS6A2ABw1uP2vzm1zdsrj+jTj8BMHHKFn+KEkitXeImEWvWg8JvMeD8arqt0GsDBqgqGjXrlHog4y0cZvv+Yuhya2CJl77BNl08urIl0qonbCiNElB8mMvWcMoyTWo7ksWD27Ao/+oOjN+/Kek132g1PV3AK8gAnJ2RPZy/bT5qZMre0vg4PdVgL6UI3afqLOQs8AvL3KG+RFg1Lw3lG/Obmitoa2+0VJrwEN+WO6D/huGn6B7v3yzuu5UrUwkZhd2/yUbnET7OdpfalqcbTbdq/teeo7TUFNp/OrNLhVb8o63mpQQ=")) 225 }) 226 227 It("Should work with PKCS8 files", func() { 228 setTLS(cfg, goodStub, "rip.mcollective", "p8") 229 sig, err := prov.SignBytes([]byte("too many secrets")) 230 Expect(err).ToNot(HaveOccurred()) 231 Expect(base64.StdEncoding.EncodeToString(sig)).To(Equal("kh5PlHXcht+FeyPdlNdpYjsW4AtOp9lRo6z3NWMcjxZq15mknzXOjkbYT1J4pp627tnlzbSC0dohP7YffGfNv5zJotx8QaIrVm2akSpWjf+M2xBf5V72f3Prn/f4dzZTP6EClM8L6SWxjQHiDamMGyT+6ZCja7Ld9TmgZV5Mx9t66pDu0OgZdi6k45/SRpLdNISnhGWpRQ5KIXgaf9gNqABNPtTstPS9i9PYNYQP6sucZPAzRa9zeyZXlKkxuBLqk4cdMUD9LgtGTy7BaAV/ZG1fzGyybw1swDAMp6x06428R+TCOaystOEbaSTqR1D1/qTDu0xUpA/izN0ZSW1g5f8K2xxv5NHoFbUyWCPGRozbrBc83uJMxhOgkeS6A2ABw1uP2vzm1zdsrj+jTj8BMHHKFn+KEkitXeImEWvWg8JvMeD8arqt0GsDBqgqGjXrlHog4y0cZvv+Yuhya2CJl77BNl08urIl0qonbCiNElB8mMvWcMoyTWo7ksWD27Ao/+oOjN+/Kek132g1PV3AK8gAnJ2RPZy/bT5qZMre0vg4PdVgL6UI3afqLOQs8AvL3KG+RFg1Lw3lG/Obmitoa2+0VJrwEN+WO6D/huGn6B7v3yzuu5UrUwkZhd2/yUbnET7OdpfalqcbTbdq/teeo7TUFNp/OrNLhVb8o63mpQQ=")) 232 }) 233 }) 234 235 Describe("VerifySignatureBytes", func() { 236 It("Should validate correctly", func() { 237 sig, err := base64.StdEncoding.DecodeString("kh5PlHXcht+FeyPdlNdpYjsW4AtOp9lRo6z3NWMcjxZq15mknzXOjkbYT1J4pp627tnlzbSC0dohP7YffGfNv5zJotx8QaIrVm2akSpWjf+M2xBf5V72f3Prn/f4dzZTP6EClM8L6SWxjQHiDamMGyT+6ZCja7Ld9TmgZV5Mx9t66pDu0OgZdi6k45/SRpLdNISnhGWpRQ5KIXgaf9gNqABNPtTstPS9i9PYNYQP6sucZPAzRa9zeyZXlKkxuBLqk4cdMUD9LgtGTy7BaAV/ZG1fzGyybw1swDAMp6x06428R+TCOaystOEbaSTqR1D1/qTDu0xUpA/izN0ZSW1g5f8K2xxv5NHoFbUyWCPGRozbrBc83uJMxhOgkeS6A2ABw1uP2vzm1zdsrj+jTj8BMHHKFn+KEkitXeImEWvWg8JvMeD8arqt0GsDBqgqGjXrlHog4y0cZvv+Yuhya2CJl77BNl08urIl0qonbCiNElB8mMvWcMoyTWo7ksWD27Ao/+oOjN+/Kek132g1PV3AK8gAnJ2RPZy/bT5qZMre0vg4PdVgL6UI3afqLOQs8AvL3KG+RFg1Lw3lG/Obmitoa2+0VJrwEN+WO6D/huGn6B7v3yzuu5UrUwkZhd2/yUbnET7OdpfalqcbTbdq/teeo7TUFNp/OrNLhVb8o63mpQQ=") 238 Expect(err).ToNot(HaveOccurred()) 239 240 valid, _ := prov.VerifySignatureBytes([]byte("too many secrets"), sig, nil) 241 Expect(valid).To(BeTrue()) 242 }) 243 244 It("Should fail for invalid sigs", func() { 245 valid, _ := prov.VerifySignatureBytes([]byte("too many secrets"), []byte("meh"), nil) 246 Expect(valid).To(BeFalse()) 247 }) 248 249 It("Should support cached certificates", func() { 250 cfg.Identity = "2.mcollective" 251 sig, err := base64.StdEncoding.DecodeString("a2FyZoRm4wIojH+s6qSo1ghOkeKOhayiMV44I03bRtlbYnBAZJQMzZ3GvA93w5ZDaEWndZIxxLOtzfVfLjJbF+uII2KJandWBd7nR7yByxOlpOdw0sIiBKWtiiugOnXQpbPNRyQxxyLFbmYo4bO/auraqZ8+AYl0nll8I5A0mZ2y6HIo8MdXu1+l1UTX8/Ji6G7f404Mw9CsXjo4EAfjtu/9i+cYMhqlv9lxobsuFzfA+lx/X1dtYmbW/pZ/ClnuydUdA5UV07Mf2iXjZ5c8xutLxnP+xhbQf7ql+yt9DaSX+RMwB+5ntGatRgYS/h8ihQZ970tCrCY456Uosa+xEmvfnZqoL++ja0pIgMJ4h7spQdCrjN2aXnL5IdiFROki1CPhJMaqipCb9kM8+ZtFehFh5Jx6WzekLCqkgKgZshYmJNQ4esAxWGNGxxSkiyYp5jea9qE5fLeidZrLfixNGfyXYfs75fUK9KZo3FkoPq4xFovWNr9KOXGKCT68dfg8S2SmV10CGGQ2wU1atYcpMz9Bua+3oDGpIt7OiDwOFBFHn8d8Nnm5qC2MQdn5Ys9PGCpAMh8b+P886mJlexVl18qXbcnPmM+acYFHMtZgH609w50l1zkd9MpdBqWcfH3r52VvAFh5SKAaWuVedBWea04tlx6E+UMjJvrK03aUJ9w=") 252 Expect(err).ToNot(HaveOccurred()) 253 254 cert, err := os.ReadFile("../testdata/good/certs/2.mcollective.pem") 255 Expect(err).ToNot(HaveOccurred()) 256 257 valid, _ := prov.VerifySignatureBytes([]byte("too many secrets"), sig, cert) 258 Expect(valid).To(BeTrue()) 259 }) 260 }) 261 262 Describe("ChecksumBytes", func() { 263 It("Should produce the right checksum", func() { 264 sum, err := base64.StdEncoding.DecodeString("Yk+jdKdZ3v8E2p6dmbfn+ZN9lBBAHEIcOMp4lzuYKTo=") 265 Expect(err).ToNot(HaveOccurred()) 266 267 Expect(prov.ChecksumBytes([]byte("too many secrets"))).To(Equal(sum)) 268 }) 269 }) 270 271 Describe("TLSConfig", func() { 272 It("Should produce a valid TLS Config", func() { 273 c, err := prov.TLSConfig() 274 Expect(err).ToNot(HaveOccurred()) 275 276 Expect(c.InsecureSkipVerify).To(BeFalse()) 277 Expect(err).ToNot(HaveOccurred()) 278 279 pub := prov.publicCertPath() 280 pri := prov.privateKeyPath() 281 282 cert, err := tls.LoadX509KeyPair(pub, pri) 283 Expect(err).ToNot(HaveOccurred()) 284 285 Expect(c.Certificates).To(HaveLen(1)) 286 Expect(c.Certificates[0].Certificate).To(Equal(cert.Certificate)) 287 }) 288 289 It("Should support disabling tls verify", func() { 290 cfg.DisableTLSVerify = true 291 292 c, err := prov.TLSConfig() 293 Expect(err).ToNot(HaveOccurred()) 294 295 Expect(c.InsecureSkipVerify).To(BeTrue()) 296 297 }) 298 }) 299 300 Describe("VerifyCertificate", func() { 301 var pem []byte 302 303 BeforeEach(func() { 304 pub := prov.publicCertPath() 305 pem, err = os.ReadFile(pub) 306 Expect(err).ToNot(HaveOccurred()) 307 }) 308 309 It("Should fail for foreign certs", func() { 310 pem, err = os.ReadFile(filepath.Join("..", "testdata", "foreign.pem")) 311 Expect(err).ToNot(HaveOccurred()) 312 err := prov.VerifyCertificate(pem, "rip.mcollective") 313 Expect(err).To(MatchError("x509: certificate signed by unknown authority")) 314 315 }) 316 317 It("Should fail for invalid names", func() { 318 err := prov.VerifyCertificate(pem, "bob") 319 Expect(err).To(MatchError("x509: certificate is valid for rip.mcollective, not bob")) 320 }) 321 322 It("Should accept valid certs", func() { 323 err := prov.VerifyCertificate(pem, "rip.mcollective") 324 Expect(err).ToNot(HaveOccurred()) 325 }) 326 327 It("Should work with client provided intermediate chains", func() { 328 c, err := config.NewDefaultConfig() 329 Expect(err).ToNot(HaveOccurred()) 330 331 c.Choria.FileSecurityCA = filepath.Join("..", "testdata", "intermediate", "certs", "ca.pem") 332 333 prov, err := New(WithChoriaConfig(&build.Info{}, c), WithLog(l.WithFields(logrus.Fields{}))) 334 Expect(err).ToNot(HaveOccurred()) 335 336 pem, err = os.ReadFile(filepath.Join("..", "testdata", "intermediate", "certs", "rip.mcollective.pem")) 337 Expect(err).ToNot(HaveOccurred()) 338 339 err = prov.VerifyCertificate(pem, "rip.mcollective") 340 Expect(err).ToNot(HaveOccurred()) 341 }) 342 343 It("Should work with server side ca intermediate chains", func() { 344 c, err := config.NewDefaultConfig() 345 Expect(err).ToNot(HaveOccurred()) 346 347 c.Choria.FileSecurityCA = filepath.Join("..", "testdata", "intermediate", "certs", "ca_chain_ca.pem") 348 349 prov, err := New(WithChoriaConfig(&build.Info{}, c), WithLog(l.WithFields(logrus.Fields{}))) 350 Expect(err).ToNot(HaveOccurred()) 351 352 pem, err = os.ReadFile(filepath.Join("..", "testdata", "intermediate", "certs", "ca_chain_rip.mcollective.pem")) 353 Expect(err).ToNot(HaveOccurred()) 354 355 err = prov.VerifyCertificate(pem, "rip.mcollective") 356 Expect(err).ToNot(HaveOccurred()) 357 }) 358 359 It("Should work with email addresses", func() { 360 c, err := config.NewDefaultConfig() 361 Expect(err).ToNot(HaveOccurred()) 362 363 c.Choria.FileSecurityCA = filepath.Join("..", "testdata", "intermediate", "certs", "ca_chain_ca.pem") 364 365 prov, err := New(WithChoriaConfig(&build.Info{}, c), WithLog(l.WithFields(logrus.Fields{}))) 366 Expect(err).ToNot(HaveOccurred()) 367 368 pem, err = os.ReadFile(filepath.Join("..", "testdata", "intermediate", "certs", "email-chain-rip.mcollective.pem")) 369 Expect(err).ToNot(HaveOccurred()) 370 371 err = prov.VerifyCertificate(pem, "email:test@choria-io.com") 372 Expect(err).ToNot(HaveOccurred()) 373 }) 374 375 It("Should not work with wrong addresses", func() { 376 c, err := config.NewDefaultConfig() 377 Expect(err).ToNot(HaveOccurred()) 378 379 c.Choria.FileSecurityCA = filepath.Join("..", "testdata", "intermediate", "certs", "ca_chain_ca.pem") 380 381 prov, err := New(WithChoriaConfig(&build.Info{}, c), WithLog(l.WithFields(logrus.Fields{}))) 382 Expect(err).ToNot(HaveOccurred()) 383 384 pem, err = os.ReadFile(filepath.Join("..", "testdata", "intermediate", "certs", "email-chain-rip.mcollective.pem")) 385 Expect(err).ToNot(HaveOccurred()) 386 387 err = prov.VerifyCertificate(pem, "email:bad@choria-io.com") 388 Expect(err).To(HaveOccurred()) 389 }) 390 }) 391 392 Describe("publicCertPem", func() { 393 It("Should return the correct pem data", func() { 394 dat, err := os.ReadFile(cfg.Certificate) 395 Expect(err).ToNot(HaveOccurred()) 396 pb, _ := pem.Decode(dat) 397 Expect(err).ToNot(HaveOccurred()) 398 399 block, err := prov.publicCertPem() 400 Expect(err).ToNot(HaveOccurred()) 401 Expect(block.Bytes).To(Equal(pb.Bytes)) 402 }) 403 }) 404 405 Describe("ShouldAllowCaller", func() { 406 It("Should only accept valid certs signed by our ca", func() { 407 pd, err := os.ReadFile(filepath.Join("..", "testdata", "foreign.pem")) 408 Expect(err).ToNot(HaveOccurred()) 409 410 priv, err := prov.ShouldAllowCaller("foo", pd) 411 Expect(err).To(HaveOccurred()) 412 Expect(priv).To(BeFalse()) 413 414 pub := prov.publicCertPath() 415 pd, err = os.ReadFile(pub) 416 Expect(err).ToNot(HaveOccurred()) 417 418 priv, err = prov.ShouldAllowCaller("rip.mcollective", pd) 419 Expect(err).ToNot(HaveOccurred()) 420 Expect(priv).To(BeFalse()) 421 }) 422 423 It("Should accept privileged certs", func() { 424 pd, err := os.ReadFile(filepath.Join("..", "testdata", "good", "certs", "1.privileged.mcollective.pem")) 425 Expect(err).ToNot(HaveOccurred()) 426 427 priv, err := prov.ShouldAllowCaller("bob", pd) 428 Expect(err).ToNot(HaveOccurred()) 429 Expect(priv).To(BeTrue()) 430 }) 431 432 It("Should not accept certs with wrong names", func() { 433 pub := prov.publicCertPath() 434 435 pd, err := os.ReadFile(pub) 436 Expect(err).ToNot(HaveOccurred()) 437 438 priv, err := prov.ShouldAllowCaller("bob", pd) 439 Expect(err).To(HaveOccurred()) 440 Expect(priv).To(BeFalse()) 441 }) 442 443 It("Should only accept certs that's on the allowed list", func() { 444 cfg.AllowList = []string{"bob"} 445 pub := prov.publicCertPath() 446 447 pd, err := os.ReadFile(pub) 448 Expect(err).ToNot(HaveOccurred()) 449 450 priv, err := prov.ShouldAllowCaller("rip.mcollective", pd) 451 Expect(priv).To(BeFalse()) 452 Expect(err).To(MatchError("not on allow list")) 453 }) 454 455 It("Should accept valid certs", func() { 456 pub := prov.publicCertPath() 457 458 pd, err := os.ReadFile(pub) 459 Expect(err).ToNot(HaveOccurred()) 460 461 priv, err := prov.ShouldAllowCaller("rip.mcollective", pd) 462 Expect(err).ToNot(HaveOccurred()) 463 Expect(priv).To(BeFalse()) 464 }) 465 }) 466 467 Describe("privateKeyExists", func() { 468 It("Should detect existing keys", func() { 469 setTLS(cfg, goodStub, "rip.mcollective", "") 470 471 Expect(prov.privateKeyExists()).To(BeTrue()) 472 }) 473 474 It("Should detect absent keys", func() { 475 setTLS(cfg, goodStub, "na.mcollective", "") 476 477 Expect(prov.privateKeyExists()).To(BeFalse()) 478 }) 479 }) 480 481 Describe("Configurable CipherSuites", func() { 482 var cipher string 483 var curve string 484 var c *config.Config 485 486 BeforeEach(func() { 487 _c, err := config.NewDefaultConfig() 488 Expect(err).ToNot(HaveOccurred()) 489 490 c = _c 491 }) 492 493 It("Should work with just one cipher", func() { 494 for _, cm := range tls.CipherSuites() { 495 cipher = cm.Name 496 break 497 } 498 499 c.Choria.CipherSuites = []string{cipher} 500 501 prov, err := New(WithChoriaConfig(&build.Info{}, c), WithLog(l.WithFields(logrus.Fields{}))) 502 Expect(err).ToNot(HaveOccurred()) 503 504 Expect(prov.conf.TLSConfig.CipherSuites).ToNot(BeNil()) 505 Expect(prov.conf.TLSConfig.CipherSuites).To(HaveLen(1)) 506 }) 507 508 It("Should work with one curve", func() { 509 for cp := range tlssetup.CurvePreferenceMap { 510 curve = cp 511 break 512 } 513 514 c.Choria.ECCCurves = []string{curve} 515 516 prov, err := New(WithChoriaConfig(&build.Info{}, c), WithLog(l.WithFields(logrus.Fields{}))) 517 Expect(err).ToNot(HaveOccurred()) 518 519 Expect(prov.conf.TLSConfig.CurvePreferences).ToNot(BeNil()) 520 Expect(prov.conf.TLSConfig.CurvePreferences).To(HaveLen(1)) 521 522 }) 523 524 It("Should have a default list cipher and curve list when not overridden", func() { 525 prov, err := New(WithChoriaConfig(&build.Info{}, c), WithLog(l.WithFields(logrus.Fields{}))) 526 Expect(err).ToNot(HaveOccurred()) 527 528 Expect(prov.conf.TLSConfig.CipherSuites).To(Equal(tlssetup.DefaultCipherSuites())) 529 530 Expect(prov.conf.TLSConfig.CurvePreferences).To(Equal(tlssetup.DefaultCurvePreferences())) 531 }) 532 }) 533 })