使用 rclone 在 Microsoft 365 中以全局管理员身份访问任意用户 OneDrive

在 Microsoft 365 企业环境中,为实现审计、留存或数据导出等功能,可能需要以自动化或编程方式访问所有用户的 OneDrive。

本文以 rclone 工具为例,介绍一种通过注册 OAuth 应用来实现这一目的的方法。

创建专用 OAuth 应用

为实现权限隔离,建议创建专用于访问任意用户 OneDrive 的内部 OAuth 应用;不要与普通用户可用的 OAuth 应用混用。

使用具有 Global Administrator(全局管理员)权限的 Microsoft 365 管理员账号,在 Microsoft Entra ID 的应用注册页面,创建新的 OAuth 应用。

  • 在「受支持的帐户类型」中,选择「仅单个租户」。
  • 在「重定向 URI」中,选择平台为「Web」,重定向 URI 为 http://localhost:53682/。这是 rclone 的默认值,若您使用其他自动化方案,需根据其文档调整重定向 URI 的值。

创建应用后,在其管理界面中记录下面的值,以备之后的使用:

  • 应用程序(客户端)ID:一个 UUID 形式的值
  • 目录(租户)ID:一个 UUID 形式的值

在管理界面的右侧导航栏中,点击「管理」——「证书与密码」,选择「客户端密码」选项卡,创建一个新的客户端密码。记录生成的客户端密码的值。

注意

客户端密码的值仅会显示一次。网页被刷新或进入其他页面后,将无法再找回。请妥善记录。

建议以保存管理员密码相同或更高的安全强度保存客户端密码。获得这个值的人将可以访问您租户中的任意文件。

在管理界面的右侧导航栏中,点击「管理」——「API 权限」,在弹出的窗口中选择「常用 Microsoft API」选项卡,添加下列 API 权限:

  • 「Microsoft Graph」——「委托的权限」:offline_accessUser.Read。这些权限是 rclone 要求的必要权限。
  • 「Microsoft Graph」——「应用程序权限」:Files.Read.AllFiles.ReadWrite.AllSites.Read.AllSites.ReadWrite.AllUser.Read.All。这些权限将允许此应用读写租户内任意用户的文件。

添加完成后,请点击「代表 您的租户名称 授予管理员同意」。

获取目标用户的 Drive ID

首先将获取到的 OAuth 应用相关参数定义为环境变量:

1
2
3
MS365_TENANT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
MS365_CLIENT_ID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
MS365_CLIENT_SECRET=xxxxxxxxx

获取 Access Token。获取到的 Access Token 应为 eyJ... 开头的 JWT 格式:

1
2
3
4
5
6
7
8
9
10
11
MS365_TOKEN="$(
curl -fsS -D /dev/stderr \
-X POST \
"https://login.microsoftonline.com/${MS365_TENANT_ID}/oauth2/v2.0/token" \
-H 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode "client_id=${MS365_CLIENT_ID}" \
--data-urlencode "client_secret=${MS365_CLIENT_SECRET}" \
--data-urlencode 'scope=https://graph.microsoft.com/.default' \
--data-urlencode 'grant_type=client_credentials' \
| jq -er '.access_token'
)"

查询租户内的用户列表:

1
2
3
4
5
tmpfile=$(mktemp)
curl -fsS -D /dev/stderr \
-H "Authorization: Bearer ${MS365_TOKEN}" \
'https://graph.microsoft.com/v1.0/users?$select=id,displayName,userPrincipalName&$top=999' \
| jq | tee $tmpfile

打印用户列表:

1
2
3
4
{
printf 'ID\tDisplayName\tUPN\n'
jq -r '.value[] | [.id, .displayName, .userPrincipalName] | @tsv' "$tmpfile"
} | column -t -s $'\t'

最后,获取每个用户对应的 Drive ID:

1
2
3
4
5
6
7
8
9
10
jq -r '.value[].userPrincipalName' "$tmpfile" |
while IFS= read -r upn; do
printf '> UPN: %s\n' "$upn" >&2
curl -fsS -D /dev/stderr \
-H "Authorization: Bearer ${MS365_TOKEN}" \
"https://graph.microsoft.com/v1.0/users/${upn}/drives?\$select=id,name,driveType,webUrl" |
jq -r --arg upn "$upn" \
'.value[] | [$upn, .id, .name, .driveType, .webUrl] | @tsv'
done |
column -t -s $'\t'

其中,第二列的字段即为 Drive ID,它通常是 b!XXXX 开头的字符串。

接入 Rclone

获取 Drive ID 后,使用 rclone config 将目标用户的 OneDrive 添加到 rclone 配置中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
e) Edit existing remote
n) New remote
d) Delete remote
r) Rename remote
c) Copy remote
s) Set configuration password
q) Quit config
e/n/d/r/c/s/q> n
name> *****此处输入您给此配置起的名字

Type of storage to configure.
Enter a string value. Press Enter for the default ("").
Choose a number from below, or type in your own value
XX / Microsoft OneDrive
\ "onedrive"
Storage> onedrive

Microsoft App Client Id
Leave blank normally.
Enter a string value. Press Enter for the default ("").
client_id> *****此处输入该应用的 Client ID
Microsoft App Client Secret
Leave blank normally.
Enter a string value. Press Enter for the default ("").
client_secret> *****此处输入该应用的 Client Secret

Option region.
Choose national cloud region for OneDrive.
Choose a number from below, or type in your own value of type string.
Press Enter for the default (global).
1 / Microsoft Cloud Global
\ (global)
2 / Microsoft Cloud for US Government
\ (us)
3 / Microsoft Cloud Germany (deprecated - try global region first).
\ (de)
4 / Azure and Office 365 operated by Vnet Group in China
\ (cn)
region>

Option tenant.
ID of the service principal's tenant. Also called its directory ID.
Set this if using
- Client Credential flow
Enter a value of type string. Press Enter for the default ("").
tenant> *****此处输入该应用的租户 ID

Edit advanced config? (y/n)
y) Yes
n) No
y/n> n

Remote config
Use web browser to automatically authenticate rclone with remote?
* Say Y if the machine running rclone has a web browser you can use
* Say N if running rclone on a (remote) machine without web browser access
If not sure try Y. If Y failed, try N.
y) Yes
n) No
y/n> y
Got code.

Option config_type.
Type of connection
Choose a number from below, or type in an existing value of type string.
Press Enter for the default (onedrive).
1 / OneDrive Personal or Business
\ (onedrive)
2 / Root Sharepoint site
\ (sharepoint)
/ Sharepoint site name or URL
3 | E.g. mysite or https://contoso.sharepoint.com/sites/mysite
\ (url)
4 / Search for a Sharepoint site
\ (search)
5 / Type in driveID (advanced)
\ (driveid)
6 / Type in SiteID (advanced)
\ (siteid)
/ Sharepoint server-relative path (advanced)
7 | E.g. /teams/hr
\ (path)
config_type> driveid

Option config_driveid_fixed.
Drive ID
Enter a value.
config_driveid_fixed> *****此处输入获取到的目标用户的 OneDrive Drive ID

Found drive 'root' of type 'business', URL: https://exampleorg-my.sharepoint.com/personal/exampleuser_example_org/Documents
Is that okay?
y) Yes
n) No
y/n> y

Configuration complete.
Options:
Keep this remote?
y) Yes this is OK
e) Edit this remote
d) Delete this remote
y/e/d> y

完成后,即可像使用个人 OAuth OneDrive 一样,操作其他用户的 OneDrive。