@@ -9,12 +9,15 @@ import (
99 "sync"
1010 "time"
1111
12- "github.com/hashicorp/errwrap"
12+ "github.com/hashicorp/go-gcp-common/gcputil"
13+ "github.com/hashicorp/go-hclog"
1314 "github.com/hashicorp/vault/sdk/framework"
15+ "github.com/hashicorp/vault/sdk/helper/pluginutil"
1416 "github.com/hashicorp/vault/sdk/helper/useragent"
1517 "github.com/hashicorp/vault/sdk/logical"
1618 "github.com/patrickmn/go-cache"
1719 "golang.org/x/oauth2/google"
20+ "golang.org/x/oauth2/google/externalaccount"
1821 "google.golang.org/api/option"
1922
2023 kmsapi "cloud.google.com/go/kms/apiv1"
@@ -182,20 +185,32 @@ func (b *backend) KMSClient(s logical.Storage) (*kmsapi.KeyManagementClient, fun
182185 return nil , nil , err
183186 }
184187
185- // If credentials were provided, use those. Otherwise fall back to the
186- // default application credentials.
188+ // If credentials were provided or workload identiy , use those.
189+ // Otherwise fall back to the default application credentials.
187190 var creds * google.Credentials
188191 if config .Credentials != "" {
189192 creds , err = google .CredentialsFromJSON (b .ctx , []byte (config .Credentials ), config .Scopes ... )
190193 if err != nil {
191194 b .kmsClientLock .Unlock ()
192- return nil , nil , errwrap .Wrapf ("failed to parse credentials: {{err}}" , err )
195+ return nil , nil , fmt .Errorf ("failed to parse credentials: %w" , err )
196+ }
197+ } else if config .IdentityTokenAudience != "" {
198+ ts := & PluginIdentityTokenSupplier {
199+ sys : b .System (),
200+ logger : b .Logger (),
201+ audience : config .IdentityTokenAudience ,
202+ ttl : config .IdentityTokenTTL ,
203+ }
204+
205+ creds , err = b .GetExternalAccountConfig (config , ts ).GetExternalAccountCredentials (b .ctx )
206+ if err != nil {
207+ return nil , nil , fmt .Errorf ("failed to fetch external account credentials: %w" , err )
193208 }
194209 } else {
195210 creds , err = google .FindDefaultCredentials (b .ctx , config .Scopes ... )
196211 if err != nil {
197212 b .kmsClientLock .Unlock ()
198- return nil , nil , errwrap . Wrapf ("failed to get default token source: {{err}} " , err )
213+ return nil , nil , fmt . Errorf ("failed to get default token source: %w " , err )
199214 }
200215 }
201216
@@ -207,7 +222,7 @@ func (b *backend) KMSClient(s logical.Storage) (*kmsapi.KeyManagementClient, fun
207222 )
208223 if err != nil {
209224 b .kmsClientLock .Unlock ()
210- return nil , nil , errwrap . Wrapf ("failed to create KMS client: {{err}} " , err )
225+ return nil , nil , fmt . Errorf ("failed to create KMS client: %w " , err )
211226 }
212227
213228 // Cache the client
@@ -228,14 +243,53 @@ func (b *backend) Config(ctx context.Context, s logical.Storage) (*Config, error
228243
229244 entry , err := s .Get (ctx , "config" )
230245 if err != nil {
231- return nil , errwrap . Wrapf ("failed to get configuration from storage: {{err}} " , err )
246+ return nil , fmt . Errorf ("failed to get configuration from storage: %w " , err )
232247 }
233248 if entry == nil || len (entry .Value ) == 0 {
234249 return c , nil
235250 }
236251
237252 if err := entry .DecodeJSON (& c ); err != nil {
238- return nil , errwrap . Wrapf ("failed to decode configuration: {{err}} " , err )
253+ return nil , fmt . Errorf ("failed to decode configuration: %w " , err )
239254 }
240255 return c , nil
241256}
257+
258+ func (b * backend ) GetExternalAccountConfig (c * Config , ts * PluginIdentityTokenSupplier ) * gcputil.ExternalAccountConfig {
259+ b .Logger ().Debug ("adding web identity token fetcher" )
260+ cfg := & gcputil.ExternalAccountConfig {
261+ ServiceAccountEmail : c .ServiceAccountEmail ,
262+ Audience : c .IdentityTokenAudience ,
263+ TTL : c .IdentityTokenTTL ,
264+ TokenSupplier : ts ,
265+ }
266+
267+ return cfg
268+ }
269+
270+ type PluginIdentityTokenSupplier struct {
271+ sys logical.SystemView
272+ logger hclog.Logger
273+ audience string
274+ ttl time.Duration
275+ }
276+
277+ var _ externalaccount.SubjectTokenSupplier = (* PluginIdentityTokenSupplier )(nil )
278+
279+ func (p * PluginIdentityTokenSupplier ) SubjectToken (ctx context.Context , opts externalaccount.SupplierOptions ) (string , error ) {
280+ p .logger .Info ("fetching new plugin identity token" )
281+ resp , err := p .sys .GenerateIdentityToken (ctx , & pluginutil.IdentityTokenRequest {
282+ Audience : p .audience ,
283+ TTL : p .ttl ,
284+ })
285+ if err != nil {
286+ return "" , fmt .Errorf ("failed to generate plugin identity token: %w" , err )
287+ }
288+
289+ if resp .TTL < p .ttl {
290+ p .logger .Debug ("generated plugin identity token has shorter TTL than requested" ,
291+ "requested" , p .ttl .Seconds (), "actual" , resp .TTL )
292+ }
293+
294+ return resp .Token .Token (), nil
295+ }
0 commit comments