1
votes

I have a Google account as a student. This account is managed by my university and recently the university informed us that students' accounts have now "unlimited" storage for Drive etc.

To perform backups with this, I created a few service accounts in Google APIs console ([email protected]). But it turns out that those accounts' storage is limited to 15GB, that is, when trying to upload files to one of service accounts that already has ~15GB in it, I get an error "the client is exceeded his storage quota".

I asked the university admins, they don't know how to help and even don't see the service account' email ([email protected]) in the list of managed accounts.

So the question is what should be done (by me or by university admins) to remove (or increase) the storage quota of my service accounts when those were open with the "unlimited" student account.

Update: trying @DaImTo suggestion:

So I created a folder in my Drive web interface and shared it with my service account. Then, with service account, I uploaded a file to that folder (using PyDrive library):

file1 = drive.CreateFile({'title': 'test2', 'parents': [{"kind": "drive#fileLink", "id": shared_folder_id}]})
file1.SetContentString('some text')
file1.Upload()
print 'File ID: %s' % file1['id']
permissions = file1.auth.service.permissions().list(fileId=file1['id']).execute()
print "permissions:", permissions

Output:

File ID: XXX
permissions: {u'items': [{u'kind': u'drive#permission', u'name': u'[email protected]', u'domain': u'developer.gserviceaccount.com', u'etag': u'"XXX"', u'emailAddress': u'[email protected]', u'role': u'owner', u'type': u'user', u'id': u'XXX', u'selfLink': u'https://www.googleapis.com/drive/v2/files/XXX/permissions/XXX'},
{u'kind': u'drive#permission', u'name': u'<my name>', u'domain': u'<my school domain>', u'etag': u'"XXX"', u'emailAddress': u'<my name>@<my school domain>', u'role': u'writer', u'type': u'user', u'id': u'XXX', u'selfLink': u'https://www.googleapis.com/drive/v2/files/XXX/permissions/XXX'}], u'kind': u'drive#permissionList', u'etag': u'"XXX"', u'selfLink': u'https://www.googleapis.com/drive/v2/files/XXX/permissions?alt=json'}

So the uploaded file automatically has two permissions: 1. Service account is "owner" 2. My main account is "writer"

Indeed, I can see the file in web interface, edit it , delete etc. But, since the service account is the owner, the file is accounted in service account storage quota, so this doesn't solve my problem, i.e. I still cannot use more than 15GB with my backup application.

I tried to transfer the ownership to my main account:

file1 = drive.CreateFile({'id': file_id})
permissions = file1.auth.service.permissions().list(fileId=file1['id']).execute()
myperm_id = permissions['items'][1]['id'] # this is the second permission, i.e. of my main account
myperm = file1.auth.service.permissions().get(fileId=file1['id'], permissionId=myperm_id).execute()
myperm['role'] = 'owner'
file1.auth.service.permissions().update(fileId=file1['id'], permissionId=myperm['id'], body=myperm).execute()

...and got an error:

googleapiclient.errors.HttpError: <HttpError 403 when requesting https://www.googleapis.com/drive/v2/files/XXX/permissions/XXX?alt=json returned "Insufficient permissions for this file">

I tried to append transferOwnership='True':

file1.auth.service.permissions().update(fileId=file1['id'], permissionId=myperm['id'], body=myperm, transferOwnership='True').execute()

got the same error. I'm stuck here.

Btw, in Google help Transfer file ownership they say "If you're a Google Apps user, you can't transfer ownership to someone else who is outside of your domain."

2

2 Answers

0
votes

A service account is not you. Think of a service account as a dummy Google user, it has its own Google drive account, Google calendar account ...

It is probably loosely related to the developers who have access to it in the Google developer console, if the application using the service account starts to spam Google drive the developer console account will be shut down. But beyond that you and any service accounts you create are separate entity's. It doesn't have access to your unlimited drive account until you give it access to your unlimited drive account. (wish I had an unlimited drive account)

Now it is an entity, but I am not all that sure the school could give it access. Really I am not sure I would want to it would remove one part of the control of the service account from me. Some school admin could just remove it one day and break everything .....

What I suggest you do is this, give the service account access to your Google account. Open Google drive the web version. I suggest you create a new directory. In the sharing permissions take the service accounts email address and give it full access to that directory. It should then be able to upload to the directory of your amazing unlimited drive account.

Update Just thought of something: You are probably going to have to check what directories it has access to once you give it access to your drive directory. You will need to be sure it uploads to the drive you shared and not its root directory.

update Permissions:

You are probably using file.insert to upload the file. that is just the first step.

Once you have the file uploaded you will need to patch it, and change the permissions grating you as in you personally not the service account access to the file. When the file is uploaded its still OWNED by the service account.

You will need to use Files: patch to update the permissions on the file and granting you as in you not the service account access to the file.

Unfortunately its not possible (at this time) to set the permissions of the file when its uploaded. I am not sure if this is a bug or its just not supported i created an issue request on this a few days ago. Issue 3717: Google drive api, upload file with shared permission

0
votes

It seems that it's impossible to transfer the ownership of the files uploaded by service account to the main account.

Finally I abandoned the service account approach and followed this approach to run my app as my regular user.

Once the steps described there were accomplished, I create the drive service like that:

import httplib2
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive

gauth = GoogleAuth()
gauth.LoadCredentialsFile("GoogleDriveCredentials.txt")
if gauth.credentials is None:
    gauth.LocalWebserverAuth()
elif gauth.access_token_expired:
    print "Google Drive Token Expired, Refreshing"
    gauth.Refresh()
else:
    gauth.Authorize()
gauth.SaveCredentialsFile("GoogleDriveCredentials.txt")
drive = GoogleDrive(gauth) 

Where GoogleDriveCredentials.txt is of the form:

{"_module": "oauth2client.client", "token_expiry": "XXX", "access_token": "XXX", "token_uri": "https://accounts.google.com/o/oauth2/token", "invalid": false, "token_response": {"access_token": "XXX", "token_type": "Bearer", "expires_in": 3600}, "client_id": "XXX.apps.googleusercontent.com", "id_token": null, "client_secret": "XXX", "revoke_uri": "https://accounts.google.com/o/oauth2/revoke", "_class": "OAuth2Credentials", "refresh_token": "XXX", "user_agent": null}

Now the uploaded files' owner is "me" in web interface and they are accounted in my main account's storage quota, so my goal is reached.