Skip to content

Commit 335fcc2

Browse files
committed
Add Go tests for AuthProvider with no CA cert configured (system trust store)
Implements the Ruby spec coverage missing from the Go test suite: Ruby: spec/nats_sync/auth_provider_spec.rb context 'user has not provided director_ca_cert' do it_behaves_like :auth_provider_shared_tests end The shared examples applied in that context were: - 'returns auth header provided by UAA' - 'reuses the same token for subsequent requests' - 'when token is about to expire / obtains new token' - 'when getting token fails / does not raise' The new Go context "when no CA cert is provided (system trust store)" adds: - CAFilePath() returns "" (equivalent to Ruby verifying ssl_cert_store with set_default_paths is used instead of ssl_ca_file) - All four token lifecycle cases above - An additional TLS test not present in Ruby: confirms InsecureSkipVerify is NOT set by asserting that a TLS UAA server with a self-signed cert fails to connect when no CA cert is configured
1 parent caa9752 commit 335fcc2

1 file changed

Lines changed: 107 additions & 0 deletions

File tree

src/bosh-nats-sync/pkg/authprovider/auth_provider_test.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,113 @@ var _ = Describe("AuthProvider", func() {
292292
Expect(provider.CAFilePath()).To(Equal(dirCertPath))
293293
})
294294
})
295+
296+
// Mirrors Ruby spec: 'user has not provided director_ca_cert'
297+
// When neither director_ca_cert nor uaa_ca_cert is set, CAFilePath() returns ""
298+
// and buildHTTPClient sets tls.Config{RootCAs: nil}, which makes Go use the
299+
// system trust store — the equivalent of Ruby's
300+
// OpenSSL::X509::Store.new.tap(&:set_default_paths).
301+
Context("when no CA cert is provided (system trust store)", func() {
302+
makeInfo := func() authprovider.InfoResponse {
303+
return authprovider.InfoResponse{
304+
UserAuthentication: &authprovider.UserAuthentication{
305+
Type: "uaa",
306+
Options: authprovider.UAAOptions{URL: uaaServer.URL},
307+
},
308+
}
309+
}
310+
makeCfg := func() config.DirectorConfig {
311+
return config.DirectorConfig{
312+
ClientID: "fake-client",
313+
ClientSecret: "fake-client-secret",
314+
// No DirectorCACert or UAACACert configured.
315+
}
316+
}
317+
318+
It("CAFilePath returns an empty string, indicating the system trust store will be used", func() {
319+
provider := authprovider.New(makeInfo(), makeCfg(), logger)
320+
Expect(provider.CAFilePath()).To(BeEmpty())
321+
})
322+
323+
It("returns auth header provided by UAA", func() {
324+
provider := authprovider.New(makeInfo(), makeCfg(), logger)
325+
326+
header, err := provider.AuthHeader()
327+
Expect(err).NotTo(HaveOccurred())
328+
Expect(header).To(Equal("Bearer token-1"))
329+
})
330+
331+
It("reuses the same token for subsequent requests", func() {
332+
provider := authprovider.New(makeInfo(), makeCfg(), logger)
333+
334+
header1, err := provider.AuthHeader()
335+
Expect(err).NotTo(HaveOccurred())
336+
header2, err := provider.AuthHeader()
337+
Expect(err).NotTo(HaveOccurred())
338+
Expect(header1).To(Equal(header2))
339+
Expect(tokenCounter).To(Equal(1))
340+
})
341+
342+
Context("when token is about to expire", func() {
343+
BeforeEach(func() {
344+
expiresIn = 30
345+
})
346+
347+
It("obtains a new token", func() {
348+
provider := authprovider.New(makeInfo(), makeCfg(), logger)
349+
350+
header1, err := provider.AuthHeader()
351+
Expect(err).NotTo(HaveOccurred())
352+
Expect(header1).To(Equal("Bearer token-1"))
353+
354+
header2, err := provider.AuthHeader()
355+
Expect(err).NotTo(HaveOccurred())
356+
Expect(header2).To(Equal("Bearer token-2"))
357+
})
358+
})
359+
360+
Context("when getting token fails", func() {
361+
It("returns an error", func() {
362+
info := authprovider.InfoResponse{
363+
UserAuthentication: &authprovider.UserAuthentication{
364+
Type: "uaa",
365+
Options: authprovider.UAAOptions{URL: "http://127.0.0.1:1"},
366+
},
367+
}
368+
provider := authprovider.New(info, makeCfg(), logger)
369+
370+
header, err := provider.AuthHeader()
371+
Expect(err).To(HaveOccurred())
372+
Expect(err.Error()).To(ContainSubstring("failed to obtain token from UAA"))
373+
Expect(header).To(BeEmpty())
374+
})
375+
})
376+
377+
// Stronger than the Ruby test: verifies that the HTTP client built for
378+
// UAA token requests does NOT use InsecureSkipVerify. When no CA cert is
379+
// configured the client uses tls.Config{RootCAs: nil} (system trust store),
380+
// so a self-signed test-server cert that isn't in the system store must
381+
// cause a TLS error — not silently succeed.
382+
It("does not skip TLS verification when connecting to a TLS UAA server", func() {
383+
tlsUAAServer := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
384+
w.Header().Set("Content-Type", "application/json")
385+
fmt.Fprint(w, `{"access_token":"tls-token","token_type":"bearer","expires_in":3600}`)
386+
}))
387+
defer tlsUAAServer.Close()
388+
389+
info := authprovider.InfoResponse{
390+
UserAuthentication: &authprovider.UserAuthentication{
391+
Type: "uaa",
392+
Options: authprovider.UAAOptions{URL: tlsUAAServer.URL},
393+
},
394+
}
395+
provider := authprovider.New(info, makeCfg(), logger)
396+
397+
_, err := provider.AuthHeader()
398+
Expect(err).To(HaveOccurred())
399+
Expect(err.Error()).To(ContainSubstring("failed to obtain token from UAA"))
400+
})
401+
})
295402
})
296403

297404
Context("when director is in non-UAA mode", func() {

0 commit comments

Comments
 (0)