diff --git a/backend/drive/drive.go b/backend/drive/drive.go index c5f05357c..5f733f9e3 100644 --- a/backend/drive/drive.go +++ b/backend/drive/drive.go @@ -446,12 +446,8 @@ func newPacer() *pacer.Pacer { return pacer.New().SetMinSleep(minSleep).SetPacer(pacer.GoogleDrivePacer) } -func getServiceAccountClient(keyJsonfilePath string) (*http.Client, error) { - data, err := ioutil.ReadFile(os.ExpandEnv(keyJsonfilePath)) - if err != nil { - return nil, errors.Wrap(err, "error opening credentials file") - } - conf, err := google.JWTConfigFromJSON(data, driveConfig.Scopes...) +func getServiceAccountClient(credentialsData []byte) (*http.Client, error) { + conf, err := google.JWTConfigFromJSON(credentialsData, driveConfig.Scopes...) if err != nil { return nil, errors.Wrap(err, "error processing credentials") } @@ -466,9 +462,18 @@ func createOAuthClient(name string) (*http.Client, error) { var oAuthClient *http.Client var err error - serviceAccountPath := config.FileGet(name, "service_account_file") - if serviceAccountPath != "" { - oAuthClient, err = getServiceAccountClient(serviceAccountPath) + // try loading service account credentials from env variable, then from a file + serviceAccountCreds := []byte(config.FileGet(name, "service_account_credentials")) + if len(serviceAccountCreds) == 0 { + serviceAccountPath := config.FileGet(name, "service_account_file") + loadedCreds, err := ioutil.ReadFile(os.ExpandEnv(serviceAccountPath)) + if err != nil { + return nil, errors.Wrap(err, "error opening service account credentials file") + } + serviceAccountCreds = loadedCreds + } + if len(serviceAccountCreds) > 0 { + oAuthClient, err = getServiceAccountClient(serviceAccountCreds) if err != nil { return nil, errors.Wrap(err, "failed to create oauth client from service account") } diff --git a/backend/googlecloudstorage/googlecloudstorage.go b/backend/googlecloudstorage/googlecloudstorage.go index 8358a37d5..0b77eb68b 100644 --- a/backend/googlecloudstorage/googlecloudstorage.go +++ b/backend/googlecloudstorage/googlecloudstorage.go @@ -277,12 +277,8 @@ func parsePath(path string) (bucket, directory string, err error) { return } -func getServiceAccountClient(keyJsonfilePath string) (*http.Client, error) { - data, err := ioutil.ReadFile(os.ExpandEnv(keyJsonfilePath)) - if err != nil { - return nil, errors.Wrap(err, "error opening credentials file") - } - conf, err := google.JWTConfigFromJSON(data, storageConfig.Scopes...) +func getServiceAccountClient(credentialsData []byte) (*http.Client, error) { + conf, err := google.JWTConfigFromJSON(credentialsData, storageConfig.Scopes...) if err != nil { return nil, errors.Wrap(err, "error processing credentials") } @@ -295,16 +291,25 @@ func NewFs(name, root string) (fs.Fs, error) { var oAuthClient *http.Client var err error - serviceAccountPath := config.FileGet(name, "service_account_file") - if serviceAccountPath != "" { - oAuthClient, err = getServiceAccountClient(serviceAccountPath) + // try loading service account credentials from env variable, then from a file + serviceAccountCreds := []byte(config.FileGet(name, "service_account_credentials")) + if len(serviceAccountCreds) == 0 { + serviceAccountPath := config.FileGet(name, "service_account_file") + loadedCreds, err := ioutil.ReadFile(os.ExpandEnv(serviceAccountPath)) if err != nil { - log.Fatalf("Failed configuring Google Cloud Storage Service Account: %v", err) + return nil, errors.Wrap(err, "error opening service account credentials file") + } + serviceAccountCreds = loadedCreds + } + if len(serviceAccountCreds) > 0 { + oAuthClient, err = getServiceAccountClient(serviceAccountCreds) + if err != nil { + return nil, errors.Wrap(err, "failed configuring Google Cloud Storage Service Account") } } else { oAuthClient, _, err = oauthutil.NewClient(name, storageConfig) if err != nil { - log.Fatalf("Failed to configure Google Cloud Storage: %v", err) + return nil, errors.Wrap(err, "failed to configure Google Cloud Storage") } } diff --git a/docs/content/drive.md b/docs/content/drive.md index 00a751f29..beda94534 100644 --- a/docs/content/drive.md +++ b/docs/content/drive.md @@ -202,7 +202,10 @@ actively logged-in users, for example build machines. To use a Service Account instead of OAuth2 token flow, enter the path to your Service Account credentials at the `service_account_file` prompt during `rclone config` and rclone won't use the browser based -authentication flow. +authentication flow. If you'd rather stuff the contents of the +credentials file into the rclone config file, you can set +`service_account_credentials` with the actual contents of the file +instead, or set the equivalent environment variable. #### Use case - Google Apps/G-suite account and individual Drive #### diff --git a/docs/content/googlecloudstorage.md b/docs/content/googlecloudstorage.md index 5ed930aba..920e997fd 100644 --- a/docs/content/googlecloudstorage.md +++ b/docs/content/googlecloudstorage.md @@ -212,7 +212,10 @@ are what rclone will use for authentication. To use a Service Account instead of OAuth2 token flow, enter the path to your Service Account credentials at the `service_account_file` prompt and rclone won't use the browser based authentication -flow. +flow. If you'd rather stuff the contents of the credentials file into +the rclone config file, you can set `service_account_credentials` with +the actual contents of the file instead, or set the equivalent +environment variable. ### --fast-list ###