Skip to content

Commit 7a91986

Browse files
authored
Add support for service account impersonation (#14)
Original PR #12
1 parent 60808bf commit 7a91986

File tree

7 files changed

+147
-26
lines changed

7 files changed

+147
-26
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1 @@
1-
@grafana/oss-big-tent
2-
@grafana/partner-datasources
1+
* @grafana/partner-datasources @grafana/oss-big-tent

CHANGELOG.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## v0.4.0
6+
7+
- Add support for service account impersonation
8+
59
## v0.3.0
610

711
- Update go version to 1.24
812
- Update dependencies
913

10-
1114
## v0.2.1
1215

1316
- Build with latest Go version 1.20.4

go.mod

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,18 @@ require (
66
github.com/grafana/grafana-plugin-sdk-go v0.277.1
77
github.com/magefile/mage v1.15.0
88
github.com/stretchr/testify v1.10.0
9-
golang.org/x/oauth2 v0.29.0
9+
golang.org/x/oauth2 v0.30.0
10+
)
11+
12+
require (
13+
cloud.google.com/go/auth v0.16.1 // indirect
14+
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
15+
github.com/felixge/httpsnoop v1.0.4 // indirect
16+
github.com/google/s2a-go v0.1.9 // indirect
17+
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
18+
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
19+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
20+
golang.org/x/crypto v0.38.0 // indirect
1021
)
1122

1223
require (
@@ -87,15 +98,16 @@ require (
8798
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
8899
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
89100
golang.org/x/mod v0.23.0 // indirect
90-
golang.org/x/net v0.39.0 // indirect
91-
golang.org/x/sync v0.13.0 // indirect
92-
golang.org/x/sys v0.32.0 // indirect
93-
golang.org/x/text v0.24.0 // indirect
101+
golang.org/x/net v0.40.0 // indirect
102+
golang.org/x/sync v0.14.0 // indirect
103+
golang.org/x/sys v0.33.0 // indirect
104+
golang.org/x/text v0.25.0 // indirect
94105
golang.org/x/tools v0.30.0 // indirect
95106
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
107+
google.golang.org/api v0.233.0
96108
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a // indirect
97-
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a // indirect
98-
google.golang.org/grpc v1.71.1 // indirect
109+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 // indirect
110+
google.golang.org/grpc v1.72.0 // indirect
99111
google.golang.org/protobuf v1.36.6 // indirect
100112
gopkg.in/fsnotify/fsnotify.v1 v1.4.7 // indirect
101113
gopkg.in/yaml.v3 v3.0.1 // indirect

go.sum

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
cloud.google.com/go/auth v0.16.1 h1:XrXauHMd30LhQYVRHLGvJiYeczweKQXZxsTbV9TiguU=
2+
cloud.google.com/go/auth v0.16.1/go.mod h1:1howDHJ5IETh/LwYs3ZxvlkXF48aSqqJUM+5o02dNOI=
3+
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
4+
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
15
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
26
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
37
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -64,8 +68,14 @@ github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
6468
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
6569
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
6670
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
71+
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
72+
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
6773
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
6874
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
75+
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
76+
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
77+
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
78+
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
6979
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
7080
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
7181
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
@@ -232,8 +242,8 @@ go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJ
232242
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
233243
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
234244
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
235-
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
236-
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
245+
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
246+
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
237247
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
238248
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
239249
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
@@ -244,6 +254,8 @@ go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
244254
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
245255
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
246256
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
257+
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
258+
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
247259
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk=
248260
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY=
249261
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@@ -254,15 +266,15 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
254266
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
255267
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
256268
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
257-
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
258-
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
259-
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
260-
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
269+
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
270+
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
271+
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
272+
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
261273
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
262274
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
263275
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
264-
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
265-
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
276+
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
277+
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
266278
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
267279
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
268280
golang.org/x/sys v0.0.0-20191020152052-9984515f0562/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -275,12 +287,14 @@ golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBc
275287
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
276288
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
277289
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
278-
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
279-
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
290+
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
291+
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
280292
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
281293
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
282-
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
283-
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
294+
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
295+
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
296+
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
297+
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
284298
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
285299
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
286300
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@@ -295,12 +309,14 @@ golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhS
295309
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
296310
gonum.org/v1/gonum v0.15.1 h1:FNy7N6OUZVUaWG9pTiD+jlhdQ3lMP+/LcTpJ6+a8sQ0=
297311
gonum.org/v1/gonum v0.15.1/go.mod h1:eZTZuRFrzu5pcyjN5wJhcIhnUdNijYxX1T2IcrOGY0o=
312+
google.golang.org/api v0.233.0 h1:iGZfjXAJiUFSSaekVB7LzXl6tRfEKhUN7FkZN++07tI=
313+
google.golang.org/api v0.233.0/go.mod h1:TCIVLLlcwunlMpZIhIp7Ltk77W+vUSdUKAAIlbxY44c=
298314
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a h1:nwKuGPlUAt+aR+pcrkfFRrTU1BVrSmYyYMxYbUIVHr0=
299315
google.golang.org/genproto/googleapis/api v0.0.0-20250218202821-56aae31c358a/go.mod h1:3kWAYMk1I75K4vykHtKt2ycnOgpA6974V7bREqbsenU=
300-
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a h1:51aaUVRocpvUOSQKM6Q7VuoaktNIaMCLuhZB6DKksq4=
301-
google.golang.org/genproto/googleapis/rpc v0.0.0-20250218202821-56aae31c358a/go.mod h1:uRxBH1mhmO8PGhU89cMcHaXKZqO+OfakD8QQO0oYwlQ=
302-
google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI=
303-
google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
316+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2 h1:IqsN8hx+lWLqlN+Sc3DoMy/watjofWiU8sRFgQ8fhKM=
317+
google.golang.org/genproto/googleapis/rpc v0.0.0-20250505200425-f936aa4a68b2/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
318+
google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
319+
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
304320
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
305321
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
306322
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

pkg/tokenprovider/token_provider_gce.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,22 @@ import (
55

66
"golang.org/x/oauth2"
77
"golang.org/x/oauth2/google"
8+
"google.golang.org/api/impersonate"
89
)
910

1011
type gceSource struct {
1112
cacheKey string
1213
scopes []string
1314
}
1415

16+
type impersonatedGceSource struct {
17+
cacheKey string
18+
scopes []string
19+
TargetPrincipal string
20+
Delegates []string
21+
Subject string
22+
}
23+
1524
// NewGceAccessTokenProvider returns a token provider for gce authentication
1625
func NewGceAccessTokenProvider(cfg Config) TokenProvider {
1726
return &tokenProviderImpl{
@@ -22,6 +31,19 @@ func NewGceAccessTokenProvider(cfg Config) TokenProvider {
2231
}
2332
}
2433

34+
// NewImpersonatedGceAccessTokenProvider returns a token provider for an impersonated service account when using gce authentication
35+
func NewImpersonatedGceAccessTokenProvider(cfg Config) TokenProvider {
36+
return &tokenProviderImpl{
37+
&impersonatedGceSource{
38+
cacheKey: createCacheKey("gce", &cfg),
39+
scopes: cfg.Scopes,
40+
TargetPrincipal: cfg.TargetPrincipal,
41+
Subject: cfg.Subject,
42+
Delegates: cfg.Delegates,
43+
},
44+
}
45+
}
46+
2547
func (source *gceSource) getCacheKey() string {
2648
return source.cacheKey
2749
}
@@ -33,3 +55,20 @@ func (source *gceSource) getToken(ctx context.Context) (*oauth2.Token, error) {
3355
}
3456
return tokenSource.Token()
3557
}
58+
59+
func (source *impersonatedGceSource) getCacheKey() string {
60+
return source.cacheKey
61+
}
62+
63+
func (source *impersonatedGceSource) getToken(ctx context.Context) (*oauth2.Token, error) {
64+
tokenSource, err := impersonate.CredentialsTokenSource(ctx, impersonate.CredentialsConfig{
65+
TargetPrincipal: source.TargetPrincipal,
66+
Scopes: source.scopes,
67+
Delegates: source.Delegates,
68+
Subject: source.Subject,
69+
})
70+
if err != nil {
71+
return nil, err
72+
}
73+
return tokenSource.Token()
74+
}

pkg/tokenprovider/token_provider_jwt.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,23 @@ import (
55

66
"golang.org/x/oauth2"
77
"golang.org/x/oauth2/jwt"
8+
"google.golang.org/api/impersonate"
9+
"google.golang.org/api/option"
810
)
911

1012
type jwtSource struct {
1113
cacheKey string
1214
conf jwt.Config
1315
}
1416

17+
type impersonatedJwtSource struct {
18+
cacheKey string
19+
conf jwt.Config
20+
TargetPrincipal string
21+
Subject string
22+
Delegates []string
23+
}
24+
1525
// NewJwtAccessTokenProvider returns a token provider for jwt file authentication
1626
func NewJwtAccessTokenProvider(cfg Config) TokenProvider {
1727
return &tokenProviderImpl{
@@ -27,6 +37,24 @@ func NewJwtAccessTokenProvider(cfg Config) TokenProvider {
2737
}
2838
}
2939

40+
// NewJwtAccessTokenProvider returns a token provider for an impersonated service account when using jwt file authentication
41+
func NewImpersonatedJwtAccessTokenProvider(cfg Config) TokenProvider {
42+
return &tokenProviderImpl{
43+
&impersonatedJwtSource{
44+
cacheKey: createCacheKey("jwt", &cfg),
45+
conf: jwt.Config{
46+
Email: cfg.JwtTokenConfig.Email,
47+
PrivateKey: cfg.JwtTokenConfig.PrivateKey,
48+
TokenURL: cfg.JwtTokenConfig.URI,
49+
Scopes: cfg.Scopes,
50+
},
51+
TargetPrincipal: cfg.TargetPrincipal,
52+
Subject: cfg.Subject,
53+
Delegates: cfg.Delegates,
54+
},
55+
}
56+
}
57+
3058
func (source *jwtSource) getCacheKey() string {
3159
return source.cacheKey
3260
}
@@ -35,6 +63,24 @@ func (source *jwtSource) getToken(ctx context.Context) (*oauth2.Token, error) {
3563
return getTokenSource(ctx, &source.conf).Token()
3664
}
3765

66+
func (source *impersonatedJwtSource) getCacheKey() string {
67+
return source.cacheKey
68+
}
69+
70+
func (source *impersonatedJwtSource) getToken(ctx context.Context) (*oauth2.Token, error) {
71+
baseTokenSource := getTokenSource(ctx, &source.conf)
72+
tokenSource, err := impersonate.CredentialsTokenSource(ctx, impersonate.CredentialsConfig{
73+
TargetPrincipal: source.TargetPrincipal,
74+
Scopes: source.conf.Scopes,
75+
Subject: source.Subject,
76+
Delegates: source.Delegates,
77+
}, option.WithTokenSource(baseTokenSource))
78+
if err != nil {
79+
return nil, err
80+
}
81+
return tokenSource.Token()
82+
}
83+
3884
// getTokenSource returns a TokenSource.
3985
// Stubbable by tests.
4086
var getTokenSource = func(ctx context.Context, conf *jwt.Config) oauth2.TokenSource {

pkg/tokenprovider/types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ type Config struct {
1010
DataSourceUpdated time.Time
1111
Scopes []string
1212

13+
// TargetPrincipal is only used when using service account impersonation
14+
TargetPrincipal string
15+
// Subject is only used when using service account impersonation
16+
Subject string
17+
// Delegates is only used when using service account impersonation
18+
Delegates []string
1319
// JwtTokenConfig is only used for JWT tokens
1420
JwtTokenConfig *JwtTokenConfig
1521
}

0 commit comments

Comments
 (0)