googleapis / python-storage

Apache License 2.0
439 stars 151 forks source link

generate_signed_post_policy_v4() should not call ensure_signed_credentials() when `service_account_email` and `access_token` are specified #1351

Open jasonkit opened 2 days ago

jasonkit commented 2 days ago

I am calling generate_signed_post_policy_v4() on pod running on GKE using Application default credentials to avoid using service account key.

In latest code, even though generate_signed_post_policy_v4() support passing in service_account_email and access_token and use them to generate signature, it still unconditional call ensure_signed_credentials() https://github.com/googleapis/python-storage/blob/02a972d35fae6d05edfb26381f6a71e3b8f59d6d/google/cloud/storage/client.py#L1726-L1727

If we are Application default credentials and getting the credential from GKE metadata server, it will not pass the ensure_signed_credentials() checking and returning AttributeError: 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://googleapis.dev/python/google-api-core/latest/auth.html#setting-up-a-service-account for more details.


generate_signed_post_policy_v4() should have similar handling as in generate_signed_url_v4()

https://github.com/googleapis/python-storage/blob/e3cfc4786209c77e3c879c9ff2978f4884a0d677/google/cloud/storage/_signing.py#L541-L547

My current workaround is to implement class an pass it to generate_signed_post_policy_v4() as credentials to by-pass the checking of ensure_signed_credentials()

from google.auth.credentials import Signing

class _SigningCredential(Signing):
    def __init__(self, service_account_email: str):
        self._signer_email = service_account_email

    @property
    def signer_email(self):
        return self._signer_email

    @property
    def signer(self):
        raise NotImplementedError('Not in use')

    def sign_bytes(self, message):
        raise NotImplementedError('Not in use')

Environment details