Skip to content

Commit

Permalink
Allowing service accounts to become admins in appengine (#4326)
Browse files Browse the repository at this point in the history
### Motivation

Sync admins only replicates admins to datastore if they conform to
'user:{email}', but it is interesting to allow service accounts for
monitoring purposes (uptime) of the form 'serviceAccount:{email}'.

This PR fixes that.

Part of #4271
  • Loading branch information
vitorguidi authored Oct 15, 2024
1 parent fdd0c7d commit 1b79928
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 12 deletions.
38 changes: 28 additions & 10 deletions src/clusterfuzz/_internal/cron/sync_admins.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
# limitations under the License.
"""Cron to sync admin users."""

from typing import List

from googleapiclient import discovery

from clusterfuzz._internal.base import utils
Expand All @@ -21,30 +23,46 @@
from clusterfuzz._internal.metrics import logs


def get_emails_from_bindings(iam_policy, principal_type,
allowed_roles) -> List[str]:
"""Returns emails that should be admins, given constraints."""
admins = []

assert principal_type in ['user', 'serviceAccount']

for binding in iam_policy['bindings']:
if binding['role'] not in allowed_roles:
continue

for member in binding['members']:
user_type, email = member.split(':', 2)
if user_type == principal_type:
admins.append(email)

return admins


def admins_from_iam_policy(iam_policy):
"""Gets a list of admins from the IAM policy."""
# Per
# https://cloud.google.com/appengine/docs/standard/python/users/adminusers, An
# administrator is a user who has the Viewer, Editor, or Owner primitive role,
# or the App Engine App Admin predefined role
roles = [
user_roles = [
'roles/editor',
'roles/owner',
'roles/viewer',
'roles/appengine.appAdmin',
]

admins = []
for binding in iam_policy['bindings']:
if binding['role'] not in roles:
continue
service_account_roles = ['roles/viewer']

for member in binding['members']:
user_type, email = member.split(':', 2)
if user_type == 'user':
admins.append(email)
user_admins = get_emails_from_bindings(iam_policy, 'user', user_roles)
service_account_admins = get_emails_from_bindings(
iam_policy, 'serviceAccount', service_account_roles)

return admins
user_admins.extend(service_account_admins)
return user_admins


def update_admins(new_admins):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,12 @@ def setUp(self):
'members': ['user:[email protected]',]
},
{
'role': 'roles/viewer',
'members': ['user:[email protected]',]
'role':
'roles/viewer',
'members': [
'user:[email protected]',
'serviceAccount:[email protected]'
]
},
]
}
Expand All @@ -87,4 +91,5 @@ def test_sync_admins(self):
'[email protected]',
'[email protected]',
'[email protected]',
'[email protected]',
], [admin.email for admin in admins])

0 comments on commit 1b79928

Please sign in to comment.