Skip to content

Commit 4c67f9c

Browse files
committed
feat: Replaced use on Access token in merlin extractor with Idtoken
1 parent 5c56953 commit 4c67f9c

File tree

2 files changed

+30
-27
lines changed

2 files changed

+30
-27
lines changed

plugins/extractors/merlin/internal/merlin/merlin_client.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,12 @@ import (
1111

1212
"github.com/raystack/meteor/metrics/otelhttpclient"
1313
"github.com/raystack/meteor/plugins/internal/urlbuilder"
14-
"golang.org/x/oauth2"
1514
"golang.org/x/oauth2/google"
15+
"google.golang.org/api/idtoken"
16+
)
17+
18+
const (
19+
audience = "sdk.caraml"
1620
)
1721

1822
var authScopes = []string{"https://www.googleapis.com/auth/userinfo.email"}
@@ -152,12 +156,12 @@ func authenticatedClient(ctx context.Context, serviceAccountJSON []byte, scopes
152156
return google.DefaultClient(ctx, scopes...)
153157
}
154158

155-
creds, err := google.CredentialsFromJSON(ctx, serviceAccountJSON, authScopes...)
159+
client, err := idtoken.NewClient(ctx, audience, idtoken.WithCredentialsJSON(serviceAccountJSON))
156160
if err != nil {
157161
return nil, fmt.Errorf("google credentials from JSON: %w", err)
158162
}
159163

160-
return oauth2.NewClient(ctx, creds.TokenSource), nil
164+
return client, nil
161165
}
162166

163167
// drainBody drains and closes the response body to avoid the following

plugins/extractors/merlin/internal/merlin/merlin_client_test.go

Lines changed: 23 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,23 @@ import (
2020
var (
2121
ctx = context.Background()
2222
credsJSON = []byte(`{"type":"service_account","project_id":"company-data-platform","private_key_id":"698vxv308w3i68p938040bz817r95b1e0k4kmvqs","private_key":"-----BEGIN PRIVATE KEY-----\nMIIEoQIBAAKCAQBVzQ0WPuaqdwMNapCGKdKUR/MOgWNByruT60SJwd5lY/2Sjx1w\nQ4sJ6xk/+Tz7bT3CgNBAPQ+rZfLD2fdQJIBeYElRcHw6a2PA/6TaX2e4qq0+5xk3\ngnItlqZm0hQElZd76LNlMcItHNmneLICowTOdzl0hUd2IgrqLB545v3KOGfwoEAp\nz3mPm/iF1+zTPWy041w7ajvWK2N3mRygKoP79ne2gDuN2+QHmW8wPFzQ3pdQZU65\n1npgP9N4wRHQT8vowTUSYdSRZG1p1MPKCXsrqhMUv7yLdrOcacAvcZqYOcMhJQ1p\nbYpsinDR65ARDduMeKoEUkFb3hf2zPUcdYNhAgMBAAECggEAQldOxCGUlr94o7n+\nz02tHavYGiIfDfLkQIYLs3wsKjc7DEQOHgyLh/q4xkc/SKR5uVeCLflIkV09bQOu\nftAKVW6bohWYaE86jTLdU1+rQhTt6ZIkZFA/WlJ+jUfn5HeJ7mvJsffcTKde/2eK\nNBG6GK4Exbx7ubKuv8unMBJiryUycioPykWZEVYl72+0IBsKCQOX39Fd/pgJF9jL\nFPelgCsrvPA/3lodgQu3m8VENlu4G6z3kPQghAvI37xC9NlUNVvx1yxCukQhf0zQ\nQ55kUTwgZ9sIGGcI/2K6H1YHv+m3vnM5D5iL9eTHn1HnlGtplQJhmhKjCxXIpbHx\nQToOwQKBgQCcEZP6H3nq3eH7d5ro1fvA6YEoERfzIzaU4Kk3Sb9e1tXjYSz8ccNv\nK3gZsHV2YZy3q9mCYnc0oPwwx5dSwhzpOrBrwvyopPbkKpD9WCXtZtRkwRTN7CXR\nE+2eSSpu2y14SKysPQoDZmyJo8bs7rseLQTiZeUPlYdlP6adOGSX+QKBgQCMvVqE\n6nbX41DcLJuUxT026T9zncnpRu3gkfyY0O5QF8/Vcq6y5LxdQtyMNbcbkDY8isAM\nwTP4KaXPul38TOCjfG3MODDbzmeQ27qKL/9Ueyi812BN4XIrpguoPKgFtlyi1JNH\nZiUtimedOoNG4LuuDEqeNyW1Qm/WlQu5fqKwqQKBgGscuVW6Ep+6RuWisePJMO62\nk9ke2jQZ39UP17NFXx1FDyjuQcTEg2AiElx3OjbUSY3ZWP/eenfZYRxNb7Lx3IvJ\nptleyq8oAPaZrEbkH6uunmjEB3ZI869qIPQ4vPG2ZZ+fKTtQ7TVmL2nLyLRGKJBO\nT4LecfZfJry7katnz8ppAoGAI0FXyI33YVNHMTBXdOgH0paRV4QCTVaARk4rqZhE\n6nlcjcqhqpyT9wTFvLXD/bqda4MSYt+PBi5go+26l3Ymm62Sz6KP0rAcz3PLgcxO\nOLp1VQDa1geQkxCQQP+Y032ALSX1EuCqlYLjO8aplfq76PiZRJLp9kMDQwypGDl5\nxakCgYAm7pO0LA/hTvdrZ7zGUIfTTZxf1qD+W0iUh2MtyaZM9uQhDoaahf7f2TT/\nt2+wlyIlHMdUxfDYf8U5owl9IysqaPMZsQmYNgYmXpW8/AhNcKFnslyrtd57Of3C\nlFHpNwfjNlxDTsql2kWbcwJbY0EblPRItplE7gDlUvfgSNTj+g==\n-----END PRIVATE KEY-----\n","client_email":"[email protected]","client_id":"043161688880430795893","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_x509_cert_url":"https://www.googleapis.com/robot/v1/metadata/x509/systems-meteor%40company-data-platform.iam.gserviceaccount.com"}`)
23+
token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"
2324
)
2425

2526
func TestNewClient(t *testing.T) {
2627
cases := []struct {
2728
name string
2829
params ClientParams
2930
errStr string
31+
ctx context.Context
3032
}{
3133
{
3234
name: "Valid",
3335
params: ClientParams{
3436
BaseURL: "http://company.com/api/merlin/",
3537
ServiceAccountJSON: credsJSON,
3638
},
39+
ctx: ctxWithClientWithIDToken(t, token),
3740
},
3841
{
3942
name: "WithoutCredentials",
@@ -55,11 +58,12 @@ func TestNewClient(t *testing.T) {
5558
ServiceAccountJSON: credsJSON,
5659
},
5760
errStr: `invalid input: parse "http://Gintama - Yorozuya Gin-chan": invalid character " " in host name`,
61+
ctx: ctxWithClientWithIDToken(t, token),
5862
},
5963
}
6064
for _, tc := range cases {
6165
t.Run(tc.name, func(t *testing.T) {
62-
_, err := NewClient(ctx, tc.params)
66+
_, err := NewClient(tc.ctx, tc.params)
6367
if tc.errStr != "" {
6468
assert.ErrorContains(t, err, tc.errStr)
6569
} else {
@@ -147,7 +151,6 @@ func TestProjects(t *testing.T) {
147151
}
148152
for _, tc := range cases {
149153
t.Run(tc.name, func(t *testing.T) {
150-
token := "MyIncrediblyPowerfulAccessToken"
151154
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
152155
assert.Equal(t, r.Method, http.MethodGet)
153156
assert.Equal(t, r.URL.Path, "/api/merlin/v1/projects")
@@ -157,7 +160,7 @@ func TestProjects(t *testing.T) {
157160
}))
158161
defer srv.Close()
159162

160-
c, err := NewClient(ctxWithClient(t, token), ClientParams{
163+
c, err := NewClient(ctxWithClientWithIDToken(t, token), ClientParams{
161164
BaseURL: srv.URL + "/api/merlin",
162165
ServiceAccountJSON: credsJSON,
163166
Timeout: 1 * time.Second,
@@ -183,7 +186,7 @@ func TestProjects(t *testing.T) {
183186
}))
184187
defer srv.Close()
185188

186-
c, err := NewClient(ctxWithClient(t, "MyIncrediblyPowerfulAccessToken"), ClientParams{
189+
c, err := NewClient(ctxWithClientWithIDToken(t, token), ClientParams{
187190
BaseURL: srv.URL + "/api/merlin",
188191
ServiceAccountJSON: credsJSON,
189192
Timeout: timeout,
@@ -346,7 +349,6 @@ func TestModels(t *testing.T) {
346349
}
347350
for _, tc := range cases {
348351
t.Run(tc.name, func(t *testing.T) {
349-
token := "MyIncrediblyPowerfulAccessToken"
350352
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
351353
assert.Equal(t, r.Method, http.MethodGet)
352354
assert.Equal(t, r.URL.Path, fmt.Sprintf("/api/merlin/v1/projects/%d/models", tc.projectID))
@@ -356,7 +358,7 @@ func TestModels(t *testing.T) {
356358
}))
357359
defer srv.Close()
358360

359-
c, err := NewClient(ctxWithClient(t, token), ClientParams{
361+
c, err := NewClient(ctxWithClientWithIDToken(t, token), ClientParams{
360362
BaseURL: srv.URL + "/api/merlin",
361363
ServiceAccountJSON: credsJSON,
362364
Timeout: 1 * time.Second,
@@ -382,7 +384,7 @@ func TestModels(t *testing.T) {
382384
}))
383385
defer srv.Close()
384386

385-
c, err := NewClient(ctxWithClient(t, "MyIncrediblyPowerfulAccessToken"), ClientParams{
387+
c, err := NewClient(ctxWithClientWithIDToken(t, token), ClientParams{
386388
BaseURL: srv.URL + "/api/merlin",
387389
ServiceAccountJSON: credsJSON,
388390
Timeout: timeout,
@@ -467,7 +469,6 @@ func TestModelVersion(t *testing.T) {
467469
}
468470
for _, tc := range cases {
469471
t.Run(tc.name, func(t *testing.T) {
470-
token := "MyIncrediblyPowerfulAccessToken"
471472
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
472473
assert.Equal(t, r.Method, http.MethodGet)
473474
assert.Equal(t, r.URL.Path, fmt.Sprintf(
@@ -479,7 +480,7 @@ func TestModelVersion(t *testing.T) {
479480
}))
480481
defer srv.Close()
481482

482-
c, err := NewClient(ctxWithClient(t, token), ClientParams{
483+
c, err := NewClient(ctxWithClientWithIDToken(t, token), ClientParams{
483484
BaseURL: srv.URL + "/api/merlin",
484485
ServiceAccountJSON: credsJSON,
485486
Timeout: 1 * time.Second,
@@ -505,7 +506,7 @@ func TestModelVersion(t *testing.T) {
505506
}))
506507
defer srv.Close()
507508

508-
c, err := NewClient(ctxWithClient(t, "MyIncrediblyPowerfulAccessToken"), ClientParams{
509+
c, err := NewClient(ctxWithClientWithIDToken(t, token), ClientParams{
509510
BaseURL: srv.URL + "/api/merlin",
510511
ServiceAccountJSON: credsJSON,
511512
Timeout: timeout,
@@ -517,23 +518,23 @@ func TestModelVersion(t *testing.T) {
517518
})
518519
}
519520

520-
func ctxWithClient(t *testing.T, token string) context.Context {
521+
func ctxWithClientWithIDToken(t *testing.T, token string) context.Context {
521522
return context.WithValue(ctx, oauth2.HTTPClient, &http.Client{
522-
Transport: mockOauthRoundTripper{
523-
T: t,
524-
AccessToken: token,
525-
Base: http.DefaultTransport,
523+
Transport: mockIDTokenRoundTripper{
524+
T: t,
525+
IDToken: token,
526+
Base: http.DefaultTransport,
526527
},
527528
})
528529
}
529530

530-
type mockOauthRoundTripper struct {
531-
T *testing.T
532-
AccessToken string
533-
Base http.RoundTripper
531+
type mockIDTokenRoundTripper struct {
532+
T *testing.T
533+
IDToken string
534+
Base http.RoundTripper
534535
}
535536

536-
func (m mockOauthRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
537+
func (m mockIDTokenRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
537538
if m.match(req) {
538539
return &http.Response{
539540
Status: http.StatusText(http.StatusOK),
@@ -543,9 +544,7 @@ func (m mockOauthRoundTripper) RoundTrip(req *http.Request) (*http.Response, err
543544
ProtoMinor: 1,
544545
Header: make(http.Header),
545546
Body: testutils.ValueAsJSONReader(m.T, map[string]interface{}{
546-
"access_token": m.AccessToken,
547-
"expires_in": 3599,
548-
"token_type": "Bearer",
547+
"id_token": m.IDToken,
549548
}),
550549
Uncompressed: true,
551550
}, nil
@@ -554,7 +553,7 @@ func (m mockOauthRoundTripper) RoundTrip(req *http.Request) (*http.Response, err
554553
return m.Base.RoundTrip(req)
555554
}
556555

557-
func (m mockOauthRoundTripper) match(r *http.Request) bool {
556+
func (m mockIDTokenRoundTripper) match(r *http.Request) bool {
558557
return r.Method == http.MethodPost &&
559558
r.URL.Host == "oauth2.googleapis.com" &&
560559
r.URL.Path == "/token"

0 commit comments

Comments
 (0)