[GH-ISSUE #1391] creating signed url's give with sdk gives AttributeError: you need a private key to sign credentials.the credentials you are currently using <class 'google.auth.credentials.AnonymousCredentials'> just contains a token. #196

Open
opened 2026-03-03 12:09:04 +03:00 by kerem · 4 comments
Owner

Originally created by @jommpy on GitHub (Nov 7, 2023).
Original GitHub issue: https://github.com/fsouza/fake-gcs-server/issues/1391

I'm using this snippet to create a pre-signed download url

                    data_object.metadata_url = metadata_object_blob.generate_signed_url(
                        version="v4",
                        expiration=datetime.timedelta(
                            minutes=self.PRESIGNED_URL_TIME_EXPIRATION
                        ),
                        method="GET",
                    )

Because this is in a test environment I'm not setting the GOOGLE_APPLICATION_CREDENTIALS because it needs to use the fake-gcs-container.
Any workarounds for this error ? help would be much appriciated.

Originally created by @jommpy on GitHub (Nov 7, 2023). Original GitHub issue: https://github.com/fsouza/fake-gcs-server/issues/1391 I'm using this snippet to create a pre-signed download url ``` data_object.metadata_url = metadata_object_blob.generate_signed_url( version="v4", expiration=datetime.timedelta( minutes=self.PRESIGNED_URL_TIME_EXPIRATION ), method="GET", ) ``` Because this is in a test environment I'm not setting the GOOGLE_APPLICATION_CREDENTIALS because it needs to use the fake-gcs-container. Any workarounds for this error ? help would be much appriciated.
Author
Owner

@fsouza commented on GitHub (Nov 7, 2023):

Signed URLs are a client-side operation, they don't involve neither the real or the fake server. You need to use fake credentials to sign the URL.

When you do send a request to the signed URL, fake-gcs-server will take any signed URL and trust that it's valid.

<!-- gh-comment-id:1798878306 --> @fsouza commented on GitHub (Nov 7, 2023): Signed URLs are a client-side operation, they don't involve neither the real or the fake server. You need to use fake credentials to sign the URL. When you do send a request to the signed URL, fake-gcs-server will take any signed URL and trust that it's valid.
Author
Owner

@ghost commented on GitHub (Jan 9, 2024):

@fsouza I am getting this error when trying to generate signed URLs using the GCS Go CDK:

storage: unable to detect default GoogleAccessID: no credentials found on client and not on GCE (Google Compute Engine). Please provide the GoogleAccessID or use a supported means for autodetecting it (see https://pkg.go.dev/cloud.google.com/go/storage#hdr-Credential_requirements_for_[BucketHandle.SignedURL]_and_[BucketHandle.GenerateSignedPostPolicyV4])

Which I believe is the same root cause as the original on this issue. Can you provide an example or some docs about how to create the fake/mock credentials?

Thank you

<!-- gh-comment-id:1883603736 --> @ghost commented on GitHub (Jan 9, 2024): @fsouza I am getting this error when trying to generate signed URLs using the GCS Go CDK: ``` storage: unable to detect default GoogleAccessID: no credentials found on client and not on GCE (Google Compute Engine). Please provide the GoogleAccessID or use a supported means for autodetecting it (see https://pkg.go.dev/cloud.google.com/go/storage#hdr-Credential_requirements_for_[BucketHandle.SignedURL]_and_[BucketHandle.GenerateSignedPostPolicyV4]) ``` Which I believe is the same root cause as the original on this issue. Can you provide an example or some docs about how to create the fake/mock credentials? Thank you
Author
Owner

@wlinna commented on GitHub (Jan 10, 2024):

Signed URLs are a client-side operation, they don't involve neither the real or the fake server. You need to use fake
credentials to sign the URL.

It seems that by default it is the real server that signs the url. The following code is from the node library

    async sign(data) {
        const client = await this.getClient();
        const crypto = (0, crypto_1.createCrypto)();
        if (client instanceof jwtclient_1.JWT && client.key) {
            const sign = await crypto.sign(client.key, data);
            return sign;
        }
        const creds = await this.getCredentials();
        if (!creds.client_email) {
            throw new Error('Cannot sign data without `client_email`.');
        }
        return this.signBlob(crypto, creds.client_email, data);
    }
    async signBlob(crypto, emailOrUniqueId, data) {
        const url = 'https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/' +
            `${emailOrUniqueId}:signBlob`;
        const res = await this.request({
            method: 'POST',
            url,
            data: {
                payload: crypto.encodeBase64StringUtf8(data),
            },
        });
        return res.data.signedBlob;
    }

So it seems like one should be able to make Storage client use a JWT client internally. I haven't figured that part yet though.

<!-- gh-comment-id:1884810133 --> @wlinna commented on GitHub (Jan 10, 2024): > Signed URLs are a client-side operation, they don't involve neither the real or the fake server. You need to use fake > credentials to sign the URL. It seems that by default it is the real server that signs the url. The following code is from the node library ``` async sign(data) { const client = await this.getClient(); const crypto = (0, crypto_1.createCrypto)(); if (client instanceof jwtclient_1.JWT && client.key) { const sign = await crypto.sign(client.key, data); return sign; } const creds = await this.getCredentials(); if (!creds.client_email) { throw new Error('Cannot sign data without `client_email`.'); } return this.signBlob(crypto, creds.client_email, data); } async signBlob(crypto, emailOrUniqueId, data) { const url = 'https://iamcredentials.googleapis.com/v1/projects/-/serviceAccounts/' + `${emailOrUniqueId}:signBlob`; const res = await this.request({ method: 'POST', url, data: { payload: crypto.encodeBase64StringUtf8(data), }, }); return res.data.signedBlob; } ``` So it seems like one should be able to make Storage client use a JWT client internally. I haven't figured that part yet though.
Author
Owner

@ghost commented on GitHub (Jan 10, 2024):

@fsouza I am getting this error when trying to generate signed URLs using the GCS Go CDK:

storage: unable to detect default GoogleAccessID: no credentials found on client and not on GCE (Google Compute Engine). Please provide the GoogleAccessID or use a supported means for autodetecting it (see https://pkg.go.dev/cloud.google.com/go/storage#hdr-Credential_requirements_for_[BucketHandle.SignedURL]_and_[BucketHandle.GenerateSignedPostPolicyV4])

Which I believe is the same root cause as the original on this issue. Can you provide an example or some docs about how to create the fake/mock credentials?

Thank you

I was able to do this by assigning dummy values to GoogleAccessID and PrivateKey in the storage.SignedURLOptions passed to the SignedURL function. I was hoping to find a way to have the client auto-load these values like it does when accessing real GCS, but it looks like the use of STORAGE_EMULATOR_HOST may be mutually exclusive with GOOGLE_APPLICATION_CREDENTIALS

<!-- gh-comment-id:1885927226 --> @ghost commented on GitHub (Jan 10, 2024): > @fsouza I am getting this error when trying to generate signed URLs using the GCS Go CDK: > > ``` > storage: unable to detect default GoogleAccessID: no credentials found on client and not on GCE (Google Compute Engine). Please provide the GoogleAccessID or use a supported means for autodetecting it (see https://pkg.go.dev/cloud.google.com/go/storage#hdr-Credential_requirements_for_[BucketHandle.SignedURL]_and_[BucketHandle.GenerateSignedPostPolicyV4]) > ``` > > Which I believe is the same root cause as the original on this issue. Can you provide an example or some docs about how to create the fake/mock credentials? > > Thank you I was able to do this by assigning dummy values to `GoogleAccessID` and `PrivateKey` in the `storage.SignedURLOptions` passed to the `SignedURL` function. I was hoping to find a way to have the client auto-load these values like it does when accessing real GCS, but it looks like the use of `STORAGE_EMULATOR_HOST` may be mutually exclusive with `GOOGLE_APPLICATION_CREDENTIALS`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/fake-gcs-server#196
No description provided.