Repository: iterative/dvc

Issue:
unable to sign url when adding files from Google Storage on Compute Engine
## Bug Report

### Please provide information about your setup

- debian 10 on google compute engine

**Output of `dvc version`:**

```console
DVC version: 0.94.0
Python version: 3.7.3
Platform: Linux-4.19.0-9-cloud-amd64-x86_64-with-debian-10.4
Binary: False
Package: pip
Supported remotes: gs, http, https

```

**Additional Information (if any):**
```
unexpected error - you need a private key to sign credentials.the credentials 
you are currently using <class 'google.auth.compute_engine.credentials.Credentials'> 
just contains a token. see https://google-cloud-python.readthedocs.io/en/latest/core/auth.html?highlight=authentication#setting-up-a-service-account for more details.
```



Discussion:
Related to this: https://github.com/googleapis/google-auth-library-python/issues/50
Was able to fix this by adding signing credentials to `GSRemote._generate_download_url` following this https://gist.github.com/jezhumble/91051485db4462add82045ef9ac2a0ec:

```
    def _generate_download_url(self, path_info, expires=3600):
        import google.auth
        from google.auth import compute_engine

        expiration = timedelta(seconds=int(expires))

        bucket = self.gs.bucket(path_info.bucket)
        blob = bucket.get_blob(path_info.path)
        if blob is None:
            raise FileNotFoundError
        if isinstance(blob.client._credentials, google.auth.credentials.Signing):
            # sign if we're able to sign with the credentials
            return blob.generate_signed_url(expiration=expiration)

        else:
            auth_request = google.auth.transport.requests.Request()
            # create signing credentials with the default credentials
            # for use with Compute Engine and other environments where
            # Client credentials cannot sign.
            signing_credentials = compute_engine.IDTokenCredentials(auth_request, "") 
            return signing_credentials.signer.sign(blob)
```

Resolving patch:
diff --git a/dvc/remote/gs.py b/dvc/remote/gs.py
--- a/dvc/remote/gs.py
+++ b/dvc/remote/gs.py
@@ -91,13 +91,30 @@ def gs(self):
         )
 
     def _generate_download_url(self, path_info, expires=3600):
+        import google.auth
+        from google.auth import compute_engine
+
         expiration = timedelta(seconds=int(expires))
 
         bucket = self.gs.bucket(path_info.bucket)
         blob = bucket.get_blob(path_info.path)
         if blob is None:
             raise FileNotFoundError
-        return blob.generate_signed_url(expiration=expiration)
+
+        if isinstance(
+            blob.client._credentials, google.auth.credentials.Signing
+        ):
+            # sign if we're able to sign with credentials.
+            return blob.generate_signed_url(expiration=expiration)
+
+        auth_request = google.auth.transport.requests.Request()
+        # create signing credentials with the default credentials
+        # for use with Compute Engine and other environments where
+        # Client credentials cannot sign.
+        signing_credentials = compute_engine.IDTokenCredentials(
+            auth_request, ""
+        )
+        return signing_credentials.signer.sign(blob)
 
     def exists(self, path_info):
         """Check if the blob exists. If it does not exist,


Test patch: