无法使用服务账号通过Google Admin SDK目录API访问用户数据

0 投票
2 回答
30 浏览
提问于 2025-04-12 22:07

我在使用Google Admin SDK目录API通过服务账户访问用户数据时遇到了问题。下面是我的情况:

我有一个Python脚本,它利用Google Admin SDK目录API来获取用户数据。我使用服务账户来验证API请求。我按照Google文档中的步骤设置了域范围的委托,并且已经给服务账户授予了必要的权限,包括“用户管理管理员”角色。

当我尝试获取非管理员用户的数据时,收到了一个403错误,提示“没有权限访问此资源/api”。以下是我Python脚本的简化版本:

from google.oauth2 import service_account
from googleapiclient.discovery import build

# Replace 'path/to/your/service-account-key.json' with the path to your service account key file
SERVICE_ACCOUNT_KEY_FILE = 'path/to/your/service-account-key.json'
# Replace 'user@example.com' with the email address you want to check
USER_EMAIL_TO_CHECK = 'user@example.com'

# Load service account credentials
credentials = service_account.Credentials.from_service_account_file(
    SERVICE_ACCOUNT_KEY_FILE,
    scopes=['https://www.googleapis.com/auth/admin.directory.user.readonly'],
)

# Impersonate the user
credentials = credentials.with_subject(USER_EMAIL_TO_CHECK)
# Build the Admin SDK Directory API client
directory_service = build('admin', 'directory_v1', credentials=credentials)

try:
    # Retrieve user information
    user = directory_service.users().get(userKey=USER_EMAIL_TO_CHECK).execute()
    print(user)
    # If the user exists, print their information
    print(f'User exists in Active Directory: {user["primaryEmail"]}')
except Exception as e:
    # If an exception occurs, the user does not exist
    print(f'User does not exist in Active Directory: {USER_EMAIL_TO_CHECK}')
    print(f'Error: {e}')

我已经确认服务账户正确设置了域范围的委托,并且拥有必要的权限。我也确保我尝试模拟的用户在活动目录中是存在的。

有没有人能告诉我,为什么在使用Google Admin SDK目录API通过服务账户访问非管理员用户数据时会收到403错误,尽管我已经设置了域范围的委托并授予了必要的权限?另外,我可以获取管理员邮箱的详细信息,但对于我工作区中的其他邮箱却收到403错误。

2 个回答

1
# Impersonate the user
credentials = credentials.with_subject(USER_WITH_ADMIN_ROLE)

只有拥有管理员角色或者被授权的管理员角色的用户才能查看其他用户的信息。

1

在谷歌工作区中,你需要把权限委托给域内的某个用户。这是通过使用 create_delegated 来实现的。

def build_service_service_account_workspace(credentials, scope, delegated_user):
    credentials = ServiceAccountCredentials.from_json_keyfile_name(
        credentials,
        scopes=scope,
    )
    credentials = credentials.create_delegated(delegated_user)
    try:
        return build('drive', 'v3', credentials=credentials)
    except HttpError as error:
        # TODO(developer) - any errors returned.
        print(f'An error occurred: {error}')

记住,服务账户只能拥有被委托用户的权限。如果这个用户没有某项操作的权限,那么服务账户也无法执行这项操作。所以听起来你应该把权限委托给一个管理员用户。

撰写回答