Skip to content

Commit

Permalink
Access Google Drive via service account.
Browse files Browse the repository at this point in the history
Our GCS backend already supports service account.  This just copies relevant
code from there.
  • Loading branch information
gilbertchen committed Apr 7, 2020
1 parent e827662 commit 7208adb
Showing 1 changed file with 35 additions and 8 deletions.
43 changes: 35 additions & 8 deletions src/duplicacy_gcdstorage.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ import (

"golang.org/x/net/context"
"golang.org/x/oauth2"
"golang.org/x/oauth2/google"
"google.golang.org/api/drive/v3"
"google.golang.org/api/googleapi"
"google.golang.org/api/option"
)

var (
Expand Down Expand Up @@ -315,25 +317,50 @@ func (storage *GCDStorage) getIDFromPath(threadIndex int, filePath string, creat
// CreateGCDStorage creates a GCD storage object.
func CreateGCDStorage(tokenFile string, driveID string, storagePath string, threads int) (storage *GCDStorage, err error) {

ctx := context.Background()

description, err := ioutil.ReadFile(tokenFile)
if err != nil {
return nil, err
}

gcdConfig := &GCDConfig{}
if err := json.Unmarshal(description, gcdConfig); err != nil {
var object map[string]interface{}

err = json.Unmarshal(description, &object)
if err != nil {
return nil, err
}

oauth2Config := oauth2.Config{
ClientID: gcdConfig.ClientID,
ClientSecret: gcdConfig.ClientSecret,
Endpoint: gcdConfig.Endpoint,
isServiceAccount := false
if value, ok := object["type"]; ok {
if authType, ok := value.(string); ok && authType == "service_account" {
isServiceAccount = true
}
}

authClient := oauth2Config.Client(context.Background(), &gcdConfig.Token)
var tokenSource oauth2.TokenSource

if isServiceAccount {
config, err := google.JWTConfigFromJSON(description, drive.DriveScope)
if err != nil {
return nil, err
}
tokenSource = config.TokenSource(ctx)
} else {
gcdConfig := &GCDConfig{}
if err := json.Unmarshal(description, gcdConfig); err != nil {
return nil, err
}

config := oauth2.Config{
ClientID: gcdConfig.ClientID,
ClientSecret: gcdConfig.ClientSecret,
Endpoint: gcdConfig.Endpoint,
}
tokenSource = config.TokenSource(ctx, &gcdConfig.Token)
}

service, err := drive.New(authClient)
service, err := drive.NewService(ctx, option.WithTokenSource(tokenSource))
if err != nil {
return nil, err
}
Expand Down

2 comments on commit 7208adb

@gilbertchen
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This commit has been mentioned on Duplicacy Forum. There might be relevant details there:

https://forum.duplicacy.com/t/cli-release-2-5-0/3448/1

@garrett-hopper
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gilbertchen, is it possible to use a service account and access a different user's drive similar to Rclone's impersonate property (https://rclone.org/drive/#drive-impersonate)?
At the moment, it looks like the service account accesses a hidden drive which I can't access through the Google Drive web interface.

Please sign in to comment.