@@ -12,21 +12,26 @@ import (
1212 "github.com/sysdiglabs/sysdig-mcp-server/internal/infra/sysdig"
1313)
1414
15+ func permissionsHandler (captureHeaders func (http.Header )) http.Handler {
16+ return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
17+ if captureHeaders != nil {
18+ captureHeaders (r .Header )
19+ }
20+ if r .URL .Path == "/api/users/me/permissions" {
21+ w .Header ().Set ("Content-Type" , "application/json" )
22+ w .WriteHeader (http .StatusOK )
23+ _ , _ = w .Write ([]byte (`{"permissions":[]}` ))
24+ return
25+ }
26+ w .WriteHeader (http .StatusNotFound )
27+ })
28+ }
29+
1530var _ = Describe ("Client TLS" , func () {
1631 var ts * httptest.Server
1732
1833 BeforeEach (func () {
19- // Start a TLS server with a self-signed certificate
20- ts = httptest .NewTLSServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
21- if r .URL .Path == "/api/users/me/permissions" {
22- w .Header ().Set ("Content-Type" , "application/json" )
23- w .WriteHeader (http .StatusOK )
24- _ , _ = w .Write ([]byte (`{"permissions":[]}` ))
25- return
26- }
27- w .WriteHeader (http .StatusNotFound )
28- }))
29- // Redirect server logs to GinkgoWriter to avoid noise in test output
34+ ts = httptest .NewTLSServer (permissionsHandler (nil ))
3035 ts .Config .ErrorLog = log .New (GinkgoWriter , "" , 0 )
3136 })
3237
@@ -35,35 +40,153 @@ var _ = Describe("Client TLS", func() {
3540 })
3641
3742 It ("should fail request with self-signed cert by default" , func () {
38- // Create client pointing to the TLS server without custom transport
3943 client , err := sysdig .NewSysdigClient (
4044 sysdig .WithFixedHostAndToken (ts .URL , "dummy-token" ),
4145 )
4246 Expect (err ).NotTo (HaveOccurred ())
4347
44- // Attempt request
4548 _ , err = client .GetMyPermissionsWithResponse (context .Background ())
4649 Expect (err ).To (HaveOccurred ())
47- // Verification that it failed due to certificate issues
4850 Expect (err .Error ()).To (Or (ContainSubstring ("certificate" ), ContainSubstring ("unknown authority" )))
4951 })
5052
5153 It ("should succeed request when using custom HTTP client with InsecureSkipVerify" , func () {
52- // Create custom HTTP client that skips verification
5354 transport := http .DefaultTransport .(* http.Transport ).Clone ()
5455 transport .TLSClientConfig = & tls.Config {InsecureSkipVerify : true }
5556 httpClient := & http.Client {Transport : transport }
5657
57- // Create client using the custom HTTP client
5858 client , err := sysdig .NewSysdigClient (
5959 sysdig .WithFixedHostAndToken (ts .URL , "dummy-token" ),
6060 sysdig .WithHTTPClient (httpClient ),
6161 )
6262 Expect (err ).NotTo (HaveOccurred ())
6363
64- // Attempt request
6564 resp , err := client .GetMyPermissionsWithResponse (context .Background ())
6665 Expect (err ).NotTo (HaveOccurred ())
6766 Expect (resp .HTTPResponse .StatusCode ).To (Equal (http .StatusOK ))
6867 })
6968})
69+
70+ var _ = Describe ("Context helpers" , func () {
71+ It ("roundtrips token through context" , func () {
72+ ctx := sysdig .WrapContextWithToken (context .Background (), "my-token" )
73+ Expect (sysdig .GetTokenFromContext (ctx )).To (Equal ("my-token" ))
74+ })
75+
76+ It ("roundtrips host through context" , func () {
77+ ctx := sysdig .WrapContextWithHost (context .Background (), "https://example.com" )
78+ Expect (sysdig .GetHostFromContext (ctx )).To (Equal ("https://example.com" ))
79+ })
80+
81+ It ("panics when token is missing from context" , func () {
82+ Expect (func () {
83+ sysdig .GetTokenFromContext (context .Background ())
84+ }).To (Panic ())
85+ })
86+
87+ It ("panics when host is missing from context" , func () {
88+ Expect (func () {
89+ sysdig .GetHostFromContext (context .Background ())
90+ }).To (Panic ())
91+ })
92+ })
93+
94+ var _ = Describe ("Client authentication" , func () {
95+ var ts * httptest.Server
96+ var lastHeaders http.Header
97+
98+ BeforeEach (func () {
99+ ts = httptest .NewServer (permissionsHandler (func (h http.Header ) {
100+ lastHeaders = h .Clone ()
101+ }))
102+ })
103+
104+ AfterEach (func () {
105+ ts .Close ()
106+ })
107+
108+ Describe ("WithHostAndTokenFromContext" , func () {
109+ It ("authenticates using context values" , func () {
110+ client , err := sysdig .NewSysdigClient (sysdig .WithHostAndTokenFromContext ())
111+ Expect (err ).NotTo (HaveOccurred ())
112+
113+ ctx := sysdig .WrapContextWithHost (context .Background (), ts .URL )
114+ ctx = sysdig .WrapContextWithToken (ctx , "ctx-token" )
115+
116+ resp , err := client .GetMyPermissionsWithResponse (ctx )
117+ Expect (err ).NotTo (HaveOccurred ())
118+ Expect (resp .HTTPResponse .StatusCode ).To (Equal (http .StatusOK ))
119+ Expect (lastHeaders .Get ("Authorization" )).To (Equal ("Bearer ctx-token" ))
120+ })
121+
122+ It ("fails when token is missing from context" , func () {
123+ client , err := sysdig .NewSysdigClient (sysdig .WithHostAndTokenFromContext ())
124+ Expect (err ).NotTo (HaveOccurred ())
125+
126+ ctx := sysdig .WrapContextWithHost (context .Background (), ts .URL )
127+
128+ _ , err = client .GetMyPermissionsWithResponse (ctx )
129+ Expect (err ).To (MatchError (ContainSubstring ("authorization token not present" )))
130+ })
131+ })
132+
133+ Describe ("WithFallbackAuthentication" , func () {
134+ It ("uses first auth when it succeeds" , func () {
135+ client , err := sysdig .NewSysdigClient (
136+ sysdig .WithFallbackAuthentication (
137+ sysdig .WithFixedHostAndToken (ts .URL , "primary-token" ),
138+ sysdig .WithFixedHostAndToken (ts .URL , "fallback-token" ),
139+ ),
140+ )
141+ Expect (err ).NotTo (HaveOccurred ())
142+
143+ resp , err := client .GetMyPermissionsWithResponse (context .Background ())
144+ Expect (err ).NotTo (HaveOccurred ())
145+ Expect (resp .HTTPResponse .StatusCode ).To (Equal (http .StatusOK ))
146+ Expect (lastHeaders .Get ("Authorization" )).To (Equal ("Bearer primary-token" ))
147+ })
148+
149+ It ("falls back to second auth when first fails" , func () {
150+ client , err := sysdig .NewSysdigClient (
151+ sysdig .WithFallbackAuthentication (
152+ sysdig .WithHostAndTokenFromContext (),
153+ sysdig .WithFixedHostAndToken (ts .URL , "fallback-token" ),
154+ ),
155+ )
156+ Expect (err ).NotTo (HaveOccurred ())
157+
158+ resp , err := client .GetMyPermissionsWithResponse (context .Background ())
159+ Expect (err ).NotTo (HaveOccurred ())
160+ Expect (resp .HTTPResponse .StatusCode ).To (Equal (http .StatusOK ))
161+ Expect (lastHeaders .Get ("Authorization" )).To (Equal ("Bearer fallback-token" ))
162+ })
163+
164+ It ("fails when all auth methods fail" , func () {
165+ client , err := sysdig .NewSysdigClient (
166+ sysdig .WithFallbackAuthentication (
167+ sysdig .WithHostAndTokenFromContext (),
168+ sysdig .WithHostAndTokenFromContext (),
169+ ),
170+ )
171+ Expect (err ).NotTo (HaveOccurred ())
172+
173+ _ , err = client .GetMyPermissionsWithResponse (context .Background ())
174+ Expect (err ).To (MatchError (ContainSubstring ("unable to authenticate" )))
175+ })
176+ })
177+
178+ Describe ("WithVersion" , func () {
179+ It ("sends User-Agent header with version" , func () {
180+ client , err := sysdig .NewSysdigClient (
181+ sysdig .WithFixedHostAndToken (ts .URL , "tok" ),
182+ sysdig .WithVersion ("2.0.0" ),
183+ )
184+ Expect (err ).NotTo (HaveOccurred ())
185+
186+ resp , err := client .GetMyPermissionsWithResponse (context .Background ())
187+ Expect (err ).NotTo (HaveOccurred ())
188+ Expect (resp .HTTPResponse .StatusCode ).To (Equal (http .StatusOK ))
189+ Expect (lastHeaders .Get ("User-Agent" )).To (Equal ("sysdig-mcp-server/2.0.0" ))
190+ })
191+ })
192+ })
0 commit comments