Skip to content

Commit 65c277f

Browse files
Add token fetching and handle exchange
1 parent 6bdf9f4 commit 65c277f

2 files changed

Lines changed: 59 additions & 9 deletions

File tree

cli/config/config.go

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,10 @@ type CommonOpts struct {
199199
// authentication
200200
Authentication *CliConfigAuthentication `json:"auth,omitempty" mapstructure:"auth"`
201201

202+
// Workload Identity Federation fields
203+
Audience string `json:"audience,omitempty" mapstructure:"audience"`
204+
IssuerURI string `json:"issuer_uri,omitempty" mapstructure:"issuer_uri"`
205+
202206
// client features
203207
Features []string `json:"features,omitempty" mapstructure:"features"`
204208

@@ -245,14 +249,26 @@ func (c *CommonOpts) GetFeatures() cnquery.Features {
245249
// GetServiceCredential returns the service credential that is defined in the config.
246250
// If no service credential is defined, it will return nil.
247251
func (c *CommonOpts) GetServiceCredential() *upstream.ServiceAccountCredentials {
248-
if c.Authentication != nil && c.Authentication.Method == "ssh" {
249-
log.Info().Msg("using ssh authentication method, generate temporary credentials")
250-
serviceAccount, err := upstream.ExchangeSSHKey(c.UpstreamApiEndpoint(), c.ServiceAccountMrn, c.GetParentMrn())
251-
if err != nil {
252-
log.Error().Err(err).Msg("could not exchange ssh key")
253-
return nil
252+
if c.Authentication != nil {
253+
switch c.Authentication.Method {
254+
case "ssh":
255+
log.Info().Msg("using ssh authentication method, generate temporary credentials")
256+
serviceAccount, err := upstream.ExchangeSSHKey(c.UpstreamApiEndpoint(), c.ServiceAccountMrn, c.GetParentMrn())
257+
if err != nil {
258+
log.Error().Err(err).Msg("could not exchange ssh key")
259+
return nil
260+
}
261+
return serviceAccount
262+
case "wif":
263+
log.Info().Msg("using wif authentication method, generate temporary credentials")
264+
serviceAccount, err := upstream.ExchangeExternalToken(c.UpstreamApiEndpoint(), c.Audience, c.IssuerURI)
265+
if err != nil {
266+
log.Error().Err(err).Msg("could not exchange external (wif) token")
267+
return nil
268+
}
269+
270+
return serviceAccount
254271
}
255-
return serviceAccount
256272
}
257273

258274
// return nil when no service account is defined

providers-sdk/v1/upstream/sts.go

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import (
1010
"encoding/base64"
1111
"encoding/hex"
1212
"encoding/json"
13+
"fmt"
14+
"io"
15+
"net/http"
1316
"net/url"
1417
"time"
1518

@@ -55,15 +58,22 @@ func ExchangeSSHKey(apiEndpoint string, identityMrn string, resourceMrn string)
5558
}, nil
5659
}
5760

58-
func ExchangeExternalToken(apiEndpoint string, audience string, issuerUri string, jsonToken string) (*ServiceAccountCredentials, error) {
61+
func ExchangeExternalToken(apiEndpoint string, audience string, issuerURI string) (*ServiceAccountCredentials, error) {
62+
// TODO: This is just a testing function to fetch a GCP identity token
63+
// it should change to be a generic function.
64+
jsonToken, err := fetchGCPIdentityToken(audience)
65+
if err != nil {
66+
return nil, err
67+
}
68+
5969
stsClient, err := NewSecureTokenServiceClient(apiEndpoint, ranger.DefaultHttpClient())
6070
if err != nil {
6171
return nil, err
6272
}
6373

6474
resp, err := stsClient.ExchangeExternalToken(context.Background(), &ExchangeExternalTokenRequest{
6575
Audience: audience,
66-
IssuerUri: issuerUri,
76+
IssuerUri: issuerURI,
6777
JwtToken: jsonToken,
6878
})
6979
if err != nil {
@@ -85,6 +95,30 @@ func ExchangeExternalToken(apiEndpoint string, audience string, issuerUri string
8595
return &creds, nil
8696
}
8797

98+
// TODO: This is just a testing function to fetch a GCP identity token
99+
// it should change to be a generic function that checks the provider and fetches the token accordingly.
100+
func fetchGCPIdentityToken(audience string) (string, error) {
101+
url := fmt.Sprintf("http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/identity?audience=%s", audience)
102+
req, err := http.NewRequest("GET", url, nil)
103+
if err != nil {
104+
return "", err
105+
}
106+
req.Header.Add("Metadata-Flavor", "Google")
107+
108+
client := &http.Client{}
109+
resp, err := client.Do(req)
110+
if err != nil {
111+
return "", err
112+
}
113+
defer resp.Body.Close()
114+
115+
tokenBytes, err := io.ReadAll(resp.Body)
116+
if err != nil {
117+
return "", err
118+
}
119+
return string(tokenBytes), nil
120+
}
121+
88122
// signClaims implements claims signing with ssh.Signer
89123
//
90124
// To generate a new SSH key use:

0 commit comments

Comments
 (0)