skip to Main Content

I am using CircleCI,my credentilas are decoded at this step

echo 'export SERVICE_ACCOUNT_DECODED="$(echo $SERVICE_ACCOUNT | base64 -di)"' >> $BASH_ENV

Later I am using Python code

service_account_file = json.dumps(os.environ['SERVICE_ACCOUNT_DECODED'])
    # Authenticate using the service account for Google Drive
credentials = service_account.Credentials.from_service_account_file(service_account_file, scopes=SCOPES)

My goal is that service_account_file is JSON.

but got error

  File "final_script.py", line 28, in <module>
    credentials = service_account.Credentials.from_service_account_file(service_account_file, scopes=SCOPES)
  File "/home/circleci/.pyenv/versions/3.8.20/lib/python3.8/site-packages/google/oauth2/service_account.py", line 260, in from_service_account_file
    info, signer = _service_account_info.from_filename(
  File "/home/circleci/.pyenv/versions/3.8.20/lib/python3.8/site-packages/google/auth/_service_account_info.py", line 78, in from_filename
    with io.open(filename, "r", encoding="utf-8") as json_file:
OSError: [Errno 36] File name too long: '"{\n

I tried json.loads before but it did not work also.

How to fix this?

2

Answers


  1. You are trying to pass a JSON string containing the credentials to a function which expects the filename of a JSON file containing the credentials.

    From the documentation, we can see in the second example provided that there also is another function for creating a Credentials object which is suitable for your case:

    Or if you already have the service account file loaded:

    service_account_info = json.load(open('service_account.json'))
    credentials = service_account.Credentials.from_service_account_info(
        service_account_info)
    

    The SERVICE_ACCOUNT_DECODED already is a JSON string. You should not be using json.dumps on it again (which is used to convert Python objects to JSON, so you would get a JSON string containing another JSON string).

    Instead, use json.loads to unpack the contents from the string, which correspond to service_account_info above:

    service_account_info = json.loads(os.environ['SERVICE_ACCOUNT_DECODED'])
    credentials = service_account.Credentials.from_service_account_info(
        service_account_info, scopes=SCOPES
    )
    
    Login or Signup to reply.
  2. Assuming SERVICE_ACCOUNT_DECODED contains the JSON content then you have to create a temporary file with this content.

    import tempfile
    
    with tempfile.NamedTemporaryFile('w+') as f:
        f.write(os.environ['SERVICE_ACCOUNT_DECODED'])
        f.flush()  # clears the internal buffer of the file
        credentials = service_account.Credentials.from_service_account_file(f.name, scopes=SCOPES)
    

    Hope it works but I recommend you do not store sensitive information like service account credentials directly in environment variables for security reasons.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search