From a5a91839609678a9fbd1fc7448e888f9349ea06c Mon Sep 17 00:00:00 2001 From: Mari Date: Wed, 14 Apr 2021 20:44:10 -0400 Subject: [PATCH] Enable the ability to connect as a service account --- main.go | 67 +++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 58 insertions(+), 9 deletions(-) diff --git a/main.go b/main.go index ca0194f..93bcd12 100644 --- a/main.go +++ b/main.go @@ -12,16 +12,41 @@ import ( "google.golang.org/api/drive/v3" "google.golang.org/api/googleapi" "google.golang.org/api/option" + "io/ioutil" "log" "os" "path/filepath" ) type TokenCache struct { - ConfigPath string - TokenPath string - configLoaded bool - ConfigData oauth2.Config + CredentialPath string + CredentialScopes []string + ConfigPath string + TokenPath string + configLoaded bool + CredentialData *google.Credentials + ConfigData oauth2.Config +} + +func (c *TokenCache) Credentials() (*google.Credentials, error) { + if c.CredentialData != nil { + f, err := os.Open(c.CredentialPath) + if err != nil { + return nil, fmt.Errorf("could not open credentials: %v", err) + } + defer func() { _ = f.Close() }() + data, err := ioutil.ReadAll(f) + if err != nil { + return nil, fmt.Errorf("could not read credentials: %v", err) + } + c.CredentialData, err = google.CredentialsFromJSON(context.Background(), data, c.CredentialScopes...) + err = json.NewDecoder(f).Decode(&c.ConfigData) + if err != nil { + return nil, fmt.Errorf("could not decode config: %v", err) + } + c.configLoaded = true + } + return c.CredentialData, nil } func (c *TokenCache) Config() (*oauth2.Config, error) { @@ -40,11 +65,29 @@ func (c *TokenCache) Config() (*oauth2.Config, error) { return &c.ConfigData, nil } -// Retrieves a token and saves the token. +func (c *TokenCache) CredentialToken() (*oauth2.Token, error) { + log.Printf("Getting token from credentials file %s", c.CredentialPath) + creds, err := c.Credentials() + if err != nil { + return nil, err + } + return creds.TokenSource.Token() +} + func (c *TokenCache) Token() (*oauth2.Token, error) { + if c.CredentialPath != "" { + return c.CredentialToken() + } else { + return c.StandardToken() + } +} + +// Retrieves a token and saves the token. +func (c *TokenCache) StandardToken() (*oauth2.Token, error) { // The file token.json stores the user's access and refresh tokens, and is // created automatically when the authorization flow completes for the first // time. + log.Printf("Getting token from secret file %s with cache in %s", c.ConfigPath, c.TokenPath) tok, err := c.CachedToken() if err == nil && tok.Valid() { return tok, nil @@ -142,6 +185,7 @@ func (c *TokenCache) SaveToken(token *oauth2.Token) error { func main() { tokenCacheSource := TokenCache{ + CredentialScopes: []string{drive.DriveScope}, ConfigData: oauth2.Config{ Endpoint: google.Endpoint, RedirectURL: "urn:ietf:wg:oauth:2.0:oob", @@ -149,15 +193,20 @@ func main() { }, } flag.StringVar( - &tokenCacheSource.ConfigPath, - "secrets", - "./secrets.json", - "The path to the json file containing the client ID and secret.") + &tokenCacheSource.CredentialPath, + "credentials", + "", + "If set, overrides secrets.json and token.json. The path where the credentials file should be read from.") flag.StringVar( &tokenCacheSource.TokenPath, "token", "./token.json", "The path where the cached token should be stored and read from.") + flag.StringVar( + &tokenCacheSource.ConfigPath, + "secrets", + "./secrets.json", + "The path to the json file containing the client ID and secret.") fileId := flag.String( "file-id", "",