diff --git a/README.md b/README.md index b2b91c62..500467a0 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,14 @@ syncing many files. Currently only one file is uploaded at the time, the speed can be improved in the future by uploading several files concurrently. To learn more see usage and the examples below. +### Service Account +For server to server communication, where user interaction is not a viable option, +is it possible to use a service account, as described in this [Google document](https://developers.google.com/identity/protocols/OAuth2ServiceAccount). +If you want to use a service account, instead of being interactively prompted for +authentication, you need to use the `--service-account ` +global option, where `serviceAccountCredentials` is a file in JSON format obtained +through the Google API Console, and its location is relative to the config dir. + #### .gdriveignore Placing a .gdriveignore in the root of your sync directory can be used to skip certain files from being synced. .gdriveignore follows the same @@ -132,6 +140,7 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) options: -m, --max Max files to list, default: 30 @@ -158,7 +167,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: -f, --force Overwrite existing file -r, --recursive Download directory recursively, documents will be skipped @@ -177,7 +187,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: -f, --force Overwrite existing file -r, --recursive Download directories recursively, documents will be skipped @@ -193,7 +204,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: -r, --recursive Upload directory recursively -p, --parent Parent id, used to upload file to a specific directory, can be specified multiple times to give many parents @@ -215,7 +227,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: -p, --parent Parent id, used to upload file to a specific directory, can be specified multiple times to give many parents --chunksize Set chunk size in bytes, default: 8388608 @@ -234,7 +247,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: -p, --parent Parent id, used to upload file to a specific directory, can be specified multiple times to give many parents --name Filename @@ -253,7 +267,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: --bytes Show size in bytes ``` @@ -266,7 +281,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: -p, --parent Parent id of created directory, can be specified multiple times to give many parents --description Directory description @@ -280,7 +296,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: --role Share role: owner/writer/commenter/reader, default: reader --type Share type: user/group/domain/anyone, default: anyone @@ -297,6 +314,7 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) ``` #### Revoke permission @@ -307,6 +325,7 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) ``` #### Delete file or directory @@ -317,7 +336,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: -r, --recursive Delete directory and all it's content ``` @@ -330,7 +350,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: --no-header Dont print the header ``` @@ -343,7 +364,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: --order Sort order. See https://godoc.org/google.golang.org/api/drive/v3#FilesListCall.OrderBy --path-width Width of path column, default: 60, minimum: 9, use 0 for full width @@ -359,7 +381,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: --keep-remote Keep remote file when a conflict is encountered --keep-local Keep local file when a conflict is encountered @@ -378,7 +401,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: --keep-remote Keep remote file when a conflict is encountered --keep-local Keep local file when a conflict is encountered @@ -398,7 +422,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: -m, --max Max changes to list, default: 100 --since Page token to start listing changes from @@ -415,7 +440,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: --name-width Width of name column, default: 40, minimum: 9, use 0 for full width --no-header Dont print the header @@ -430,7 +456,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: -f, --force Overwrite existing file --no-progress Hide progress @@ -447,6 +474,7 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) ``` #### Upload and convert file to a google document, see 'about import' for available conversions @@ -457,7 +485,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: -p, --parent Parent id, used to upload file to a specific directory, can be specified multiple times to give many parents --no-progress Hide progress @@ -471,7 +500,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: -f, --force Overwrite existing file --mime Mime type of exported file @@ -486,7 +516,8 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) - + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) + options: --bytes Show size in bytes ``` @@ -499,6 +530,7 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) ``` #### Show supported export formats @@ -509,6 +541,7 @@ global: -c, --config Application path, default: /Users//.gdrive --refresh-token Oauth refresh token used to get access token (for advanced users) --access-token Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users) + --service-account Oauth service account filename, used for server to server communication without user interaction (file is relative to config dir) ``` diff --git a/auth/file_source.go b/auth/file_source.go index 52002033..11e73250 100644 --- a/auth/file_source.go +++ b/auth/file_source.go @@ -31,7 +31,7 @@ func (self *fileSource) Token() (*oauth2.Token, error) { return token, nil } -func ReadToken(path string) (*oauth2.Token, bool, error) { +func ReadFile(path string) ([]byte, bool, error) { if !fileExists(path) { return nil, false, nil } @@ -40,8 +40,19 @@ func ReadToken(path string) (*oauth2.Token, bool, error) { if err != nil { return nil, true, err } + return content, true, nil +} + + +func ReadToken(path string) (*oauth2.Token, bool, error) { + + content, exists, err := ReadFile(path) + if err != nil { + return nil, exists, err + } + token := &oauth2.Token{} - return token, true, json.Unmarshal(content, token) + return token, exists, json.Unmarshal(content, token) } func SaveToken(path string, token *oauth2.Token) error { diff --git a/auth/oauth.go b/auth/oauth.go index 150642cc..bc567385 100644 --- a/auth/oauth.go +++ b/auth/oauth.go @@ -3,6 +3,7 @@ package auth import ( "fmt" "golang.org/x/oauth2" + "golang.org/x/oauth2/google" "net/http" "time" ) @@ -64,6 +65,23 @@ func NewAccessTokenClient(clientId, clientSecret, accessToken string) *http.Clie ) } +func NewServiceAccountClient(serviceAccountFile string) (*http.Client, error) { + content, exists, err := ReadFile(serviceAccountFile) + if(!exists) { + return nil, fmt.Errorf("Service account filename %q not found", serviceAccountFile) + } + + if(err != nil) { + return nil, err + } + + conf, err := google.JWTConfigFromJSON(content, "https://www.googleapis.com/auth/drive") + if(err != nil) { + return nil, err + } + return conf.Client(oauth2.NoContext), nil +} + func getConfig(clientId, clientSecret string) *oauth2.Config { return &oauth2.Config{ ClientID: clientId, diff --git a/gdrive.go b/gdrive.go index 971dc4c4..c1a817e7 100644 --- a/gdrive.go +++ b/gdrive.go @@ -40,6 +40,11 @@ func main() { Patterns: []string{"--access-token"}, Description: "Oauth access token, only recommended for short-lived requests because of short lifetime (for advanced users)", }, + cli.StringFlag{ + Name: "serviceAccount", + Patterns: []string{"--service-account"}, + Description: "Oauth service account filename, used for server to server communication without user interaction (filename path is relative to config dir)", + }, } handlers := []*cli.Handler{ diff --git a/handlers_drive.go b/handlers_drive.go index 5240566f..7bda872f 100644 --- a/handlers_drive.go +++ b/handlers_drive.go @@ -354,6 +354,16 @@ func getOauthClient(args cli.Arguments) (*http.Client, error) { } configDir := getConfigDir(args) + + if args.String("serviceAccount") != "" { + serviceAccountPath := ConfigFilePath(configDir, args.String("serviceAccount")) + serviceAccountClient, err := auth.NewServiceAccountClient(serviceAccountPath) + if err != nil { + return nil, err + } + return serviceAccountClient, nil + } + tokenPath := ConfigFilePath(configDir, TokenFilename) return auth.NewFileSourceClient(ClientId, ClientSecret, tokenPath, authCodePrompt) }