@@ -3,12 +3,17 @@ package api
33import (
44 "context"
55 "fmt"
6+ "net/http"
7+ "net/http/httptest"
8+ "testing"
9+ "time"
10+
611 "github.com/DataDog/datadog-api-client-go/v2/api/datadog"
12+ "github.com/DataDog/datadog-api-client-go/v2/api/datadogV2"
713 "github.com/DataDog/datadog-api-client-go/v2/tests/api/mocks"
814 "github.com/golang/mock/gomock"
915 "github.com/stretchr/testify/assert"
10- "testing"
11- "time"
16+ "github.com/stretchr/testify/require"
1217)
1318
1419const FAKE_TOKEN = "fake-token"
@@ -155,3 +160,103 @@ func TestApiAppKeyAuthenticate(t *testing.T) {
155160 assert .Equal (t , headers ["DD-API-KEY" ], apiKey )
156161 assert .Equal (t , headers ["DD-APPLICATION-KEY" ], appKey )
157162}
163+
164+ func TestPATAuthentication (t * testing.T ) {
165+ pat := "ddapp_test-pat-token"
166+ keys := map [string ]datadog.APIKey {
167+ "apiKeyAuth" : {Key : "api-key" },
168+ }
169+ testAuthCtx := context .WithValue (
170+ context .Background (),
171+ datadog .ContextAPIKeys ,
172+ keys ,
173+ )
174+ testAuthCtx = context .WithValue (testAuthCtx , datadog .ContextBearerToken , pat )
175+
176+ headers := map [string ]string {}
177+ datadog .SetAuthKeys (
178+ testAuthCtx ,
179+ & headers ,
180+ [2 ]string {"apiKeyAuth" , "DD-API-KEY" },
181+ [2 ]string {"appKeyAuth" , "DD-APPLICATION-KEY" },
182+ )
183+ assert .Equal (t , "Bearer ddapp_test-pat-token" , headers ["Authorization" ])
184+ assert .Empty (t , headers ["DD-API-KEY" ], "PAT auth should not send DD-API-KEY" )
185+ assert .Empty (t , headers ["DD-APPLICATION-KEY" ], "PAT auth should not send DD-APPLICATION-KEY" )
186+ }
187+
188+ func TestNewDefaultContextWithBearerToken (t * testing.T ) {
189+ t .Setenv ("DD_API_KEY" , "test-api-key" )
190+ t .Setenv ("DD_BEARER_TOKEN" , "ddapp_test-pat-token" )
191+
192+ ctx := datadog .NewDefaultContext (context .Background ())
193+ keys := ctx .Value (datadog .ContextAPIKeys ).(map [string ]datadog.APIKey )
194+ assert .Equal (t , "test-api-key" , keys ["apiKeyAuth" ].Key )
195+ bearerToken := ctx .Value (datadog .ContextBearerToken ).(string )
196+ assert .Equal (t , "ddapp_test-pat-token" , bearerToken )
197+ }
198+
199+ func TestNewDefaultContextBearerTokenOverridesAppKey (t * testing.T ) {
200+ t .Setenv ("DD_API_KEY" , "test-api-key" )
201+ t .Setenv ("DD_APP_KEY" , "test-app-key" )
202+ t .Setenv ("DD_BEARER_TOKEN" , "ddapp_test-pat-token" )
203+
204+ ctx := datadog .NewDefaultContext (context .Background ())
205+ // App key is still stored, but bearer token takes precedence in SetAuthKeys
206+ keys := ctx .Value (datadog .ContextAPIKeys ).(map [string ]datadog.APIKey )
207+ assert .Equal (t , "test-app-key" , keys ["appKeyAuth" ].Key )
208+ bearerToken := ctx .Value (datadog .ContextBearerToken ).(string )
209+ assert .Equal (t , "ddapp_test-pat-token" , bearerToken )
210+
211+ // Verify bearer token is used — no API key or app key headers
212+ headers := map [string ]string {}
213+ datadog .SetAuthKeys (
214+ ctx ,
215+ & headers ,
216+ [2 ]string {"apiKeyAuth" , "DD-API-KEY" },
217+ [2 ]string {"appKeyAuth" , "DD-APPLICATION-KEY" },
218+ )
219+ assert .Equal (t , "Bearer ddapp_test-pat-token" , headers ["Authorization" ])
220+ assert .Empty (t , headers ["DD-API-KEY" ], "Bearer auth should not send DD-API-KEY" )
221+ assert .Empty (t , headers ["DD-APPLICATION-KEY" ], "Bearer auth should not send DD-APPLICATION-KEY" )
222+ }
223+
224+ func TestNewDefaultContextAppKeyWithoutBearerToken (t * testing.T ) {
225+ t .Setenv ("DD_API_KEY" , "test-api-key" )
226+ t .Setenv ("DD_APP_KEY" , "test-app-key" )
227+
228+ ctx := datadog .NewDefaultContext (context .Background ())
229+ keys := ctx .Value (datadog .ContextAPIKeys ).(map [string ]datadog.APIKey )
230+ assert .Equal (t , "test-app-key" , keys ["appKeyAuth" ].Key )
231+ assert .Nil (t , ctx .Value (datadog .ContextBearerToken ))
232+ }
233+
234+ func TestPATBearerHeaderSentViaHTTPClient (t * testing.T ) {
235+ pat := "ddapp_test-token"
236+
237+ var capturedHeaders http.Header
238+ ts := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
239+ capturedHeaders = r .Header .Clone ()
240+ w .Header ().Set ("Content-Type" , "application/json" )
241+ w .WriteHeader (200 )
242+ fmt .Fprint (w , `{"data":[],"meta":{"page":{"total_count":0,"total_filtered_count":0}}}` )
243+ }))
244+ defer ts .Close ()
245+
246+ ctx := context .Background ()
247+ ctx = context .WithValue (ctx , datadog .ContextBearerToken , pat )
248+
249+ cfg := datadog .NewConfiguration ()
250+ cfg .Servers = datadog.ServerConfigurations {{URL : ts .URL }}
251+ client := datadog .NewAPIClient (cfg )
252+ usersAPI := datadogV2 .NewUsersApi (client )
253+
254+ _ , httpResp , err := usersAPI .ListUsers (ctx , * datadogV2 .NewListUsersOptionalParameters ())
255+ require .NoError (t , err )
256+ defer httpResp .Body .Close ()
257+
258+ assert .Equal (t , 200 , httpResp .StatusCode )
259+ assert .Equal (t , "Bearer " + pat , capturedHeaders .Get ("Authorization" ))
260+ assert .Empty (t , capturedHeaders .Get ("DD-API-KEY" ), "PAT auth should not send DD-API-KEY" )
261+ assert .Empty (t , capturedHeaders .Get ("DD-APPLICATION-KEY" ), "PAT auth should not send DD-APPLICATION-KEY" )
262+ }
0 commit comments