Compare commits

...

203 Commits

Author SHA1 Message Date
Ross Scroggs
226781766b Add drive/sheets read command data scopes 2025-10-03 17:34:33 -07:00
Ross Scroggs
434e30d57c Update Vault-Takeout.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
2025-10-03 13:17:13 -07:00
Ross Scroggs
2ab059926b Fixed bug in gam print|show admins
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14-dev freethread, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-10-03 08:50:29 -07:00
Ross Scroggs
5ae25495f7 Fixed bug in gam print|show admins 2025-10-03 07:27:31 -07:00
Ross Scroggs
20e226e57d Added option types <AdminAssigneeTypeList> to gam print|show admins
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14-dev freethread, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-10-02 17:36:31 -07:00
Ross Scroggs
b4677585bb Added option types <AdminAssigneeTypeList> to gam print|show admins 2025-10-02 16:47:40 -07:00
Ross Scroggs
3a1437872c Update Administrators.md
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14-dev freethread, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-10-02 13:33:48 -07:00
Ross Scroggs
602dce2f5a Update Administrators.md 2025-10-02 13:26:42 -07:00
Ross Scroggs
8ce930f01b Added option recursive to gam print|show admins 2025-10-02 13:24:19 -07:00
Ross Scroggs
9631882be0 Added option recursive to gam print|show admins 2025-10-02 12:27:06 -07:00
Jay Lee
32d2858e4b Update build.yml 2025-10-02 13:16:14 -04:00
Jay Lee
98370925e7 actions: fix caching excludes 2025-10-02 12:35:49 -04:00
Jay Lee
1ef5d030f6 actions: exclude .git folder from caching, rebuild
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14-dev freethread, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-10-02 09:57:58 -04:00
Jay Lee
d50b5fb61e actions: update dependent action versions 2025-10-02 09:25:20 -04:00
Jay Lee
e070e92be2 Update pypi.yml 2025-10-02 09:15:29 -04:00
Ross Scroggs
b3b6fff2f1 Added option addcsvdata <FieldName> <String> to print events
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
2025-10-01 18:36:25 -07:00
Ross Scroggs
fea94fcc1c Added option addcsvdata <FieldName> <String> to 1print events`
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14-dev freethread, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-10-01 16:03:32 -07:00
Ross Scroggs
a0cd228110 Merge branch 'main' of https://github.com/GAM-team/GAM 2025-10-01 12:52:06 -07:00
Jay Lee
acfcd8b723 actions: do export on OU level also 2025-10-01 13:42:54 -04:00
Jay Lee
a26494e5c6 Update build.yml 2025-10-01 13:26:54 -04:00
Jay Lee
5605e5d1b6 actions: place vault hold on OU not user to try to avoid license delays 2025-10-01 13:16:35 -04:00
Ross Scroggs
e0fdac6e17 Merge branch 'main' of https://github.com/GAM-team/GAM 2025-10-01 10:07:06 -07:00
Ross Scroggs
53dc8e3265 Update Domain-SharedContacts.md 2025-10-01 10:06:55 -07:00
Jay Lee
993a0b403e Update build.yml 2025-10-01 11:42:25 -04:00
Jay Lee
2d7d118d32 actions: rebuild for OpenSSL 3.6.0
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14-dev freethread, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-10-01 08:30:58 -04:00
Ross Scroggs
f2bc704fd6 Upgraded to OpenSSL 3.5.4.
Some checks failed
Build and test GAM / build (false, build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (false, build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (false, build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (false, build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (false, build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (false, build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (false, build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (false, test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14-dev freethread, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-30 18:55:52 -07:00
Jay Lee
46e0c85308 Update build.yml 2025-09-30 20:11:46 -04:00
Jay Lee
9221d075fe Update build.yml 2025-09-30 20:10:11 -04:00
Jay Lee
12b84a5fcf Update build.yml 2025-09-30 19:47:26 -04:00
Jay Lee
6d411972ac Update build.yml 2025-09-30 19:45:23 -04:00
Jay Lee
d665a66d3e Update build.yml 2025-09-30 19:43:04 -04:00
Jay Lee
b2a340d99d Update build.yml 2025-09-30 19:34:36 -04:00
Jay Lee
c76164fbef actions: re-enable some python version testing 2025-09-30 19:29:02 -04:00
Jay Lee
3d22891052 Update build.yml 2025-09-30 19:00:50 -04:00
Jay Lee
48de06613f Update build.yml 2025-09-30 18:50:05 -04:00
Ross Scroggs
4d1879a9a8 Upgraded to OpenSSL 3.5.4.
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-30 15:14:40 -07:00
Jay Lee
454caa5a76 [no ci] actions: cleanup some debug output and unnecessary commands 2025-09-30 17:27:09 -04:00
Jay Lee
12ffa7e823 Update build.yml 2025-09-30 16:35:26 -04:00
Jay Lee
8fc41cbc64 Update build.yml 2025-09-30 16:32:01 -04:00
Jay Lee
dd16c29ee7 Update build.yml 2025-09-30 16:22:20 -04:00
Jay Lee
1a24b4c855 Update build.yml 2025-09-30 16:10:14 -04:00
Jay Lee
f9dfc7d094 Update build.yml 2025-09-30 16:00:51 -04:00
Jay Lee
bc64a292c3 Update build.yml 2025-09-30 15:41:31 -04:00
Ross Scroggs
524ef0df55 Merge branch 'main' of https://github.com/GAM-team/GAM 2025-09-30 11:02:41 -07:00
Ross Scroggs
38f7f39b44 Version info updates 2025-09-30 11:02:35 -07:00
Jay Lee
183e40ef4e Update build.yml 2025-09-30 13:22:53 -04:00
Jay Lee
ba43c4ea5f Update build.yml 2025-09-30 13:17:06 -04:00
Jay Lee
70c88dacf3 Update build.yml 2025-09-30 13:05:30 -04:00
Jay Lee
cc883b6bb7 Update build.yml 2025-09-30 12:47:17 -04:00
Jay Lee
4c320110b3 Update build.yml 2025-09-30 11:40:58 -04:00
Jay Lee
fe7c46e04d Update build.yml 2025-09-30 11:37:05 -04:00
Jay Lee
5b1c3a3a46 Update build.yml 2025-09-30 11:34:05 -04:00
Jay Lee
ce728a991f Update build.yml 2025-09-30 11:32:19 -04:00
Jay Lee
502bda4fe9 Update build.yml 2025-09-30 11:27:39 -04:00
Jay Lee
3f3d882c74 Update build.yml 2025-09-30 11:21:48 -04:00
Jay Lee
a1948eb3ca Update build.yml 2025-09-30 11:16:06 -04:00
Jay Lee
f0fb6336d1 Update build.yml 2025-09-30 11:04:55 -04:00
Jay Lee
71e5ef2399 Update build.yml 2025-09-30 11:01:46 -04:00
Jay Lee
9d9698a669 actions: use a venv for build and test 2025-09-30 10:59:02 -04:00
Jay Lee
eeb180f1f2 actions: rebuild for OpenSSL 3.5.4
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-30 10:13:33 -04:00
Ross Scroggs
6079ab20b3 Added option oneitemperrow to 'gam print course-materials|course-work`
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-29 20:52:00 -07:00
Ross Scroggs
6189ca92ab Added option oneitemperrow to 'gam print course-materials|course-work` 2025-09-29 19:23:50 -07:00
Ross Scroggs
33b60c4b14 Added option oneitemperrow to 'gam print course-materials|course-work` 2025-09-29 19:18:57 -07:00
Ross Scroggs
0c5f747c36 Added option oneitemperrow to 'gam print course-materials|course-work` 2025-09-29 17:13:39 -07:00
Ross Scroggs
826619857c Bump version 2025-09-29 17:09:41 -07:00
Ross Scroggs
9a2880e411 Added chat_max_results variable to gam.cfg.
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-29 13:33:20 -07:00
Ross Scroggs
95caeaba5e Added chat_max_results variable to gam.cfg. 2025-09-29 12:07:13 -07:00
Ross Scroggs
d8ad1b27a4 Update Reports.md 2025-09-29 10:25:55 -07:00
Ross Scroggs
fefeae7c60 Update Vault-Takeout.md 2025-09-29 07:23:45 -07:00
Ross Scroggs
65f7b82d53 Vault query updates
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-28 20:26:46 -07:00
Ross Scroggs
bebafb428d Vault query updates 2025-09-28 19:40:33 -07:00
Ross Scroggs
5e59363a0c Update Vault-Takeout.md 2025-09-28 16:11:55 -07:00
Ross Scroggs
4b2e0db720 Added commands to create, copy and delete Vault saved queries.
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-28 14:22:33 -07:00
Ross Scroggs
938b2bf5a4 Added commands to create, copy and delete Vault saved queries. 2025-09-28 13:20:50 -07:00
Ross Scroggs
34ff0329c4 Added commands to create, copy and delete Vault saved queries. 2025-09-28 13:11:21 -07:00
Ross Scroggs
bed610405b Added a variant of gam create vaultexport
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
2025-09-27 14:40:12 -07:00
Ross Scroggs
1b0c8b75cb Added a variant of gam create vaultexport
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-09-27 13:25:39 -07:00
Ross Scroggs
6eb7e59d56 Update Vault-Takeout.md 2025-09-27 06:57:23 -07:00
Ross Scroggs
5b4cf97702 Added a variant of gam create vaulthold
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
2025-09-26 22:18:49 -07:00
Ross Scroggs
997bd56bd6 Added a variant of gam create vaulthold
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-26 21:36:21 -07:00
Ross Scroggs
e66db1a117 Update Users-Drive-Copy-Move.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-25 17:23:57 -07:00
Ross Scroggs
e3a5f33981 Update Users-Drive-Permissions.md 2025-09-25 17:14:25 -07:00
Ross Scroggs
877465a82f Update Users-Drive-Permissions.md 2025-09-25 17:08:41 -07:00
Ross Scroggs
7e9477c6ea Fix print users #1840
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-09-25 09:06:54 -07:00
Ross Scroggs
1b2fc06f6f Fix print users #1840 2025-09-25 09:00:14 -07:00
Ross Scroggs
3d3b3eac85 Fix print users #1840 2025-09-25 08:59:39 -07:00
Ross Scroggs
882b930928 Update _Sidebar.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-23 13:09:48 -07:00
Jay Lee
4d804177c4 Update pushwiki.yml
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-09-23 14:59:18 -04:00
Jay Lee
de71baff60 move old articles to legacy and remove from wiki 2025-09-23 18:53:53 +00:00
Ross Scroggs
79de854440 Bump version
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build x86_64 macOS 15, macos-15-intel) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 13, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-22 18:22:46 -07:00
Ross Scroggs
f0406af938 Bump version 2025-09-22 17:50:04 -07:00
Ross Scroggs
d51ca45626 Update GamUpdates.md 2025-09-22 17:35:27 -07:00
Jay Lee
00953b2984 install pysocks, undo httplib2 downgrade 2025-09-22 19:22:25 -04:00
Jay Lee
735b131b44 Update build.yml 2025-09-22 18:11:00 -04:00
Jay Lee
cb6069bcb5 actions: fix goal for mac 15 intel 2025-09-22 17:56:47 -04:00
Jay Lee
3a18143ba7 Update build.yml 2025-09-22 17:36:44 -04:00
Jay Lee
5021f685c1 macos-15-intel, rebuild to force httplib2 downgrade 2025-09-22 17:30:20 -04:00
Jay Lee
2dd88a7d9e GAM 7.22.01 2025-09-22 21:22:37 +00:00
Jay Lee
3496c2c96a [no ci] force httplib2 0.22.0 for now due to #1835 2025-09-22 17:16:19 -04:00
Ross Scroggs
98404e91b6 Update GAM7-FAQ.md 2025-09-22 12:32:59 -07:00
Ross Scroggs
ddc36b42ba Add FAQ 2025-09-22 12:29:15 -07:00
Ross Scroggs
1cae3daa4a Merge pull request #1834 from yuangaonyc/main
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Add documentation for Google WIF Integration
2025-09-22 11:17:27 -07:00
Yuan Gao
cc7b5c1a14 Add documentation for Google WIF Integration 2025-09-22 10:10:47 -07:00
Ross Scroggs
cd266ebec9 Update Authorization.md 2025-09-22 09:12:48 -07:00
Ross Scroggs
c1010d412b Update Authorization.md 2025-09-22 09:08:19 -07:00
Ross Scroggs
b41c49ea69 Expanded <UserTypeEntity> to allow specification of non-archived/archived users.
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-21 15:18:56 -07:00
Ross Scroggs
8617e9f57f Expanded <UserTypeEntity> to allow specification of non-archived/archived users. 2025-09-21 14:44:06 -07:00
Jay Lee
b47f2fc4ea Document pip install
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-09-19 06:31:46 -04:00
Ross Scroggs
77f0d3abb3 Update Users-Drive-Permissions.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-18 08:55:10 -07:00
Ross Scroggs
71721d06f2 Update Users-Drive-Permissions.md 2025-09-18 08:53:36 -07:00
Ross Scroggs
d51428f3dc Update GAM-Release-Process.md 2025-09-18 08:32:36 -07:00
Ross Scroggs
b92239fb6f Update Users-Drive-Permissions.md 2025-09-18 08:32:17 -07:00
Ross Scroggs
b50376656e Update Users-Gmail-Labels.md 2025-09-18 08:19:00 -07:00
Ross Scroggs
7796baf685 Update Users-Drive-Permissions.md 2025-09-18 08:15:26 -07:00
Ross Scroggs
6639e1be33 Update Users-Drive-Permissions.md 2025-09-18 08:12:15 -07:00
Ross Scroggs
a8b666b32d Update Users-Drive-Permissions.md 2025-09-18 08:09:21 -07:00
Ross Scroggs
97ce3e9b8d Update Users-Drive-Permissions.md 2025-09-18 07:35:10 -07:00
Ross Scroggs
f9402cb21a Add option notifyrecoveryemail to create|update user
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-09-17 20:36:21 -07:00
Ross Scroggs
1dc7868078 Add option notifyrecoveryemail to create|update user 2025-09-17 19:52:13 -07:00
Jay Lee
c0dc8ae790 Create GAM-Release-Process.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
2025-09-17 16:50:35 -04:00
Jay Lee
8c12e33321 GAM 7.21.02
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-17 13:26:18 +00:00
Jay Lee
d1d48f3b90 actions: forcefully update installed python packages
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-16 18:31:46 -04:00
Jay Lee
3e52d6a924 actions: we no longer need a custom win ARM64 cryptography 2025-09-16 18:26:16 -04:00
Jay Lee
c6e2031d45 actions: disable python 3.14-dev testing for now, bump cache to force rebuild
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 12, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-16 08:49:14 -04:00
Jay Lee
186541d751 Merge branch 'main' of https://github.com/GAM-team/GAM 2025-09-16 12:46:20 +00:00
Jay Lee
5efde2a967 Tahoe, macOS not MacOS 2025-09-16 12:46:14 +00:00
Jay Lee
83ed93a298 actions: MacOS 26 image builds 2025-09-16 08:26:44 -04:00
Ross Scroggs
986672370a Update version
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-09-13 16:26:15 -07:00
Ross Scroggs
c313c5fa83 Update version
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
2025-09-13 15:28:04 -07:00
Ross Scroggs
aaae733452 Another #1829 fix 2025-09-13 14:39:22 -07:00
Ross Scroggs
c810e1c8df Python date libraries update 2025-09-13 13:27:41 -07:00
Ross Scroggs
e95ba0818e Disable testing print admins due to hangs 2025-09-13 12:11:30 -07:00
Ross Scroggs
4b234c44a8 Final (hopefully) #1829 work
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-12 16:30:08 -07:00
Ross Scroggs
266bd68c94 More #1829 work
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-12 11:54:20 -07:00
Ross Scroggs
36bf671251 Debug csa
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-09-11 20:34:12 -07:00
Ross Scroggs
ee71be86b5 Debug build 2025-09-11 19:13:15 -07:00
Ross Scroggs
0c3edfea62 Debug build 2025-09-11 19:11:12 -07:00
Ross Scroggs
4e85960954 Move #1829 work 2025-09-11 18:29:21 -07:00
Ross Scroggs
61c23e2862 Force rebuild 2025-09-11 16:00:50 -07:00
Ross Scroggs
0613eb2c5f Upgrade date libraries to arrow #1829 2025-09-11 15:41:00 -07:00
Jay Lee
5b192a8f67 Update ssd.mjs
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-09-09 12:24:42 -04:00
Jay Lee
a3eedc360b Update ssd.mjs
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-09 07:56:13 -04:00
Jay Lee
c3225344ee Update ssd.mjs 2025-09-09 07:08:02 -04:00
Jay Lee
dddf8a389d Update build.yml
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-08 20:14:29 -04:00
Jay Lee
61847d0d89 Update ssd.mjs 2025-09-08 20:07:47 -04:00
Jay Lee
e11510b2bc Update build.yml
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-08 13:26:27 -04:00
Jay Lee
52b5745b85 Update build.yml 2025-09-08 13:22:44 -04:00
Jay Lee
82f5dd1864 caccerts.pem is not needed in gam.spec 2025-09-08 13:15:36 -04:00
Jay Lee
b9ae49cf43 actions: rebuild to force new httplib2 version 2025-09-08 08:45:16 -04:00
Ross Scroggs
2cf9f1d5c6 Cleaned up Python library imports: googleapiclient, iso8601. #1829
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-09-06 09:02:40 -07:00
Ross Scroggs
544263099b Cleaned up Python library imports: googleapiclient, iso8601. #1829 2025-09-06 07:47:46 -07:00
Ross Scroggs
085988dfde Cleaned up Python library imports: googleapiclient, iso8601. #1829 2025-09-06 07:36:20 -07:00
Jay Lee
4a330ec1b6 We no longer include cacerts.pem in the GAM binary
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-06 10:12:05 +00:00
Jay Lee
7a69cd0b19 Update build.yml 2025-09-06 06:00:25 -04:00
Jay Lee
1be149bba2 see if we need cacerts.pem in gam binary 2025-09-06 05:51:02 -04:00
Jay Lee
7911317184 [no ci] Update build.yml 2025-09-06 05:50:07 -04:00
Jay Lee
14f74b0d0a [no ci] Update get-cacerts.yml 2025-09-06 05:48:43 -04:00
Jay Lee
bb2635565d [no ci] Rename src/cacerts.pem to src/gam/cacerts.pem 2025-09-06 05:47:49 -04:00
Jay Lee
399149a946 Delete src/gam/iso8601.shouldnotbehere directory 2025-09-06 05:43:04 -04:00
Jay Lee
b9237f9f63 [no ci] Delete src/gam/googleapiclient.shouldnotbehere directory 2025-09-06 05:42:53 -04:00
Jay Lee
dacd8f3c48 Delete src/requirements-dev.txt 2025-09-06 05:41:10 -04:00
Jay Lee
86b260d302 [no ci] Delete .pre-commit-config.yaml 2025-09-06 05:40:35 -04:00
Jay Lee
6396740269 Update build.yml
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-05 22:02:10 -04:00
Jay Lee
e3931cff8d actions: copy cacerts.pem for test runs also 2025-09-05 21:57:09 -04:00
Jay Lee
f5568ff474 Delete src/gam/cacerts.pem 2025-09-05 21:39:06 -04:00
Jay Lee
38f8bdc910 delete six.py #1829 2025-09-05 21:38:44 -04:00
Jay Lee
10c1557494 tell PyInstaller to use our custom hooks 2025-09-05 18:01:59 -04:00
Jay Lee
71bd2f9cbc [no ci] Create hook-httplib2.py 2025-09-05 18:00:29 -04:00
Jay Lee
fc99f9b29b [no ci] Create hook-googleapiclient.model.py 2025-09-05 17:59:22 -04:00
Jay Lee
201f0b0eab actions: remove unit tests no longer in use 2025-09-05 17:29:53 -04:00
Jay Lee
9ad64c9efa Merge branch 'main' of https://github.com/GAM-team/GAM 2025-09-05 21:18:39 +00:00
Jay Lee
4fb7448d40 iso8601.parse_date does not return separate tz anymore. #1829 2025-09-05 21:18:34 +00:00
Jay Lee
993ab3d8d2 Add iso8601 as a dependency so it gets proper updates 2025-09-05 16:55:09 -04:00
Jay Lee
3befbf4419 rename iso8601 also 2025-09-05 20:51:09 +00:00
Jay Lee
06b2c83937 rename googleapiclient before removal 2025-09-05 20:47:49 +00:00
Ross Scroggs
c171b6100b Update Reports.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-05 07:51:16 -07:00
Ross Scroggs
fa243f0894 Update Users-Chat.md 2025-09-05 07:37:46 -07:00
Ross Scroggs
59b61715aa Update Authorization.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-04 09:00:25 -07:00
Ross Scroggs
2717908558 Update Licenses.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-09-03 14:05:39 -07:00
Ross Scroggs
ae3c5f2ef6 More course student group updates 2025-09-03 13:14:46 -07:00
Ross Scroggs
0df08967ce Rebranded license SKU 1010470004; student group updates 2025-09-03 12:12:51 -07:00
Ross Scroggs
6dbdc4db07 Rebranded license SKU 1010470004; student group updates 2025-09-03 12:12:40 -07:00
Ross Scroggs
f4aed33e30 Update Users-Drive-Permissions.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-02 13:26:11 -07:00
Ross Scroggs
90fb2309ec Update Users-Drive-Permissions.md 2025-09-02 13:22:24 -07:00
Jay Lee
9151de0f35 actions: actually use cert env variable
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-09-02 08:19:14 -04:00
Jay Lee
69c27d2553 actions: switch to new cert for Windows signing 2025-09-02 08:09:03 -04:00
Ross Scroggs
1c433b69e4 Update Users-Shared-Drives.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
2025-09-01 18:55:36 -07:00
Ross Scroggs
b44e104b50 Update Shared-Drives.md 2025-09-01 18:55:28 -07:00
Ross Scroggs
210d4720c2 Update Users-Shared-Drives.md 2025-09-01 18:47:47 -07:00
Ross Scroggs
e313006f54 Update Shared-Drives.md 2025-09-01 18:47:42 -07:00
Ross Scroggs
ae058424f6 Update Shared-Drives.md 2025-09-01 18:41:30 -07:00
Ross Scroggs
5c09998f9a Update Users-Shared-Drives.md 2025-09-01 18:41:24 -07:00
Ross Scroggs
985b6cc5e2 Update Shared-Drives.md 2025-09-01 18:36:12 -07:00
Ross Scroggs
f7ac9aab21 Update Shared-Drives.md 2025-09-01 18:18:47 -07:00
Ross Scroggs
5c2c049774 Update Shared-Drives.md 2025-09-01 18:14:11 -07:00
Ross Scroggs
e290d6d200 Update Shared-Drives.md 2025-09-01 17:55:04 -07:00
Ross Scroggs
006b885e7f Update Shared-Drives.md 2025-09-01 17:49:04 -07:00
Ross Scroggs
bdfa8cbec7 Update Shared-Drives.md
Some checks failed
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2025) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-certs (push) Has been cancelled
2025-09-01 17:12:08 -07:00
Ross Scroggs
a47ca4f602 Update Shared-Drives.md 2025-09-01 17:01:02 -07:00
Ross Scroggs
9ba4eb88a6 Update Shared-Drives.md 2025-09-01 16:57:51 -07:00
Ross Scroggs
69fd2ef738 Update Shared-Drives.md 2025-09-01 16:55:00 -07:00
Ross Scroggs
a0733242ef Update Shared-Drives.md 2025-09-01 16:52:32 -07:00
Ross Scroggs
7546ed2fe1 Upgraded gam create course-studentgroups to allow specification of multiple student group titles 2025-09-01 16:12:39 -07:00
136 changed files with 3251 additions and 9082 deletions

View File

@@ -30,7 +30,7 @@ env:
PYTHON_SOURCE_PATH: ${{ github.workspace }}/src/cpython
CRYPTOGRAPHY_BUILD_OPENSSL_NO_LEGACY: 1
CRYPTOGRAPHY_OPENSSL_NO_LEGACY: 1
WINDOWS_CODESIGN_CERT_HASH: 590dc5bb10dfb31dbff38c0e2f9c35ef0f6d0e9e
WINDOWS_CODESIGN_CERT_HASH: 3B11D9340A45CF078FF7FD984F1C3E30DA82FD05
jobs:
build:
@@ -41,70 +41,101 @@ jobs:
include:
- os: ubuntu-22.04
jid: 1
freethreaded: false
goal: build
name: Build Intel Ubuntu Jammy
- os: ubuntu-24.04
jid: 2
freethreaded: false
goal: build
name: Build Intel Ubuntu Noble
- os: ubuntu-24.04-arm
jid: 3
freethreaded: false
goal: build
name: Build Arm Ubuntu Noble
- os: ubuntu-22.04-arm
jid: 4
freethreaded: false
goal: build
name: Build Arm Ubuntu Jammy
- os: ubuntu-22.04
jid: 5
freethreaded: false
goal: build
staticx: yes
name: Build Intel StaticX Legacy
- os: ubuntu-22.04-arm
jid: 6
freethreaded: false
goal: build
staticx: yes
name: Build Arm StaticX Legacy
- os: macos-13
jid: 7
freethreaded: false
goal: build
name: Build Intel MacOS
- os: macos-14
jid: 8
freethreaded: false
goal: build
name: Build Arm MacOS 14
- os: macos-15
jid: 9
freethreaded: false
goal: build
name: Build Arm MacOS 15
- os: windows-2025
- os: macos-15-intel
jid: 10
freethreaded: false
goal: build
name: Build x86_64 macOS 15
- os: macos-26
jid: 11
freethreaded: false
goal: build
name: Build Arm MacOS 26
- os: windows-2025
jid: 12
freethreaded: false
goal: build
name: Build Intel Windows
- os: windows-11-arm
jid: 11
jid: 13
freethreaded: false
goal: build
name: Build Arm Windows
- os: ubuntu-24.04
goal: test
python: "3.10"
jid: 12
freethreaded: false
jid: 14
name: Test Python 3.10
- os: ubuntu-24.04
goal: test
python: "3.11"
jid: 13
freethreaded: false
jid: 15
name: Test Python 3.11
- os: ubuntu-24.04
goal: test
python: "3.12"
jid: 14
freethreaded: false
jid: 16
name: Test Python 3.12
- os: ubuntu-24.04
goal: test
python: "3.14-dev"
jid: 15
freethreaded: false
jid: 17
name: Test Python 3.14-dev
- os: ubuntu-24.04
goal: test
python: "3.14-dev"
freethreaded: true
jid: 18
name: Test Python 3.14-dev freethread
steps:
@@ -127,7 +158,7 @@ jobs:
with:
path: |
cache.tar.xz
key: gam-${{ matrix.jid }}-20250814
key: gam-${{ matrix.jid }}-20251002
- name: Untar Cache archive
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true'
@@ -137,17 +168,19 @@ jobs:
- name: Use pre-compiled Python for testing
if: matrix.python != ''
uses: actions/setup-python@3d1e2d2ca0a067f27da6fec484fce7f5256def85 # v5.6.0
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0
with:
python-version: ${{ matrix.python }}
allow-prereleases: true
check-latest: true
freethreaded: ${{ matrix.freethreaded }}
- name: common variables for all runs
env:
JID: ${{ matrix.jid }}
ACTIONS_CACHE: ${{ steps.cache-python-ssl.outputs.cache-hit }}
ACTIONS_GOAL: ${{ matrix.goal }}
freethreaded: ${{ matrix.freethreaded }}
run: |
case $RUNNER_ARCH in
X64)
@@ -161,6 +194,12 @@ jobs:
;;
esac
echo "JID=${JID}" >> $GITHUB_ENV
echo "freethreaded=${freethreaded}" >> $GITHUB_ENV
if "$freethreaded"; then
# Hush some warnings while we test
export PYTHON_GIL=0
echo "PYTHON_GIL=${PYTHON_GIL}" >> $GITHUB_ENV
fi
echo "ACTIONS_CACHE=${ACTIONS_CACHE}" >> $GITHUB_ENV
echo "ACTIONS_GOAL=${ACTIONS_GOAL}" >> $GITHUB_ENV
curl_version=$(curl --version | head -n 1 | awk '{ print $2 }')
@@ -186,13 +225,9 @@ jobs:
if: matrix.goal == 'test'
run: |
export PYTHON=$(which python3)
export PIP=$(which pip3)
export gam="${PYTHON} -m gam"
export gampath="$(readlink -e .)"
echo -e "PYTHON: ${PYTHON}\nPIP: ${PIP}\gam: ${gam}\ngampath: ${gampath}"
export gampath="$(readlink -e .)/gam"
echo -e "PYTHON: ${PYTHON}\ngam: ${gam}\ngampath: ${gampath}"
echo "PYTHON=${PYTHON}" >> $GITHUB_ENV
echo "PIP=${PIP}" >> $GITHUB_ENV
echo "gam=${gam}" >> $GITHUB_ENV
echo "gampath=${gampath}" >> $GITHUB_ENV
- name: Install necessary Github-hosted Linux packages
@@ -223,7 +258,7 @@ jobs:
p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }}
- name: Windows Configure VCode
uses: ilammy/msvc-dev-cmd@460a772e4cf7358f9f2f23773240813e40e7a894 # v1.13.0
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
if: runner.os == 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true'
with:
arch: ${{ runner.arch }}
@@ -253,14 +288,15 @@ jobs:
MAKEOPT=""
PERL="c:\strawberry\perl\bin\perl.exe"
if [[ "$RUNNER_ARCH" == "ARM64" ]]; then
PYEXTERNALS_PATH="arm64"
PYEXTERNALS_ARCH="arm64"
WIX_ARCH="arm64"
elif [[ "$RUNNER_ARCH" == "X64" ]]; then
PYEXTERNALS_PATH="amd64"
PYEXTERNALS_ARCH="amd64"
WIX_ARCH="x64"
fi
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_PATH}"
echo "PYTHON=${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_PATH}/python.exe" >> $GITHUB_ENV
PYEXTERNALS_PATH=$(cygpath -u "${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_ARCH}")
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${PYEXTERNALS_PATH}"
echo "PYTHON=${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_ARCH}/python.exe" >> $GITHUB_ENV
echo "WIX_ARCH=${WIX_ARCH}" >> $GITHUB_ENV
fi
echo "We'll run make with: ${MAKEOPT}"
@@ -285,7 +321,7 @@ jobs:
echo "COMPILED_OPENSSL_VERSION=${COMPILED_OPENSSL_VERSION}" >> $GITHUB_ENV
- name: Windows NASM Install
uses: ilammy/setup-nasm@3a5c2907aab40613bec4a2c63f5d0ef0b11fbd9f # v1.5.2
uses: ilammy/setup-nasm@72793074d3c8cdda771dba85f6deafe00623038b # v1.5.2
if: matrix.goal == 'build' && runner.os == 'Windows' && runner.arch == 'X64' && steps.cache-python-ssl.outputs.cache-hit != 'true'
- name: Config OpenSSL
@@ -449,26 +485,37 @@ jobs:
"$PYTHON" get-pip.py
"$PYTHON" -m pip install --upgrade pip
"$PYTHON" -m pip install --upgrade wheel
"$PYTHON" -m pip install setuptools
"$PYTHON" -m pip install --upgrade setuptools
"$PYTHON" -m pip install --upgrade importlib-metadata
"$PYTHON" -m pip install --upgrade setuptools-scm
"$PYTHON" -m pip list
- name: Custom wheels for Win arm64
if: runner.os == 'Windows' && runner.arch == 'ARM64'
- name: Create and use Python venv
run: |
latest_crypt_whl=$(curl https://api.github.com/repos/jay0lee/cryptography/releases/latest -s | jq -r .assets.[0].browser_download_url)
echo "Downloading ${latest_crypt_whl}..."
curl -O -L "$latest_crypt_whl"
"$PYTHON" -m pip install cryptography*.whl
cd "$GITHUB_WORKSPACE"
"$PYTHON" -m venv venv
if [[ "$RUNNER_OS" == "Windows" ]]; then
# hack till pyscard has a wheel for win arm64
"$PYTHON" -m pip install --upgrade --force-reinstall pyscard
export PYTHON="${GITHUB_WORKSPACE}/venv/scripts/python.exe"
else
export PYTHON="${GITHUB_WORKSPACE}/venv/bin/python3"
fi
echo "PYTHON=${PYTHON}" >> $GITHUB_ENV
if [[ "$ACTIONS_GOAL" == "test" ]]; then
export gam="${PYTHON} gam.py"
echo "gam=${gam}" >> $GITHUB_ENV
fi
- name: Install pip requirements
run: |
echo "before anything..."
"$PYTHON" -m pip list
echo "--info--"
"$PYTHON" -m pip cache info
echo "--list--"
"$PYTHON" -m pip cache list
"$PYTHON" -m pip install --upgrade ..[yubikey]
"$PYTHON" -m pip list
#"$PYTHON" -m pip install --force-reinstall --no-deps --upgrade cryptography
echo "after everything..."
"$PYTHON" -m pip list
@@ -538,7 +585,7 @@ jobs:
- name: Copy extra package files
if: matrix.goal == 'build'
run: |
cp -v cacerts.pem "$gampath"
cp -v gam/cacerts.pem "$gampath"
cp -v LICENSE "$gampath"
cp -v GamCommands.txt "$gampath"
cp -v GamUpdate.txt "$gampath"
@@ -588,7 +635,6 @@ jobs:
- name: Basic Tests all jobs
id: basictests
run: |
$PYTHON -m unittest discover --start-directory ./ --pattern "*_test.py" --buffer || if [ $? != 5 ]; then exit $?; fi # exit 5 is no tests
$gam version extended nooffseterror
export GAMVERSION=$($gam version simple)
echo "GAM Version ${GAMVERSION}"
@@ -655,7 +701,7 @@ jobs:
write-Host "Signing ${env:gam}...."
# Always explicitely use x64 version os signtool.exe, arm64 version apparently can't
# see Certum certs since SimplySignDesktop is x64-only today.
Start-Process -Wait -NoNewWindow -ErrorAction Continue -FilePath 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe' -ArgumentList "sign", "/sha1", "590dc5bb10dfb31dbff38c0e2f9c35ef0f6d0e9e", "/tr", "http://time.certum.pl", "/td", "SHA256", "/fd", "SHA256", "/v", "$env:gam"
Start-Process -Wait -NoNewWindow -ErrorAction Continue -FilePath 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe' -ArgumentList "sign", "/sha1", "$env:WINDOWS_CODESIGN_CERT_HASH", "/tr", "http://time.certum.pl", "/td", "SHA256", "/fd", "SHA256", "/v", "$env:gam"
write-Host "Verifying signature of ${env:gam}...."
# verify signature. If we failed to sign we should fail to verify and die.
& 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe' verify /pa /v "$env:gam"
@@ -727,7 +773,7 @@ jobs:
write-Host "Signing ${env:MSI_FILENAME}...."
# Always explicitely use x64 version os signtool.exe, arm64 version apparently can't
# see Certum certs since SimplySignDesktop is x64-only today.
Start-Process -Wait -NoNewWindow -ErrorAction Continue -FilePath 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe' -ArgumentList "sign", "/sha1", "590dc5bb10dfb31dbff38c0e2f9c35ef0f6d0e9e", "/tr", "http://time.certum.pl", "/td", "SHA256", "/fd", "SHA256", "/v", "$env:MSI_FILENAME"
Start-Process -Wait -NoNewWindow -ErrorAction Continue -FilePath 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe' -ArgumentList "sign", "/sha1", "$env:WINDOWS_CODESIGN_CERT_HASH", "/tr", "http://time.certum.pl", "/td", "SHA256", "/fd", "SHA256", "/v", "$env:MSI_FILENAME"
write-Host "Verifying signature of ${env:MSI_FILENAME}...."
# verify signature. If we failed to sign we should fail to verify and die.
& 'C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe' verify /pa /v "$env:MSI_FILENAME"
@@ -750,6 +796,7 @@ jobs:
gam*.tar.xz
gam*.zip
gam*.msi
*.png
- name: Basic Tests build jobs only
if: matrix.goal != 'test' && steps.cache-python-ssl.outputs.cache-hit != 'true'
@@ -842,9 +889,10 @@ jobs:
$gam config enable_dasa false save
# 9/17/24 temp disable due to Google API sluggishness to see new users for admin commands
# $gam create admin $newuser _GROUPS_EDITOR_ROLE CUSTOMER # condition nonsecuritygroup
$gam create admin $newgroup _HELP_DESK_ADMIN_ROLE org_unit "${newou}"
$gam config csv_output_row_filter "assignedToUser:regex:${newuser}" print admins | $gam csv - gam delete admin "~roleAssignmentId"
$gam config csv_output_row_filter "assignedToGroup:regex:${newgroup}" print admins | $gam csv - gam delete admin "~roleAssignmentId"
# 9/13/25 temp disable due to hangs
# $gam create admin $newgroup _HELP_DESK_ADMIN_ROLE org_unit "${newou}"
# $gam config csv_output_row_filter "assignedToUser:regex:${newuser}" print admins | $gam csv - gam delete admin "~roleAssignmentId"
# $gam config csv_output_row_filter "assignedToGroup:regex:${newgroup}" print admins | $gam csv - gam delete admin "~roleAssignmentId"
$gam config enable_dasa false save
$gam csv sample.csv gam create user ~~email~~ firstname "GHA Bulk" lastname ~~email~~ gha.jid $JID ou "${newou}"
$gam csv sample.csv gam update user ~~email~~ recoveryphone 12125121110 recoveryemail jay0lee@gmail.com password random displayname "GitHub Actions Bulk ${JID}"
@@ -895,11 +943,11 @@ jobs:
$gam calendar $gam_user printevents after -0d
$gam config enable_dasa false save
matterid=uid:$($gam create vaultmatter name "GHA matter $newbase" description "test matter" returnidonly)
$gam create vaulthold matter $matterid name "GHA hold $newbase" corpus mail accounts $newuser
$gam create vaulthold matter $matterid name "GHA hold ${newbase}" corpus mail ou "$newou"
$gam print vaultmatters matterstate open
$gam print vaultholds matter $matterid
$gam print vaultcount matter $matterid corpus mail everyone todrive tdnobrowser
$gam create vaultexport matter $matterid name "GHA export $newbase" corpus mail accounts $newuser
$gam create vaultexport matter $matterid name "GHA export $newbase" corpus mail ou "$newou"
$gam print exports matter $matterid | $gam csv - gam info export $matterid id:~~id~~
$gam config enable_dasa true save
$gam csv sample.csv gam user ~email add calendar id:$newresource
@@ -979,7 +1027,8 @@ jobs:
else
tar_folders="bin/"
fi
tar cJvvf cache.tar.xz $tar_folders
echo '.git*' > ./excludes.txt
tar cJvvf cache.tar.xz --exclude-from=excludes.txt $tar_folders
merge:
if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
@@ -1029,7 +1078,7 @@ jobs:
echo "dateversion=${dateversion}" >> $GITHUB_OUTPUT
- name: Publish draft release
uses: softprops/action-gh-release@fbadcc90e88ecface60a0a0d123795b784ceb239 # v2.3.2
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3
with:
draft: true
prerelease: false

View File

@@ -13,7 +13,7 @@ on:
defaults:
run:
shell: bash
working-directory: src
working-directory: src/gam
jobs:
check-certs:

View File

@@ -37,7 +37,7 @@ jobs:
cd GAM.wiki
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add *.md
git add -A
git commit -m "[no ci] Push Wiki changes"
git status
git push

View File

@@ -30,6 +30,6 @@ jobs:
python -m build
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
uses: pypa/gh-action-pypi-publish@ed0c53931b1dc9bd32cbe73a98c7f6766f8a527e # v1.13.0
with:
attestation: true

View File

@@ -1,32 +0,0 @@
# See https://pre-commit.com for more information
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.5.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: double-quote-string-fixer
- id: check-yaml
- id: check-docstring-first
- id: name-tests-test
- id: requirements-txt-fixer
- id: check-merge-conflict
- repo: https://github.com/pre-commit/mirrors-yapf
rev: v0.30.0
hooks:
- id: yapf
args: [--style=google, --in-place]
- repo: https://github.com/PyCQA/pylint
rev: pylint-2.5.0
hooks:
- id: pylint
args: [--output-format=colorized]
- repo: https://github.com/asottile/pyupgrade
rev: v2.31.0
hooks:
- id: pyupgrade
args: [--py37-plus]

View File

@@ -18,6 +18,11 @@ this will download GAM, install it and start setup.
Download the MSI Installer from the [GitHub Releases] page. Install the MSI and you'll be prompted to setup GAM.
## Use your own Python
If you'd prefer to install GAM as a Python package you can install with pip:
```
pip install gam7
```
# Documentation
The GAM documentation is hosted in the [GitHub Wiki]

View File

@@ -10,6 +10,7 @@ authors = [
# notice that yubikey-manager remains optional further down since it is less command and adds
#significant compile dependencies.
dependencies = [
"arrow>=1.3.0",
"chardet>=5.2.0",
"cryptography>=44.0.2",
"distro; sys_platform=='linux'",
@@ -18,11 +19,11 @@ dependencies = [
"google-auth-httplib2>=0.2.0",
"google-auth-oauthlib>=1.2.2",
"google-auth>=2.39.0",
"httplib2>=0.22.0",
"httplib2>=0.31.0",
"lxml>=5.4.0",
"passlib>=1.7.4",
"pathvalidate>=3.2.3",
"python-dateutil",
"pysocks>=1.7.1",
]
description = "CLI tool to manage Google Workspace"
readme = "README.md"

View File

@@ -266,7 +266,7 @@ If an item contains spaces, it should be surrounded by ".
appsheetstandard | appsheetenterprisestandard | 1010380002 | AppSheet Enterprise Standard |
appsheetplus | appsheetenterpriseplus | 1010380003 | AppSheet Enterprise Plus |
assuredcontrols | 1010390001 | Assured Controls |
assuredcontrolsplus | 1010390002 | Assured Controls Plus |
assuredcontrolsplus | 1010390002 | Assured Controls Plus |
bce | beyondcorp | beyondcorpenterprise | cep | chromeenterprisepremium | 1010400001 | Chrome Enterprise Premium |
cdm | chrome | googlechromedevicemanagement | Google-Chrome-Device-Management |
cloudidentity | identity | 1010010001 | Cloud Identity |
@@ -275,8 +275,8 @@ If an item contains spaces, it should be surrounded by ".
colabpro | 1010500001 | Colab Pro |
colabpro+ | colabproplus | 1010500002 | Colab Pro+ |
eeu | 1010490001 | SKU Endpoint Education Upgrade |
gaiproedu | geminiedu | 1010470004 | Google AI Pro for Education |
geminibiz | 1010470003 | Gemini Business |
geminiedu | 1010470004 | Gemini Education |
geminiedupremium| 1010470005 | Gemini Education Premium |
geminient| duetai | 1010470001 | Gemini Enterprise |
geminiultra | 1010470008 | Google AI Ultra for Business |
@@ -316,12 +316,12 @@ If an item contains spaces, it should be surrounded by ".
wsbizstarter | workspacebusinessstarter | wsbizstart | 1010020027 | Google Workspace Business Starter |
wsbizstarterarchived | workspacebusinessstarterarchived | 1010340005 | Google Workspace Business Starter - Archived User |
wsentess | workspaceenterpriseessentials | 1010060003 | Google Workspace Enterprise Essentials |
wsentplus | workspaceenterpriseplus | gae | gse | enterprise | gsuiteenterprise | 1010020020 | Google Workspace Enterprise Plus |
wsentplus | workspaceenterpriseplus | gae | gse | enterprise | gsuiteenterprise | 1010020020 | Google Workspace Enterprise Plus (formerly G Suite Enterprise) |
wsentstan | workspaceenterprisestandard | 1010020026 | Google Workspace Enterprise Standard |
wsentstanarchived | workspaceenterprisestandardarchived | 1010340004 | Google Workspace Enterprise Standard - Archived User |
wsentstarter | workspaceenterprisestarter | wes | 1010020029 | Workspace Enterprise Starter |
wsess | workspaceesentials | gsuiteessentials | essentials | d4e | driveenterprise | drive4enterprise | 1010060001 | Google Workspace Essentials |
wsessplus | workspaceessentialsplus | 1010060005 | Google Workspace Essentials Plus |
wsess | workspaceesentials | gsuiteessentials | essentials | d4e | driveenterprise | drive4enterprise | 1010060001 | Google Workspace Essentials (formerly G Suite Essentials) |
wsessplus | workspaceessentialsplus | 1010060005 | Google Workspace Enterprise Essentials Plus |
wsflw | workspacefrontline | workspacefrontlineworker | 1010020030 | Google Workspace Frontline Starter |
wsflwstan | workspacefrontlinestan | workspacefrontlineworkerstan | 1010020031 | Google Workspace Frontline Standard |
wsflwplus | workspacefrontlineplus | workspacefrontlineworkerplus | 1010020034 | Google Workspace Frontline Plus
@@ -368,6 +368,7 @@ If an item contains spaces, it should be surrounded by ".
## Named items
<AccessToken> ::= <String>
<AdminAssigneeType> ::= group|user|serviceaccount|unknown
<AlertID> ::= <String>
<APIScopeURL> ::= <String>
<APPID> ::= <String>
@@ -428,6 +429,8 @@ If an item contains spaces, it should be surrounded by ".
<CourseWorkState> ::= draft|published|deleted
<CrOSID> ::= <String>
<CustomerID> ::= <String>
<DateTimeFormat> ::= <String>
See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
<DeliverySetting> ::=
allmail|
abridged|daily|
@@ -563,6 +566,7 @@ If an item contains spaces, it should be surrounded by ".
See: https://support.google.com/mail/answer/7190
<QueryGroup> ::= <String>
See: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
<QueryItem> ::= <UniqueID>|<String>
<QueryMemberRestrictions> ::= <String>
See: https://cloud.google.com/identity/docs/reference/rest/v1beta1/SecuritySettings#MemberRestriction
<QueryMobile> ::= <String>
@@ -663,11 +667,11 @@ If an item contains spaces, it should be surrounded by ".
(tdreturnidonly [<Boolean>])|
(tdshare <EmailAddress> commenter|reader|writer)*|
(tdsheet (id:<Number>)|<String>)|
(tdsheettimestamp [<Boolean>] [tdsheettimeformat <String>])
(tdsheettimestamp [<Boolean>] [tdsheettimeformat <DateTimeFormat>])
(tdsheettitle <String>)|
(tdsubject <String>)|
([tdsheetdaysoffset <Number>] [tdsheethoursoffset <Number>])|
(tdtimestamp [<Boolean>] [tdtimeformat <String>]
(tdtimestamp [<Boolean>] [tdtimeformat <DateTimeFormat>]
[tddaysoffset <Number>] [tdhoursoffset <Number>])|
(tdtimezone <TimeZone>)|
(tdtitle <String>)|
@@ -688,6 +692,7 @@ If an item contains spaces, it should be surrounded by ".
## Lists of basic items
<AdminAssigneeTypeList> ::= "<AdminAssigneeType>(,<AdminAssigneeType>)*"
<APIScopeURLList> ::= "<APIScopeURL>(,<APIScopeURL>)*"
<ASPIDList> ::= "<ASPID>(,<ASPID>)*"
<AssetTagList> ::= "<AssetTag>(,<AssetTag>)*"
@@ -726,6 +731,7 @@ If an item contains spaces, it should be surrounded by ".
<DomainNameList> ::= "<DomainName>(,<DomainName>)*"
<DriveFileACLRoleList> ::= "<DriveFileACLRole>(,<DriveFileACLRole>)*"
<DriveFileACLTypeList> ::= "<DriveFileACLType>(,<DriveFileACLType>)*"
<DriveFileIDList> ::= "<DriveFileID>(,<DriveFileID>)*"
<DriveFileList> ::= "<DriveFileItem>(,<DriveFileItem>)*"
<DriveFilePermissionList> ::= "<DriveFilePermission>(,<DriveFilePermission>)*"
<DriveFilePermissionIDList> ::= "<DriveFilePermissionID>(,<DriveFilePermissionID>)*"
@@ -902,25 +908,25 @@ Specify a collection of ChromeOS devices by directly specifying them or by speci
Specify a collection of Users by directly specifying them or by specifying items that will yield a list of users.
<UserTypeEntity> ::=
(all users|users_ns|users_susp|users_ns_susp)|
(all users|users_na|users_arch|users_ns|users_susp|users_arch_or_susp|users_na_ns|users_ns_susp)|
(user <UserItem>)|
(users <UserList>)|
(oauthuser)
(domains|domains_ns|domains_susp <DomainNameListList>)|
(group|group_ns|group_susp|group_inde <GroupItem>)|
(groups|groups_ns|groups_susp|groups_inde <GroupList>)|
(domains|domains_na|domains_arch|domains_ns|domains_susp|domains_na_ns <DomainNameListList>)|
(group|group_na|group_arch|group_ns|group_susp|group_na_ns|group_inde <GroupItem>)|
(groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde <GroupList>)|
(group_inde <GroupItem>)|(groups_inde <GroupList>)|
(group_users|group_users_ns|group_users_susp <GroupList>
(group_users|group_users_na|group_users_arch|group_users_ns|group_users_susp|group_users_na_ns <GroupList>
[members] [managers] [owners]
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
(group_users_select <GroupList>
[members] [managers] [owners]
[notsuspended|suspended] [notarchived|archived]
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
(ou|ou_ns|ou_susp <OrgUnitItem>)|
(ou_and_children|ou_and_children_ns|ou_and_children_susp <OrgUnitItem>)|
(ous|ous_ns|ous_susp <OrgUnitList>)|
(ous_and_children|ous_and_children_ns|ous_and_children_susp <OrgUnitList>)|
(ou|ou_na|ou_arch|ou_ns|ou_susp|ou_na_ns <OrgUnitItem>)|
(ou_and_children|ou_and_children_na|ou_and_children_arch|ou_and_children_ns|ou_and_children_susp|ou_and_children_na_ns <OrgUnitItem>)|
(ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns <OrgUnitList>)|
(ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns <OrgUnitList>)|
(courseparticipants <CourseIDList>)|
(students <CourseIDList>)|
(teachers <CourseIDList>)|
@@ -940,20 +946,24 @@ Specify a collection of Users by directly specifying them or by specifying items
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <REMatchPattern>)*
(matchfield|skipfield <FieldName> <RESearchPattern>)*
[delimiter <Character>])|
(datafile
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
users|
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
ous|ous_na|ous_arch|ous_ns|ous_susps|ous_na_ns|
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
courseparticipants|students|teachers
((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>])|
(csvdatafile
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
users|
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
ous|ous_na|ous_arch|ous_ns|ous_susps|ous_na_ns|
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
courseparticipants|students|teachers
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
@@ -961,21 +971,23 @@ Specify a collection of Users by directly specifying them or by specifying items
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <REMatchPattern>)*
(matchfield|skipfield <FieldName> <RESearchPattern>)*
[delimiter <Character>])|
(csvkmd
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
users|
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
ous|ous_na|ous_arch|ous_ns|ous_susps|ous_na_ns|
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
courseparticipants|students|teachers
((<FileName>|
(gsheet <UserGoogleSheet>)|
(gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <REMatchPattern>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <REMatchPattern>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <REMatchPattern>)*
keyfield <FieldName> [keypattern <RESearchPattern>] [keyvalue <RESubstitution>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RESearchPattern>] [keyvalue <RESubstitution>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RESearchPattern>)*
[datafield <FieldName>(:<FieldName>)* [delimiter <Character>]])
(csvdata <FieldName>(:<FieldName>*))
@@ -1007,23 +1019,25 @@ Specify a collection of items by directly specifying them; the item type is dete
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <REMatchPattern>)*
(matchfield|skipfield <FieldName> <RESearchPattern>)*
[delimiter <Character>]
<CSVkmdSelector> ::=
csvkmd
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
users|
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_inde|
ous|ous_na|ous_arch|ous_ns|ous_susp|
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
((<FileName>|
(gsheet <UserGoogleSheet>)|
(gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <REMatchPattern>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <REMatchPattern>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <REMatchPattern>)*
keyfield <FieldName> [keypattern <RESearchPattern>] [keyvalue <String>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RESearchPattern>] [keyvalue <String>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RESearchPattern>)*
[datafield <FieldName>(:<FieldName>)* [delimiter <Character>]]
<CSVSubkeySelector> ::= csvsubkey <FieldName>
<CSVDataSelector> ::= csvdata <FieldName>(:<FieldName>)*
@@ -1379,13 +1393,13 @@ gam tbatch <BatchContent> [showcmds [<Boolean>]]
gam csv <CSVLoopContent> [warnifnodata]
[columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>]
(matchfield|skipfield <FieldName> <REMatchPattern>)* [showcmds [<Boolean>]]
(matchfield|skipfield <FieldName> <RESearchPattern>)* [showcmds [<Boolean>]]
[skiprows <Integer>] [maxrows <Integer>]
gam <GAMArgumentList>
gam loop <CSVLoopContent> [warnifnodata]
[columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>]
(matchfield|skipfield <FieldName> <REMatchPattern>)* [showcmds [<Boolean>]]
(matchfield|skipfield <FieldName> <RESearchPattern>)* [showcmds [<Boolean>]]
[skiprows <Integer>] [maxrows <Integer>]
gam <GAMArgumentList>
@@ -1532,18 +1546,24 @@ gam print adminroles|roles [todrive <ToDriveAttribute>*]
[formatjson [quotechar <Character>]]
gam show adminroles|roles
[role <RoleItem>] [privileges]
[nosystemroles]
[formatjson]
[nosystemroles]
[formatjson]
gam create|add admin <EmailAddress>|<UniqueID> <RoleItem> customer|(org_unit <OrgUnitItem>)
[condition securitygroup|nonsecuritygroup]
gam delete admin <RoleAssignmentId>
<AdminAssigneeType> ::= group|user|serviceaccount|unknown
<AdminAssigneeTypeList> ::= "<AdminAssigneeType>(,<AdminAssigneeType>)*"
gam print admins [todrive <ToDriveAttribute>*]
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition]
[privileges] [oneitemperrow]
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
[types <AdminAssigneeTypeList>]
[recursive] [condition] [privileges] [oneitemperrow]
gam show admins
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition] [privileges]
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
[types <AdminAssigneeTypeList>]
[recursive] [condition] [privileges]
# Alert Center
@@ -1582,7 +1602,7 @@ gam print alias|aliases [todrive <ToDriveAttribute>*]
[limittoou <OrgUnitItem>])
[user|users <EmailAddressList>] [group|groups <EmailAddressList>]
[select <UserTypeEntity>]
[aliasmatchpattern <REMatchPattern>]
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
[shownoneditable] [nogroups] [nousers]
[onerowpertarget] [delimiter <Character>]
[suppressnoaliasrows]
@@ -1743,7 +1763,7 @@ gam calendar <CalendarEntity> printacl [todrive <ToDriveAttribute>*]
(range <Date> <Date>)|
(recurrence <RRULE, EXRULE, RDATE and EXDATE line>)|
(reminder <Number> email|popup))|
(resource <ResourceID>)|
(resource <ResourceID>)|
(selectattendees [<AttendeeAttendance>] [<AttendeeStatus>] <UserTypeEntity>)|
(sequence <Integer>)|
(sharedproperty <PropertyKey> <PropertyValue>)|
@@ -1920,12 +1940,12 @@ gam calendar|calendars <CalendarEntity> info events [<EventEntity>] [maxinstance
[formatjson]
gam calendar|calendars <CalendarEntity> show events [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek]
[countsonly]
[formatjson]
[countsonly|formatjson]
gam calendar|calendars <CalendarEntity> print events [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek]
[countsonly [eventrowfilter]]
[formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*]
(addcsvdata <FieldName> <String>)*
[eventrowfilter]
[countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
gam calendar <CalendarEntity> addevent <EventAttribute>+ [<EventNotificationAttribute>]
[showdayofweek]
@@ -3371,6 +3391,7 @@ gam print course-materials [todrive <ToDriveAttribute>*]
(orderby <CourseMaterialOrderByFieldName> [ascending|descending])*)
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>]
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[oneitemperrow]
[countsonly] [formatjson [quotechar <Character>]]
gam print course-submissions [todrive <ToDriveAttribute>*]
(course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] states <CourseStateList>])
@@ -3392,6 +3413,7 @@ gam print course-works [todrive <ToDriveAttribute>*]
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseWorkFieldNameList>]
[showstudentsaslist [<Boolean>]] [delimiter <Character>]
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[oneitemperrow]
[countsonly] [formatjson [quotechar <Character>]]
# Classroom - Student Groups
@@ -3731,16 +3753,14 @@ gam print domaincontacts|peoplecontacts [todrive <ToDriveAttribute>*]
[sources <PeopleSourceName>]
[query <String>]
[mergesources <PeopleMergeSourceName>]
[coountsonly]
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
[formatjson [quotechar <Character>]]
[coountsonly|(formatjson [quotechar <Character>])]
gam show domaincontacts|peoplecontacts
[sources <PeopleSourceName>]
[query <String>]
[mergesources <PeopleMergeSourceName>]
[coountsonly]
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
[formatjson]
[coountsonly|formatjson]
gam info people|peopleprofile <PeopleResourceNameEntity>
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
@@ -3748,15 +3768,13 @@ gam info people|peopleprofile <PeopleResourceNameEntity>
gam print people|peopleprofile [todrive <ToDriveAttribute>*]
[query <String>]
[mergesources <PeopleMergeSourceName>]
[coountsonly]
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
[formatjson [quotechar <Character>]]
[coountsonly|(formatjson [quotechar <Character>])]
gam show people|peopleprofile
[query <String>]
[mergesources <PeopleMergeSourceName>]
[coountsonly]
[allfields|(fields <PeopleFieldNameList>)] [showmetadata]
[formatjson]
[coountsonly|formatjson]
# Email Audit Monitor
@@ -4470,8 +4488,10 @@ gam update orgs|ous <OrgUnitEntity> sync <CrOSTypeEntity> [removetoou <OrgUnitIt
gam update orgs|ous <OrgUnitEntity> sync <UserTypeEntity> [removetoou <OrgUnitItem>]
gam delete orgs|ous <OrgUnitEntity>
gam info org|ou <OrgUnitItem> [nousers|notsuspended|suspended] [children|child]
gam info orgs|ous <OrgUnitEntity> [nousers|notsuspended|suspended] [children|child]
gam info org|ou <OrgUnitItem>
[nousers | ([notarchived|archived] [notsuspended|suspended])] [children|child]
gam info orgs|ous <OrgUnitEntity>
[nousers | ([notarchived|archived] [notsuspended|suspended])] [children|child]
<OrgUnitSelector> ::=
cros_ou | cros_ou_and_children|
@@ -5096,7 +5116,7 @@ gam create|add drivefileacl <SharedDriveEntityAdmin>
anyone|(user <UserItem>)|(group <GroupItem>)|(domain <DomainName>)
(role <DriveFileACLRole>) [withlink|(allowfilediscovery|discoverable [<Boolean>])]
(mappermissionsdomain <DomainName> <DomainName>)*
[expiration <Time>] [sendemail] [emailmessage <String>]
[expiration <Time>] [sendemail|sendnotification] [emailmessage <String>]
[showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])]
gam update drivefileacl <SharedDriveEntityAdmin> <DriveFilePermissionIDorEmail>
(role <DriveFileACLRole>) [expires|expiration <Time>] [removeexpiration [<Boolean>]]
@@ -5123,7 +5143,7 @@ gam print drivefileacls <SharedDriveEntityAdmin> [todrive <ToDriveAttribute>*]
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
[formatjson [quotechar <Character>]]
gam create|add permissions <SharedDriveEntityAdmin> <DriveFilePermissionEntity>
[expires|expiration <Time>] [sendemail] [emailmessage <String>]
[expires|expiration <Time>] [sendemail|sendnotification] [emailmessage <String>]
<PermissionMatch>* [<PermissionMatchAction>]
gam delete permissions <SharedDriveEntityAdmin> <DriveFilePermissionIDEntity>
<PermissionMatch>* [<PermissionMatchAction>]
@@ -5136,7 +5156,7 @@ gam <UserTypeEntity> create|add drivefileacl <SharedDriveEntityAdmin>
(role <DriveFileACLRole>) [withlink|(allowfilediscovery|discoverable [<Boolean>])]
(mappermissionsdomain <DomainName> <DomainName>)*
[movetonewownersroot [<Boolean>]]
[expiration <Time>] [sendemail] [emailmessage <String>]
[expiration <Time>] [sendemail|sendnotification] [emailmessage <String>]
[showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])]
adminaccess
gam <UserTypeEntity> update drivefileacl <SharedDriveEntityAdmin> <DriveFilePermissionIDorEmail>
@@ -5167,7 +5187,7 @@ gam <UserTypeEntity> print drivefileacls <SharedDriveEntityAdmin> [todrive <ToDr
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
[formatjson [quotechar <Character>]]
gam <UserTypeEntity> create|add permissions <SharedDriveEntityAdmin> <DriveFilePermissionEntity>
[expires|expiration <Time>] [sendemail] [emailmessage <String>] adminaccess
[expires|expiration <Time>] [sendemail|sendnotification] [emailmessage <String>] adminaccess
<PermissionMatch>* [<PermissionMatchAction>]
gam <UserTypeEntity> delete permissions <SharedDriveEntityAdmin> <DriveFilePermissionIDEntity> adminaccess
<PermissionMatch>* [<PermissionMatchAction>]
@@ -5398,34 +5418,48 @@ gam show vaultmatters|matters [matterstate <MatterStateList>]
[formatjson]
gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem> corpus mail|groups
[(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone]
[(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))]
matter <MatterItem> <QueryItem>
[wait <Integer>]
gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem>
corpus mail|groups
[scope [all_data|held_data|unprocessed_data]]
[(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone]
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[excludedrafts <Boolean>]
[<JSONData>]
[wait <Integer>]
gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem> operation <String> [wait <Integer>]
gam create vaultexport|export matter <MatterItem> [name <String>] corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
gam create vaultexport|export matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[driveclientsideencryption any|encrypted|unencrypted]
[includeaccessinfo <Boolean>]
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
[format ics|mbox|pst|xml]
[region any|europe|us] [showdetails|returnidonly]
gam create vaultexport|export matter <MatterItem> [name <String>]
corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
[scope all_data|held_data|unprocessed_data]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(documentids (<DriveFileIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
[driveversiondate <Date>|<Time>]
[includerooms <Boolean>]
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
[driveversiondate <Date>|<Time>] [includeaccessinfo <Boolean>]
(covereddata calllogs|textmessages|voicemails)*
[driveclientsideencryption any|encrypted|unencrypted]
[includerooms <Boolean>]
[includeaccessinfo <Boolean>]
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
[covereddata calllogs|textmessages|voicemails]
[format ics|mbox|pst|xml]
[region any|europe|us] [showdetails|returnidonly]
gam delete vaultexport|export <ExportItem> matter <MatterItem>
@@ -5481,18 +5515,21 @@ gam show vaultexports|exports
[fields <VaultExportFieldNameList>] [shownames]
[formatjson]
gam create vaulthold|hold matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[showdetails|returnidonly]
gam create vaulthold|hold matter <MatterItem> [name <String>] corpus calendar|drive|mail|groups|hangouts_chat|voice
[(accounts|groups|users <EmailItemList>) | (orgunit|org|ou <OrgUnit>)]
[query <QueryVaultCorpus>]
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[includerooms <Boolean>] [covereddata calllogs|textmessages|voicemails]
[includerooms <Boolean>] (covereddata calllogs|textmessages|voicemails)*
[includeshareddrives <Boolean>]
[showdetails|returnidonly]
gam update vaulthold|hold <HoldItem> matter <MatterItem>
[([addaccounts|addgroups|addusers <EmailItemList>] [removeaccounts|removegroups|removeusers <EmailItemList>]) | (orgunit|org|ou <OrgUnit>)]
[query <QueryVaultCorpus>]
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[includerooms <Boolean>] [covereddata calllogs|textmessages|voicemails]
[includerooms <Boolean>] (covereddata calllogs|textmessages|voicemails)*
[includeshareddrives <Boolean>]
[showdetails]
gam delete vaulthold|hold <HoldItem> matter <MatterItem>
@@ -5532,6 +5569,32 @@ gam show vaultholds|holds [matters <MatterItemList>]
gam <UserTypeEntity> print vaultholds|holds [todrive <ToDriveAttribute>*]
gam <UserTypeEntity> show vaultholds|holds
gam create vaultquery <MatterItem> [name <String>]
corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
[scope all_data|held_data|unprocessed_data]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(documentids (<DriveFileIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
[driveversiondate <Date>|<Time>]
[includerooms <Boolean>]
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
(covereddata calllogs|textmessages|voicemails)*
[<JSONData>]
[shownames]
[showdetails|returnidonly|formatjson]
gam copy vaultquery <MatterItem> <QueryItem> [targetmatter <MatterItem>] [name <String>]
[shownames]
[showdetails|returnidonly|formatjson]
gam delete vaultquery <QueryItem> matter <MatterItem>
gam delete vaultquery <MatterItem> <QueryItem>
<VaultQueryFieldName> ::=
createtime |
displayname |
@@ -5710,7 +5773,7 @@ gam create|add user <EmailAddress> [ignorenullpassword] <UserAttribute>*
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
[alias|aliases <EmailAddressList>]
[license <SKUIDList> [product|productid <ProductID>]]
[notify <EmailAddressList>
[[notify <EmailAddressList>] [notifyrecoveryemail]
[subject <String>]
[notifypassword <String>]
[from <EmailAaddress>]
@@ -5736,7 +5799,7 @@ gam update user <UserItem> [ignorenullpassword] <UserAttribute>*
[createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
[alias|aliases <EmailAddressList>]
[notify <EmailAddressList>
[[notify <EmailAddressList>] [notifyrecoveryemail]
[subject <String>]
[notifypassword <String>]
[from <EmailAaddress>]
@@ -5774,7 +5837,7 @@ gam update users <UserTypeEntity> [ignorenullpassword] <UserAttribute>*
[createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
[alias|aliases <EmailAddressList>]
[notify <EmailAddressList>
[[notify <EmailAddressList>] [notifyrecoveryemail]
[subject <String>]
[notifypassword <String>]
[from <EmailAddress>]
@@ -5811,7 +5874,7 @@ gam <UserTypeEntity> update users [ignorenullpassword] <UserAttribute>*
[createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
[alias|aliases <EmailAddressList>]
[notify <EmailAddressList>
[[notify <EmailAddressList>] [notifyrecoveryemail]
[subject <String>]
[notifypassword <String>]
[from <EmailAaddress>]
@@ -5856,7 +5919,7 @@ gam print users [todrive <ToDriveAttribute>*]
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
[issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
[showitemcountonly]
@@ -5873,7 +5936,7 @@ gam print users [todrive <ToDriveAttribute>*] select <UserTypeEntity>
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
[issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
[showitemcountonly]
@@ -5888,7 +5951,7 @@ gam <UserTypeEntity> print users [todrive <ToDriveAttribute>*]
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
[issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
[showitemcountonly]
@@ -5909,7 +5972,7 @@ gam print users [todrive <ToDriveAttribute>*]
([domain|domains <DomainNameEntity>] [(query <QueryUser>)|(queries <QueryUserList>)]
[limittoou <OrgUnitItem>] [deleted_only|only_deleted])
[formatjson [quotechar <Character>]] [countsonly|countonly]
[issuspended <Boolean>]
[issuspended <Boolean>] [isarchived <Boolean>]
Print user domain counts for specified users.
@@ -6256,12 +6319,11 @@ gam <UserTypeEntity> info events <UserCalendarEntity> [<EventEntity>] [maxinstan
[formatjson]
gam <UserTypeEntity> show events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek]
[countsonly]
[formatjson]
[countsonly|formatjson]
gam <UserTypeEntity> print events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek]
[countsonly [eventrowfilter]]
[formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*]
[eventrowfilter]]
[countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
gam <UserTypeEntity> update calattendees <UserCalendarEntity> <EventEntity> [anyorganizer]
[<EventNotificationAttribute>] [splitupdate] [dryrun|doit]
@@ -6688,7 +6750,7 @@ gam <UserTypeEntity> create|add drivefile
[(localfile <FileName>|-)|(url <URL>)]
[(drivefilename|newfilename <DriveFileName>) | (replacefilename <REMatchPattern> <RESubstitution>)*]
[stripnameprefix <String>] [noduplicate]
[timestamp [<Boolean>]] [timeformat <String>]
[timestamp [<Boolean>]] [timeformat <DateTimeFormat>]
<DriveFileCreateAttribute>*
[(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> currenttime|<String>)*) |
(returnidonly|returnlinkonly|returneditlinkonly|showdetails)]
@@ -6709,7 +6771,7 @@ gam <UserTypeEntity> update drivefile <DriveFileEntity> [copy] [returnidonly|ret
[(localfile <FileName>|-)|(url <URL>)]
[retainname | (newfilename <DriveFileName>) | (replacefilename <REMatchPattern> <RESubstitution>)*]
[stripnameprefix <String>]
[timestamp [<Boolean>]] [timeformat <String>]
[timestamp [<Boolean>]] [timeformat <DateTimeFormat>]
<DriveFileUpdateAttribute>*
[(gsheet|csvsheet <SheetEntity> [clearfilter])|(addsheet <String>)]
[charset <Charset>] [columndelimiter <Character>]
@@ -6896,7 +6958,7 @@ gam <UserTypeEntity> create|add drivefileacl <DriveFileEntity> [adminaccess|asad
anyone|(user <UserItem>)|(group <GroupItem>)|(domain <DomainName>) (role <DriveFileACLRole>)
[withlink|(allowfilediscovery|discoverable [<Boolean>])] [expiration <Time>]
[moveToNewOwnersRoot [<Boolean>]]
[sendemail] [emailmessage <String>]
[sendemail|sendnotification] [emailmessage <String>]
[updatesheetprotectedranges [<Boolean>]]
[showtitles] [nodetails|(csv [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]])]
gam <UserTypeEntity> update drivefileacl <DriveFileEntity> <DriveFilePermissionIDorEmail>
@@ -6922,7 +6984,7 @@ gam <UserTypeEntity> print drivefileacls <DriveFileEntity> [todrive <ToDriveAttr
(orderby <DriveFileOrderByFieldName> [ascending|descending])*
[formatjson [quotechar <Character>]]
gam <UserTypeEntity> create|add permissions <DriveFileEntity> <DriveFilePermissionEntity>
[expires|expiration <Time>] [sendemail] [emailmessage <String>]
[expires|expiration <Time>] [sendemail|sendnotification] [emailmessage <String>]
[movetonewownersroot [<Boolean>]]
<PermissionMatch>* [<PermissionMatchAction>]
gam <UserTypeEntity> delete permissions <DriveFileEntity> <DriveFilePermissionIDEntity>
@@ -8285,13 +8347,13 @@ gam <UserTypeEntity> info contacts
gam <UserTypeEntity> show contacts
<PeoplePrintShowUserContactSelection>
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
[countsonly|allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
[formatjson]
[allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
[countsonly|formatjson]
gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*]
<PeoplePrintShowUserContactSelection>
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
[countsonly|allfields|(fields <PeopleFieldNameList>)] [[showgroups|showgroupnameslist] showmetadata]
[formatjson [quotechar <Character>]]
[allfields|(fields <PeopleFieldNameList>)] [[showgroups|showgroupnameslist] showmetadata]
[countsonly|(formatjson [quotechar <Character>])]
<OtherContactsFieldName> ::=
emailaddresses|
@@ -8525,7 +8587,7 @@ gam <UserTypeEntity> info tasklist <TasklistEntity>
gam <UserTypeEntity> show tasklists
[countsonly|formatjson]
gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*]
[countsonly | (formatjson [quotechar <Character>])]
[countsonly|(formatjson [quotechar <Character>])]
# Users - Shared Drives
@@ -8591,7 +8653,7 @@ gam <UserTypeEntity> print shareddriveorganizers [todrive <ToDriveAttribute>*]
[shownorganizerdrives [false|true|only]]
[includefileorganizers [<Boolean>]]
[delimiter <Character>]
# Users - Force Signout and Turn Off 2-Step Verification
gam <UserTypeEntity> signout

View File

@@ -1,3 +1,195 @@
7.24.00
If you want to disable a user's service account access to Drive and Sheets but still allow reading command data from Google Docs and Sheets,
issue the following command and make these settings:
```
gam user user@domain.com update serviceaccount
[ ] 20) Drive API (supports readonly)
[*] 21) Drive API - read command data
[ ] 42) Sheets API (supports readonly)
[*] 43) Sheets API - read command data
```
7.23.07
Fixed bug in `gam print|show admins` where all admin assignments were not displayed when
`types <AdminAssigneeTypeList>` was not specified, i.e., all assignments should be displayed.
7.23.06
Added option `types <AdminAssigneeTypeList>` to `gam print|show admins` that allows filtering
of admin assignments by the type of the assignee; by default, all assignee types are displayed.
```
<AdminAssigneeType> ::= group|user|serviceaccount|unknown
<AdminAssigneeTypeList> ::= "<AdminAssigneeType>(,<AdminAssigneeType>)*"
```
7.23.05
Added option `recursive` that will display assignments to the members
of security groups assigned to roles; the security group membership is recursively expanded.
7.23.04
Added option `addcsvdata <FieldName> <String>` to `gam <UserTypeEntity> print events`
and `gam calendars <CalendarEntity> print events` that adds additional columns of data to the CSV file output.
An example would be to get the calendar name in addition to the calendar ID when printing events.
```
gam redirect csv ./Resources.csv print resources fields email,name
gam redirect csv ./ResourceEventCounts.csv multiprocess redirect stderr - multiprocess csv Resources.csv gam calendar "~resourceEmail" print events starttime -1y countsonly addcsvdata calendarName "~resourceName"
```
Upgraded to OpenSSL 3.6.0.
7.23.03
Upgraded to OpenSSL 3.5.4.
7.23.02
Added option `oneitemperrow` to 'gam print course-materials|course-work` to have each of a
course's materials displayed on a separate row with all of the other course fields.
This produces a CSV file that can be used in subsequent commands to process the materials without further script processing.
7.23.00
Added `chat_max_results` variable to `gam.cfg`.
```
chat_max_results
When retrieving lists of Chat items from API,
how many should be retrieved in each API call
Default: 100
Range: 1 - 1000
```
Previously, this vaule was always set to 1000 which could cause errors.
7.22.07
Added options `showdetails` and `returnidonly` to `gam create|copy vaultquery`.
Added option `<JSONData>` to `gam create vaultexport|vaultquery` and `gam print vaultcounts`.
7.22.06
Added commands to create, copy and delete Vault saved queries.
```
gam create vaultquery <MatterItem> [name <String>]
corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
[scope all_data|held_data|unprocessed_data]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(documentids (<DriveFileIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
[driveversiondate <Date>|<Time>]
[includerooms <Boolean>]
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
(covereddata calllogs|textmessages|voicemails)*
[shownames] [formatjson]
gam copy vaultquery <MatterItem> <QueryItem> [targetmatter <MatterItem>] [name <String>]
[shownames] [formatjson]
gam delete vaultquery <QueryItem> matter <MatterItem>
gam delete vaultquery <MatterItem> <QueryItem>
```
Added a variant of `gam print vaultcounts` that gets its query parameters from a saved Vault query.
```
gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem> <QueryItem>
[wait <Integer>]
```
7.22.05
Added a variant of `gam create vaultexport` that gets its query parameters from a saved Vault query.
```
gam create vaultexport|export matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[driveclientsideencryption any|encrypted|unencrypted]
[includeaccessinfo <Boolean>]
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
[format ics|mbox|pst|xml]
[region any|europe|us] [showdetails|returnidonly]
```
7.22.04
Added a variant of `gam create vaulthold` that gets its parameters from a saved Vault query.
```
gam create vaulthold matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[showdetails|returnidonly]
```
7.22.03
Fix backwards compatability bug introduced in 7.22.00 for `gam print users` that changed `suspended`
from a field name to a query option; it is now correctly interpreted as a field name.
7.22.02
An update to the httplib2 library caused GAM proxy connections to fail; this has been fixed
by including the pysocks library needed by the latest httplib2 library.
7.22.00
Expanded `<UserTypeEntity>` to allow specification of non-archived/archived users.
* See [Collections of Users](Collections-of-Users)
These commands have been updated:
* `gam print aliases`
* `gam update groups`
* `gam info orgs`
* `gam print orgs`
* `gam print users`
Added `datetime <DateTimeFormat>` command that can be embedded in Gam batch files. The current time is formatted with `<DateTimeFormat>`
and subsequent lines in `<BatchContent>` will have `%datetime%` replaced with the formatted time value.
See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
7.21.03
Added option `notifyrecoveryemail` to `gam create user` and `gam <UserTypeEntity> update user password <String>`
that sends the passsword notification email to the user's recovery email address (if defined).
7.21.02
GAM now builds on macOS 26 Tahoe and properly identifies the OS.
A custom build of the cryptography library is no longer needed for Windows arm64 builds as the project now releases their own build for the OS.
Upgraded to OpenSSL 3.5.3.
7.21.01
Replaced datetime, dateutil, calendar and iso8601 Python libraries with arrow library.
This should have no performance impact; report any problems.
You can now use timezone names when setting `timezone` in `gam.cfg`.
* See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
```
gam config timezone America/Los_Angeles save
```
7.20.04
Cleaned up Python library imports: googleapiclient, iso8601.
7.20.03
Rebranded license SKU `1010470004` from `Gemini Education` to `Google AI Pro for Education`.
Additional updates to student groups in Google Classroom.
7.20.02
Upgraded `gam create course-studentgroups` to allow specification of multiple student group titles;

View File

@@ -1,747 +0,0 @@
# Operating CA: DigiCert
# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
# Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com
# Label: "DigiCert Assured ID Root CA"
# Serial: 17154717934120587862167794914071425081
# MD5 Fingerprint: 87:ce:0b:7b:2a:0e:49:00:e1:58:71:9b:37:a8:93:72
# SHA1 Fingerprint: 05:63:b8:63:0d:62:d7:5a:bb:c8:ab:1e:4b:df:b5:a8:99:b2:4d:43
# SHA256 Fingerprint: 3e:90:99:b5:01:5e:8f:48:6c:00:bc:ea:9d:11:1e:e7:21:fa:ba:35:5a:89:bc:f1:df:69:56:1e:3d:c6:32:5c
-----BEGIN CERTIFICATE-----
MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
-----END CERTIFICATE-----
# Operating CA: DigiCert
# Issuer: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com
# Subject: CN=DigiCert Assured ID Root G2 O=DigiCert Inc OU=www.digicert.com
# Label: "DigiCert Assured ID Root G2"
# Serial: 15385348160840213938643033620894905419
# MD5 Fingerprint: 92:38:b9:f8:63:24:82:65:2c:57:33:e6:fe:81:8f:9d
# SHA1 Fingerprint: a1:4b:48:d9:43:ee:0a:0e:40:90:4f:3c:e0:a4:c0:91:93:51:5d:3f
# SHA256 Fingerprint: 7d:05:eb:b6:82:33:9f:8c:94:51:ee:09:4e:eb:fe:fa:79:53:a1:14:ed:b2:f4:49:49:45:2f:ab:7d:2f:c1:85
-----BEGIN CERTIFICATE-----
MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG
EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA
n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc
biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp
EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA
bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu
YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB
AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW
BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI
QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I
0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni
lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9
B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv
ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
IhNzbM8m9Yop5w==
-----END CERTIFICATE-----
# Operating CA: DigiCert
# Issuer: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com
# Subject: CN=DigiCert Assured ID Root G3 O=DigiCert Inc OU=www.digicert.com
# Label: "DigiCert Assured ID Root G3"
# Serial: 15459312981008553731928384953135426796
# MD5 Fingerprint: 7c:7f:65:31:0c:81:df:8d:ba:3e:99:e2:5c:ad:6e:fb
# SHA1 Fingerprint: f5:17:a2:4f:9a:48:c6:c9:f8:a2:00:26:9f:dc:0f:48:2c:ab:30:89
# SHA256 Fingerprint: 7e:37:cb:8b:4c:47:09:0c:ab:36:55:1b:a6:f4:5d:b8:40:68:0f:ba:16:6a:95:2d:b1:00:71:7f:43:05:3f:c2
-----BEGIN CERTIFICATE-----
MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw
CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg
RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV
UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq
hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf
Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q
RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD
AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY
JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv
6pZjamVFkpUBtA==
-----END CERTIFICATE-----
# Operating CA: DigiCert
# Issuer: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
# Subject: CN=DigiCert Global Root CA O=DigiCert Inc OU=www.digicert.com
# Label: "DigiCert Global Root CA"
# Serial: 10944719598952040374951832963794454346
# MD5 Fingerprint: 79:e4:a9:84:0d:7d:3a:96:d7:c0:4f:e2:43:4c:89:2e
# SHA1 Fingerprint: a8:98:5d:3a:65:e5:e5:c4:b2:d7:d6:6d:40:c6:dd:2f:b1:9c:54:36
# SHA256 Fingerprint: 43:48:a0:e9:44:4c:78:cb:26:5e:05:8d:5e:89:44:b4:d8:4f:96:62:bd:26:db:25:7f:89:34:a4:43:c7:01:61
-----BEGIN CERTIFICATE-----
MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
-----END CERTIFICATE-----
# Operating CA: DigiCert
# Issuer: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com
# Subject: CN=DigiCert Global Root G2 O=DigiCert Inc OU=www.digicert.com
# Label: "DigiCert Global Root G2"
# Serial: 4293743540046975378534879503202253541
# MD5 Fingerprint: e4:a6:8a:c8:54:ac:52:42:46:0a:fd:72:48:1b:2a:44
# SHA1 Fingerprint: df:3c:24:f9:bf:d6:66:76:1b:26:80:73:fe:06:d1:cc:8d:4f:82:a4
# SHA256 Fingerprint: cb:3c:cb:b7:60:31:e5:e0:13:8f:8d:d3:9a:23:f9:de:47:ff:c3:5e:43:c1:14:4c:ea:27:d4:6a:5a:b1:cb:5f
-----BEGIN CERTIFICATE-----
MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
MrY=
-----END CERTIFICATE-----
# Operating CA: DigiCert
# Issuer: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com
# Subject: CN=DigiCert Global Root G3 O=DigiCert Inc OU=www.digicert.com
# Label: "DigiCert Global Root G3"
# Serial: 7089244469030293291760083333884364146
# MD5 Fingerprint: f5:5d:a4:50:a5:fb:28:7e:1e:0f:0d:cc:96:57:56:ca
# SHA1 Fingerprint: 7e:04:de:89:6a:3e:66:6d:00:e6:87:d3:3f:fa:d9:3b:e8:3d:34:9e
# SHA256 Fingerprint: 31:ad:66:48:f8:10:41:38:c7:38:f3:9e:a4:32:01:33:39:3e:3a:18:cc:02:29:6e:f9:7c:2a:c9:ef:67:31:d0
-----BEGIN CERTIFICATE-----
MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw
CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe
Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw
EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF
K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG
fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO
Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd
BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx
AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/
oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8
sycX
-----END CERTIFICATE-----
# Operating CA: DigiCert
# Issuer: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
# Subject: CN=DigiCert High Assurance EV Root CA O=DigiCert Inc OU=www.digicert.com
# Label: "DigiCert High Assurance EV Root CA"
# Serial: 3553400076410547919724730734378100087
# MD5 Fingerprint: d4:74:de:57:5c:39:b2:d3:9c:85:83:c5:c0:65:49:8a
# SHA1 Fingerprint: 5f:b7:ee:06:33:e2:59:db:ad:0c:4c:9a:e6:d3:8f:1a:61:c7:dc:25
# SHA256 Fingerprint: 74:31:e5:f4:c3:c1:ce:46:90:77:4f:0b:61:e0:54:40:88:3b:a9:a0:1e:d0:0b:a6:ab:d7:80:6e:d3:b1:18:cf
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
+OkuE6N36B9K
-----END CERTIFICATE-----
# Operating CA: DigiCert
# Issuer: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com
# Subject: CN=DigiCert Trusted Root G4 O=DigiCert Inc OU=www.digicert.com
# Label: "DigiCert Trusted Root G4"
# Serial: 7451500558977370777930084869016614236
# MD5 Fingerprint: 78:f2:fc:aa:60:1f:2f:b4:eb:c9:37:ba:53:2e:75:49
# SHA1 Fingerprint: dd:fb:16:cd:49:31:c9:73:a2:03:7d:3f:c8:3a:4d:7d:77:5d:05:e4
# SHA256 Fingerprint: 55:2f:7b:dc:f1:a7:af:9e:6c:e6:72:01:7f:4f:12:ab:f7:72:40:c7:8e:76:1a:c2:03:d1:d9:d2:0a:c8:99:88
-----BEGIN CERTIFICATE-----
MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg
RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV
UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG
SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y
ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If
xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV
ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO
DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ
jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/
CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi
EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM
fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY
uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK
chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t
9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2
SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd
+SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc
fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa
sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N
cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N
0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie
4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI
r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1
/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm
gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+
-----END CERTIFICATE-----
# Operating CA: GlobalSign
# Issuer: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
# Subject: CN=GlobalSign Root CA O=GlobalSign nv-sa OU=Root CA
# Label: "GlobalSign Root CA"
# Serial: 4835703278459707669005204
# MD5 Fingerprint: 3e:45:52:15:09:51:92:e1:b7:5d:37:9f:b1:87:29:8a
# SHA1 Fingerprint: b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c
# SHA256 Fingerprint: eb:d4:10:40:e4:bb:3e:c7:42:c9:e3:81:d3:1e:f2:a4:1a:48:b6:68:5c:96:e7:ce:f3:c1:df:6c:d4:33:1c:99
-----BEGIN CERTIFICATE-----
MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
-----END CERTIFICATE-----
# Operating CA: GlobalSign
# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R3
# Label: "GlobalSign Root CA - R3"
# Serial: 4835703278459759426209954
# MD5 Fingerprint: c5:df:b8:49:ca:05:13:55:ee:2d:ba:1a:c3:3e:b0:28
# SHA1 Fingerprint: d6:9b:56:11:48:f0:1c:77:c5:45:78:c1:09:26:df:5b:85:69:76:ad
# SHA256 Fingerprint: cb:b5:22:d7:b7:f1:27:ad:6a:01:13:86:5b:df:1c:d4:10:2e:7d:07:59:af:63:5a:7c:f4:72:0d:c9:63:c5:3b
-----BEGIN CERTIFICATE-----
MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
WD9f
-----END CERTIFICATE-----
# Operating CA: GlobalSign
# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5
# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign ECC Root CA - R5
# Label: "GlobalSign ECC Root CA - R5"
# Serial: 32785792099990507226680698011560947931244
# MD5 Fingerprint: 9f:ad:3b:1c:02:1e:8a:ba:17:74:38:81:0c:a2:bc:08
# SHA1 Fingerprint: 1f:24:c6:30:cd:a4:18:ef:20:69:ff:ad:4f:dd:5f:46:3a:1b:69:aa
# SHA256 Fingerprint: 17:9f:bc:14:8a:3d:d0:0f:d2:4e:a1:34:58:cc:43:bf:a7:f5:9c:81:82:d7:83:a5:13:f6:eb:ec:10:0c:89:24
-----BEGIN CERTIFICATE-----
MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk
MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH
bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc
8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke
hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI
KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg
515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO
xwy8p2Fp8fc74SrL+SvzZpA3
-----END CERTIFICATE-----
# Operating CA: GlobalSign
# Issuer: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6
# Subject: CN=GlobalSign O=GlobalSign OU=GlobalSign Root CA - R6
# Label: "GlobalSign Root CA - R6"
# Serial: 1417766617973444989252670301619537
# MD5 Fingerprint: 4f:dd:07:e4:d4:22:64:39:1e:0c:37:42:ea:d1:c6:ae
# SHA1 Fingerprint: 80:94:64:0e:b5:a7:a1:ca:11:9c:1f:dd:d5:9f:81:02:63:a7:fb:d1
# SHA256 Fingerprint: 2c:ab:ea:fe:37:d0:6c:a2:2a:ba:73:91:c0:03:3d:25:98:29:52:c4:53:64:73:49:76:3a:3a:b5:ad:6c:cf:69
-----BEGIN CERTIFICATE-----
MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg
MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh
bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx
MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET
MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ
KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI
xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k
ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD
aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw
LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw
1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX
k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2
SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h
bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n
WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY
rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce
MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD
AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu
bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt
Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61
55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj
vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf
cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz
oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp
nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs
pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v
JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R
8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4
5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
-----END CERTIFICATE-----
# Note: "GlobalSign Root CA - R7" not added on purpose. It is P-521.
# Operating CA: GoDaddy
# Issuer: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
# Subject: CN=Go Daddy Root Certificate Authority - G2 O=GoDaddy.com, Inc.
# Label: "Go Daddy Root Certificate Authority - G2"
# Serial: 0
# MD5 Fingerprint: 80:3a:bc:22:c1:e6:fb:8d:9b:3b:27:4a:32:1b:9a:01
# SHA1 Fingerprint: 47:be:ab:c9:22:ea:e8:0e:78:78:34:62:a7:9f:45:c2:54:fd:e6:8b
# SHA256 Fingerprint: 45:14:0b:32:47:eb:9c:c8:c5:b4:f0:d7:b5:30:91:f7:32:92:08:9e:6e:5a:63:e2:74:9d:d3:ac:a9:19:8e:da
-----BEGIN CERTIFICATE-----
MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
4uJEvlz36hz1
-----END CERTIFICATE-----
# Operating CA: GoDaddy
# Issuer: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
# Subject: CN=Starfield Root Certificate Authority - G2 O=Starfield Technologies, Inc.
# Label: "Starfield Root Certificate Authority - G2"
# Serial: 0
# MD5 Fingerprint: d6:39:81:c6:52:7e:96:69:fc:fc:ca:66:ed:05:f2:96
# SHA1 Fingerprint: b5:1c:06:7c:ee:2b:0c:3d:f8:55:ab:2d:92:f4:fe:39:d4:e7:0f:0e
# SHA256 Fingerprint: 2c:e1:cb:0b:f9:d2:f9:e1:02:99:3f:be:21:51:52:c3:b2:dd:0c:ab:de:1c:68:e5:31:9b:83:91:54:db:b7:f5
-----BEGIN CERTIFICATE-----
MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
-----END CERTIFICATE-----
# Operating CA: Sectigo
# Issuer: CN=COMODO Certification Authority O=COMODO CA Limited
# Subject: CN=COMODO Certification Authority O=COMODO CA Limited
# Label: "COMODO Certification Authority"
# Serial: 43390818032842818540635488309124489234
# MD5 Fingerprint: 20:E7:4F:82:C2:7E:94:80:34:82:8A:13:A9:17:1D:97
# SHA1 Fingerprint EE:86:93:87:FF:FD:83:49:AB:5A:D1:43:22:58:87:89:A4:57:B0:12
# SHA256 Fingerprint: 1A:0D:20:44:5D:E5:BA:18:62:D1:9E:F8:80:85:8C:BC:E5:01:02:B3:6E:8F:0A:04:0C:3C:69:E7:45:22:FE:6E
-----BEGIN CERTIFICATE-----
MIID0DCCArigAwIBAgIQIKTEf93f4cdTYwcTiHdgEjANBgkqhkiG9w0BAQUFADCB
gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xMTAxMDEwMDAw
MDBaFw0zMDEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
nKVIrLsm9wIDAQABo0IwQDAdBgNVHQ4EFgQUC1jli8ZMFTekQKkwqSG+RzZaVv8w
DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
ggEBAC/JxBwHO89hAgCx2SFRdXIDMLDEFh9sAIsQrK/xR9SuEDwMGvjUk2ysEDd8
t6aDZK3N3w6HM503sMZ7OHKx8xoOo/lVem0DZgMXlUrxsXrfViEGQo+x06iF3u6X
HWLrp+cxEmbDD6ZLLkGC9/3JG6gbr+48zuOcrigHoSybJMIPIyaDMouGDx8rEkYl
Fo92kANr3ryqImhrjKGsKxE5pttwwn1y6TPn/CbxdFqR5p2ErPioBhlG5qfpqjQi
pKGfeq23sqSaM4hxAjwu1nqyH6LKwN0vEJT9s4yEIHlG1QXUEOTS22RPuFvuG8Ug
R1uUq27UlTMdphVx8fiUylQ5PsE=
-----END CERTIFICATE-----
# Operating CA: Sectigo
# Issuer: CN=COMODO ECC Certification Authority O=COMODO CA Limited
# Subject: CN=COMODO ECC Certification Authority O=COMODO CA Limited
# Label: "COMODO ECC Certification Authority"
# Serial: 41578283867086692638256921589707938090
# MD5 Fingerprint: 7c:62:ff:74:9d:31:53:5e:68:4a:d5:78:aa:1e:bf:23
# SHA1 Fingerprint: 9f:74:4e:9f:2b:4d:ba:ec:0f:31:2c:50:b6:56:3b:8e:2d:93:c3:11
# SHA256 Fingerprint: 17:93:92:7a:06:14:54:97:89:ad:ce:2f:8f:34:f7:f0:b6:6d:0f:3a:e3:a3:b8:4d:21:ec:15:db:ba:4f:ad:c7
-----BEGIN CERTIFICATE-----
MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
-----END CERTIFICATE-----
# Operating CA: Sectigo
# Issuer: CN=COMODO RSA Certification Authority O=COMODO CA Limited
# Subject: CN=COMODO RSA Certification Authority O=COMODO CA Limited
# Label: "COMODO RSA Certification Authority"
# Serial: 101909084537582093308941363524873193117
# MD5 Fingerprint: 1b:31:b0:71:40:36:cc:14:36:91:ad:c4:3e:fd:ec:18
# SHA1 Fingerprint: af:e5:d2:44:a8:d1:19:42:30:ff:47:9f:e2:f8:97:bb:cd:7a:8c:b4
# SHA256 Fingerprint: 52:f0:e1:c4:e5:8e:c6:29:29:1b:60:31:7f:07:46:71:b8:5d:7e:a8:0d:5b:07:27:34:63:53:4b:32:b4:02:34
-----BEGIN CERTIFICATE-----
MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB
hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5
MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh
dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR
6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X
pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC
9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV
/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf
Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z
+pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w
qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah
SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC
u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf
Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq
crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl
wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM
4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV
2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna
FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ
CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK
boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke
jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL
S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb
QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl
0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB
NVOFBkpdn627G190
-----END CERTIFICATE-----
# Operating CA: Sectigo
# Issuer: CN=USERTrust ECC Certification Authority O=The USERTRUST Network
# Subject: CN=USERTrust ECC Certification Authority O=The USERTRUST Network
# Label: "USERTrust ECC Certification Authority"
# Serial: 123013823720199481456569720443997572134
# MD5 Fingerprint: fa:68:bc:d9:b5:7f:ad:fd:c9:1d:06:83:28:cc:24:c1
# SHA1 Fingerprint: d1:cb:ca:5d:b2:d5:2a:7f:69:3b:67:4d:e5:f0:5a:1d:0c:95:7d:f0
# SHA256 Fingerprint: 4f:f4:60:d5:4b:9c:86:da:bf:bc:fc:57:12:e0:40:0d:2b:ed:3f:bc:4d:4f:bd:aa:86:e0:6a:dc:d2:a9:ad:7a
-----BEGIN CERTIFICATE-----
MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL
MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl
eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT
JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx
MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg
VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm
aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo
I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng
o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G
A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD
VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB
zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW
RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
-----END CERTIFICATE-----
# Operating CA: Sectigo
# Issuer: CN=USERTrust RSA Certification Authority O=The USERTRUST Network
# Subject: CN=USERTrust RSA Certification Authority O=The USERTRUST Network
# Label: "USERTrust RSA Certification Authority"
# Serial: 2645093764781058787591871645665788717
# MD5 Fingerprint: 1b:fe:69:d1:91:b7:19:33:a3:72:a8:0f:e1:55:e5:b5
# SHA1 Fingerprint: 2b:8f:1b:57:33:0d:bb:a2:d0:7a:6c:51:f7:0e:e9:0d:da:b9:ad:8e
# SHA256 Fingerprint: e7:93:c9:b0:2f:d8:aa:13:e2:1c:31:22:8a:cc:b0:81:19:64:3b:74:9c:89:89:64:b1:74:6d:46:c3:d4:cb:d2
-----BEGIN CERTIFICATE-----
MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw
MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV
BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy
dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B
3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/
Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2
VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT
79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6
c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT
Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l
c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee
UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE
Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G
A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF
Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO
VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3
ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs
8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR
iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze
Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ
XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/
qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB
VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
jjxDah2nGN59PRbxYvnKkKj9
-----END CERTIFICATE-----
# Operating CA: Google Trust Services LLC
# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R1
# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R1
# Label: "GTS Root R1"
# Serial: 0203E5936F31B01349886BA217
# MD5 Fingerprint: 05:FE:D0:BF:71:A8:A3:76:63:DA:01:E0:D8:52:DC:40
# SHA1 Fingerprint: E5:8C:1C:C4:91:3B:38:63:4B:E9:10:6E:E3:AD:8E:6B:9D:D9:81:4A
# SHA256 Fingerprint: D9:47:43:2A:BD:E7:B7:FA:90:FC:2E:6B:59:10:1B:12:80:E0:E1:C7:E4:E4:0F:A3:C6:88:7F:FF:57:A7:F4:CF
-----BEGIN CERTIFICATE-----
MIIFVzCCAz+gAwIBAgINAgPlk28xsBNJiGuiFzANBgkqhkiG9w0BAQwFADBHMQsw
CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
MBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEBAQUA
A4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaMf/vo
27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vXmX7w
Cl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7zUjw
TcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0Pfybl
qAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtcvfaH
szVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4Zor8
Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUspzBmk
MiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOORc92
wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYWk70p
aDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+DVrN
VjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgFlQID
AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
FgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBAJ+qQibb
C5u+/x6Wki4+omVKapi6Ist9wTrYggoGxval3sBOh2Z5ofmmWJyq+bXmYOfg6LEe
QkEzCzc9zolwFcq1JKjPa7XSQCGYzyI0zzvFIoTgxQ6KfF2I5DUkzps+GlQebtuy
h6f88/qBVRRiClmpIgUxPoLW7ttXNLwzldMXG+gnoot7TiYaelpkttGsN/H9oPM4
7HLwEXWdyzRSjeZ2axfG34arJ45JK3VmgRAhpuo+9K4l/3wV3s6MJT/KYnAK9y8J
ZgfIPxz88NtFMN9iiMG1D53Dn0reWVlHxYciNuaCp+0KueIHoI17eko8cdLiA6Ef
MgfdG+RCzgwARWGAtQsgWSl4vflVy2PFPEz0tv/bal8xa5meLMFrUKTX5hgUvYU/
Z6tGn6D/Qqc6f1zLXbBwHSs09dR2CQzreExZBfMzQsNhFRAbd03OIozUhfJFfbdT
6u9AWpQKXCBfTkBdYiJ23//OYb2MI3jSNwLgjt7RETeJ9r/tSQdirpLsQBqvFAnZ
0E6yove+7u7Y/9waLd64NnHi/Hm3lCXRSHNboTXns5lndcEZOitHTtNCjv0xyBZm
2tIMPNuzjsmhDYAPexZ3FL//2wmUspO8IFgV6dtxQ/PeEMMA3KgqlbbC1j+Qa3bb
bP6MvPJwNQzcmRk13NfIRmPVNnGuV/u3gm3c
-----END CERTIFICATE-----
# Operating CA: Google Trust Services LLC
# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R2
# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R2
# Label: "GTS Root R2"
# Serial: 0203E5AEC58D04251AAB1125AA
# MD5 Fingerprint=1E:39:C0:53:E6:1E:29:82:0B:CA:52:55:36:5D:57:DC
# SHA1 Fingerprint=9A:44:49:76:32:DB:DE:FA:D0:BC:FB:5A:7B:17:BD:9E:56:09:24:94
# SHA256 Fingerprint=8D:25:CD:97:22:9D:BF:70:35:6B:DA:4E:B3:CC:73:40:31:E2:4C:F0:0F:AF:CF:D3:2D:C7:6E:B5:84:1C:7E:A8
-----BEGIN CERTIFICATE-----
MIIFVzCCAz+gAwIBAgINAgPlrsWNBCUaqxElqjANBgkqhkiG9w0BAQwFADBHMQsw
CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
MBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEBAQUA
A4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3LvCvpt
nfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3KgGjSY
6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9BuXvAu
MC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOdre7k
RXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXuPuWg
f9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1mKPV
+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K8Yzo
dDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqjx5RW
Ir9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsRnTKa
G73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0kzCq
gc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9OktwID
AQABo0IwQDAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
FgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBAB/Kzt3H
vqGf2SdMC9wXmBFqiN495nFWcrKeGk6c1SuYJF2ba3uwM4IJvd8lRuqYnrYb/oM8
0mJhwQTtzuDFycgTE1XnqGOtjHsB/ncw4c5omwX4Eu55MaBBRTUoCnGkJE+M3DyC
B19m3H0Q/gxhswWV7uGugQ+o+MePTagjAiZrHYNSVc61LwDKgEDg4XSsYPWHgJ2u
NmSRXbBoGOqKYcl3qJfEycel/FVL8/B/uWU9J2jQzGv6U53hkRrJXRqWbTKH7QMg
yALOWr7Z6v2yTcQvG99fevX4i8buMTolUVVnjWQye+mew4K6Ki3pHrTgSAai/Gev
HyICc/sgCq+dVEuhzf9gR7A/Xe8bVr2XIZYtCtFenTgCR2y59PYjJbigapordwj6
xLEokCZYCDzifqrXPW+6MYgKBesntaFJ7qBFVHvmJ2WZICGoo7z7GJa7Um8M7YNR
TOlZ4iBgxcJlkoKM8xAfDoqXvneCbT+PHV28SSe9zE8P4c52hgQjxcCMElv924Sg
JPFI/2R80L5cFtHvma3AH/vLrrw4IgYmZNralw4/KBVEqE8AyvCazM90arQ+POuV
7LXTWtiBmelDGDfrs7vRWGJB82bSj6p4lVQgw1oudCvV0b4YacCs1aTPObpRhANl
6WLAYv7YTVWW4tAR+kg0Eeye7QUd5MjWHYbL
-----END CERTIFICATE-----
# Operating CA: Google Trust Services LLC
# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R3
# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R3
# Label: "GTS Root R3"
# Serial: 0203E5B882EB20F825276D3D66
# MD5 Fingerprint: 3E:E7:9D:58:02:94:46:51:94:E5:E0:22:4A:8B:E7:73
# SHA1 Fingerprint: ED:E5:71:80:2B:C8:92:B9:5B:83:3C:D2:32:68:3F:09:CD:A0:1E:46
# SHA256 Fingerprint: 34:D8:A7:3E:E2:08:D9:BC:DB:0D:95:65:20:93:4B:4E:40:E6:94:82:59:6E:8B:6F:73:C8:42:6B:01:0A:6F:48
-----BEGIN CERTIFICATE-----
MIICCTCCAY6gAwIBAgINAgPluILrIPglJ209ZjAKBggqhkjOPQQDAzBHMQswCQYD
VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG
A1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw
WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz
IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
AAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout736G
jOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2ADDL2
4CejQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
BBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEA9uEglRR7
VKOQFhG/hMjqb2sXnh5GmCCbn9MN2azTL818+FsuVbu/3ZL3pAzcMeGiAjEA/Jdm
ZuVDFhOD3cffL74UOO0BzrEXGhF16b0DjyZ+hOXJYKaV11RZt+cRLInUue4X
-----END CERTIFICATE-----
# Operating CA: Google Trust Services LLC
# Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R4
# Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R4
# Label: "GTS Root R4"
# Serial: 0203E5C068EF631A9C72905052
# MD5 Fingerprint=43:96:83:77:19:4D:76:B3:9D:65:52:E4:1D:22:A5:E8
# SHA1 Fingerprint=77:D3:03:67:B5:E0:0C:15:F6:0C:38:61:DF:7C:E1:3B:92:46:4D:47
# SHA256 Fingerprint=34:9D:FA:40:58:C5:E2:63:12:3B:39:8A:E7:95:57:3C:4E:13:13:C8:3F:E6:8F:93:55:6C:D5:E8:03:1B:3C:7D
-----BEGIN CERTIFICATE-----
MIICCTCCAY6gAwIBAgINAgPlwGjvYxqccpBQUjAKBggqhkjOPQQDAzBHMQswCQYD
VQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEUMBIG
A1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAwMDAw
WjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2Vz
IExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQAIgNi
AATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzuhXyi
QHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/lxKvR
HYqjQjBAMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
BBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNpADBmAjEA6ED/g94D
9J+uHXqnLrmvT/aDHQ4thQEd0dlq7A/Cr8deVl5c1RxYIigL9zC2L7F8AjEA8GE8
p/SgguMh1YQdc4acLa/KNJvxn7kjNuK8YAOdgLOaVsjh4rsUecrNIdSUtUlD
-----END CERTIFICATE-----
# Operating CA: Google Trust Services LLC
# Subject: OU = GlobalSign ECC Root CA - R4, O = GlobalSign, CN = GlobalSign
# Issuer: OU = GlobalSign ECC Root CA - R4, O = GlobalSign, CN = GlobalSign
# Label: "GlobalSign R4"
# Serial: 0203E57EF53F93FDA50921B2A6
# MD5 Fingerprint: 26:29:F8:6D:E1:88:BF:A2:65:7F:AA:C4:CD:0F:7F:FC
# SHA1 Fingerprint: 6B:A0:B0:98:E1:71:EF:5A:AD:FE:48:15:80:77:10:F4:BD:6F:0B:28
# SHA256 Fingerprint: B0:85:D7:0B:96:4F:19:1A:73:E4:AF:0D:54:AE:7A:0E:07:AA:FD:AF:9B:71:DD:08:62:13:8A:B7:32:5A:24:A2
-----BEGIN CERTIFICATE-----
MIIB3DCCAYOgAwIBAgINAgPlfvU/k/2lCSGypjAKBggqhkjOPQQDAjBQMSQwIgYD
VQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0gUjQxEzARBgNVBAoTCkdsb2Jh
bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTIxMTEzMDAwMDAwWhcNMzgw
MTE5MDMxNDA3WjBQMSQwIgYDVQQLExtHbG9iYWxTaWduIEVDQyBSb290IENBIC0g
UjQxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wWTAT
BgcqhkjOPQIBBggqhkjOPQMBBwNCAAS4xnnTj2wlDp8uORkcA6SumuU5BwkWymOx
uYb4ilfBV85C+nOh92VC/x7BALJucw7/xyHlGKSq2XE/qNS5zowdo0IwQDAOBgNV
HQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUVLB7rUW44kB/
+wpu+74zyTyjhNUwCgYIKoZIzj0EAwIDRwAwRAIgIk90crlgr/HmnKAWBVBfw147
bmF0774BxL4YSFlhgjICICadVGNA3jdgUM/I2O2dgq43mLyjj0xMqTQrbO/7lZsm
-----END CERTIFICATE-----

View File

@@ -33,7 +33,6 @@ datas += [('gam/contactdelegation-v1.json', '.')]
datas += [('gam/datastudio-v1.json', '.')]
datas += [('gam/meet-v2beta.json', '.')]
datas += [('gam/serviceaccountlookup-v1.json', '.')]
datas += [('cacerts.pem', '.')]
hiddenimports = [
'gam.gamlib.yubikey',
]
@@ -49,7 +48,7 @@ a = Analysis(
binaries=[],
datas=datas,
hiddenimports=hiddenimports,
hookspath=[],
hookspath=['tools/hooks'],
hooksconfig={},
runtime_hooks=runtime_hooks,
excludes=excludes,

File diff suppressed because it is too large Load Diff

View File

@@ -60,6 +60,7 @@ DIRECTORY = 'directory'
DOCS = 'docs'
DRIVE2 = 'drive2'
DRIVE3 = 'drive3'
DRIVECD = 'drivecd'
DRIVETD = 'drivetd'
DRIVEACTIVITY = 'driveactivity'
DRIVELABELS = 'drivelabels'
@@ -91,6 +92,7 @@ SERVICEACCOUNTLOOKUP = 'serviceaccountlookup'
SERVICEMANAGEMENT = 'servicemanagement'
SERVICEUSAGE = 'serviceusage'
SHEETS = 'sheets'
SHEETSCD = 'sheetscd'
SHEETSTD = 'sheetstd'
SITEVERIFICATION = 'siteVerification'
STORAGE = 'storage'
@@ -253,7 +255,8 @@ _INFO = {
DOCS: {'name': 'Docs API', 'version': 'v1', 'v2discovery': True},
DRIVE2: {'name': 'Drive API v2', 'version': 'v2', 'v2discovery': False, 'mappedAPI': 'drive'},
DRIVE3: {'name': 'Drive API v3', 'version': 'v3', 'v2discovery': False, 'mappedAPI': 'drive'},
DRIVETD: {'name': 'Drive API v3 - todrive', 'version': 'v3', 'v2discovery': False, 'mappedAPI': 'drive'},
DRIVECD: {'name': 'Drive API v3 - read command data', 'version': 'v3', 'v2discovery': False, 'mappedAPI': 'drive'},
DRIVETD: {'name': 'Drive API v3 - write todrive data', 'version': 'v3', 'v2discovery': False, 'mappedAPI': 'drive'},
DRIVEACTIVITY: {'name': 'Drive Activity API v2', 'version': 'v2', 'v2discovery': True},
DRIVELABELS_ADMIN: {'name': 'Drive Labels API - Admin', 'version': 'v2', 'v2discovery': True, 'mappedAPI': DRIVELABELS},
DRIVELABELS_USER: {'name': 'Drive Labels API - User', 'version': 'v2', 'v2discovery': True, 'mappedAPI': DRIVELABELS},
@@ -283,7 +286,8 @@ _INFO = {
SERVICEMANAGEMENT: {'name': 'Service Management API', 'version': 'v1', 'v2discovery': True},
SERVICEUSAGE: {'name': 'Service Usage API', 'version': 'v1', 'v2discovery': True},
SHEETS: {'name': 'Sheets API', 'version': 'v4', 'v2discovery': True},
SHEETSTD: {'name': 'Sheets API - todrive', 'version': 'v4', 'v2discovery': True, 'mappedAPI': SHEETS},
SHEETSCD: {'name': 'Sheets API - read command data', 'version': 'v4', 'v2discovery': True, 'mappedAPI': SHEETS},
SHEETSTD: {'name': 'Sheets API - write todrive data', 'version': 'v4', 'v2discovery': True, 'mappedAPI': SHEETS},
SITEVERIFICATION: {'name': 'Site Verification API', 'version': 'v1', 'v2discovery': True},
STORAGE: {'name': 'Cloud Storage API', 'version': 'v1', 'v2discovery': True},
STORAGEREAD: {'name': 'Cloud Storage API - Read', 'version': 'v1', 'v2discovery': True, 'mappedAPI': STORAGE},
@@ -750,9 +754,15 @@ _SVCACCT_SCOPES = [
]
_SVCACCT_SPECIAL_SCOPES = [
{'name': 'Drive API - todrive',
{'name': 'Drive API - read command data',
'api': DRIVECD,
'subscopes': [],
'offByDefault': True,
'scope': DRIVE_SCOPE+'.readonly'},
{'name': 'Drive API - write todrive data',
'api': DRIVETD,
'subscopes': [],
'offByDefault': True,
'scope': DRIVE_SCOPE},
{'name': 'Gmail API - Full Access - read only',
'api': GMAIL,
@@ -764,8 +774,14 @@ _SVCACCT_SPECIAL_SCOPES = [
'subscopes': [],
'offByDefault': True,
'scope': GMAIL_SEND_SCOPE},
{'name': 'Sheets API - todrive',
{'name': 'Sheets API - read command data',
'api': SHEETSCD,
'offByDefault': True,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/spreadsheets.readonly'},
{'name': 'Sheets API - write todrive data',
'api': SHEETSTD,
'offByDefault': True,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/spreadsheets'},
]

View File

@@ -69,6 +69,8 @@ CACHE_DISCOVERY_ONLY = 'cache_discovery_only'
CHANNEL_CUSTOMER_ID = 'channel_customer_id'
# Character set of batch, csv, data files
CHARSET = 'charset'
# When retrieving lists of Chat items from API, how many should be retrieved in each chunk
CHAT_MAX_RESULTS = 'chat_max_results'
# When retrieving lists of Google Classroom items from API, how many should be retrieved in each chunk
CLASSROOM_MAX_RESULTS = 'classroom_max_results'
# Path to client_secrets.json
@@ -335,6 +337,7 @@ Defaults = {
CACHE_DISCOVERY_ONLY: TRUE,
CHARSET: DEFAULT_CHARSET,
CHANNEL_CUSTOMER_ID: '',
CHAT_MAX_RESULTS: '100',
CLASSROOM_MAX_RESULTS: '0',
CLIENT_SECRETS_JSON: FN_CLIENT_SECRETS_JSON,
CLOCK_SKEW_IN_SECONDS: '10',
@@ -502,6 +505,7 @@ VAR_INFO = {
CACHE_DISCOVERY_ONLY: {VAR_TYPE: TYPE_BOOLEAN, VAR_SIGFILE: 'allcache.txt', VAR_SFFT: (TRUE, FALSE)},
CHARSET: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'GAM_CHARSET', VAR_LIMITS: (1, None)},
CHANNEL_CUSTOMER_ID: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
CHAT_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 1000)},
CLASSROOM_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (0, 1000)},
CLIENT_SECRETS_JSON: {VAR_TYPE: TYPE_FILE, VAR_ENVVAR: 'CLIENTSECRETS', VAR_ACCESS: os.R_OK},
CLOCK_SKEW_IN_SECONDS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (10, 3600)},

View File

@@ -49,43 +49,71 @@ class GamCLArgs():
ENTITY_CROS_OUS_AND_CHILDREN_QUERIES = 'cros_ous_and_children_queries'
ENTITY_CROS_SN = 'cros_sn'
ENTITY_DOMAINS = 'domains'
ENTITY_DOMAINS_NA = 'domains_na'
ENTITY_DOMAINS_ARCH = 'domains_arch'
ENTITY_DOMAINS_NS = 'domains_ns'
ENTITY_DOMAINS_SUSP = 'domains_susp'
ENTITY_DOMAINS_NA_NS = 'domains_na_ns'
ENTITY_GROUP = 'group'
ENTITY_GROUP_INDE = 'group_inde'
ENTITY_GROUP_NA = 'group_na'
ENTITY_GROUP_ARCH = 'group_arch'
ENTITY_GROUP_NS = 'group_ns'
ENTITY_GROUP_SUSP = 'group_susp'
ENTITY_GROUP_NA_NS = 'group_na_ns'
ENTITY_GROUPS = 'groups'
ENTITY_GROUPS_INDE = 'groups_inde'
ENTITY_GROUPS_NA = 'groups_na'
ENTITY_GROUPS_ARCH = 'groups_arch'
ENTITY_GROUPS_NS = 'groups_ns'
ENTITY_GROUPS_SUSP = 'groups_susp'
ENTITY_GROUPS_NA_NS = 'groups_na_ns'
ENTITY_GROUP_USERS = 'group_users'
ENTITY_GROUP_USERS_NA = 'group_users_na'
ENTITY_GROUP_USERS_ARCH = 'group_users_arch'
ENTITY_GROUP_USERS_NS = 'group_users_ns'
ENTITY_GROUP_USERS_SUSP = 'group_users_susp'
ENTITY_GROUP_USERS_NA_NS = 'group_users_na_ns'
ENTITY_GROUP_USERS_SELECT = 'group_users_select'
ENTITY_LICENSES = 'licenses'
ENTITY_OAUTHUSER = 'oauthuser'
ENTITY_OU = 'ou'
ENTITY_OU_NA = 'ou_na'
ENTITY_OU_ARCH = 'ou_arch'
ENTITY_OU_NS = 'ou_ns'
ENTITY_OU_SUSP = 'ou_susp'
ENTITY_OU_NA_NS = 'ou_na_ns'
ENTITY_OU_AND_CHILDREN = 'ou_and_children'
ENTITY_OU_AND_CHILDREN_NA = 'ou_and_children_na'
ENTITY_OU_AND_CHILDREN_ARCH = 'ou_and_children_arch'
ENTITY_OU_AND_CHILDREN_NS = 'ou_and_children_ns'
ENTITY_OU_AND_CHILDREN_SUSP = 'ou_and_children_susp'
ENTITY_OU_AND_CHILDREN_NA_NS = 'ou_and_children_na_ns'
ENTITY_OUS = 'ous'
ENTITY_OUS_NA = 'ous_na'
ENTITY_OUS_ARCH = 'ous_arch'
ENTITY_OUS_NS = 'ous_ns'
ENTITY_OUS_SUSP = 'ous_susp'
ENTITY_OUS_NA_NS = 'ous_na_ns'
ENTITY_OUS_AND_CHILDREN = 'ous_and_children'
ENTITY_OUS_AND_CHILDREN_NA = 'ous_and_children_na'
ENTITY_OUS_AND_CHILDREN_ARCH = 'ous_and_children_arch'
ENTITY_OUS_AND_CHILDREN_NS = 'ous_and_children_ns'
ENTITY_OUS_AND_CHILDREN_SUSP = 'ous_and_children_susp'
ENTITY_OUS_AND_CHILDREN_NA_NS = 'ous_and_children_na_ns'
ENTITY_QUERIES = 'queries'
ENTITY_QUERY = 'query'
ENTITY_STUDENTS = 'students'
ENTITY_TEACHERS = 'teachers'
ENTITY_USER = 'user'
ENTITY_USERS = 'users'
ENTITY_USERS_NA = 'users_na'
ENTITY_USERS_ARCH = 'users_arch'
ENTITY_USERS_NS = 'users_ns'
ENTITY_USERS_NS_SUSP = 'users_ns_susp'
ENTITY_USERS_SUSP = 'users_susp'
ENTITY_USERS_NA_NS = 'users_na_ns'
ENTITY_USERS_ARCH_OR_SUSP = 'users_arch_or_susp'
ENTITY_USERS_NS_SUSP = 'users_ns_susp'
#
BROWSER_ENTITIES = [
ENTITY_BROWSER,
@@ -118,34 +146,58 @@ class GamCLArgs():
ENTITY_CIGROUP_USERS,
ENTITY_COURSEPARTICIPANTS,
ENTITY_DOMAINS,
ENTITY_DOMAINS_NA,
ENTITY_DOMAINS_ARCH,
ENTITY_DOMAINS_NS,
ENTITY_DOMAINS_SUSP,
ENTITY_DOMAINS_NA_NS,
ENTITY_GROUP,
ENTITY_GROUP_INDE,
ENTITY_GROUP_NA,
ENTITY_GROUP_ARCH,
ENTITY_GROUP_NS,
ENTITY_GROUP_SUSP,
ENTITY_GROUP_NA_NS,
ENTITY_GROUPS,
ENTITY_GROUPS_INDE,
ENTITY_GROUPS_NA,
ENTITY_GROUPS_ARCH,
ENTITY_GROUPS_NS,
ENTITY_GROUPS_SUSP,
ENTITY_GROUPS_NA_NS,
ENTITY_GROUP_USERS,
ENTITY_GROUP_USERS_NA,
ENTITY_GROUP_USERS_ARCH,
ENTITY_GROUP_USERS_NS,
ENTITY_GROUP_USERS_SUSP,
ENTITY_GROUP_USERS_NA_NS,
ENTITY_GROUP_USERS_SELECT,
ENTITY_LICENSES,
ENTITY_OAUTHUSER,
ENTITY_OU,
ENTITY_OU_NA,
ENTITY_OU_ARCH,
ENTITY_OU_NS,
ENTITY_OU_SUSP,
ENTITY_OU_NA_NS,
ENTITY_OU_AND_CHILDREN,
ENTITY_OU_AND_CHILDREN_NA,
ENTITY_OU_AND_CHILDREN_ARCH,
ENTITY_OU_AND_CHILDREN_NS,
ENTITY_OU_AND_CHILDREN_SUSP,
ENTITY_OU_AND_CHILDREN_NA_NS,
ENTITY_OUS,
ENTITY_OUS_NA,
ENTITY_OUS_ARCH,
ENTITY_OUS_NS,
ENTITY_OUS_SUSP,
ENTITY_OUS_NA_NS,
ENTITY_OUS_AND_CHILDREN,
ENTITY_OUS_AND_CHILDREN_NA,
ENTITY_OUS_AND_CHILDREN_ARCH,
ENTITY_OUS_AND_CHILDREN_NS,
ENTITY_OUS_AND_CHILDREN_SUSP,
ENTITY_OUS_AND_CHILDREN_NA_NS,
ENTITY_QUERIES,
ENTITY_QUERY,
ENTITY_STUDENTS,
@@ -222,29 +274,53 @@ class GamCLArgs():
'licence': ENTITY_LICENSES,
'licences': ENTITY_LICENSES,
'org': ENTITY_OU,
'org_na': ENTITY_OU_NA,
'org_arch': ENTITY_OU_ARCH,
'org_ns': ENTITY_OU_NS,
'org_susp': ENTITY_OU_SUSP,
'org_na_ns': ENTITY_OU_NA_NS,
'org_and_child': ENTITY_OU_AND_CHILDREN,
'org_and_child_na': ENTITY_OU_AND_CHILDREN_NA,
'org_and_child_arch': ENTITY_OU_AND_CHILDREN_ARCH,
'org_and_child_ns': ENTITY_OU_AND_CHILDREN_NS,
'org_and_child_susp': ENTITY_OU_AND_CHILDREN_SUSP,
'org_and_child_na_ns': ENTITY_OU_AND_CHILDREN_NA_NS,
'org_and_children': ENTITY_OU_AND_CHILDREN,
'org_and_children_na': ENTITY_OU_AND_CHILDREN_NA,
'org_and_children_arch': ENTITY_OU_AND_CHILDREN_ARCH,
'org_and_children_ns': ENTITY_OU_AND_CHILDREN_NS,
'org_and_children_susp': ENTITY_OU_AND_CHILDREN_SUSP,
'org_and_children_na_ns': ENTITY_OU_AND_CHILDREN_NA_NS,
'orgs': ENTITY_OUS,
'orgs_na': ENTITY_OUS_NA,
'orgs_arch': ENTITY_OUS_ARCH,
'orgs_ns': ENTITY_OUS_NS,
'orgs_susp': ENTITY_OUS_SUSP,
'orgs_na_ns': ENTITY_OUS_NA_NS,
'orgs_and_child': ENTITY_OUS_AND_CHILDREN,
'orgs_and_child_na': ENTITY_OUS_AND_CHILDREN_NA,
'orgs_and_child_arch': ENTITY_OUS_AND_CHILDREN_ARCH,
'orgs_and_child_ns': ENTITY_OUS_AND_CHILDREN_NS,
'orgs_and_child_susp': ENTITY_OUS_AND_CHILDREN_SUSP,
'orgs_and_child_na_ns': ENTITY_OUS_AND_CHILDREN_NA_NS,
'orgs_and_children': ENTITY_OUS_AND_CHILDREN,
'orgs_and_children_na': ENTITY_OUS_AND_CHILDREN_NA,
'orgs_and_children_arch': ENTITY_OUS_AND_CHILDREN_ARCH,
'orgs_and_children_ns': ENTITY_OUS_AND_CHILDREN_NS,
'orgs_and_children_susp': ENTITY_OUS_AND_CHILDREN_SUSP,
'orgs_and_children_na_ns': ENTITY_OUS_AND_CHILDREN_NA_NS,
'ou_and_child': ENTITY_OU_AND_CHILDREN,
'ou_and_child_na': ENTITY_OU_AND_CHILDREN_NA,
'ou_and_child_arch': ENTITY_OU_AND_CHILDREN_ARCH,
'ou_and_child_ns': ENTITY_OU_AND_CHILDREN_NS,
'ou_and_child_susp': ENTITY_OU_AND_CHILDREN_SUSP,
'ou_and_child_na_ns': ENTITY_OU_AND_CHILDREN_NA_NS,
'ous_and_child': ENTITY_OUS_AND_CHILDREN,
'ous_and_child_na': ENTITY_OUS_AND_CHILDREN_NA,
'ous_and_child_arch': ENTITY_OUS_AND_CHILDREN_ARCH,
'ous_and_child_ns': ENTITY_OUS_AND_CHILDREN_NS,
'ous_and_child_susp': ENTITY_OUS_AND_CHILDREN_SUSP,
'ous_and_child_na_ns': ENTITY_OUS_AND_CHILDREN_NA_NS,
}
# CL entity source selectors
ENTITY_SELECTOR_ALL = 'all'
@@ -315,30 +391,217 @@ class GamCLArgs():
]
USER_ENTITY_SELECTOR_ALL_SUBTYPES = [
ENTITY_USERS,
ENTITY_USERS_NA,
ENTITY_USERS_ARCH,
ENTITY_USERS_NS,
ENTITY_USERS_NS_SUSP,
ENTITY_USERS_SUSP,
ENTITY_USERS_ARCH_OR_SUSP,
ENTITY_USERS_NA_NS,
ENTITY_USERS_NS_SUSP,
]
#
ENTITY_ALL_CROS = ENTITY_SELECTOR_ALL+' '+ENTITY_CROS
ENTITY_ALL_USERS = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS
ENTITY_ALL_USERS_NA = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NA
ENTITY_ALL_USERS_ARCH = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_ARCH
ENTITY_ALL_USERS_NS = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NS
ENTITY_ALL_USERS_NS_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NS_SUSP
ENTITY_ALL_USERS_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_SUSP
ENTITY_ALL_USERS_NA_NS = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NA_NS
ENTITY_ALL_USERS_ARCH_OR_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_ARCH_OR_SUSP
ENTITY_ALL_USERS_NS_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NS_SUSP
#
ALL_USER_ENTITY_TYPES = {
ENTITY_ALL_USERS,
ENTITY_ALL_USERS_NA,
ENTITY_ALL_USERS_ARCH,
ENTITY_ALL_USERS_NS,
ENTITY_ALL_USERS_SUSP,
ENTITY_ALL_USERS_NA_NS,
ENTITY_ALL_USERS_NS_SUSP,
}
DOMAIN_ENTITY_TYPES = {
ENTITY_DOMAINS,
ENTITY_DOMAINS_NA,
ENTITY_DOMAINS_ARCH,
ENTITY_DOMAINS_NS,
ENTITY_DOMAINS_SUSP,
ENTITY_DOMAINS_NA_NS,
}
GROUP_ENTITY_TYPES = {
ENTITY_GROUP,
ENTITY_GROUP_NA,
ENTITY_GROUP_ARCH,
ENTITY_GROUP_NS,
ENTITY_GROUP_SUSP,
ENTITY_GROUP_NA_NS,
ENTITY_GROUP_INDE,
}
GROUPS_ENTITY_TYPES = {
ENTITY_GROUPS,
ENTITY_GROUPS_NA,
ENTITY_GROUPS_ARCH,
ENTITY_GROUPS_NS,
ENTITY_GROUPS_SUSP,
ENTITY_GROUPS_NA_NS,
ENTITY_GROUPS_INDE,
}
GROUP_USERS_ENTITY_TYPES = {
ENTITY_GROUP_USERS,
ENTITY_GROUP_USERS_NA,
ENTITY_GROUP_USERS_ARCH,
ENTITY_GROUP_USERS_NS,
ENTITY_GROUP_USERS_SUSP,
ENTITY_GROUP_USERS_NA_NS,
ENTITY_GROUP_USERS_SELECT,
}
OU_ENTITY_TYPES = {
ENTITY_OU,
ENTITY_OU_AND_CHILDREN,
ENTITY_OU_NA,
ENTITY_OU_AND_CHILDREN_NA,
ENTITY_OU_ARCH,
ENTITY_OU_AND_CHILDREN_ARCH,
ENTITY_OU_NS,
ENTITY_OU_AND_CHILDREN_NS,
ENTITY_OU_SUSP,
ENTITY_OU_AND_CHILDREN_SUSP,
ENTITY_OU_NA_NS,
ENTITY_OU_AND_CHILDREN_NA_NS,
}
OUS_ENTITY_TYPES = {
ENTITY_OUS,
ENTITY_OUS_AND_CHILDREN,
ENTITY_OUS_NA,
ENTITY_OUS_AND_CHILDREN_NA,
ENTITY_OUS_ARCH,
ENTITY_OUS_AND_CHILDREN_ARCH,
ENTITY_OUS_NS,
ENTITY_OUS_AND_CHILDREN_NS,
ENTITY_OUS_SUSP,
ENTITY_OUS_AND_CHILDREN_SUSP,
ENTITY_OUS_NA_NS,
ENTITY_OUS_AND_CHILDREN_NA_NS,
}
OU_DIRECT_ENTITY_TYPES = {
ENTITY_OU,
ENTITY_OUS,
ENTITY_OU_NA,
ENTITY_OUS_NA,
ENTITY_OU_ARCH,
ENTITY_OUS_ARCH,
ENTITY_OU_NS,
ENTITY_OUS_NS,
ENTITY_OU_SUSP,
ENTITY_OUS_SUSP,
ENTITY_OU_NA_NS,
ENTITY_OUS_NA_NS,
}
CROS_OU_ENTITY_TYPES = {
ENTITY_CROS_OU,
ENTITY_CROS_OU_AND_CHILDREN,
ENTITY_CROS_OU_QUERY,
ENTITY_CROS_OU_AND_CHILDREN_QUERY,
ENTITY_CROS_OU_QUERIES,
ENTITY_CROS_OU_AND_CHILDREN_QUERIES,
}
CROS_OUS_ENTITY_TYPES = {
ENTITY_CROS_OUS,
ENTITY_CROS_OUS_AND_CHILDREN,
ENTITY_CROS_OUS_QUERY,
ENTITY_CROS_OUS_AND_CHILDREN_QUERY,
ENTITY_CROS_OUS_QUERIES,
ENTITY_CROS_OUS_AND_CHILDREN_QUERIES,
}
CROS_OU_CHILDREN_ENTITY_TYPES = {
ENTITY_CROS_OU_AND_CHILDREN,
ENTITY_CROS_OU_AND_CHILDREN_QUERY,
ENTITY_CROS_OU_AND_CHILDREN_QUERIES,
ENTITY_CROS_OUS_AND_CHILDREN,
ENTITY_CROS_OUS_AND_CHILDREN_QUERY,
ENTITY_CROS_OUS_AND_CHILDREN_QUERIES,
}
CROS_OU_QUERY_ENTITY_TYPES = {
ENTITY_CROS_OU_QUERY,
ENTITY_CROS_OU_AND_CHILDREN_QUERY,
ENTITY_CROS_OUS_QUERY,
ENTITY_CROS_OUS_AND_CHILDREN_QUERY,
}
CROS_OU_QUERIES_ENTITY_TYPES = {
ENTITY_CROS_OU_QUERIES,
ENTITY_CROS_OU_AND_CHILDREN_QUERIES,
ENTITY_CROS_OUS_QUERIES,
ENTITY_CROS_OUS_AND_CHILDREN_QUERIES,
}
#
ALL_USERS_QUERY_MAP = {
ENTITY_ALL_USERS: 'isSuspended=False',
ENTITY_ALL_USERS_NA: 'isArchived=False',
ENTITY_ALL_USERS_ARCH: 'isArchived=True',
ENTITY_ALL_USERS_NS: 'isSuspended=False',
ENTITY_ALL_USERS_NS_SUSP: None,
ENTITY_ALL_USERS_SUSP: 'isSuspended=True',
ENTITY_ALL_USERS_NA_NS: 'isArchived=False isSuspended=False',
ENTITY_ALL_USERS_NS_SUSP: None,
}
DOMAINS_QUERY_MAP = {
ENTITY_DOMAINS: None,
ENTITY_DOMAINS_NA: 'isArchived=False',
ENTITY_DOMAINS_ARCH: 'isArchived=True',
ENTITY_DOMAINS_NS: 'isSuspended=False',
ENTITY_DOMAINS_SUSP: 'isSuspended=True',
ENTITY_DOMAINS_NA_NS: 'isArchived=False isSuspended=False',
}
GROUPS_QUERY_MAP = { #(isArchived, isSuspended)
ENTITY_GROUP_NA: (False, None),
ENTITY_GROUPS_NA: (False, None),
ENTITY_GROUP_ARCH: (True, None),
ENTITY_GROUPS_ARCH: (True, None),
ENTITY_GROUP_NS: (None, False),
ENTITY_GROUPS_NS: (None, False),
ENTITY_GROUP_SUSP: (None, True),
ENTITY_GROUPS_SUSP: (None, True),
ENTITY_GROUP_NA_NS: (False, False),
ENTITY_GROUPS_NA_NS: (False, False),
}
GROUP_USERS_QUERY_MAP = { #(isArchived, isSuspended)
ENTITY_GROUP_USERS_NA: (False, None),
ENTITY_GROUP_USERS_ARCH: (True, None),
ENTITY_GROUP_USERS_NS: (None, False),
ENTITY_GROUP_USERS_SUSP: (None, True),
ENTITY_GROUP_USERS_NA_NS: (False, False),
}
OU_QUERY_MAP = { #(isArchived, isSuspended)
ENTITY_OU_NA: (False, None),
ENTITY_OUS_NA: (False, None),
ENTITY_OU_AND_CHILDREN_NA: (False, None),
ENTITY_OUS_AND_CHILDREN_NA: (False, None),
ENTITY_OU_ARCH: (True, None),
ENTITY_OUS_ARCH: (True, None),
ENTITY_OU_AND_CHILDREN_ARCH: (True, None),
ENTITY_OUS_AND_CHILDREN_ARCH: (True, None),
ENTITY_OU_NS: (None, False),
ENTITY_OUS_NS: (None, False),
ENTITY_OU_AND_CHILDREN_NS: (None, False),
ENTITY_OUS_AND_CHILDREN_NS: (None, False),
ENTITY_OU_SUSP: (None, True),
ENTITY_OUS_SUSP: (None, True),
ENTITY_OU_AND_CHILDREN_SUSP: (None, True),
ENTITY_OUS_AND_CHILDREN_SUSP: (None, True),
ENTITY_OU_NA_NS: (False, False),
ENTITY_OUS_NA_NS: (False, False),
ENTITY_OU_AND_CHILDREN_NA_NS: (False, False),
ENTITY_OUS_AND_CHILDREN_NA_NS: (False, False),
}
#
ENTITY_SELECTOR_ALL_SUBTYPES_MAP = {
ENTITY_CROS: ENTITY_ALL_CROS,
ENTITY_USERS: ENTITY_ALL_USERS,
ENTITY_USERS_NA: ENTITY_ALL_USERS_NA,
ENTITY_USERS_ARCH: ENTITY_ALL_USERS_ARCH,
ENTITY_USERS_NS: ENTITY_ALL_USERS_NS,
ENTITY_USERS_NS_SUSP: ENTITY_ALL_USERS_NS_SUSP,
ENTITY_USERS_SUSP: ENTITY_ALL_USERS_SUSP,
ENTITY_USERS_NA_NS: ENTITY_ALL_USERS_NA_NS,
ENTITY_USERS_ARCH_OR_SUSP: ENTITY_ALL_USERS_ARCH_OR_SUSP,
ENTITY_USERS_NS_SUSP: ENTITY_ALL_USERS_NS_SUSP,
}
# Allowed values for CL source selector datafile, csvkmd
CROS_ENTITY_SELECTOR_DATAFILE_CSVKMD_SUBTYPES = [
@@ -352,22 +615,37 @@ class GamCLArgs():
ENTITY_CIGROUPS,
ENTITY_CIGROUP_USERS,
ENTITY_DOMAINS,
ENTITY_DOMAINS_NA,
ENTITY_DOMAINS_ARCH,
ENTITY_DOMAINS_NS,
ENTITY_DOMAINS_SUSP,
ENTITY_DOMAINS_NA_NS,
ENTITY_GROUPS,
ENTITY_GROUPS_INDE,
ENTITY_GROUPS_NA,
ENTITY_GROUPS_ARCH,
ENTITY_GROUPS_NS,
ENTITY_GROUPS_SUSP,
ENTITY_GROUPS_NA_NS,
ENTITY_GROUP_USERS,
ENTITY_GROUP_USERS_NA,
ENTITY_GROUP_USERS_ARCH,
ENTITY_GROUP_USERS_NS,
ENTITY_GROUP_USERS_SUSP,
ENTITY_GROUP_USERS_NA_NS,
ENTITY_GROUP_USERS_SELECT,
ENTITY_OUS,
ENTITY_OUS_NA,
ENTITY_OUS_ARCH,
ENTITY_OUS_NS,
ENTITY_OUS_SUSP,
ENTITY_OUS_NA_NS,
ENTITY_OUS_AND_CHILDREN,
ENTITY_OUS_AND_CHILDREN_NA,
ENTITY_OUS_AND_CHILDREN_ARCH,
ENTITY_OUS_AND_CHILDREN_NS,
ENTITY_OUS_AND_CHILDREN_SUSP,
ENTITY_OUS_AND_CHILDREN_NA_NS,
ENTITY_COURSEPARTICIPANTS,
ENTITY_STUDENTS,
ENTITY_TEACHERS,
@@ -377,6 +655,7 @@ class GamCLArgs():
GAM_CMD = 'gam'
COMMIT_BATCH_CMD = 'commit-batch'
PRINT_CMD = 'print'
DATETIME_CMD = 'datetime'
SET_CMD = 'set'
CLEAR_CMD = 'clear'
SLEEP_CMD = 'sleep'
@@ -859,6 +1138,7 @@ class GamCLArgs():
OB_ARGUMENT = 'argument'
OB_ASP_ID_LIST = 'ASPIDList'
OB_ASSET_ID = 'AssetID'
OB_ADMIN_ASSIGNEE_TYPE_LIST = 'AdminAssigneeTypeList'
OB_BROWSER_ENROLLEMNT_TOKEN_ID = 'BrowserEnrollmentTokenID'
OB_BROWSER_ENTITY = 'BrowserEntity'
OB_BUILDING_ID = 'BuildingID'
@@ -924,6 +1204,7 @@ class GamCLArgs():
OB_CSE_KEYPAIR_ID = 'CSEKeyPairID'
OB_CUSTOMER_ID = 'CustomerID'
OB_CUSTOMER_AUTH_TOKEN = 'CustomerAuthToken'
OB_DATETIME_FORMAT = 'DateTimeFormat'
OB_DEVICE_FILE_ENTITY = 'DeviceFileEntity'
OB_DEVICE_ENTITY = 'DeviceEntity'
OB_DEVICE_ID = 'DeviceID'
@@ -936,6 +1217,7 @@ class GamCLArgs():
OB_DOMAIN_NAME_LIST = 'DomainNameList'
OB_DRIVE_FILE_ENTITY = 'DriveFileEntity'
OB_DRIVE_FILE_ID = 'DriveFileID'
OB_DRIVE_FILE_ID_LIST = 'DriveFileIDList'
OB_DRIVE_FILE_NAME = 'DriveFileName'
OB_DRIVE_FILE_PERMISSION_ENTITY = 'DriveFilePermissionEntity'
OB_DRIVE_FILE_PERMISSION_ID = 'DriveFilePermissionID'

View File

@@ -96,6 +96,7 @@ class GamEntity():
CHAT_MEMBER_USER = 'chmu'
CHAT_MESSAGE = 'chms'
CHAT_MESSAGE_ID = 'chmi'
CHAT_OWNER_USER = 'chou'
CHAT_SPACE = 'chsp'
CHAT_THREAD = 'chth'
CHILD_ORGANIZATIONAL_UNIT = 'corg'
@@ -384,11 +385,13 @@ class GamEntity():
URL = 'url '
USER = 'user'
USER_ALIAS = 'uali'
USER_NOT_ARCHIVED = 'usna'
USER_ARCHIVED = 'usar'
USER_EMAIL = 'uema'
USER_INVITATION = 'uinv'
USER_NOT_SUSPENDED = 'uns'
USER_SCHEMA = 'usch'
USER_NOT_SUSPENDED = 'usns'
USER_SUSPENDED = 'usup'
USER_SCHEMA = 'usch'
VACATION = 'vaca'
VACATION_ENABLED = 'vace'
VALUE = 'val'
@@ -460,6 +463,7 @@ class GamEntity():
CHAT_MEMBER: ['Chat Members', 'Chat Member'],
CHAT_MEMBER_GROUP: ['Chat Group Members', 'Chat Group Member'],
CHAT_MEMBER_USER: ['Chat User Members', 'Chat User Member'],
CHAT_OWNER_USER: ['Chat User Owners', 'Chat User Owner'],
CHAT_SPACE: ['Chat Spaces', 'Chat Space'],
CHAT_THREAD: ['Chat Threads', 'Chat Thread'],
CHILD_ORGANIZATIONAL_UNIT: ['Child Organizational Units', 'Child Organizational Unit'],
@@ -748,11 +752,13 @@ class GamEntity():
URL: ['URLs', 'URL'],
USER: ['Users', 'User'],
USER_ALIAS: ['User Aliases', 'User Alias'],
USER_NOT_ARCHIVED: ['Users (Not archived)', 'User (Not archived)'],
USER_ARCHIVED: ['Users (Archived)', 'User (Archived)'],
USER_EMAIL: ['User Emails', 'User Email'],
USER_INVITATION: ['User Invitations', 'User Invitation'],
USER_NOT_SUSPENDED: ['Users (Not suspended)', 'User (Not suspended)'],
USER_SCHEMA: ['Schemas', 'Schema'],
USER_SUSPENDED: ['Users (Suspended)', 'User (Suspended)'],
USER_SCHEMA: ['Schemas', 'Schema'],
VACATION: ['Vacation', 'Vacation'],
VACATION_ENABLED: ['Vacation Enabled', 'Vacation Enabled'],
VALUE: ['Values', 'Value'],

View File

@@ -499,6 +499,7 @@ STATISTICS_MOVE_FILE = 'Total: {0}, Moved: {1}, Shortcut created {2}, Shortcut e
STATISTICS_MOVE_FOLDER = 'Total: {0}, Moved: {1}, Shortcut created {2}, Shortcut exists {3}, Duplicate: {4}, Merged: {5}, Move Failed: {6}, Not writable: {7}'
STATISTICS_USER_NOT_ORGANIZER = 'User not organizer: {0}'
STRING_LENGTH = 'string length'
STUDENT_NOT_IN_COURSE = 'Student not in course'
SUBKEY_FIELD_MISMATCH = 'subkeyfield {0} does not match saved subkeyfield {1}'
SUBSCRIPTION_NOT_FOUND = 'Could not find subscription'
SUFFIX_NOT_ALLOWED_WITH_CUSTOMLANGUAGE = 'Suffix {0} not allowed with customLanguage {1}'

View File

@@ -100,7 +100,7 @@ _SKUS = {
'1010470003': {
'product': '101047', 'aliases': ['geminibiz'], 'displayName': 'Gemini Business'},
'1010470004': {
'product': '101047', 'aliases': ['geminiedu'], 'displayName': 'Gemini Education'},
'product': '101047', 'aliases': ['gaiproedu', 'geminiedu'], 'displayName': 'Google AI Pro for Education'},
'1010470005': {
'product': '101047', 'aliases': ['geminiedupremium'], 'displayName': 'Gemini Education Premium'},
'1010470006': {

View File

@@ -21,6 +21,7 @@
"""
GAM_VER_LIBS = [
'arrow',
'chardet',
'cryptography',
'filelock',
@@ -33,6 +34,5 @@ GAM_VER_LIBS = [
'passlib',
'pathvalidate',
'pyscard',
'python-dateutil',
'yubikey-manager',
]

View File

@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2023 Ross Scroggs All Rights Reserved.
# Copyright (C) 2025 Ross Scroggs All Rights Reserved.
#
# All Rights Reserved.
#
@@ -19,11 +19,20 @@
"""YubiKey"""
import base64
import datetime
from secrets import SystemRandom
import string
import sys
import arrow
from gam import mplock
from gam import systemErrorExit
from gam import readStdin
from gam import writeStdout
from gam.gamlib import glmsgs as Msg
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
from smartcard.Exceptions import CardConnectionException
@@ -49,14 +58,6 @@ YUBIKEY_VALUE_ERROR_RC = 85
YUBIKEY_MULTIPLE_CONNECTED_RC = 86
YUBIKEY_NOT_FOUND_RC = 87
from gam import mplock
from gam import systemErrorExit
from gam import readStdin
from gam import writeStdout
from gam.gamlib import glmsgs as Msg
PIN_PUK_CHARS = string.ascii_letters+string.digits+string.punctuation
class YubiKey():
@@ -155,8 +156,8 @@ class YubiKey():
KEY_TYPE.RSA2048,
PIN_POLICY.ALWAYS,
TOUCH_POLICY.NEVER)
now = datetime.datetime.utcnow()
valid_to = now + datetime.timedelta(days=36500)
now = arrow.utcnow()
valid_to = now.shift(days=36500)
subject = 'CN=GAM Created Key'
piv.authenticate(MANAGEMENT_KEY_TYPE.TDES, DEFAULT_MANAGEMENT_KEY)
piv.verify_pin(new_pin)

View File

@@ -1,27 +0,0 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Set default logging handler to avoid "No handler found" warnings.
import logging
try: # Python 2.7+
from logging import NullHandler
except ImportError:
class NullHandler(logging.Handler):
def emit(self, record):
pass
logging.getLogger(__name__).addHandler(NullHandler())

View File

@@ -1,167 +0,0 @@
# Copyright 2016 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Helpers for authentication using oauth2client or google-auth."""
import httplib2
try:
import google.auth
import google.auth.credentials
HAS_GOOGLE_AUTH = True
except ImportError: # pragma: NO COVER
HAS_GOOGLE_AUTH = False
try:
import google_auth_httplib2
except ImportError: # pragma: NO COVER
google_auth_httplib2 = None
try:
import oauth2client
import oauth2client.client
HAS_OAUTH2CLIENT = True
except ImportError: # pragma: NO COVER
HAS_OAUTH2CLIENT = False
def credentials_from_file(filename, scopes=None, quota_project_id=None):
"""Returns credentials loaded from a file."""
if HAS_GOOGLE_AUTH:
credentials, _ = google.auth.load_credentials_from_file(
filename, scopes=scopes, quota_project_id=quota_project_id
)
return credentials
else:
raise EnvironmentError(
"client_options.credentials_file is only supported in google-auth."
)
def default_credentials(scopes=None, quota_project_id=None):
"""Returns Application Default Credentials."""
if HAS_GOOGLE_AUTH:
credentials, _ = google.auth.default(
scopes=scopes, quota_project_id=quota_project_id
)
return credentials
elif HAS_OAUTH2CLIENT:
if scopes is not None or quota_project_id is not None:
raise EnvironmentError(
"client_options.scopes and client_options.quota_project_id are not supported in oauth2client."
"Please install google-auth."
)
return oauth2client.client.GoogleCredentials.get_application_default()
else:
raise EnvironmentError(
"No authentication library is available. Please install either "
"google-auth or oauth2client."
)
def with_scopes(credentials, scopes):
"""Scopes the credentials if necessary.
Args:
credentials (Union[
google.auth.credentials.Credentials,
oauth2client.client.Credentials]): The credentials to scope.
scopes (Sequence[str]): The list of scopes.
Returns:
Union[google.auth.credentials.Credentials,
oauth2client.client.Credentials]: The scoped credentials.
"""
if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
return google.auth.credentials.with_scopes_if_required(credentials, scopes)
else:
try:
if credentials.create_scoped_required():
return credentials.create_scoped(scopes)
else:
return credentials
except AttributeError:
return credentials
def authorized_http(credentials):
"""Returns an http client that is authorized with the given credentials.
Args:
credentials (Union[
google.auth.credentials.Credentials,
oauth2client.client.Credentials]): The credentials to use.
Returns:
Union[httplib2.Http, google_auth_httplib2.AuthorizedHttp]: An
authorized http client.
"""
from googleapiclient.http import build_http
if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
if google_auth_httplib2 is None:
raise ValueError(
"Credentials from google.auth specified, but "
"google-api-python-client is unable to use these credentials "
"unless google-auth-httplib2 is installed. Please install "
"google-auth-httplib2."
)
return google_auth_httplib2.AuthorizedHttp(credentials, http=build_http())
else:
return credentials.authorize(build_http())
def refresh_credentials(credentials):
# Refresh must use a new http instance, as the one associated with the
# credentials could be a AuthorizedHttp or an oauth2client-decorated
# Http instance which would cause a weird recursive loop of refreshing
# and likely tear a hole in spacetime.
refresh_http = httplib2.Http()
if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
request = google_auth_httplib2.Request(refresh_http)
return credentials.refresh(request)
else:
return credentials.refresh(refresh_http)
def apply_credentials(credentials, headers):
# oauth2client and google-auth have the same interface for this.
if not is_valid(credentials):
refresh_credentials(credentials)
return credentials.apply(headers)
def is_valid(credentials):
if HAS_GOOGLE_AUTH and isinstance(credentials, google.auth.credentials.Credentials):
return credentials.valid
else:
return (
credentials.access_token is not None
and not credentials.access_token_expired
)
def get_credentials_from_http(http):
if http is None:
return None
elif hasattr(http.request, "credentials"):
return http.request.credentials
elif hasattr(http, "credentials") and not isinstance(
http.credentials, httplib2.Credentials
):
return http.credentials
else:
return None

View File

@@ -1,207 +0,0 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Helper functions for commonly used utilities."""
import functools
import inspect
import logging
import urllib
logger = logging.getLogger(__name__)
POSITIONAL_WARNING = "WARNING"
POSITIONAL_EXCEPTION = "EXCEPTION"
POSITIONAL_IGNORE = "IGNORE"
POSITIONAL_SET = frozenset(
[POSITIONAL_WARNING, POSITIONAL_EXCEPTION, POSITIONAL_IGNORE]
)
positional_parameters_enforcement = POSITIONAL_WARNING
_SYM_LINK_MESSAGE = "File: {0}: Is a symbolic link."
_IS_DIR_MESSAGE = "{0}: Is a directory"
_MISSING_FILE_MESSAGE = "Cannot access {0}: No such file or directory"
def positional(max_positional_args):
"""A decorator to declare that only the first N arguments may be positional.
This decorator makes it easy to support Python 3 style keyword-only
parameters. For example, in Python 3 it is possible to write::
def fn(pos1, *, kwonly1=None, kwonly2=None):
...
All named parameters after ``*`` must be a keyword::
fn(10, 'kw1', 'kw2') # Raises exception.
fn(10, kwonly1='kw1') # Ok.
Example
^^^^^^^
To define a function like above, do::
@positional(1)
def fn(pos1, kwonly1=None, kwonly2=None):
...
If no default value is provided to a keyword argument, it becomes a
required keyword argument::
@positional(0)
def fn(required_kw):
...
This must be called with the keyword parameter::
fn() # Raises exception.
fn(10) # Raises exception.
fn(required_kw=10) # Ok.
When defining instance or class methods always remember to account for
``self`` and ``cls``::
class MyClass(object):
@positional(2)
def my_method(self, pos1, kwonly1=None):
...
@classmethod
@positional(2)
def my_method(cls, pos1, kwonly1=None):
...
The positional decorator behavior is controlled by
``_helpers.positional_parameters_enforcement``, which may be set to
``POSITIONAL_EXCEPTION``, ``POSITIONAL_WARNING`` or
``POSITIONAL_IGNORE`` to raise an exception, log a warning, or do
nothing, respectively, if a declaration is violated.
Args:
max_positional_arguments: Maximum number of positional arguments. All
parameters after this index must be
keyword only.
Returns:
A decorator that prevents using arguments after max_positional_args
from being used as positional parameters.
Raises:
TypeError: if a keyword-only argument is provided as a positional
parameter, but only if
_helpers.positional_parameters_enforcement is set to
POSITIONAL_EXCEPTION.
"""
def positional_decorator(wrapped):
@functools.wraps(wrapped)
def positional_wrapper(*args, **kwargs):
if len(args) > max_positional_args:
plural_s = ""
if max_positional_args != 1:
plural_s = "s"
message = (
"{function}() takes at most {args_max} positional "
"argument{plural} ({args_given} given)".format(
function=wrapped.__name__,
args_max=max_positional_args,
args_given=len(args),
plural=plural_s,
)
)
if positional_parameters_enforcement == POSITIONAL_EXCEPTION:
raise TypeError(message)
elif positional_parameters_enforcement == POSITIONAL_WARNING:
logger.warning(message)
return wrapped(*args, **kwargs)
return positional_wrapper
if isinstance(max_positional_args, int):
return positional_decorator
else:
args, _, _, defaults, _, _, _ = inspect.getfullargspec(max_positional_args)
return positional(len(args) - len(defaults))(max_positional_args)
def parse_unique_urlencoded(content):
"""Parses unique key-value parameters from urlencoded content.
Args:
content: string, URL-encoded key-value pairs.
Returns:
dict, The key-value pairs from ``content``.
Raises:
ValueError: if one of the keys is repeated.
"""
urlencoded_params = urllib.parse.parse_qs(content)
params = {}
for key, value in urlencoded_params.items():
if len(value) != 1:
msg = "URL-encoded content contains a repeated value:" "%s -> %s" % (
key,
", ".join(value),
)
raise ValueError(msg)
params[key] = value[0]
return params
def update_query_params(uri, params):
"""Updates a URI with new query parameters.
If a given key from ``params`` is repeated in the ``uri``, then
the URI will be considered invalid and an error will occur.
If the URI is valid, then each value from ``params`` will
replace the corresponding value in the query parameters (if
it exists).
Args:
uri: string, A valid URI, with potential existing query parameters.
params: dict, A dictionary of query parameters.
Returns:
The same URI but with the new query parameters added.
"""
parts = urllib.parse.urlparse(uri)
query_params = parse_unique_urlencoded(parts.query)
query_params.update(params)
new_query = urllib.parse.urlencode(query_params)
new_parts = parts._replace(query=new_query)
return urllib.parse.urlunparse(new_parts)
def _add_query_parameter(url, name, value):
"""Adds a query parameter to a url.
Replaces the current value if it already exists in the URL.
Args:
url: string, url to add the query parameter to.
name: string, query parameter name.
value: string, query parameter value.
Returns:
Updated query parameter. Does not update the url if value is None.
"""
if value is None:
return url
else:
return update_query_params(url, {name: value})

View File

@@ -1,315 +0,0 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Channel notifications support.
Classes and functions to support channel subscriptions and notifications
on those channels.
Notes:
- This code is based on experimental APIs and is subject to change.
- Notification does not do deduplication of notification ids, that's up to
the receiver.
- Storing the Channel between calls is up to the caller.
Example setting up a channel:
# Create a new channel that gets notifications via webhook.
channel = new_webhook_channel("https://example.com/my_web_hook")
# Store the channel, keyed by 'channel.id'. Store it before calling the
# watch method because notifications may start arriving before the watch
# method returns.
...
resp = service.objects().watchAll(
bucket="some_bucket_id", body=channel.body()).execute()
channel.update(resp)
# Store the channel, keyed by 'channel.id'. Store it after being updated
# since the resource_id value will now be correct, and that's needed to
# stop a subscription.
...
An example Webhook implementation using webapp2. Note that webapp2 puts
headers in a case insensitive dictionary, as headers aren't guaranteed to
always be upper case.
id = self.request.headers[X_GOOG_CHANNEL_ID]
# Retrieve the channel by id.
channel = ...
# Parse notification from the headers, including validating the id.
n = notification_from_headers(channel, self.request.headers)
# Do app specific stuff with the notification here.
if n.resource_state == 'sync':
# Code to handle sync state.
elif n.resource_state == 'exists':
# Code to handle the exists state.
elif n.resource_state == 'not_exists':
# Code to handle the not exists state.
Example of unsubscribing.
service.channels().stop(channel.body()).execute()
"""
from __future__ import absolute_import
import datetime
import uuid
from googleapiclient import _helpers as util
from googleapiclient import errors
# The unix time epoch starts at midnight 1970.
EPOCH = datetime.datetime(1970, 1, 1)
# Map the names of the parameters in the JSON channel description to
# the parameter names we use in the Channel class.
CHANNEL_PARAMS = {
"address": "address",
"id": "id",
"expiration": "expiration",
"params": "params",
"resourceId": "resource_id",
"resourceUri": "resource_uri",
"type": "type",
"token": "token",
}
X_GOOG_CHANNEL_ID = "X-GOOG-CHANNEL-ID"
X_GOOG_MESSAGE_NUMBER = "X-GOOG-MESSAGE-NUMBER"
X_GOOG_RESOURCE_STATE = "X-GOOG-RESOURCE-STATE"
X_GOOG_RESOURCE_URI = "X-GOOG-RESOURCE-URI"
X_GOOG_RESOURCE_ID = "X-GOOG-RESOURCE-ID"
def _upper_header_keys(headers):
new_headers = {}
for k, v in headers.items():
new_headers[k.upper()] = v
return new_headers
class Notification(object):
"""A Notification from a Channel.
Notifications are not usually constructed directly, but are returned
from functions like notification_from_headers().
Attributes:
message_number: int, The unique id number of this notification.
state: str, The state of the resource being monitored.
uri: str, The address of the resource being monitored.
resource_id: str, The unique identifier of the version of the resource at
this event.
"""
@util.positional(5)
def __init__(self, message_number, state, resource_uri, resource_id):
"""Notification constructor.
Args:
message_number: int, The unique id number of this notification.
state: str, The state of the resource being monitored. Can be one
of "exists", "not_exists", or "sync".
resource_uri: str, The address of the resource being monitored.
resource_id: str, The identifier of the watched resource.
"""
self.message_number = message_number
self.state = state
self.resource_uri = resource_uri
self.resource_id = resource_id
class Channel(object):
"""A Channel for notifications.
Usually not constructed directly, instead it is returned from helper
functions like new_webhook_channel().
Attributes:
type: str, The type of delivery mechanism used by this channel. For
example, 'web_hook'.
id: str, A UUID for the channel.
token: str, An arbitrary string associated with the channel that
is delivered to the target address with each event delivered
over this channel.
address: str, The address of the receiving entity where events are
delivered. Specific to the channel type.
expiration: int, The time, in milliseconds from the epoch, when this
channel will expire.
params: dict, A dictionary of string to string, with additional parameters
controlling delivery channel behavior.
resource_id: str, An opaque id that identifies the resource that is
being watched. Stable across different API versions.
resource_uri: str, The canonicalized ID of the watched resource.
"""
@util.positional(5)
def __init__(
self,
type,
id,
token,
address,
expiration=None,
params=None,
resource_id="",
resource_uri="",
):
"""Create a new Channel.
In user code, this Channel constructor will not typically be called
manually since there are functions for creating channels for each specific
type with a more customized set of arguments to pass.
Args:
type: str, The type of delivery mechanism used by this channel. For
example, 'web_hook'.
id: str, A UUID for the channel.
token: str, An arbitrary string associated with the channel that
is delivered to the target address with each event delivered
over this channel.
address: str, The address of the receiving entity where events are
delivered. Specific to the channel type.
expiration: int, The time, in milliseconds from the epoch, when this
channel will expire.
params: dict, A dictionary of string to string, with additional parameters
controlling delivery channel behavior.
resource_id: str, An opaque id that identifies the resource that is
being watched. Stable across different API versions.
resource_uri: str, The canonicalized ID of the watched resource.
"""
self.type = type
self.id = id
self.token = token
self.address = address
self.expiration = expiration
self.params = params
self.resource_id = resource_id
self.resource_uri = resource_uri
def body(self):
"""Build a body from the Channel.
Constructs a dictionary that's appropriate for passing into watch()
methods as the value of body argument.
Returns:
A dictionary representation of the channel.
"""
result = {
"id": self.id,
"token": self.token,
"type": self.type,
"address": self.address,
}
if self.params:
result["params"] = self.params
if self.resource_id:
result["resourceId"] = self.resource_id
if self.resource_uri:
result["resourceUri"] = self.resource_uri
if self.expiration:
result["expiration"] = self.expiration
return result
def update(self, resp):
"""Update a channel with information from the response of watch().
When a request is sent to watch() a resource, the response returned
from the watch() request is a dictionary with updated channel information,
such as the resource_id, which is needed when stopping a subscription.
Args:
resp: dict, The response from a watch() method.
"""
for json_name, param_name in CHANNEL_PARAMS.items():
value = resp.get(json_name)
if value is not None:
setattr(self, param_name, value)
def notification_from_headers(channel, headers):
"""Parse a notification from the webhook request headers, validate
the notification, and return a Notification object.
Args:
channel: Channel, The channel that the notification is associated with.
headers: dict, A dictionary like object that contains the request headers
from the webhook HTTP request.
Returns:
A Notification object.
Raises:
errors.InvalidNotificationError if the notification is invalid.
ValueError if the X-GOOG-MESSAGE-NUMBER can't be converted to an int.
"""
headers = _upper_header_keys(headers)
channel_id = headers[X_GOOG_CHANNEL_ID]
if channel.id != channel_id:
raise errors.InvalidNotificationError(
"Channel id mismatch: %s != %s" % (channel.id, channel_id)
)
else:
message_number = int(headers[X_GOOG_MESSAGE_NUMBER])
state = headers[X_GOOG_RESOURCE_STATE]
resource_uri = headers[X_GOOG_RESOURCE_URI]
resource_id = headers[X_GOOG_RESOURCE_ID]
return Notification(message_number, state, resource_uri, resource_id)
@util.positional(2)
def new_webhook_channel(url, token=None, expiration=None, params=None):
"""Create a new webhook Channel.
Args:
url: str, URL to post notifications to.
token: str, An arbitrary string associated with the channel that
is delivered to the target address with each notification delivered
over this channel.
expiration: datetime.datetime, A time in the future when the channel
should expire. Can also be None if the subscription should use the
default expiration. Note that different services may have different
limits on how long a subscription lasts. Check the response from the
watch() method to see the value the service has set for an expiration
time.
params: dict, Extra parameters to pass on channel creation. Currently
not used for webhook channels.
"""
expiration_ms = 0
if expiration:
delta = expiration - EPOCH
expiration_ms = (
delta.microseconds / 1000 + (delta.seconds + delta.days * 24 * 3600) * 1000
)
if expiration_ms < 0:
expiration_ms = 0
return Channel(
"web_hook",
str(uuid.uuid4()),
token,
url,
expiration=expiration_ms,
params=params,
)

File diff suppressed because it is too large Load Diff

View File

@@ -1,78 +0,0 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Caching utility for the discovery document."""
from __future__ import absolute_import
import logging
import os
LOGGER = logging.getLogger(__name__)
DISCOVERY_DOC_MAX_AGE = 60 * 60 * 24 # 1 day
DISCOVERY_DOC_DIR = os.path.join(
os.path.dirname(os.path.realpath(__file__)), "documents"
)
def autodetect():
"""Detects an appropriate cache module and returns it.
Returns:
googleapiclient.discovery_cache.base.Cache, a cache object which
is auto detected, or None if no cache object is available.
"""
if "GAE_ENV" in os.environ:
try:
from . import appengine_memcache
return appengine_memcache.cache
except Exception:
pass
try:
from . import file_cache
return file_cache.cache
except Exception:
LOGGER.info(
"file_cache is only supported with oauth2client<4.0.0", exc_info=False
)
return None
def get_static_doc(serviceName, version):
"""Retrieves the discovery document from the directory defined in
DISCOVERY_DOC_DIR corresponding to the serviceName and version provided.
Args:
serviceName: string, name of the service.
version: string, the version of the service.
Returns:
A string containing the contents of the JSON discovery document,
otherwise None if the JSON discovery document was not found.
"""
content = None
doc_name = "{}.{}.json".format(serviceName, version)
try:
with open(os.path.join(DISCOVERY_DOC_DIR, doc_name), "r") as f:
content = f.read()
except FileNotFoundError:
# File does not exist. Nothing to do here.
pass
return content

View File

@@ -1,55 +0,0 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""App Engine memcache based cache for the discovery document."""
import logging
# This is only an optional dependency because we only import this
# module when google.appengine.api.memcache is available.
from google.appengine.api import memcache
from . import base
from ..discovery_cache import DISCOVERY_DOC_MAX_AGE
LOGGER = logging.getLogger(__name__)
NAMESPACE = "google-api-client"
class Cache(base.Cache):
"""A cache with app engine memcache API."""
def __init__(self, max_age):
"""Constructor.
Args:
max_age: Cache expiration in seconds.
"""
self._max_age = max_age
def get(self, url):
try:
return memcache.get(url, namespace=NAMESPACE)
except Exception as e:
LOGGER.warning(e, exc_info=True)
def set(self, url, content):
try:
memcache.set(url, content, time=int(self._max_age), namespace=NAMESPACE)
except Exception as e:
LOGGER.warning(e, exc_info=True)
cache = Cache(max_age=DISCOVERY_DOC_MAX_AGE)

View File

@@ -1,46 +0,0 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""An abstract class for caching the discovery document."""
import abc
class Cache(object):
"""A base abstract cache class."""
__metaclass__ = abc.ABCMeta
@abc.abstractmethod
def get(self, url):
"""Gets the content from the memcache with a given key.
Args:
url: string, the key for the cache.
Returns:
object, the value in the cache for the given key, or None if the key is
not in the cache.
"""
raise NotImplementedError()
@abc.abstractmethod
def set(self, url, content):
"""Sets the given key and content in the cache.
Args:
url: string, the key for the cache.
content: string, the discovery document.
"""
raise NotImplementedError()

View File

@@ -1,145 +0,0 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""File based cache for the discovery document.
The cache is stored in a single file so that multiple processes can
share the same cache. It locks the file whenever accessing to the
file. When the cache content is corrupted, it will be initialized with
an empty cache.
"""
from __future__ import division
import datetime
import json
import logging
import os
import tempfile
try:
from oauth2client.contrib.locked_file import LockedFile
except ImportError:
# oauth2client < 2.0.0
try:
from oauth2client.locked_file import LockedFile
except ImportError:
# oauth2client > 4.0.0 or google-auth
raise ImportError(
"file_cache is unavailable when using oauth2client >= 4.0.0 or google-auth"
)
from . import base
from ..discovery_cache import DISCOVERY_DOC_MAX_AGE
LOGGER = logging.getLogger(__name__)
FILENAME = "google-api-python-client-discovery-doc.cache"
EPOCH = datetime.datetime(1970, 1, 1)
def _to_timestamp(date):
try:
return (date - EPOCH).total_seconds()
except AttributeError:
# The following is the equivalent of total_seconds() in Python2.6.
# See also: https://docs.python.org/2/library/datetime.html
delta = date - EPOCH
return (
delta.microseconds + (delta.seconds + delta.days * 24 * 3600) * 10**6
) / 10**6
def _read_or_initialize_cache(f):
f.file_handle().seek(0)
try:
cache = json.load(f.file_handle())
except Exception:
# This means it opens the file for the first time, or the cache is
# corrupted, so initializing the file with an empty dict.
cache = {}
f.file_handle().truncate(0)
f.file_handle().seek(0)
json.dump(cache, f.file_handle())
return cache
class Cache(base.Cache):
"""A file based cache for the discovery documents."""
def __init__(self, max_age):
"""Constructor.
Args:
max_age: Cache expiration in seconds.
"""
self._max_age = max_age
self._file = os.path.join(tempfile.gettempdir(), FILENAME)
f = LockedFile(self._file, "a+", "r")
try:
f.open_and_lock()
if f.is_locked():
_read_or_initialize_cache(f)
# If we can not obtain the lock, other process or thread must
# have initialized the file.
except Exception as e:
LOGGER.warning(e, exc_info=True)
finally:
f.unlock_and_close()
def get(self, url):
f = LockedFile(self._file, "r+", "r")
try:
f.open_and_lock()
if f.is_locked():
cache = _read_or_initialize_cache(f)
if url in cache:
content, t = cache.get(url, (None, 0))
if _to_timestamp(datetime.datetime.now()) < t + self._max_age:
return content
return None
else:
LOGGER.debug("Could not obtain a lock for the cache file.")
return None
except Exception as e:
LOGGER.warning(e, exc_info=True)
finally:
f.unlock_and_close()
def set(self, url, content):
f = LockedFile(self._file, "r+", "r")
try:
f.open_and_lock()
if f.is_locked():
cache = _read_or_initialize_cache(f)
cache[url] = (content, _to_timestamp(datetime.datetime.now()))
# Remove stale cache.
for k, (_, timestamp) in list(cache.items()):
if (
_to_timestamp(datetime.datetime.now())
>= timestamp + self._max_age
):
del cache[k]
f.file_handle().truncate(0)
f.file_handle().seek(0)
json.dump(cache, f.file_handle())
else:
LOGGER.debug("Could not obtain a lock for the cache file.")
except Exception as e:
LOGGER.warning(e, exc_info=True)
finally:
f.unlock_and_close()
cache = Cache(max_age=DISCOVERY_DOC_MAX_AGE)

View File

@@ -1,197 +0,0 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Errors for the library.
All exceptions defined by the library
should be defined in this file.
"""
from __future__ import absolute_import
__author__ = "jcgregorio@google.com (Joe Gregorio)"
import json
from googleapiclient import _helpers as util
class Error(Exception):
"""Base error for this module."""
pass
class HttpError(Error):
"""HTTP data was invalid or unexpected."""
@util.positional(3)
def __init__(self, resp, content, uri=None):
self.resp = resp
if not isinstance(content, bytes):
raise TypeError("HTTP content should be bytes")
self.content = content
self.uri = uri
self.error_details = ""
self.reason = self._get_reason()
@property
def status_code(self):
"""Return the HTTP status code from the response content."""
return self.resp.status
def _get_reason(self):
"""Calculate the reason for the error from the response content."""
reason = self.resp.reason
try:
try:
data = json.loads(self.content.decode("utf-8"))
except json.JSONDecodeError:
# In case it is not json
data = self.content.decode("utf-8")
if isinstance(data, dict):
reason = data["error"]["message"]
error_detail_keyword = next(
(
kw
for kw in ["detail", "details", "errors", "message"]
if kw in data["error"]
),
"",
)
if error_detail_keyword:
self.error_details = data["error"][error_detail_keyword]
elif isinstance(data, list) and len(data) > 0:
first_error = data[0]
reason = first_error["error"]["message"]
if "details" in first_error["error"]:
self.error_details = first_error["error"]["details"]
else:
self.error_details = data
except (ValueError, KeyError, TypeError):
pass
if reason is None:
reason = ""
return reason.strip()
def __repr__(self):
if self.error_details:
return '<HttpError %s when requesting %s returned "%s". Details: "%s">' % (
self.resp.status,
self.uri,
self.reason,
self.error_details,
)
elif self.uri:
return '<HttpError %s when requesting %s returned "%s">' % (
self.resp.status,
self.uri,
self.reason,
)
else:
return '<HttpError %s "%s">' % (self.resp.status, self.reason)
__str__ = __repr__
class InvalidJsonError(Error):
"""The JSON returned could not be parsed."""
pass
class UnknownFileType(Error):
"""File type unknown or unexpected."""
pass
class UnknownLinkType(Error):
"""Link type unknown or unexpected."""
pass
class UnknownApiNameOrVersion(Error):
"""No API with that name and version exists."""
pass
class UnacceptableMimeTypeError(Error):
"""That is an unacceptable mimetype for this operation."""
pass
class MediaUploadSizeError(Error):
"""Media is larger than the method can accept."""
pass
class ResumableUploadError(HttpError):
"""Error occurred during resumable upload."""
pass
class InvalidChunkSizeError(Error):
"""The given chunksize is not valid."""
pass
class InvalidNotificationError(Error):
"""The channel Notification is invalid."""
pass
class BatchError(HttpError):
"""Error occurred during batch operations."""
@util.positional(2)
def __init__(self, reason, resp=None, content=None):
self.resp = resp
self.content = content
self.reason = reason
def __repr__(self):
if getattr(self.resp, "status", None) is None:
return '<BatchError "%s">' % (self.reason)
else:
return '<BatchError %s "%s">' % (self.resp.status, self.reason)
__str__ = __repr__
class UnexpectedMethodError(Error):
"""Exception raised by RequestMockBuilder on unexpected calls."""
@util.positional(1)
def __init__(self, methodId=None):
"""Constructor for an UnexpectedMethodError."""
super(UnexpectedMethodError, self).__init__(
"Received unexpected call %s" % methodId
)
class UnexpectedBodyError(Error):
"""Exception raised by RequestMockBuilder on unexpected bodies."""
def __init__(self, expected, provided):
"""Constructor for an UnexpectedMethodError."""
super(UnexpectedBodyError, self).__init__(
"Expected: [%s] - Provided: [%s]" % (expected, provided)
)

File diff suppressed because it is too large Load Diff

View File

@@ -1,183 +0,0 @@
# Copyright 2014 Joe Gregorio
#
# Licensed under the MIT License
"""MIME-Type Parser
This module provides basic functions for handling mime-types. It can handle
matching mime-types against a list of media-ranges. See section 14.1 of the
HTTP specification [RFC 2616] for a complete explanation.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
Contents:
- parse_mime_type(): Parses a mime-type into its component parts.
- parse_media_range(): Media-ranges are mime-types with wild-cards and a 'q'
quality parameter.
- quality(): Determines the quality ('q') of a mime-type when
compared against a list of media-ranges.
- quality_parsed(): Just like quality() except the second parameter must be
pre-parsed.
- best_match(): Choose the mime-type with the highest quality ('q')
from a list of candidates.
"""
from __future__ import absolute_import
from functools import reduce
__version__ = "0.1.3"
__author__ = "Joe Gregorio"
__email__ = "joe@bitworking.org"
__license__ = "MIT License"
__credits__ = ""
def parse_mime_type(mime_type):
"""Parses a mime-type into its component parts.
Carves up a mime-type and returns a tuple of the (type, subtype, params)
where 'params' is a dictionary of all the parameters for the media range.
For example, the media range 'application/xhtml;q=0.5' would get parsed
into:
('application', 'xhtml', {'q', '0.5'})
"""
parts = mime_type.split(";")
params = dict(
[tuple([s.strip() for s in param.split("=", 1)]) for param in parts[1:]]
)
full_type = parts[0].strip()
# Java URLConnection class sends an Accept header that includes a
# single '*'. Turn it into a legal wildcard.
if full_type == "*":
full_type = "*/*"
(type, subtype) = full_type.split("/")
return (type.strip(), subtype.strip(), params)
def parse_media_range(range):
"""Parse a media-range into its component parts.
Carves up a media range and returns a tuple of the (type, subtype,
params) where 'params' is a dictionary of all the parameters for the media
range. For example, the media range 'application/*;q=0.5' would get parsed
into:
('application', '*', {'q', '0.5'})
In addition this function also guarantees that there is a value for 'q'
in the params dictionary, filling it in with a proper default if
necessary.
"""
(type, subtype, params) = parse_mime_type(range)
if (
"q" not in params
or not params["q"]
or not float(params["q"])
or float(params["q"]) > 1
or float(params["q"]) < 0
):
params["q"] = "1"
return (type, subtype, params)
def fitness_and_quality_parsed(mime_type, parsed_ranges):
"""Find the best match for a mime-type amongst parsed media-ranges.
Find the best match for a given mime-type against a list of media_ranges
that have already been parsed by parse_media_range(). Returns a tuple of
the fitness value and the value of the 'q' quality parameter of the best
match, or (-1, 0) if no match was found. Just as for quality_parsed(),
'parsed_ranges' must be a list of parsed media ranges.
"""
best_fitness = -1
best_fit_q = 0
(target_type, target_subtype, target_params) = parse_media_range(mime_type)
for (type, subtype, params) in parsed_ranges:
type_match = type == target_type or type == "*" or target_type == "*"
subtype_match = (
subtype == target_subtype or subtype == "*" or target_subtype == "*"
)
if type_match and subtype_match:
param_matches = reduce(
lambda x, y: x + y,
[
1
for (key, value) in target_params.items()
if key != "q" and key in params and value == params[key]
],
0,
)
fitness = (type == target_type) and 100 or 0
fitness += (subtype == target_subtype) and 10 or 0
fitness += param_matches
if fitness > best_fitness:
best_fitness = fitness
best_fit_q = params["q"]
return best_fitness, float(best_fit_q)
def quality_parsed(mime_type, parsed_ranges):
"""Find the best match for a mime-type amongst parsed media-ranges.
Find the best match for a given mime-type against a list of media_ranges
that have already been parsed by parse_media_range(). Returns the 'q'
quality parameter of the best match, 0 if no match was found. This function
bahaves the same as quality() except that 'parsed_ranges' must be a list of
parsed media ranges.
"""
return fitness_and_quality_parsed(mime_type, parsed_ranges)[1]
def quality(mime_type, ranges):
"""Return the quality ('q') of a mime-type against a list of media-ranges.
Returns the quality 'q' of a mime-type when compared against the
media-ranges in ranges. For example:
>>> quality('text/html','text/*;q=0.3, text/html;q=0.7,
text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5')
0.7
"""
parsed_ranges = [parse_media_range(r) for r in ranges.split(",")]
return quality_parsed(mime_type, parsed_ranges)
def best_match(supported, header):
"""Return mime-type with the highest quality ('q') from list of candidates.
Takes a list of supported mime-types and finds the best match for all the
media-ranges listed in header. The value of header must be a string that
conforms to the format of the HTTP Accept: header. The value of 'supported'
is a list of mime-types. The list of supported mime-types should be sorted
in order of increasing desirability, in case of a situation where there is
a tie.
>>> best_match(['application/xbel+xml', 'text/xml'],
'text/*;q=0.5,*/*; q=0.1')
'text/xml'
"""
split_header = _filter_blank(header.split(","))
parsed_header = [parse_media_range(r) for r in split_header]
weighted_matches = []
pos = 0
for mime_type in supported:
weighted_matches.append(
(fitness_and_quality_parsed(mime_type, parsed_header), pos, mime_type)
)
pos += 1
weighted_matches.sort()
return weighted_matches[-1][0][1] and weighted_matches[-1][2] or ""
def _filter_blank(i):
for s in i:
if s.strip():
yield s

View File

@@ -1,429 +0,0 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Model objects for requests and responses.
Each API may support one or more serializations, such
as JSON, Atom, etc. The model classes are responsible
for converting between the wire format and the Python
object representation.
"""
from __future__ import absolute_import
__author__ = "jcgregorio@google.com (Joe Gregorio)"
import json
import logging
import platform
import urllib
import warnings
from googleapiclient import version as googleapiclient_version
from googleapiclient.errors import HttpError
try:
from google.api_core.version_header import API_VERSION_METADATA_KEY
HAS_API_VERSION = True
except ImportError:
HAS_API_VERSION = False
_LIBRARY_VERSION = googleapiclient_version.__version__
_PY_VERSION = platform.python_version()
LOGGER = logging.getLogger(__name__)
dump_request_response = False
def _abstract():
raise NotImplementedError("You need to override this function")
class Model(object):
"""Model base class.
All Model classes should implement this interface.
The Model serializes and de-serializes between a wire
format such as JSON and a Python object representation.
"""
def request(self, headers, path_params, query_params, body_value):
"""Updates outgoing requests with a serialized body.
Args:
headers: dict, request headers
path_params: dict, parameters that appear in the request path
query_params: dict, parameters that appear in the query
body_value: object, the request body as a Python object, which must be
serializable.
Returns:
A tuple of (headers, path_params, query, body)
headers: dict, request headers
path_params: dict, parameters that appear in the request path
query: string, query part of the request URI
body: string, the body serialized in the desired wire format.
"""
_abstract()
def response(self, resp, content):
"""Convert the response wire format into a Python object.
Args:
resp: httplib2.Response, the HTTP response headers and status
content: string, the body of the HTTP response
Returns:
The body de-serialized as a Python object.
Raises:
googleapiclient.errors.HttpError if a non 2xx response is received.
"""
_abstract()
class BaseModel(Model):
"""Base model class.
Subclasses should provide implementations for the "serialize" and
"deserialize" methods, as well as values for the following class attributes.
Attributes:
accept: The value to use for the HTTP Accept header.
content_type: The value to use for the HTTP Content-type header.
no_content_response: The value to return when deserializing a 204 "No
Content" response.
alt_param: The value to supply as the "alt" query parameter for requests.
"""
accept = None
content_type = None
no_content_response = None
alt_param = None
def _log_request(self, headers, path_params, query, body):
"""Logs debugging information about the request if requested."""
if dump_request_response:
LOGGER.info("--request-start--")
LOGGER.info("-headers-start-")
for h, v in headers.items():
LOGGER.info("%s: %s", h, v)
LOGGER.info("-headers-end-")
LOGGER.info("-path-parameters-start-")
for h, v in path_params.items():
LOGGER.info("%s: %s", h, v)
LOGGER.info("-path-parameters-end-")
LOGGER.info("body: %s", body)
LOGGER.info("query: %s", query)
LOGGER.info("--request-end--")
def request(self, headers, path_params, query_params, body_value, api_version=None):
"""Updates outgoing requests with a serialized body.
Args:
headers: dict, request headers
path_params: dict, parameters that appear in the request path
query_params: dict, parameters that appear in the query
body_value: object, the request body as a Python object, which must be
serializable by json.
api_version: str, The precise API version represented by this request,
which will result in an API Version header being sent along with the
HTTP request.
Returns:
A tuple of (headers, path_params, query, body)
headers: dict, request headers
path_params: dict, parameters that appear in the request path
query: string, query part of the request URI
body: string, the body serialized as JSON
"""
query = self._build_query(query_params)
headers["accept"] = self.accept
headers["accept-encoding"] = "gzip, deflate"
if "user-agent" in headers:
headers["user-agent"] += " "
else:
headers["user-agent"] = ""
headers["user-agent"] += "(gzip)"
if "x-goog-api-client" in headers:
headers["x-goog-api-client"] += " "
else:
headers["x-goog-api-client"] = ""
headers["x-goog-api-client"] += "gdcl/%s gl-python/%s" % (
_LIBRARY_VERSION,
_PY_VERSION,
)
if api_version and HAS_API_VERSION:
headers[API_VERSION_METADATA_KEY] = api_version
elif api_version:
warnings.warn(
"The `api_version` argument is ignored as a newer version of "
"`google-api-core` is required to use this feature."
"Please upgrade `google-api-core` to 2.19.0 or newer."
)
if body_value is not None:
headers["content-type"] = self.content_type
body_value = self.serialize(body_value)
self._log_request(headers, path_params, query, body_value)
return (headers, path_params, query, body_value)
def _build_query(self, params):
"""Builds a query string.
Args:
params: dict, the query parameters
Returns:
The query parameters properly encoded into an HTTP URI query string.
"""
if self.alt_param is not None:
params.update({"alt": self.alt_param})
astuples = []
for key, value in params.items():
if type(value) == type([]):
for x in value:
x = x.encode("utf-8")
astuples.append((key, x))
else:
if isinstance(value, str) and callable(value.encode):
value = value.encode("utf-8")
astuples.append((key, value))
return "?" + urllib.parse.urlencode(astuples)
def _log_response(self, resp, content):
"""Logs debugging information about the response if requested."""
if dump_request_response:
LOGGER.info("--response-start--")
for h, v in resp.items():
LOGGER.info("%s: %s", h, v)
if content:
LOGGER.info(content)
LOGGER.info("--response-end--")
def response(self, resp, content):
"""Convert the response wire format into a Python object.
Args:
resp: httplib2.Response, the HTTP response headers and status
content: string, the body of the HTTP response
Returns:
The body de-serialized as a Python object.
Raises:
googleapiclient.errors.HttpError if a non 2xx response is received.
"""
self._log_response(resp, content)
# Error handling is TBD, for example, do we retry
# for some operation/error combinations?
if resp.status < 300:
if resp.status == 204:
# A 204: No Content response should be treated differently
# to all the other success states
return self.no_content_response
return self.deserialize(content)
else:
LOGGER.debug("Content from bad request was: %r" % content)
raise HttpError(resp, content)
def serialize(self, body_value):
"""Perform the actual Python object serialization.
Args:
body_value: object, the request body as a Python object.
Returns:
string, the body in serialized form.
"""
_abstract()
def deserialize(self, content):
"""Perform the actual deserialization from response string to Python
object.
Args:
content: string, the body of the HTTP response
Returns:
The body de-serialized as a Python object.
"""
_abstract()
class JsonModel(BaseModel):
"""Model class for JSON.
Serializes and de-serializes between JSON and the Python
object representation of HTTP request and response bodies.
"""
accept = "application/json"
content_type = "application/json"
alt_param = "json"
def __init__(self, data_wrapper=False):
"""Construct a JsonModel.
Args:
data_wrapper: boolean, wrap requests and responses in a data wrapper
"""
self._data_wrapper = data_wrapper
def serialize(self, body_value):
if (
isinstance(body_value, dict)
and "data" not in body_value
and self._data_wrapper
):
body_value = {"data": body_value}
return json.dumps(body_value)
def deserialize(self, content):
try:
content = content.decode("utf-8")
except AttributeError:
pass
try:
body = json.loads(content)
except json.decoder.JSONDecodeError:
body = content
else:
if self._data_wrapper and "data" in body:
body = body["data"]
return body
@property
def no_content_response(self):
return {}
class RawModel(JsonModel):
"""Model class for requests that don't return JSON.
Serializes and de-serializes between JSON and the Python
object representation of HTTP request, and returns the raw bytes
of the response body.
"""
accept = "*/*"
content_type = "application/json"
alt_param = None
def deserialize(self, content):
return content
@property
def no_content_response(self):
return ""
class MediaModel(JsonModel):
"""Model class for requests that return Media.
Serializes and de-serializes between JSON and the Python
object representation of HTTP request, and returns the raw bytes
of the response body.
"""
accept = "*/*"
content_type = "application/json"
alt_param = "media"
def deserialize(self, content):
return content
@property
def no_content_response(self):
return ""
class ProtocolBufferModel(BaseModel):
"""Model class for protocol buffers.
Serializes and de-serializes the binary protocol buffer sent in the HTTP
request and response bodies.
"""
accept = "application/x-protobuf"
content_type = "application/x-protobuf"
alt_param = "proto"
def __init__(self, protocol_buffer):
"""Constructs a ProtocolBufferModel.
The serialized protocol buffer returned in an HTTP response will be
de-serialized using the given protocol buffer class.
Args:
protocol_buffer: The protocol buffer class used to de-serialize a
response from the API.
"""
self._protocol_buffer = protocol_buffer
def serialize(self, body_value):
return body_value.SerializeToString()
def deserialize(self, content):
return self._protocol_buffer.FromString(content)
@property
def no_content_response(self):
return self._protocol_buffer()
def makepatch(original, modified):
"""Create a patch object.
Some methods support PATCH, an efficient way to send updates to a resource.
This method allows the easy construction of patch bodies by looking at the
differences between a resource before and after it was modified.
Args:
original: object, the original deserialized resource
modified: object, the modified deserialized resource
Returns:
An object that contains only the changes from original to modified, in a
form suitable to pass to a PATCH method.
Example usage:
item = service.activities().get(postid=postid, userid=userid).execute()
original = copy.deepcopy(item)
item['object']['content'] = 'This is updated.'
service.activities.patch(postid=postid, userid=userid,
body=makepatch(original, item)).execute()
"""
patch = {}
for key, original_value in original.items():
modified_value = modified.get(key, None)
if modified_value is None:
# Use None to signal that the element is deleted
patch[key] = None
elif original_value != modified_value:
if type(original_value) == type({}):
# Recursively descend objects
patch[key] = makepatch(original_value, modified_value)
else:
# In the case of simple types or arrays we just replace
patch[key] = modified_value
else:
# Don't add anything to patch if there's no change
pass
for key in modified:
if key not in original:
patch[key] = modified[key]
return patch

View File

@@ -1,317 +0,0 @@
# Copyright 2014 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Schema processing for discovery based APIs
Schemas holds an APIs discovery schemas. It can return those schema as
deserialized JSON objects, or pretty print them as prototype objects that
conform to the schema.
For example, given the schema:
schema = \"\"\"{
"Foo": {
"type": "object",
"properties": {
"etag": {
"type": "string",
"description": "ETag of the collection."
},
"kind": {
"type": "string",
"description": "Type of the collection ('calendar#acl').",
"default": "calendar#acl"
},
"nextPageToken": {
"type": "string",
"description": "Token used to access the next
page of this result. Omitted if no further results are available."
}
}
}
}\"\"\"
s = Schemas(schema)
print s.prettyPrintByName('Foo')
Produces the following output:
{
"nextPageToken": "A String", # Token used to access the
# next page of this result. Omitted if no further results are available.
"kind": "A String", # Type of the collection ('calendar#acl').
"etag": "A String", # ETag of the collection.
},
The constructor takes a discovery document in which to look up named schema.
"""
from __future__ import absolute_import
# TODO(jcgregorio) support format, enum, minimum, maximum
__author__ = "jcgregorio@google.com (Joe Gregorio)"
from collections import OrderedDict
from googleapiclient import _helpers as util
class Schemas(object):
"""Schemas for an API."""
def __init__(self, discovery):
"""Constructor.
Args:
discovery: object, Deserialized discovery document from which we pull
out the named schema.
"""
self.schemas = discovery.get("schemas", {})
# Cache of pretty printed schemas.
self.pretty = {}
@util.positional(2)
def _prettyPrintByName(self, name, seen=None, dent=0):
"""Get pretty printed object prototype from the schema name.
Args:
name: string, Name of schema in the discovery document.
seen: list of string, Names of schema already seen. Used to handle
recursive definitions.
Returns:
string, A string that contains a prototype object with
comments that conforms to the given schema.
"""
if seen is None:
seen = []
if name in seen:
# Do not fall into an infinite loop over recursive definitions.
return "# Object with schema name: %s" % name
seen.append(name)
if name not in self.pretty:
self.pretty[name] = _SchemaToStruct(
self.schemas[name], seen, dent=dent
).to_str(self._prettyPrintByName)
seen.pop()
return self.pretty[name]
def prettyPrintByName(self, name):
"""Get pretty printed object prototype from the schema name.
Args:
name: string, Name of schema in the discovery document.
Returns:
string, A string that contains a prototype object with
comments that conforms to the given schema.
"""
# Return with trailing comma and newline removed.
return self._prettyPrintByName(name, seen=[], dent=0)[:-2]
@util.positional(2)
def _prettyPrintSchema(self, schema, seen=None, dent=0):
"""Get pretty printed object prototype of schema.
Args:
schema: object, Parsed JSON schema.
seen: list of string, Names of schema already seen. Used to handle
recursive definitions.
Returns:
string, A string that contains a prototype object with
comments that conforms to the given schema.
"""
if seen is None:
seen = []
return _SchemaToStruct(schema, seen, dent=dent).to_str(self._prettyPrintByName)
def prettyPrintSchema(self, schema):
"""Get pretty printed object prototype of schema.
Args:
schema: object, Parsed JSON schema.
Returns:
string, A string that contains a prototype object with
comments that conforms to the given schema.
"""
# Return with trailing comma and newline removed.
return self._prettyPrintSchema(schema, dent=0)[:-2]
def get(self, name, default=None):
"""Get deserialized JSON schema from the schema name.
Args:
name: string, Schema name.
default: object, return value if name not found.
"""
return self.schemas.get(name, default)
class _SchemaToStruct(object):
"""Convert schema to a prototype object."""
@util.positional(3)
def __init__(self, schema, seen, dent=0):
"""Constructor.
Args:
schema: object, Parsed JSON schema.
seen: list, List of names of schema already seen while parsing. Used to
handle recursive definitions.
dent: int, Initial indentation depth.
"""
# The result of this parsing kept as list of strings.
self.value = []
# The final value of the parsing.
self.string = None
# The parsed JSON schema.
self.schema = schema
# Indentation level.
self.dent = dent
# Method that when called returns a prototype object for the schema with
# the given name.
self.from_cache = None
# List of names of schema already seen while parsing.
self.seen = seen
def emit(self, text):
"""Add text as a line to the output.
Args:
text: string, Text to output.
"""
self.value.extend([" " * self.dent, text, "\n"])
def emitBegin(self, text):
"""Add text to the output, but with no line terminator.
Args:
text: string, Text to output.
"""
self.value.extend([" " * self.dent, text])
def emitEnd(self, text, comment):
"""Add text and comment to the output with line terminator.
Args:
text: string, Text to output.
comment: string, Python comment.
"""
if comment:
divider = "\n" + " " * (self.dent + 2) + "# "
lines = comment.splitlines()
lines = [x.rstrip() for x in lines]
comment = divider.join(lines)
self.value.extend([text, " # ", comment, "\n"])
else:
self.value.extend([text, "\n"])
def indent(self):
"""Increase indentation level."""
self.dent += 1
def undent(self):
"""Decrease indentation level."""
self.dent -= 1
def _to_str_impl(self, schema):
"""Prototype object based on the schema, in Python code with comments.
Args:
schema: object, Parsed JSON schema file.
Returns:
Prototype object based on the schema, in Python code with comments.
"""
stype = schema.get("type")
if stype == "object":
self.emitEnd("{", schema.get("description", ""))
self.indent()
if "properties" in schema:
properties = schema.get("properties", {})
sorted_properties = OrderedDict(sorted(properties.items()))
for pname, pschema in sorted_properties.items():
self.emitBegin('"%s": ' % pname)
self._to_str_impl(pschema)
elif "additionalProperties" in schema:
self.emitBegin('"a_key": ')
self._to_str_impl(schema["additionalProperties"])
self.undent()
self.emit("},")
elif "$ref" in schema:
schemaName = schema["$ref"]
description = schema.get("description", "")
s = self.from_cache(schemaName, seen=self.seen)
parts = s.splitlines()
self.emitEnd(parts[0], description)
for line in parts[1:]:
self.emit(line.rstrip())
elif stype == "boolean":
value = schema.get("default", "True or False")
self.emitEnd("%s," % str(value), schema.get("description", ""))
elif stype == "string":
value = schema.get("default", "A String")
self.emitEnd('"%s",' % str(value), schema.get("description", ""))
elif stype == "integer":
value = schema.get("default", "42")
self.emitEnd("%s," % str(value), schema.get("description", ""))
elif stype == "number":
value = schema.get("default", "3.14")
self.emitEnd("%s," % str(value), schema.get("description", ""))
elif stype == "null":
self.emitEnd("None,", schema.get("description", ""))
elif stype == "any":
self.emitEnd('"",', schema.get("description", ""))
elif stype == "array":
self.emitEnd("[", schema.get("description"))
self.indent()
self.emitBegin("")
self._to_str_impl(schema["items"])
self.undent()
self.emit("],")
else:
self.emit("Unknown type! %s" % stype)
self.emitEnd("", "")
self.string = "".join(self.value)
return self.string
def to_str(self, from_cache):
"""Prototype object based on the schema, in Python code with comments.
Args:
from_cache: callable(name, seen), Callable that retrieves an object
prototype for a schema with the given name. Seen is a list of schema
names already seen as we recursively descend the schema definition.
Returns:
Prototype object based on the schema, in Python code with comments.
The lines of the code will all be properly indented.
"""
self.from_cache = from_cache
return self._to_str_impl(self.schema)

View File

@@ -1,15 +0,0 @@
# Copyright 2021 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
__version__ = "2.179.0"

View File

@@ -1,28 +0,0 @@
# -*- coding: utf-8 -*-
#
# Copyright (c) 2007 - 2015 Michael Twomey
#
# Permission is hereby granted, free of charge, to any person obtaining a
# copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
"""ISO 8601 date time string parsing
"""
__all__ = ["parse_date", "ParseError", "UTC"]

View File

@@ -1,160 +0,0 @@
# -*- coding: utf-8 -*-
"""ISO 8601 date time string parsing
"""
from datetime import (datetime, timedelta, tzinfo)
import time as _time
import re
ISO8601_REGEX = re.compile(r'^(?P<year>[0-9]{4})-(?P<month>[0-9]{2})-(?P<day>[0-9]{2})(?P<separator>[ T])(?P<hour>[0-9]{2}):(?P<minute>[0-9]{2}):(?P<second>[0-9]{2})([.,](?P<second_fraction>[0-9]+)){0,1}(?P<timezone>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9]{2}):(?P<tz_minute>[0-9]{2}))$')
ISO8601_TZ_REGEX = re.compile(r'^(?P<timezone>Z|(?P<tz_sign>[-+])(?P<tz_hour>[0-9]{2}):(?P<tz_minute>[0-9]{2}))$')
class ParseError(Exception):
"""Raised when there is a problem parsing a date string"""
# Yoinked from python docs
ZERO = timedelta(0)
class Utc(tzinfo):
"""UTC Timezone
"""
def utcoffset(self, dt):
return ZERO
def tzname(self, dt):
return "UTC"
def dst(self, dt):
return ZERO
def __repr__(self):
return "<iso8601.Utc>"
UTC = Utc()
class FixedOffset(tzinfo):
"""Fixed offset in hours and minutes from UTC
"""
def __init__(self, offset_hours, offset_minutes, name):
self.__offset_hours = offset_hours # Keep for later __getinitargs__
self.__offset_minutes = offset_minutes # Keep for later __getinitargs__
self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes)
self.__name = name
def __eq__(self, other):
if isinstance(other, FixedOffset):
return (other.__offset == self.__offset) and (other.__name == self.__name)
if isinstance(other, tzinfo):
return other == self
return False
def __getinitargs__(self):
return (self.__offset_hours, self.__offset_minutes, self.__name)
def utcoffset(self, dt):
return self.__offset
def tzname(self, dt):
return self.__name
def dst(self, dt):
return ZERO
def __repr__(self):
return "<FixedOffset %r %r>" % (self.__name, self.__offset)
# A class capturing the platform's idea of local time.
STDOFFSET = timedelta(seconds = -_time.timezone)
if _time.daylight:
DSTOFFSET = timedelta(seconds = -_time.altzone)
else:
DSTOFFSET = STDOFFSET
DSTDIFF = DSTOFFSET - STDOFFSET
class LocalTimezone(tzinfo):
"""Local time zone
"""
def utcoffset(self, dt):
if self._isdst(dt):
return DSTOFFSET
else:
return STDOFFSET
def dst(self, dt):
if self._isdst(dt):
return DSTDIFF
else:
return ZERO
def tzname(self, dt):
return _time.tzname[self._isdst(dt)]
def _isdst(self, dt):
tt = (dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.weekday(), 0, 0)
stamp = _time.mktime(tt)
tt = _time.localtime(stamp)
return tt.tm_isdst > 0
Local = LocalTimezone()
def parse_timezone(matches):
"""Parses ISO 8601 time zone specs into tzinfo offsets
"""
if matches["timezone"] == "Z":
return UTC
sign = matches["tz_sign"]
hours = int(matches['tz_hour'])
minutes = int(matches['tz_minute'])
description = "%s%02d:%02d" % (sign, hours, minutes)
if sign == "-":
hours = -hours
minutes = -minutes
return FixedOffset(hours, minutes, description)
def parse_timezone_str(tzstring):
m = ISO8601_TZ_REGEX.match(tzstring)
if not m:
raise ParseError("Unable to parse timezone string %r" % tzstring)
groups = m.groupdict()
return parse_timezone(groups)
def parse_date(datestring):
"""Parses ISO 8601 dates into datetime objects
The timezone is parsed from the date string. However it is quite common to
have dates without a timezone (not strictly correct). In this case the
default timezone specified in default_timezone is used. This is UTC by
default.
:param datestring: The date to parse as a string
:returns: A datetime.datetime instance
:raises: ParseError when there is a problem parsing the date or
constructing the datetime instance.
"""
m = ISO8601_REGEX.match(datestring)
if not m:
raise ParseError("Unable to parse date string %r" % datestring)
groups = m.groupdict()
tz = parse_timezone(groups)
try:
return (datetime(year=int(groups['year']),
month=int(groups['month']),
day=int(groups['day']),
hour=int(groups['hour']),
minute=int(groups['minute']),
second=int(groups['second']),
tzinfo=tz),
tz)
except Exception as e:
raise ParseError(e)

View File

@@ -1,982 +0,0 @@
# Copyright (c) 2010-2020 Benjamin Peterson
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
"""Utilities for writing code that runs on Python 2 and 3"""
from __future__ import absolute_import
import functools
import itertools
import operator
import sys
import types
__author__ = "Benjamin Peterson <benjamin@python.org>"
__version__ = "1.15.0"
# Useful for very coarse version differentiation.
PY2 = sys.version_info[0] == 2
PY3 = sys.version_info[0] == 3
PY34 = sys.version_info[0:2] >= (3, 4)
if PY3:
string_types = str,
integer_types = int,
class_types = type,
text_type = str
binary_type = bytes
MAXSIZE = sys.maxsize
else:
string_types = basestring,
integer_types = (int, long)
class_types = (type, types.ClassType)
text_type = unicode
binary_type = str
if sys.platform.startswith("java"):
# Jython always uses 32 bits.
MAXSIZE = int((1 << 31) - 1)
else:
# It's possible to have sizeof(long) != sizeof(Py_ssize_t).
class X(object):
def __len__(self):
return 1 << 31
try:
len(X())
except OverflowError:
# 32-bit
MAXSIZE = int((1 << 31) - 1)
else:
# 64-bit
MAXSIZE = int((1 << 63) - 1)
del X
def _add_doc(func, doc):
"""Add documentation to a function."""
func.__doc__ = doc
def _import_module(name):
"""Import module, returning the module after the last dot."""
__import__(name)
return sys.modules[name]
class _LazyDescr(object):
def __init__(self, name):
self.name = name
def __get__(self, obj, tp):
result = self._resolve()
setattr(obj, self.name, result) # Invokes __set__.
try:
# This is a bit ugly, but it avoids running this again by
# removing this descriptor.
delattr(obj.__class__, self.name)
except AttributeError:
pass
return result
class MovedModule(_LazyDescr):
def __init__(self, name, old, new=None):
super(MovedModule, self).__init__(name)
if PY3:
if new is None:
new = name
self.mod = new
else:
self.mod = old
def _resolve(self):
return _import_module(self.mod)
def __getattr__(self, attr):
_module = self._resolve()
value = getattr(_module, attr)
setattr(self, attr, value)
return value
class _LazyModule(types.ModuleType):
def __init__(self, name):
super(_LazyModule, self).__init__(name)
self.__doc__ = self.__class__.__doc__
def __dir__(self):
attrs = ["__doc__", "__name__"]
attrs += [attr.name for attr in self._moved_attributes]
return attrs
# Subclasses should override this
_moved_attributes = []
class MovedAttribute(_LazyDescr):
def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
super(MovedAttribute, self).__init__(name)
if PY3:
if new_mod is None:
new_mod = name
self.mod = new_mod
if new_attr is None:
if old_attr is None:
new_attr = name
else:
new_attr = old_attr
self.attr = new_attr
else:
self.mod = old_mod
if old_attr is None:
old_attr = name
self.attr = old_attr
def _resolve(self):
module = _import_module(self.mod)
return getattr(module, self.attr)
class _SixMetaPathImporter(object):
"""
A meta path importer to import six.moves and its submodules.
This class implements a PEP302 finder and loader. It should be compatible
with Python 2.5 and all existing versions of Python3
"""
def __init__(self, six_module_name):
self.name = six_module_name
self.known_modules = {}
def _add_module(self, mod, *fullnames):
for fullname in fullnames:
self.known_modules[self.name + "." + fullname] = mod
def _get_module(self, fullname):
return self.known_modules[self.name + "." + fullname]
def find_module(self, fullname, path=None):
if fullname in self.known_modules:
return self
return None
def __get_module(self, fullname):
try:
return self.known_modules[fullname]
except KeyError:
raise ImportError("This loader does not know module " + fullname)
def load_module(self, fullname):
try:
# in case of a reload
return sys.modules[fullname]
except KeyError:
pass
mod = self.__get_module(fullname)
if isinstance(mod, MovedModule):
mod = mod._resolve()
else:
mod.__loader__ = self
sys.modules[fullname] = mod
return mod
def is_package(self, fullname):
"""
Return true, if the named module is a package.
We need this method to get correct spec objects with
Python 3.4 (see PEP451)
"""
return hasattr(self.__get_module(fullname), "__path__")
def get_code(self, fullname):
"""Return None
Required, if is_package is implemented"""
self.__get_module(fullname) # eventually raises ImportError
return None
get_source = get_code # same as get_code
_importer = _SixMetaPathImporter(__name__)
class _MovedItems(_LazyModule):
"""Lazy loading of moved objects"""
__path__ = [] # mark as package
_moved_attributes = [
MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"),
MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
MovedAttribute("intern", "__builtin__", "sys"),
MovedAttribute("map", "itertools", "builtins", "imap", "map"),
MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"),
MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"),
MovedAttribute("getoutput", "commands", "subprocess"),
MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"),
MovedAttribute("reduce", "__builtin__", "functools"),
MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
MovedAttribute("StringIO", "StringIO", "io"),
MovedAttribute("UserDict", "UserDict", "collections"),
MovedAttribute("UserList", "UserList", "collections"),
MovedAttribute("UserString", "UserString", "collections"),
MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"),
MovedModule("builtins", "__builtin__"),
MovedModule("configparser", "ConfigParser"),
MovedModule("collections_abc", "collections", "collections.abc" if sys.version_info >= (3, 3) else "collections"),
MovedModule("copyreg", "copy_reg"),
MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
MovedModule("dbm_ndbm", "dbm", "dbm.ndbm"),
MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread" if sys.version_info < (3, 9) else "_thread"),
MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
MovedModule("http_cookies", "Cookie", "http.cookies"),
MovedModule("html_entities", "htmlentitydefs", "html.entities"),
MovedModule("html_parser", "HTMLParser", "html.parser"),
MovedModule("http_client", "httplib", "http.client"),
MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"),
MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"),
MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
MovedModule("cPickle", "cPickle", "pickle"),
MovedModule("queue", "Queue"),
MovedModule("reprlib", "repr"),
MovedModule("socketserver", "SocketServer"),
MovedModule("_thread", "thread", "_thread"),
MovedModule("tkinter", "Tkinter"),
MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
MovedModule("tkinter_colorchooser", "tkColorChooser",
"tkinter.colorchooser"),
MovedModule("tkinter_commondialog", "tkCommonDialog",
"tkinter.commondialog"),
MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
MovedModule("tkinter_font", "tkFont", "tkinter.font"),
MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
MovedModule("tkinter_tksimpledialog", "tkSimpleDialog",
"tkinter.simpledialog"),
MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
]
# Add windows specific modules.
if sys.platform == "win32":
_moved_attributes += [
MovedModule("winreg", "_winreg"),
]
for attr in _moved_attributes:
setattr(_MovedItems, attr.name, attr)
if isinstance(attr, MovedModule):
_importer._add_module(attr, "moves." + attr.name)
del attr
_MovedItems._moved_attributes = _moved_attributes
moves = _MovedItems(__name__ + ".moves")
_importer._add_module(moves, "moves")
class Module_six_moves_urllib_parse(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_parse"""
_urllib_parse_moved_attributes = [
MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
MovedAttribute("urljoin", "urlparse", "urllib.parse"),
MovedAttribute("urlparse", "urlparse", "urllib.parse"),
MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
MovedAttribute("quote", "urllib", "urllib.parse"),
MovedAttribute("quote_plus", "urllib", "urllib.parse"),
MovedAttribute("unquote", "urllib", "urllib.parse"),
MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
MovedAttribute("unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"),
MovedAttribute("urlencode", "urllib", "urllib.parse"),
MovedAttribute("splitquery", "urllib", "urllib.parse"),
MovedAttribute("splittag", "urllib", "urllib.parse"),
MovedAttribute("splituser", "urllib", "urllib.parse"),
MovedAttribute("splitvalue", "urllib", "urllib.parse"),
MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
MovedAttribute("uses_params", "urlparse", "urllib.parse"),
MovedAttribute("uses_query", "urlparse", "urllib.parse"),
MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
]
for attr in _urllib_parse_moved_attributes:
setattr(Module_six_moves_urllib_parse, attr.name, attr)
del attr
Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
"moves.urllib_parse", "moves.urllib.parse")
class Module_six_moves_urllib_error(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_error"""
_urllib_error_moved_attributes = [
MovedAttribute("URLError", "urllib2", "urllib.error"),
MovedAttribute("HTTPError", "urllib2", "urllib.error"),
MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
]
for attr in _urllib_error_moved_attributes:
setattr(Module_six_moves_urllib_error, attr.name, attr)
del attr
Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
"moves.urllib_error", "moves.urllib.error")
class Module_six_moves_urllib_request(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_request"""
_urllib_request_moved_attributes = [
MovedAttribute("urlopen", "urllib2", "urllib.request"),
MovedAttribute("install_opener", "urllib2", "urllib.request"),
MovedAttribute("build_opener", "urllib2", "urllib.request"),
MovedAttribute("pathname2url", "urllib", "urllib.request"),
MovedAttribute("url2pathname", "urllib", "urllib.request"),
MovedAttribute("getproxies", "urllib", "urllib.request"),
MovedAttribute("Request", "urllib2", "urllib.request"),
MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
MovedAttribute("FileHandler", "urllib2", "urllib.request"),
MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
MovedAttribute("urlretrieve", "urllib", "urllib.request"),
MovedAttribute("urlcleanup", "urllib", "urllib.request"),
MovedAttribute("URLopener", "urllib", "urllib.request"),
MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
MovedAttribute("parse_http_list", "urllib2", "urllib.request"),
MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"),
]
for attr in _urllib_request_moved_attributes:
setattr(Module_six_moves_urllib_request, attr.name, attr)
del attr
Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
"moves.urllib_request", "moves.urllib.request")
class Module_six_moves_urllib_response(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_response"""
_urllib_response_moved_attributes = [
MovedAttribute("addbase", "urllib", "urllib.response"),
MovedAttribute("addclosehook", "urllib", "urllib.response"),
MovedAttribute("addinfo", "urllib", "urllib.response"),
MovedAttribute("addinfourl", "urllib", "urllib.response"),
]
for attr in _urllib_response_moved_attributes:
setattr(Module_six_moves_urllib_response, attr.name, attr)
del attr
Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
"moves.urllib_response", "moves.urllib.response")
class Module_six_moves_urllib_robotparser(_LazyModule):
"""Lazy loading of moved objects in six.moves.urllib_robotparser"""
_urllib_robotparser_moved_attributes = [
MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
]
for attr in _urllib_robotparser_moved_attributes:
setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
del attr
Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes
_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
"moves.urllib_robotparser", "moves.urllib.robotparser")
class Module_six_moves_urllib(types.ModuleType):
"""Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
__path__ = [] # mark as package
parse = _importer._get_module("moves.urllib_parse")
error = _importer._get_module("moves.urllib_error")
request = _importer._get_module("moves.urllib_request")
response = _importer._get_module("moves.urllib_response")
robotparser = _importer._get_module("moves.urllib_robotparser")
def __dir__(self):
return ['parse', 'error', 'request', 'response', 'robotparser']
_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"),
"moves.urllib")
def add_move(move):
"""Add an item to six.moves."""
setattr(_MovedItems, move.name, move)
def remove_move(name):
"""Remove item from six.moves."""
try:
delattr(_MovedItems, name)
except AttributeError:
try:
del moves.__dict__[name]
except KeyError:
raise AttributeError("no such move, %r" % (name,))
if PY3:
_meth_func = "__func__"
_meth_self = "__self__"
_func_closure = "__closure__"
_func_code = "__code__"
_func_defaults = "__defaults__"
_func_globals = "__globals__"
else:
_meth_func = "im_func"
_meth_self = "im_self"
_func_closure = "func_closure"
_func_code = "func_code"
_func_defaults = "func_defaults"
_func_globals = "func_globals"
try:
advance_iterator = next
except NameError:
def advance_iterator(it):
return it.next()
next = advance_iterator
try:
callable = callable
except NameError:
def callable(obj):
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
if PY3:
def get_unbound_function(unbound):
return unbound
create_bound_method = types.MethodType
def create_unbound_method(func, cls):
return func
Iterator = object
else:
def get_unbound_function(unbound):
return unbound.im_func
def create_bound_method(func, obj):
return types.MethodType(func, obj, obj.__class__)
def create_unbound_method(func, cls):
return types.MethodType(func, None, cls)
class Iterator(object):
def next(self):
return type(self).__next__(self)
callable = callable
_add_doc(get_unbound_function,
"""Get the function out of a possibly unbound function""")
get_method_function = operator.attrgetter(_meth_func)
get_method_self = operator.attrgetter(_meth_self)
get_function_closure = operator.attrgetter(_func_closure)
get_function_code = operator.attrgetter(_func_code)
get_function_defaults = operator.attrgetter(_func_defaults)
get_function_globals = operator.attrgetter(_func_globals)
if PY3:
def iterkeys(d, **kw):
return iter(d.keys(**kw))
def itervalues(d, **kw):
return iter(d.values(**kw))
def iteritems(d, **kw):
return iter(d.items(**kw))
def iterlists(d, **kw):
return iter(d.lists(**kw))
viewkeys = operator.methodcaller("keys")
viewvalues = operator.methodcaller("values")
viewitems = operator.methodcaller("items")
else:
def iterkeys(d, **kw):
return d.iterkeys(**kw)
def itervalues(d, **kw):
return d.itervalues(**kw)
def iteritems(d, **kw):
return d.iteritems(**kw)
def iterlists(d, **kw):
return d.iterlists(**kw)
viewkeys = operator.methodcaller("viewkeys")
viewvalues = operator.methodcaller("viewvalues")
viewitems = operator.methodcaller("viewitems")
_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
_add_doc(iteritems,
"Return an iterator over the (key, value) pairs of a dictionary.")
_add_doc(iterlists,
"Return an iterator over the (key, [values]) pairs of a dictionary.")
if PY3:
def b(s):
return s.encode("latin-1")
def u(s):
return s
unichr = chr
import struct
int2byte = struct.Struct(">B").pack
del struct
byte2int = operator.itemgetter(0)
indexbytes = operator.getitem
iterbytes = iter
import io
StringIO = io.StringIO
BytesIO = io.BytesIO
del io
_assertCountEqual = "assertCountEqual"
if sys.version_info[1] <= 1:
_assertRaisesRegex = "assertRaisesRegexp"
_assertRegex = "assertRegexpMatches"
_assertNotRegex = "assertNotRegexpMatches"
else:
_assertRaisesRegex = "assertRaisesRegex"
_assertRegex = "assertRegex"
_assertNotRegex = "assertNotRegex"
else:
def b(s):
return s
# Workaround for standalone backslash
def u(s):
return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape")
unichr = unichr
int2byte = chr
def byte2int(bs):
return ord(bs[0])
def indexbytes(buf, i):
return ord(buf[i])
iterbytes = functools.partial(itertools.imap, ord)
import StringIO
StringIO = BytesIO = StringIO.StringIO
_assertCountEqual = "assertItemsEqual"
_assertRaisesRegex = "assertRaisesRegexp"
_assertRegex = "assertRegexpMatches"
_assertNotRegex = "assertNotRegexpMatches"
_add_doc(b, """Byte literal""")
_add_doc(u, """Text literal""")
def assertCountEqual(self, *args, **kwargs):
return getattr(self, _assertCountEqual)(*args, **kwargs)
def assertRaisesRegex(self, *args, **kwargs):
return getattr(self, _assertRaisesRegex)(*args, **kwargs)
def assertRegex(self, *args, **kwargs):
return getattr(self, _assertRegex)(*args, **kwargs)
def assertNotRegex(self, *args, **kwargs):
return getattr(self, _assertNotRegex)(*args, **kwargs)
if PY3:
exec_ = getattr(moves.builtins, "exec")
def reraise(tp, value, tb=None):
try:
if value is None:
value = tp()
if value.__traceback__ is not tb:
raise value.with_traceback(tb)
raise value
finally:
value = None
tb = None
else:
def exec_(_code_, _globs_=None, _locs_=None):
"""Execute code in a namespace."""
if _globs_ is None:
frame = sys._getframe(1)
_globs_ = frame.f_globals
if _locs_ is None:
_locs_ = frame.f_locals
del frame
elif _locs_ is None:
_locs_ = _globs_
exec("""exec _code_ in _globs_, _locs_""")
exec_("""def reraise(tp, value, tb=None):
try:
raise tp, value, tb
finally:
tb = None
""")
if sys.version_info[:2] > (3,):
exec_("""def raise_from(value, from_value):
try:
raise value from from_value
finally:
value = None
""")
else:
def raise_from(value, from_value):
raise value
print_ = getattr(moves.builtins, "print", None)
if print_ is None:
def print_(*args, **kwargs):
"""The new-style print function for Python 2.4 and 2.5."""
fp = kwargs.pop("file", sys.stdout)
if fp is None:
return
def write(data):
if not isinstance(data, basestring):
data = str(data)
# If the file has an encoding, encode unicode with it.
if (isinstance(fp, file) and
isinstance(data, unicode) and
fp.encoding is not None):
errors = getattr(fp, "errors", None)
if errors is None:
errors = "strict"
data = data.encode(fp.encoding, errors)
fp.write(data)
want_unicode = False
sep = kwargs.pop("sep", None)
if sep is not None:
if isinstance(sep, unicode):
want_unicode = True
elif not isinstance(sep, str):
raise TypeError("sep must be None or a string")
end = kwargs.pop("end", None)
if end is not None:
if isinstance(end, unicode):
want_unicode = True
elif not isinstance(end, str):
raise TypeError("end must be None or a string")
if kwargs:
raise TypeError("invalid keyword arguments to print()")
if not want_unicode:
for arg in args:
if isinstance(arg, unicode):
want_unicode = True
break
if want_unicode:
newline = unicode("\n")
space = unicode(" ")
else:
newline = "\n"
space = " "
if sep is None:
sep = space
if end is None:
end = newline
for i, arg in enumerate(args):
if i:
write(sep)
write(arg)
write(end)
if sys.version_info[:2] < (3, 3):
_print = print_
def print_(*args, **kwargs):
fp = kwargs.get("file", sys.stdout)
flush = kwargs.pop("flush", False)
_print(*args, **kwargs)
if flush and fp is not None:
fp.flush()
_add_doc(reraise, """Reraise an exception.""")
if sys.version_info[0:2] < (3, 4):
# This does exactly the same what the :func:`py3:functools.update_wrapper`
# function does on Python versions after 3.2. It sets the ``__wrapped__``
# attribute on ``wrapper`` object and it doesn't raise an error if any of
# the attributes mentioned in ``assigned`` and ``updated`` are missing on
# ``wrapped`` object.
def _update_wrapper(wrapper, wrapped,
assigned=functools.WRAPPER_ASSIGNMENTS,
updated=functools.WRAPPER_UPDATES):
for attr in assigned:
try:
value = getattr(wrapped, attr)
except AttributeError:
continue
else:
setattr(wrapper, attr, value)
for attr in updated:
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
wrapper.__wrapped__ = wrapped
return wrapper
_update_wrapper.__doc__ = functools.update_wrapper.__doc__
def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS,
updated=functools.WRAPPER_UPDATES):
return functools.partial(_update_wrapper, wrapped=wrapped,
assigned=assigned, updated=updated)
wraps.__doc__ = functools.wraps.__doc__
else:
wraps = functools.wraps
def with_metaclass(meta, *bases):
"""Create a base class with a metaclass."""
# This requires a bit of explanation: the basic idea is to make a dummy
# metaclass for one level of class instantiation that replaces itself with
# the actual metaclass.
class metaclass(type):
def __new__(cls, name, this_bases, d):
if sys.version_info[:2] >= (3, 7):
# This version introduced PEP 560 that requires a bit
# of extra care (we mimic what is done by __build_class__).
resolved_bases = types.resolve_bases(bases)
if resolved_bases is not bases:
d['__orig_bases__'] = bases
else:
resolved_bases = bases
return meta(name, resolved_bases, d)
@classmethod
def __prepare__(cls, name, this_bases):
return meta.__prepare__(name, bases)
return type.__new__(metaclass, 'temporary_class', (), {})
def add_metaclass(metaclass):
"""Class decorator for creating a class with a metaclass."""
def wrapper(cls):
orig_vars = cls.__dict__.copy()
slots = orig_vars.get('__slots__')
if slots is not None:
if isinstance(slots, str):
slots = [slots]
for slots_var in slots:
orig_vars.pop(slots_var)
orig_vars.pop('__dict__', None)
orig_vars.pop('__weakref__', None)
if hasattr(cls, '__qualname__'):
orig_vars['__qualname__'] = cls.__qualname__
return metaclass(cls.__name__, cls.__bases__, orig_vars)
return wrapper
def ensure_binary(s, encoding='utf-8', errors='strict'):
"""Coerce **s** to six.binary_type.
For Python 2:
- `unicode` -> encoded to `str`
- `str` -> `str`
For Python 3:
- `str` -> encoded to `bytes`
- `bytes` -> `bytes`
"""
if isinstance(s, binary_type):
return s
if isinstance(s, text_type):
return s.encode(encoding, errors)
raise TypeError("not expecting type '%s'" % type(s))
def ensure_str(s, encoding='utf-8', errors='strict'):
"""Coerce *s* to `str`.
For Python 2:
- `unicode` -> encoded to `str`
- `str` -> `str`
For Python 3:
- `str` -> `str`
- `bytes` -> decoded to `str`
"""
# Optimization: Fast return for the common case.
if type(s) is str:
return s
if PY2 and isinstance(s, text_type):
return s.encode(encoding, errors)
elif PY3 and isinstance(s, binary_type):
return s.decode(encoding, errors)
elif not isinstance(s, (text_type, binary_type)):
raise TypeError("not expecting type '%s'" % type(s))
return s
def ensure_text(s, encoding='utf-8', errors='strict'):
"""Coerce *s* to six.text_type.
For Python 2:
- `unicode` -> `unicode`
- `str` -> `unicode`
For Python 3:
- `str` -> `str`
- `bytes` -> decoded to `str`
"""
if isinstance(s, binary_type):
return s.decode(encoding, errors)
elif isinstance(s, text_type):
return s
else:
raise TypeError("not expecting type '%s'" % type(s))
def python_2_unicode_compatible(klass):
"""
A class decorator that defines __unicode__ and __str__ methods under Python 2.
Under Python 3 it does nothing.
To support Python 2 and 3 with a single code base, define a __str__ method
returning text and apply this decorator to the class.
"""
if PY2:
if '__str__' not in klass.__dict__:
raise ValueError("@python_2_unicode_compatible cannot be applied "
"to %s because it doesn't define __str__()." %
klass.__name__)
klass.__unicode__ = klass.__str__
klass.__str__ = lambda self: self.__unicode__().encode('utf-8')
return klass
# Complete the moves implementation.
# This code is at the end of this module to speed up module loading.
# Turn this module into a package.
__path__ = [] # required for PEP 302 and PEP 451
__package__ = __name__ # see PEP 366 @ReservedAssignment
if globals().get("__spec__") is not None:
__spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable
# Remove other six meta path importers, since they cause problems. This can
# happen if six is removed from sys.modules and then reloaded. (Setuptools does
# this for some reason.)
if sys.meta_path:
for i, importer in enumerate(sys.meta_path):
# Here's some real nastiness: Another "instance" of the six module might
# be floating around. Therefore, we can't use isinstance() to check for
# the six meta path importer, since the other six instance will have
# inserted an importer with different class.
if (type(importer).__name__ == "_SixMetaPathImporter" and
importer.name == __name__):
del sys.meta_path[i]
break
del i, importer
# Finally, add the importer to the meta path import hook.
sys.meta_path.append(_importer)

View File

@@ -1,7 +0,0 @@
# This file contains all requirements needed for GAM development work
# Include all build requirements
-r requirements.txt
# Dev-specific requirements
pre-commit

View File

@@ -0,0 +1,21 @@
# ------------------------------------------------------------------
# Copyright (c) 2021 PyInstaller Development Team.
#
# This file is distributed under the terms of the GNU General Public
# License (version 2.0 or later).
#
# The full license is available in LICENSE, distributed with
# this software.
#
# SPDX-License-Identifier: GPL-2.0-or-later
# ------------------------------------------------------------------
from PyInstaller.utils.hooks import copy_metadata
from PyInstaller.utils.hooks import collect_data_files
# googleapiclient.model queries the library version via
# pkg_resources.get_distribution("google-api-python-client").version,
# so we need to collect that package's metadata
datas = copy_metadata('google_api_python_client')
# we don't want these cached discovery files and they make the binary HUUUGEEEE
#datas += collect_data_files('googleapiclient.discovery_cache', excludes=['*.txt', '**/__pycache__'])

View File

@@ -0,0 +1,19 @@
# ------------------------------------------------------------------
# Copyright (c) 2020 PyInstaller Development Team.
#
# This file is distributed under the terms of the GNU General Public
# License (version 2.0 or later).
#
# The full license is available in LICENSE, distributed with
# this software.
#
# SPDX-License-Identifier: GPL-2.0-or-later
# ------------------------------------------------------------------
# This is needed to bundle cacerts.txt that comes with httplib2 module
# WE DON'T NEED httplib2/cacerts.txt since we get our own
#from PyInstaller.utils.hooks import collect_data_files
#datas = collect_data_files('httplib2')

View File

@@ -81,11 +81,13 @@ async function runSSD() {
await driver.sendKeys(id_arr);
await screenshot(driver, 'login02.png');
await driver.sendKeys([Key.Tab]);
console.log('Our secret is ' + process.env.TOTP_SECRET.length + ' characters.');
// We wait until the last possible second to generate
// our TOTP to ensure it's still valid.
const token_value = TOTP.generate(process.env.TOTP_SECRET, {algorithm: 'SHA-256'}).otp;
const token_arr = [...token_value];
await driver.sendKeys(token_arr);
const { otp } = await TOTP.generate(process.env.TOTP_SECRET, {algorithm: 'SHA-256'});
console.log('Our token is ' + otp.length + ' characters.');
const otp_arr = [...otp];
await driver.sendKeys(otp_arr);
await screenshot(driver, 'login03.png');
await driver.sendKeys([Key.Enter]);
@@ -111,7 +113,8 @@ async function runSSD() {
await screenshot(driver, 'login12.png');
} catch (error) {
console.error("Error during Appium run:", error.name);
console.error(error);
//console.error("Error during Appium run:");
}
// INTENTIONAL Keep driver open so tray icon for Certum doesn't close

View File

@@ -19,6 +19,8 @@
## Definitions
```
<AdminAssigneeType> ::= group|user|serviceaccount|unknown
<AdminAssigneeTypeList> ::= "<AdminAssigneeType>(,<AdminAssigneeType>)*"
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<GroupItem> ::= <EmailAddress>|<UniqueID>|<String>
@@ -1475,16 +1477,25 @@ gam delete admin <RoleAssignmentId>
## Display administrators
```
gam print admins [todrive <ToDriveAttribute>*]
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition]
[privileges] [oneitemperrow]
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
[types <AdminAssigneeTypeList>]
[recursive] [condition] [privileges] [oneitemperrow]
gam show admins
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>] [condition] [privileges]
[user|group <EmailAddress>|<UniqueID>] [role <RoleItem>]
[types <AdminAssigneeTypeList>]
[recursive] [condition] [privileges]
```
By default, all administrators and roles are displayed; choose from the following
options to limit the display:
* `user <UserItem>` - Display only this administrator
* `user|group <EmailAddress>|<UniqueID>` - Display assignments to this administrator
* `role <RoleItem>` - Display only administrators with this role
By default, all admin assignee types are displayed. use `types <AdminAssigneeTypeList>` to filter
admin assignments by the type of the assignee.
By default, assignments to security groups are displayed as a single item; use `recursive`
to display assignments to the members of the security groups; the security group membershop is recursively expanded.
* `condition` - Display any conditions associated with a role assignment
* `privileges` - Display privileges associated with each role assignment

View File

@@ -103,7 +103,7 @@ gam print aliases [todrive <ToDriveAttribute>*]
[limittoou <OrgUnitItem>])
[user|users <EmailAddressList>] [group|groups <EmailAddressList>]
[select <UserTypeEntity>]
[aliasmatchpattern <REMatchPattern>]
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
[shownoneditable] [nogroups] [nousers]
[onerowpertarget] [delimiter <Character>]
[suppressnoaliasrows]
@@ -117,6 +117,8 @@ By default, group and user aliases in all domains in the account are selected; t
* `user|users <EmailAddressList>` - Print aliases for users in `<EmailAddressList`
* `select <UserTypeEntity>` - Print aliases for users in `<UserTypeEntity>`
* `group|groups <EmailAddressList>` - Print aliases for groups in `<EmailAddressList`
* `issuspended <Boolean>` - Limit users based on their status
* `isarchived <Boolean>` - Limit users based on their status
* `aliasmatchpattern <REMatchPattern>` - Print aliases that match a pattern
* `nogroups` - Print only user aliases
* `nousers` - Print only group aliases

View File

@@ -184,7 +184,7 @@ perform these steps and then retry the create project command.
## Authorize Service Account Key Uploads
*IMPORTANT:* Google best practice is to NOT use service account keys. Rather than overriding Google's default policy please consider [running GAM on Google Compute Engine Securely](https://github.com/GAM-team/GAM/wiki/l-Running-GAM-on-Google-Compute-Engine-(GCE)-Securely) so that service account keys are not necessary.
*IMPORTANT:* Google best practice is to NOT use service account keys. Rather than overriding Google's default policy please consider [Running GAM7 securely on a Google Compute Engine](https://github.com/GAM-team/GAM/wiki/Running-GAM7-securely-on-a-Google-Compute-Engine) (if running in Google Cloud) or [Workload Identity Federation](https://github.com/GAM-team/GAM/wiki/Using-GAM7-with-keyless-authentication-Workload-Identity-Federation) (if running outside Google Cloud) so that service account keys are not necessary.
If you try to create a project and get an error saying that Constraint `constraints/iam.disableServiceAccountKeyUpload violated for service account projects/gam-project-xxxxx`,
perform these steps and then you should be able to authorize and use your project.
@@ -326,7 +326,7 @@ Use an existing project to create and download two files: `client_secrets.json`
Use an existing uninitialized/uncredentialed project and configure it to be a GAM project; this typically used when
the GCP administrators have created a basic project because project creation is not available for most users.
See Jay's notes about how to do this: https://github.com/GAM-team/GAM/wiki/GAM-with--minimal-GCP-rights
See Jay's notes about how to do this: https://github.com/GAM-team/GAM/wiki/GAM-with-minimal-GCP-rights
```
gam use project [<EmailAddress>] [project <ProjectID>]

View File

@@ -265,6 +265,7 @@
## Named items
```
<AccessToken> ::= <String>
<AdminAssigneeType> ::= group|user|serviceaccount|unknown
<AlertID> ::= <String>
<APIScopeURL> ::= <String>
<APPID> ::= <String>
@@ -325,6 +326,8 @@
<CourseWorkState> ::= draft|published|deleted
<CrOSID> ::= <String>
<CustomerID> ::= <String>
<DateTimeFormat> ::= <String>
See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
<DeliverySetting> ::=
allmail|
abridged|daily|
@@ -460,6 +463,7 @@
See: https://support.google.com/mail/answer/7190
<QueryGroup> ::= <String>
See: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
<QueryItem> ::= <UniqueID>|<String>
<QueryMemberRestrictions> ::= <String>
See: https://cloud.google.com/identity/docs/reference/rest/v1beta1/SecuritySettings#MemberRestriction
<QueryMobile> ::= <String>

View File

@@ -18,6 +18,9 @@ The variables `num_threads`, `num_tbatch_threads` and `auto_batch_min` in `gam.c
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
`gdoc <UserGoogleDoc>` and `gsheet <UserGoogleSheet>`
<DateTimeFormat> ::= <String>
See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
## Batch files
There are two types of batch processing, one that uses processes and one that uses threads. Using processes is higher performance but `gam csv` commands are not supported.
* `gam batch` - gam commands are run as processes, gam csv commands are not allowed in the batch file
@@ -45,6 +48,9 @@ Batch files can contain the following types of lines:
* sleep \<Integer\> - Batch processing will suspend for \<Integer\> seconds before the next command line is processed
* To be effective, this should immediately follow commit-batch
* print \<String\> - Print \<String\> on stderr
* datetime \<DateTimeFormat\>
* The current time is formatted with \<DateTimeFormat\> and subsequent lines will have `%datetime%` replaced with the formatted time value.
* See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
* set \<KeywordString\> \<ValueString\>
* Subsequent lines will have %\<KeywordString\>% replaced with \<ValueString\>
* clear \<KeywordString\>

View File

@@ -567,7 +567,7 @@ By default, Gam displays the information as an indented list of keys and values.
```
gam calendar <CalendarEntity> show events [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek]
[countsly] [formatjson]
[countsly|formatjson]
```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
@@ -586,8 +586,9 @@ By default, Gam displays event details, use `countsonly` to display only the num
```
gam calendar <CalendarEntity> print events [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek]
[countsonly [eventrowfilter]]
[formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*]
(addcsvdata <FieldName> <String>)*
[eventrowfilter]
[countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
@@ -598,6 +599,9 @@ option `singleevents` to display all instances of a recurring event.
`showdayofweek` displays columns `start.dayOfWeek` and `end.dayOfWeek` when event start and end times are displayed.
Add additional columns of data from the command line to the output after the calendarId.
* `addcsvdata <FieldName> <String>`
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.

View File

@@ -570,6 +570,7 @@ gam print course-materials [todrive <ToDriveAttribute>*]
(orderby <CourseMaterialOrderByFieldName> [ascending|descending])*)
[showcreatoremails|creatoremail] [showtopicnames] [fields <CourseMaterialFieldNameList>]
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[oneitemperrow]
[countsonly] [formatjson [quotechar <Character>]]
```
By default, the `print course-materials` command displays course materials information for all courses.
@@ -600,6 +601,10 @@ By default, all course materials fields are displayed; use the following options
* `showtopicnames` - Display topic names; requires and additional API call per course.
* `fields <CourseMaterialsFieldNameList>` - Select specific fields to display.
With `print course-materials`, the materials selected for display are all output on one row/line as a repeating item with the other course fields.
When `oneitemperrow` is specified, each material is output on a separate row/line with the other course fields.
This simplifies processing the materials in the CSV file with subsequent Gam commands.
Use the `countsonly` option to display the number of course materials in a course but not their details.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
@@ -662,6 +667,7 @@ gam print course-work [todrive <ToDriveAttribute>*]
[showcreatoremails] [showtopicnames] [fields <CourseWorkFieldNameList>]
[showstudentsaslist [<Boolean>]] [delimiter <Character>]
[timefilter creationtime|updatetime|scheduledtime] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[oneitemperrow]
[countsonly] [formatjson [quotechar <Character>]]
```
By default, the `print course-work` command displays course work information for all courses.
@@ -695,6 +701,10 @@ By default, all course work fields are displayed; use the following options to m
By default, when course work is assigned to individual students, the student IDs are displayed in multiple indexed columns.
Use options `showstudentsaslist [<Boolean>]` and `delimiter <Character>` to display the student IDs is a single column as a delimited list.
With `print course-work`, any materials are all output on one row/line as a repeating item with the other course fields.
When `oneitemperrow` is specified, each material is output on a separate row/line with the other course fields.
This simplifies processing the materials in the CSV file with subsequent Gam commands.
Use the `countsonly` option to display the number of course works in a course but not their details.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,

View File

@@ -160,6 +160,7 @@ Middle Students
Beginner Students
$ gam redirect csv ./StudentGroups.csv add coursestudentgroups course <CourseID> select csvfile titles.csv:title csv
Course: <CourseID>, Add 3 Course Student Groups
$ more StudentGroups.csv
courseId,courseName,studentGroupId,studentGroupTitle

View File

@@ -351,6 +351,8 @@ Data fields identified in a `csvkmd` argument.
<SiteACLScopeList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<SiteEntity> ::=
<SiteList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
<StringEntity> ::=
<StringList> | <FileSelector> | <CSVFileSelector>
<StudentGroupEntity> ::=
<StudentGroupIDList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector>
<TagManagerAccountPathEntity> ::=

View File

@@ -1,5 +1,6 @@
# Collections of Users
- [Python Regular Expressions](Python-Regular-Expressions) Search function
- [Notes](#notes)
- [Definitions](#definitions)
- [User Type Entity](#user-type-entity)
- [All non-suspended Users](#all-non-suspended-users)
@@ -37,6 +38,37 @@
- [Examples using CSV files to print users from groups](#examples-using-CSV-files-to-print-users-from-groups)
- [Examples using multiple queries](#examples-using-multiple-queries)
## Notes
The followig items referencing non-archived/archived users were added to `<UserTypeEntity>` in version 7.22.00.
```
all users_na
all users_arch
all users_na_ns
all users_arch_or_susp
domains_na
domains_arch
domains_na_ns
groups_na
groups_arch
groups_na_ns
group_users_na
group_users_arch
group_users_na_ns
ou_na
ou_arch
ou_na_ns
ou_and_children_na
ou_and_children_arch
ou_and_children_na_ns
ous_na
ous_arch
ous_na_ns
ous_and_children_na
ous_and_children_arch
ous_and_children_na_ns
```
## Definitions
* [Basic Items](Basic-Items)
@@ -90,25 +122,25 @@
<SharedDriveNameEntity>
<UserTypeEntity> ::=
(all users|users_ns|users_susp|users_ns_susp)|
(all users|users_na|users_arch|users_ns|users_susp|users_ns_susp|users_arch_or_susp|users_na_ns)|
(user <UserItem>)|
(users <UserList>)|
(oauthuser)
(domains|domains_ns|domains_susp <DomainNameList>)|
(group|group_ns|group_susp|group_inde <GroupItem>)|
(groups|groups_ns|groups_susp|groups_inde <GroupList>)|
(domains|domains_na|domains_arch|domains_ns|domains_susp|domains_na_ns <DomainNameListList>)|
(group|group_na|group_arch|group_ns|group_susp|group_na_ns|group_inde <GroupItem>)|
(groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde <GroupList>)|
(group_inde <GroupItem>)|(groups_inde <GroupList>)|
(group_users|group_users_ns|group_users_susp <GroupList>
(group_users|group_users_na|group_users_arch|group_users_ns|group_users_susp|group_users_na_ns <GroupList>
[members] [managers] [owners]
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
(group_users_select <GroupList>
[members] [managers] [owners]
[notsuspended|suspended] [notarchived|archived]
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
(ou|ou_ns|ou_susp <OrgUnitItem>)|
(ou_and_children|ou_and_children_ns|ou_and_children_susp <OrgUnitItem>)|
(ous|ous_ns|ous_susp <OrgUnitList>)|
(ous_and_children|ous_and_children_ns|ous_and_children_susp <OrgUnitList>)|
(ou|ou_na|ou_arch|ou_ns|ou_susp|ou_na_ns <OrgUnitItem>)|
(ou_and_children|ou_and_children_na|ou_and_children_arch|ou_and_children_ns|ou_and_children_susp|ou_and_children_na_ns <OrgUnitItem>)|
(ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns <OrgUnitList>)|
(ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns <OrgUnitList>)|
(courseparticipants <CourseIDList>)|
(students <CourseIDList>)|
(teachers <CourseIDList>)|
@@ -126,41 +158,47 @@
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>][quotechar <Character>]
[warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RESearchPattern>)*
[delimiter <Character>])|
(datafile
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
users|
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
ous|ous_na|ous_arch|ous_ns|ous_susps|ous_na_ns|
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
courseparticipants|students|teachers
((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>])|
(csvdatafile
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
users|
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
ous|ous_na|ous_arch|ous_ns|ous_susps|ous_na_ns|
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
courseparticipants|students|teachers
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
[warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>][quotechar <Character>]
[warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
[endcsv|(fields <FieldNameList>)]
(matchfield|skipfield <FieldName> <RESearchPattern>)*
[delimiter <Character>])|
(csvkmd
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
users|
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
ous|ous_na|ous_arch|ous_ns|ous_susps|ous_na_ns|
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
courseparticipants|students|teachers
((<FileName>|
(gsheet <UserGoogleSheet>)|
(gdoc <UserGoogleDoc>)|
(gcscsv <StorageBucketObjectName>)|
(gcsdoc <StorageBucketObjectName>))
[charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>][quotechar <Character>] [fields <FieldNameList>])
[charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>])
keyfield <FieldName> [keypattern <RESearchPattern>] [keyvalue <RESubstitution>] [delimiter <Character>]
subkeyfield <FieldName> [keypattern <RESearchPattern>] [keyvalue <RESubstitution>] [delimiter <Character>]
(matchfield|skipfield <FieldName> <RESearchPattern>)*
@@ -172,6 +210,12 @@
Use these options to select users for GAM commands.
## All non-archived Users
* `all users_na`
## All archived Users
* `all users_arch`
## All non-suspended Users
* `all users`
* `all users_ns`
@@ -179,6 +223,12 @@ Use these options to select users for GAM commands.
## All suspended Users
* `all users_susp`
## All archived or suspended Users
* `all users_arch_or_susp`
## All non-archived and non-suspended Users
* `all users_na_ns`
## All non-suspended and suspended Users
* `all users_ns_susp`
@@ -192,22 +242,31 @@ Use these options to select users for GAM commands.
* `oauthuser`
## Users in the domains `<DomainNameList>`
* `domains|domains_ns|domains_susp <DomainNameList>`
* `domains|domains_na|domains_arch|domains_ns|domains_susp|domains_na_ns <DomainNameList>`
* `domains` - All users
* `domains_na` - Non-archived users
* `domains_arch` - Archived users
* `domains_ns` - Non-suspended users
* `domains_susp` - Suspended users
* `domains_na_ns` - Non-archived and non-suspended users
## Users directly in the group `<GroupItem>`
* `group|group_ns|group_susp <GroupItem>`
* `group|group_na|group_arch|group_ns|group_susp|group_na_ns <GroupItem>`
* `group` - All user members
* `group_na` - Non-archived user members
* `group_arch` - Archived user members
* `group_ns` - Non-suspended user members
* `group_susp` - Suspended user members
* `group_na_ns` - Non-archived and non-suspended user members
## Users directly in the groups `<GroupList>`
* `groups|groups_ns|groups_susp <GroupList>`
* `groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns <GroupList>`
* `groups` - All user members
* `groups_na` - Non-archived user members
* `groups_arch` - Archived user members
* `groups_ns` - Non-suspended user members
* `groups_susp` - Suspended user members
* `groups_na_ns` - Non-archived and non-suspended user members
## Users directly and indirectly in the group `<GroupItem>`
* `group_inde` - All user members including those from all subgroups
@@ -216,10 +275,13 @@ Use these options to select users for GAM commands.
* `groups_inde` - All user members including those from all subgroups
## Selected Users from groups
* `group_users|group_users_ns|group_users_susp <GroupList> [members] [managers] [owners] [primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end`
* `group_users|group_users_na|group_users_arch|group_users_ns|group_users_susp|group_users_na_ns <GroupList> [members] [managers] [owners] [primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end`
* `group_users` - All user members
* `group_users_na` - Non-archived user members
* `group_users_arch` - Archived user members
* `group_users_ns` - Non-suspended user members
* `group_users_susp` - Suspended user members
* `group_users_na_ns` - Non-archived and non-suspended user members
* `[members] [managers] [owners]` - The desired roles; if roles are not specified, all roles are included
* `primarydomain` - Select Users from the primary domain
* `domains <DomainNameList>` - Select Users from the list of domains
@@ -259,30 +321,41 @@ Use these options to select users for GAM commands.
* `end` - Terminate the selection
## Users directly in the Organization Unit `<OrgUnitItem>`
* `ou|ou_ns|ou_susp <OrgUnitItem>`
* `ou|ou_na|ou_arch|ou_ns|ou_susp|ou_na_ns <OrgUnitItem>`
* `ou` - All users
* `ou_ns` - Non-Suspended users
* `ou_na` - Non-archived users
* `ou_arch` - Archived users
* `ou_ns` - Non-suspended users
* `ou_susp` - Suspended users
* `ou_na_ns` - Non-archived and nn-suspended users
## Users in the Organization Unit `<OrgUnitItem>` and all of its sub Organization Units
* `ou_and_children|ou_and_children_ns|ou_and_children_susp <OrgUnitItem>`
* `ou_and_children|ou_and_children_na|ou_and_children_arch|ou_and_children_ns|ou_and_children_susp|ou_and_children_na_ns <OrgUnitItem>`
* `ou_and_children` - All users
* `ou_and_children_na` - Non-archived users
* `ou_and_children_arch` - Archived users
* `ou_and_children_ns` - Non-suspended users
* `ou_and_children_susp` - Suspended users
* `ou_and_children_na_ns` - Non-archived and nn-suspended users
## Users directly in the Organization Units `<OrgUnitList>`
* `ous|ous_ns|ous_susp <OrgUnitList>` - Users directly in the Organization Units `<OrgUnitList>`
* `ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns <OrgUnitList>` - Users directly in the Organization Units `<OrgUnitList>`
* `ous` - All users
* `ous_na` - Non-archived users
* `ous_arch` - Archived users
* `ous_ns` - Non-suspended users
* `ous_susp` - Suspended users
* `ous_na_ns` - Non-archived and nn-suspended users
`<OrgUnitList>` may require special quoting based on whether the OUs contain spaces, commas or single quotes.
For quoting rules, see: [List Quoting Rules](Command-Line-Parsing)
## Users in the Organization Units `<OrgUnitList>` and all of their sub Organization Units
* `ous_and_children|ous_and_children_ns|ous_and_children_susp <OrgUnitList>` - Users in the Organization Units `<OrgUnitList>` and all of their sub Organization Units
* `ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns <OrgUnitList>` - Users in the Organization Units `<OrgUnitList>` and all of their sub Organization Units
* `ous_and_children` - All users
* `ous_and_children_na` - Non-archived users
* `ous_and_children_arch` - Archived users
* `ous_and_children_ns` - Non-suspended users
* `ous_and_children_susp` - Suspended users
@@ -363,15 +436,21 @@ csvfile
## Users from groups/OUs/courses in a flat file/Google Doc/Google Cloud Storage Object
```
datafile
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
users|
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns|
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
courseparticipants|students|teachers
((<FileName> [charset <Charset>])|
(gdoc <UserGoogleDoc>)|
(gcsdoc <StorageBucketObjectName>))
[delimiter <Character>]
```
* `users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|ous_and_children|ous_and_children_ns|ous_and_children_susp|courseparticipants|students|teachers` - The type of item in the file
* `users|`
* `groups|groups_na|groups_arch|groups_ns_|groups_susp|groups_na_ns|groups_inde|`
* `ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns|`
* `ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|`
* `courseparticipants|students|teachers` - The type of item in the file
* `<FileName>` - A flat file containing rows of the type of item specified
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `gdoc <UserGoogleDoc>` - A Google Doc containing rows of the type of item specified
@@ -381,9 +460,11 @@ datafile
## Users from groups/OUs/courses in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object
```
csvdatafile
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
users|
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns|
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
courseparticipants|students|teachers
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
@@ -394,9 +475,13 @@ csvdatafile
(matchfield|skipfield <FieldName> <RESearchPattern>)*
[delimiter <Character>]
```
* `users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|ous_and_children|ous_and_children_ns|ous_and_children_susp|courseparticipants|students|teachers` - The type of item in the file
* `users|`
* `groups|groups_na|groups_arch|groups_ns_|groups_susp|groups_na_ns|groups_inde|`
* `ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns|`
* `ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|`
* `courseparticipants|students|teachers` - The type of item in the file
* `<FileName>(:<FieldName>)+` - A CSV file and the one or more columns contain the type of item specified
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `charset <Charset>` - The character set of the file if it isn't UTF-8
* `gsheet(:<FieldName>)+ <UserGoogleSheet>` - A Google Sheet and the one or more columns contain the type of item specified
* `gdoc(:<FieldName>)+ <UserGoogleDoc>` - A Google Doc and the one or more columns contain the type of item specified
* `gcscsv(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns contain the type of item specified
@@ -413,9 +498,11 @@ csvdatafile
## Users directly in or from groups/OUs/courses in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object
```
csvkmd
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
ous_and_children|ous_and_children_ns|ous_and_children_susp|
courseparticipants|students|teachers
users|
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns|
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
courseparticipants|students|teachers
((<FileName>|
(gsheet <UserGoogleSheet>)|
(gdoc <UserGoogleDoc>)|
@@ -427,9 +514,13 @@ csvkmd
(matchfield|skipfield <FieldName> <RESearchPattern>)*
[datafield <FieldName>(:<FieldName>)* [delimiter <Character>]]
```
* `users|groups|groups_ns_|groups_susp|groups_inde|ous|ous_ns|ous_susp|ous_and_children|ous_and_children_ns|ous_and_children_susp|courseparticipants|students|teachers` - The type of item in the file
* `users|`
* `groups|groups_na|groups_arch|groups_ns_|groups_susp|groups_na_ns|groups_inde|`
* `ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns|`
* `ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|`
* `courseparticipants|students|teachers` - The type of item in the file
* `<FileName>` - A CSV file containing rows with columns of the type of item specified
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
* `charset <Charset>` - The character set of the file if it isn't UTF-8
* `gsheet <UserGoogleSheet>` - A Google Sheet containing rows with columns of the type of item specified
* `gdoc <UserGoogleDoc>` - A Google Doc containing rows with columns of the type of item specified
* `gcscsv <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object with columns of the type of item specified

View File

@@ -10,7 +10,7 @@
- [Delete duplicate email addresses from contacts](#delete-duplicate-email-addresses-from-contacts)
- [Manage domain contact photos](#manage-domain-contact-photos)
- [Display domain shared contacts](#display-domain-shared-contacts)
- [Display global address list](#display-global-address-list)
- [Display global address list](#Global-Address-List)
## API documentation
* [Domain Shared Contacts API](https://developers.google.com/admin-sdk/domain-shared-contacts)

View File

@@ -25,14 +25,14 @@ start a new terminal session and reissue the command from above.
## Executable, Manual
* Executable Archive, Manual, Linux/Google Cloud Shell
- `gam-7.wx.yz-linux-x86_64-glibc2.35.tar.xz`
- `gam-7.wx.yz-linux-x86_64-glibc2.36.tar.xz`
- `gam-7.wx.yz-linux-x86_64-glibc2.39.tar.xz`
- `gam-7.wx.yz-linux-x86_64-legacy.tar.xz`
- Download the archive, extract the contents into some directory.
- Start a terminal session.
* Executable Archive, Manual, Raspberry Pi/ChromeOS ARM devices
- `gam-7.wx.yz-linux-arm64-glibc2.35.tar.xz`
- `gam-7.wx.yz-linux-arm64-glibc2.36.tar.xz`
- `gam-7.wx.yz-linux-arm64-glibc2.39.tar.xz`
- `gam-7.wx.yz-linux-arm64-legacy.tar.xz`
- Download the archive, extract the contents into some directory.
@@ -43,16 +43,26 @@ start a new terminal session and reissue the command from above.
- Download the archive, extract the contents into some directory.
- Start a terminal session.
* Executable Archive, Manual, Mac OS versions Sequoia - M3
- `gam-7.wx.yz-macos15.4-arm64.tar.xz`
* Executable Archive, Manual, Mac OS versions Sequoia - M2/M3
- `gam-7.wx.yz-macos15.6-arm64.tar.xz`
- Download the archive, extract the contents into some directory.
- Start a terminal session.
* Executable Archive, Manual, Mac OS, versions Ventura, Sonoma, Sequoia - Intel
* Executable Archive, Manual, Mac OS versions Tahoe - M2/M3/M4
- `gam-7.wx.yz-macos26.0-arm64.tar.xz`
- Download the archive, extract the contents into some directory.
- Start a terminal session.
* Executable Archive, Manual, Mac OS, versions Ventura, Sonoma - Intel
- `gam-7.wx.yz-macos13.7-x86_64.tar.xz`
- Download the archive, extract the contents into some directory.
- Start a terminal session.
* Executable Archive, Manual, Mac OS, versions Sequoia, Tahoe - Intel
- `gam-7.wx.yz-macos15.6-x86_64.tar.xz`
- Download the archive, extract the contents into some directory.
- Start a terminal session.
* Executable Archive, Manual, Windows 64 bit
- `gam-7.wx.yz-windows-x86_64.zip`
- Download the archive, extract the contents into some directory.

View File

@@ -0,0 +1,21 @@
# Steps to release a new GAM version
1. In a final commit before release:
- [src/gam/__init.py](https://github.com/GAM-team/GAM/blob/main/src/gam/__init__.py) `__version___` value should be updated to the new version.
- [src/GamUpdate.txt](https://github.com/GAM-team/GAM/blob/main/src/GamUpdate.txt) should be updated with a high-level changelog.
- [wiki/GamUpdates.md](https://github.com/GAM-team/GAM/blob/main/wiki/GamUpdates.md) should be updated with same high-level changelog.
- [wiki/Version-and-Help.md](https://github.com/GAM-team/GAM/blob/main/wiki/Version-and-Help.md) should be updated with current version N.NN.NN
- [wiki/How-to-Upgrade-Legacy-GAM-to-GAM7.md](https://github.com/GAM-team/GAM/blob/main/wiki/How-to-Upgrade-Legacy-GAM-to-GAM7.md) should be updated with current version N.NN.NN
2. The [build.yaml](https://github.com/GAM-team/GAM/blob/main/.github/workflows/build.yml) Github Action for final commit should complete successfully and creating a new dated Draft release.
- We should *NEVER* upload release files manually. Only release files automatically created and [attested](https://github.com/GAM-team/GAM/wiki/Verifying-a-GAM7-Build-is-Legitimate-and-Official#github-attestation-linuxmacoswindows) as created by the Github Action should be used.
3. Edit the Draft release:
- Create a new tag with the format: `vN.NN.NN` where N.NN.NN is the GAM release version.
- name the release "GAM N.NN.NN" where N.NN.NN is the GAM release version.
- Include the changelog details for the new version in details.
- leave "Set as pre-release" unchecked and "Set as the latest release" checked.
- Publish the release.
# TODO: Release Process Improvements
- copying changelog between GamUpdate.txt, GamUpdates.md and release description is manual and tedious. Automate it.
- copying version string from gam/__init__.py, changelogs and release details and tag in manual and tedious. Automate it.
- See if we can block releases with binaries not uploaded by GitHub Actions to further secure release pipelines.

View File

@@ -15,7 +15,7 @@ The 27ft RV Jay drove his family to Niagara Falls this summer. Theyre all sti
some in full sentences 🙂
# Has something changed with Ross?
Hes just older, 75 and counting.
Hes just older, 76 and counting.
(Jay here, this is all I could get from Ross but hes his usual awesome self helping admins in Chat and Groups forums as I write this and adding new features. Because some have asked, Ross is a real person. He is not an Advanced GenAI as rumours have claimed. 🙂)
@@ -49,8 +49,8 @@ Both GAM7 and GAM-ADV versions use the same configuration file (gam.cfg), and cr
# Help!!! Something went wrong!
Well thats not really a question but as ever, please reach out to either the GAM email support group:
[git.io/gam-group](http://git.io/gam-group)
[GAM Discussion Forum](https://groups.google.com/forum/#!forum/google-apps-manager)
Or the Google Chat Space:
[git.io/gam-chat](http://git.io/gam-chat)
[GAM Public Chat Room](GAM-Public-Chat-Room)

View File

@@ -10,6 +10,192 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Installs) for Windows or other options, including manual installation
### 7.23.07
Fixed bug in `gam print|show admins` where all admin assignments were not displayed when
`types <AdminAssigneeTypeList>` was not specified, i.e., all assignments should be displayed.
### 7.23.06
Added option `types <AdminAssigneeTypeList>` to `gam print|show admins` that allows filtering
of admin assignments by the type of the assignee; by default, all assignee types are displayed.
```
<AdminAssigneeType> ::= group|user|serviceaccount|unknown
<AdminAssigneeTypeList> ::= "<AdminAssigneeType>(,<AdminAssigneeType>)*"
```
### 7.23.05
Added option `recursive` to `gam print|show admins` that will display assignments to the members
of security groups assigned to roles; the security group membership is recursively expanded.
### 7.23.04
Added option `addcsvdata <FieldName> <String>` to `gam <UserTypeEntity> print events`
and `gam calendars <CalendarEntity> print events` that adds additional columns of data to the CSV file output.
An example would be to get the calendar name in addition to the calendar ID when printing events.
```
gam redirect csv ./Resources.csv print resources fields email,name
gam redirect csv ./ResourceEventCounts.csv multiprocess redirect stderr - multiprocess csv Resources.csv gam calendar "~resourceEmail" print events starttime -1y countsonly addcsvdata calendarName "~resourceName"
```
Upgraded to OpenSSL 3.6.0.
### 7.23.03
Upgraded to OpenSSL 3.5.4.
### 7.23.02
Added option `oneitemperrow` to 'gam print course-materials|course-work` to have each of a
course's materials displayed on a separate row with all of the other course fields.
This produces a CSV file that can be used in subsequent commands to process the materials without further script processing.
### 7.23.00
Added `chat_max_results` variable to `gam.cfg`.
```
chat_max_results
When retrieving lists of Chat items from API,
how many should be retrieved in each API call
Default: 100
Range: 1 - 1000
```
Previously, this vaule was always set to 1000 which could cause errors.
### 7.22.07
Added options `showdetails` and `returnidonly` to `gam create|copy vaultquery`.
Added option `<JSONData>` to `gam create vaultexport|vaultquery and `gam print vaultcounts``.
### 7.22.06
Added commands to create, copy and delete Vault saved queries.
```
gam create vaultquery <MatterItem> [name <String>]
corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
[scope all_data|held_data|unprocessed_data]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(documentids (<DriveFileIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
[driveversiondate <Date>|<Time>]
[includerooms <Boolean>]
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
(covereddata calllogs|textmessages|voicemails)*
[shownames] [formatjson]
gam copy vaultquery <MatterItem> <QueryItem> [targetmatter <MatterItem"] [name <String>]
[shownames] [formatjson]
gam delete vaultquery <QueryItem> matter <MatterItem>
gam delete vaultquery <MatterItem> <QueryItem>
```
Added a variant of `gam print vaultcounts` that gets its query parameters from a saved Vault query.
```
gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem> <QueryItem>
[wait <Integer>]
```
### 7.22.05
Added a variant of `gam create vaultexport` that gets its query parameters from a saved Vault query.
```
gam create vaultexport|export matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[driveclientsideencryption any|encrypted|unencrypted]
[includeaccessinfo <Boolean>]
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
[format ics|mbox|pst|xml]
[region any|europe|us] [showdetails|returnidonly]
```
### 7.22.04
Added a variant of `gam create vaulthold` that gets its parameters from a saved Vault query.
```
gam create vaulthold matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[showdetails|returnidonly]
```
### 7.22.03
Fix backwards compatability bug introduced in 7.22.00 for `gam print users` that changed `suspended`
from a field name to a query option; it is now correctly interpreted as a field name.
### 7.22.02
An update to the httplib2 library caused GAM proxy connections to fail; this has been fixed
by including the pysocks library needed by the latest httplib2 library.
### 7.22.00
Expanded `<UserTypeEntity>` to allow specification of non-archived/archived users.
* See [Collections of Users](Collections-of-Users)
These commands have also been updated to deal with archived users:
* `gam print aliases`
* `gam update groups`
* `gam info orgs`
* `gam print orgs`
* `gam print users`
Added `datetime <DateTimeFormat>` command that can be embedded in Gam batch files.
The current time is formatted with `<DateTimeFormat>` and subsequent lines in `<BatchContent>`
will have `%datetime%` replaced with the formatted time value.
See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
### 7.21.03
Added option `notifyrecoveryemail` to `gam create user` and `gam <UserTypeEntity> update user password <String>`
that sends the passsword notification email to the user's recovery email address (if defined).
### 7.21.02
GAM now builds on macOS 26 Tahoe and properly identifies the OS.
A custom build of the cryptography library is no longer needed for Windows arm64 builds as the project now releases their own build for the OS.
Upgrade to OpenSSL 3.5.3 latest
### 7.21.01
Replaced datetime, dateutil, calendar and iso8601 Python libraries with arrow library.
This should have no performance impact; report any problems.
You can now use timezone names when setting `timezone` in `gam.cfg`.
* See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
```
gam config timezone America/Los_Angeles save
```
### 7.20.04
Cleaned up Python library imports: googleapiclient, iso8601
### 7.20.03
Rebranded license SKU `1010470004` from `Gemini Education` to `Google AI Pro for Education`.
Additional updates to student groups in Google Classroom.
### 7.20.02
Upgraded `gam create course-studentgroups` to allow specification of multiple student group titles;
multiple student groups can be created in a single command.
* `((title <String>)|(select <StringEntity))+`
### 7.20.01
Added option `showaccesssettings` to `gam [<UserTypeEntity>] print|show chatspaces`. When listing
@@ -1877,7 +2063,7 @@ number of domain aliasess on stdout; no CSV file is written.
Added option `showitemcountonly` to `gam print domains` that causes GAM to display the
number of domains on stdout; no CSV file is written.
### 6.77.16
Fixed bug in `gam <UserTypeEntity> print filelist` that caused a trap.
@@ -2641,7 +2827,7 @@ Batch processing will suspend for `<Integer>` seconds before the next command li
Added the following options to `<PermissionMatch>` that allow more powerful matching.
```
nottype <DriveFileACLType>
nottype <DriveFileACLType>
typelist <DriveFileACLTypeList>
nottypelist <DriveFileACLTypeList>
rolelist <DriveFileACLRoleList>
@@ -3293,7 +3479,7 @@ Added support for Google Workspace Labs license.
### 6.64.10
Fixed bug introduced in 6.64.09 that caused a trap when `gam redirect csv <FileName> multiprocess` was used.
Fixed bug introduced in 6.64.09 that caused a trap when `gam redirect csv <FileName> multiprocess` was used.
### 6.64.09

View File

@@ -92,6 +92,38 @@ See [Collections of Items](Collections-of-Items)
Group membership commands involve specifying collections of users;
for `<UserTypeEntity>`, see: [Collections of Users](Collections-of-Users)
### Select users based on archived state
When adding, deleting or synchronizing group members, to select only archived or non-archived users, use the following`<UserTypeEntity>`:
```
(all users_na|users_arch)|
(domains_na|domains_arch <DomainNameList>)|
(group_na|group_arch <GroupItem>)|
(groups_na|groups_arch <GroupList>)|
(group_users_na|group_users_arch <GroupList>
[members] [managers] [owners]
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
(ou_na|ou_arch <OrgUnitItem>)|
(ou_and_children_na|ou_and_children_arch <OrgUnitItem>)|
(ous_na|ous_arch <OrgUnitList>)|
(ous_and_children_na|ous_and_children_arch <OrgUnitList>)
```
When adding, deleting or synchronizing group members, the `notarchived|archived` option can be used to select
users in a particular archived state. This option can be used with the following `<UserTypeEntity>`:
```
(all users)|
(domains <DomainNameList>)|
(group <GroupItem>)|
(groups <GroupList>)|
(group_users <GroupList>
[members] [managers] [owners]
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
(ou <OrgUnitItem>)|
(ou_and_children <OrgUnitItem>)|
(ous <OrgUnitList>)|
(ous_and_children <OrgUnitList>)
```
### Select users based on suspension state
When adding, deleting or synchronizing group members, to select only suspended or non-suspended users, use the following`<UserTypeEntity>`:
```
@@ -124,25 +156,6 @@ users in a particular suspension state. This option can be used with the followi
(ous_and_children <OrgUnitList>)
```
### Select users based on archived state
When adding, deleting or synchronizing group members, the `notarchived|archived` option can be used to select
users in a particular archived state. This option can be used with the following `<UserTypeEntity>`:
```
(all users|users_ns|users_susp|users_ns_susp)|
(domains|domains_ns|domains_susp <DomainNameList>)|
(group|group_ns|group_susp <GroupItem>)|
(groups|groups_ns|groups_susp <GroupList>)|
(group_users|group_users_ns|group_users_susp <GroupList>
[members] [managers] [owners]
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
(ou|ou_ns|ou_susp <OrgUnitItem>)|
(ou_and_children|ou_and_children_ns|ou_and_children_susp <OrgUnitItem>)|
(ous|ous_ns|ous_susp <OrgUnitList>)|
(ous_and_children|ous_and_children_ns|ous_and_children_susp <OrgUnitList>)|
(query <QueryUser>)|
(queries <QueryUserList>)
```
## Add members to a group
```
gam update group|groups <GroupEntity> create|add [<GroupRole>]
@@ -275,6 +288,11 @@ For `notarchived|archived`, see: [Select users based on archived state](#select-
The `notsuspended|suspended` and `notarchived|archived` not only control what users are selected from `<UserTypeEntity>`
but they also control what users are selected from `<GroupEntity>`.
* `notsuspended` - Select only non-suspended members
* `suspended` - Select only suspended members
* `notarchived` - Select only non-archived members
* `archived` - Select only archived users
* `notsuspended notarchived` - Select non-suspended and non-archived members
The `remove_domain_nostatus_members` option is used to remove members from the group that are in your domain but have no status.
These members were added to the group before the user or group that they represent was created.
@@ -373,10 +391,7 @@ By default, when clearing members from a group, all members, whether suspended/a
* `suspended` - Clear only suspended members
* `notarchived` - Clear only non-archived members
* `archived` - Clear only archived users
* `notsuspended notarchived` - Do not clear suspended and archived members
* `suspended archived` - Clear suspended and archived members
* `notsuspended archived` - Do not clear archived members
* `suspended notarchived` - Do not clear suspended members
* `notsuspended notarchived` - Clear non-suspended and non-archived members
Members that have met the above qualifications to be cleared can be further qualifed by their email address.
* `emailclearpattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be cleared; others will be retained
@@ -417,19 +432,12 @@ When `<UserTypeEntity>` specifies a group or groups:
* `usersonly` - Only the user members from the specified groups are added
* `groupsonly` - Only the group members from the specified groups are added
By default, when updating members from organization units, all users, whether suspended or not, are included.
* `notsuspended` - Do not include suspended users
* `suspended` - Only include suspended users
By default, when updating members from groups, all users, whether suspended/archived or not, are included.
* `notsuspended` - Do not include suspended users
* `suspended` - Only include suspended users
* `notarchived` - Do not include archived users
* `archived` - Only include archived users
* `notsuspended notarchived` - Do not include suspended and archived users
* `suspended archived` - Include only suspended or archived users
* `notsuspended archived` - Only include archived users
* `suspended notarchived` - Only include suspended users
By default, when updating members from groups/organization units, all users, whether suspended/archived or not, are included.
* `notsuspended` - Update only non-suspended members
* `suspended` - Update only suspended members
* `notarchived` - Update only non-archived members
* `archived` - Update only archived users
* `notsuspended notarchived` - Update non-suspended and non-archived members
You can set the `delivery` option for the updated members:
* `allmail` - All messages, delivered as soon as they arrive

View File

@@ -252,10 +252,10 @@ writes the credentials into the file oauth2.txt.
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin$ gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAM 7.20.01 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.23.07 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final
MacOS Sequoia 15.6.1 x86_64
macOS Tahoe 26.0.1 x86_64
Path: /Users/admin/bin/gam7
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
@@ -990,7 +990,7 @@ writes the credentials into the file oauth2.txt.
C:\>del C:\GAMConfig\oauth2.txt
C:\>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAM 7.20.01 - https://github.com/GAM-team/GAM - pythonsource
GAM 7.23.07 - https://github.com/GAM-team/GAM - pythonsource
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final
Windows-10-10.0.17134 AMD64

View File

@@ -60,9 +60,9 @@
| G Suite Legacy | Google-Apps | standard |
| G Suite Lite | Google-Apps-Lite | gsuitelite |
| Gemini Business | 1010470003 | geminibiz
| Gemini Education | 1010470004 | geminiedu |
| Gemini Education Premium | 1010470005 | geminiedupremium |
| Gemini Enterprise | 1010470001 | geminient | duetai |
| Google AI Pro for Education | 1010470004 | gaiproedu |
| Google AI Ultra for Business | 1010470008 | geminiultra |
| Google Apps Message Security | Google-Apps-For-Postini | postini |
| Google Chrome Device Management | Google-Chrome-Device-Management | cdm |
@@ -161,18 +161,17 @@
assuredcontrolsplus | 1010390002 | Assured Controls Plus |
bce | beyondcorp | beyondcorpenterprise | cep | chromeenterprisepremium | 1010400001 | Chrome Enterprise Premium |
cdm | chrome | googlechromedevicemanagement | Google-Chrome-Device-Management |
bce | beyondcorp | beyondcorpenterprise | cep | chromeenterprisepremium | 1010400001 | Chrome Enterprise Premium |
cdm | chrome | googlechromedevicemanagement | Google-Chrome-Device-Management |
cloudidentity | identity | 1010010001 | Cloud Identity |
cloudidentitypremium | identitypremium | 1010050001 | Cloud Identity Premium |
cloudsearch | 1010350001 | Cloud Search |
colabpro | 1010500001 | Colab Pro |
colabpro+ | colabproplus | 1010500002 | Colab Pro+ |
eeu | 1010490001 | SKU Endpoint Education Upgrade |
gaiproedu | geminiedu | 1010470004 | Google AI Pro for Education |
geminibiz | 1010470003 | Gemini Business |
geminiedu | 1010470004 | Gemini Education |
geminiedupremium| 1010470005 | Gemini Education Premium |
geminient| duetai | 1010470001 | Gemini Enterprise |
geminiultra | 1010470008 | Google AI Ultra for Business |
gsuitebasic | gafb | gafw | basic | Google-Apps-For-Business |
gsuitebusiness | gau | gsb | unlimited | Google-Apps-Unlimited |
gsuitebusinessarchived | gsbau | businessarchived | 1010340002 | Google Workspace Business - Archived User |
@@ -216,7 +215,8 @@
wsess | workspaceesentials | gsuiteessentials | essentials | d4e | driveenterprise | drive4enterprise | 1010060001 | Google Workspace Essentials (formerly G Suite Essentials) |
wsessplus | workspaceessentialsplus | 1010060005 | Google Workspace Enterprise Essentials Plus |
wsflw | workspacefrontline | workspacefrontlineworker | 1010020030 | Google Workspace Frontline Starter |
wsflwstan | workspacefrontlinestan | workspacefrontlineworkerstan | 1010020031 | Google Workspace Frontline Standard
wsflwstan | workspacefrontlinestan | workspacefrontlineworkerstan | 1010020031 | Google Workspace Frontline Standard |
wsflwplus | workspacefrontlineplus | workspacefrontlineworkerplus | 1010020034 | Google Workspace Frontline Plus
<SKUIDList> ::= "<SKUID>(,<SKUID>)*"
```
## Notes

View File

@@ -5,6 +5,7 @@
## Lists of basic items
```
<AdminAssigneeTypeList> ::= "<AdminAssigneeType>(,<AdminAssigneeType>)*"
<APIScopeURLList> ::= "<APIScopeURL>(,<APIScopeURL>)*"
<ASPIDList> ::= "<ASPID>(,<ASPID>)*"
<AssetTagList> ::= "<AssetTag>(,<AssetTag>)*"
@@ -43,6 +44,7 @@
<DomainNameList> ::= "<DomainName>(,<DomainName>)*"
<DriveFileACLRoleList> ::= "<DriveFileACLRole>(,<DriveFileACLRole>)*"
<DriveFileACLTypeList> ::= "<DriveFileACLType>(,<DriveFileACLType>)*"
<DriveFileIDList> ::= "<DriveFileID>(,<DriveFileID>)*"
<DriveFileList> ::= "<DriveFileItem>(,<DriveFileItem>)*"
<DriveFilePermissionList> ::= "<DriveFilePermission>(,<DriveFilePermission>)*"
<DriveFilePermissionIDList> ::= "<DriveFilePermissionID>(,<DriveFilePermissionID>)*"

View File

@@ -187,11 +187,15 @@ given if invalid CrOS deviceIds are specified.
## Display organizational units
These commands display information as an indented list of keys and values.
```
gam info org|ou <OrgUnitPath> [nousers|notsuspended|suspended] [children|child]
gam info orgs|ous <OrgUnitEntity> [nousers|notsuspended|suspended] [children|child]
gam info org|ou <OrgUnitPath> [nousers|notarchived|archived|notsuspended|suspended] [children|child]
[nousers | ([notarchived|archived] [notsuspended|suspended])] [children|child]
gam info orgs|ous <OrgUnitEntity> [nousers|notarchived|archived|notsuspended|suspended] [children|child]
[nousers | ([notarchived|archived] [notsuspended|suspended])] [children|child]
```
By default, all users of the org units are displayed:
* `nousers` - Don't display users of the org units
* `notarchived` - Display non-archived users of the org units
* `archived` - Display archived users of the org units
* `notsuspended` - Display non-suspended users of the org units
* `suspended` - Display suspended users of the org units
* `children|child` - Display users in any child org unit
@@ -214,7 +218,7 @@ By default, Gam prints all child org units of /.
* `convertcrnl` - In the description field, convert carriage return to \r and new line to \n.
Options `parentselector <OrgUnitSelector>` and `childselector <OrgUnitSelector>` add an additional column `orgUnitSelector` to the output.
This column value can be used in subsequent `gam csv` commands to appropriateley select members without duplication.
This column value can be used in subsequent `gam csv` commands to appropriately select members without duplication.
By default, all OUs are displayed. You can limit the display of OUs to those where the number
of ChromeOS devices/users falls within a range. Gathering this data requires additional API calls

View File

@@ -12,6 +12,8 @@
- [User reports](#user-reports)
## API documentation
These pages show event/parameter names; scroll down in the left column to: Reports.
* [Reports API - Activities](https://developers.google.com/admin-sdk/reports/v1/reference/activities)
* [Reports API - Customer Usage](https://developers.google.com/admin-sdk/reports/v1/reference/customerUsageReports)
* [Reports API - User Usage](https://developers.google.com/admin-sdk/reports/v1/reference/userUsageReport)
@@ -177,8 +179,8 @@ Example output from SharedDrivesActivity.csv:
name,id.time,shared_drive_id,shared_drive_name
NoActivities,,0AERPpMc23znvUkPXYZ,Shared Drive 1
view,2023-10-18T21:27:51-07:00,0AMhgLk82dhsuUkPXYZ,Shared Drive 2
edit,2023-09-05T15:27:01-07:00,0AM8lpdkkJaKYUkPXYZ,Shared Drive 3
view,2025-10-18T21:27:51-07:00,0AMhgLk82dhsuUkPXYZ,Shared Drive 2
edit,2025-09-05T15:27:01-07:00,0AM8lpdkkJaKYUkPXYZ,Shared Drive 3
```
Get activities with full activty data.
@@ -189,8 +191,8 @@ Example output from SharedDrivesActivity.csv:
name,actor.callerType,actor.email,actor.key,actor.profileId,actor_is_collaborator_account,added_role,billable,destination_folder_id,destination_folder_title,doc_id,doc_title,doc_type,id.applicationName,id.customerId,id.time,id.uniqueQualifier,ipAddress,is_encrypted,membership_change_type,new_settings_state,old_settings_state,originating_app_id,owner,owner_is_shared_drive,owner_is_team_drive,owner_team_drive_id,primary_event,removed_role,shared_drive_id,shared_drive_name,shared_drive_settings_change_type,target,team_drive_id,team_drive_settings_change_type,type,visibility
NoActivities,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0AERPpMc23znvUkPXYZ,Shared Drive 1,,,,,,
view,,user1@domain.com,,100016760394505151666,False,,True,,,1SDNu-yzDapqjdJq4y4xKDUATJlOPRIBodpGGeGt1n4I,Digital Poetry Journal,document,drive,C03kt1z99,2023-10-18T21:27:51-07:00,-2856812962461786835,2600:1700:9580:f4b0:2127:3b2:dd21:3806,False,,,,263492796725,Shared Drive 2,True,True,0AMhgLk82dhsuUkPXYZ,True,,0AMhgLk82dhsuUkPXYZ,Shared Drive 2,,,0AMhgLk82dhsuUkPXYZ,,access,people_with_link
edit,,user2@domain.com,,104066776037911136666,False,,True,,,1ZwHi_v-JVXH8W6zwgb7QYoUHrZD6NzIshJEqoTCaDD0,High School Scavenger Hunt,form,drive,C03kt1z99,2023-09-05T15:27:01-07:00,-1272095408714453395,50.204.178.246,False,,,,,Shared Drive 3,True,True,0AM8lpdkkJaKYUkPXYZ,True,,0AM8lpdkkJaKYUkPXYZ,Shared Drive 3,,,0AM8lpdkkJaKYUkPXYZ,,access,shared_internally
view,,user1@domain.com,,100016760394505151666,False,,True,,,1SDNu-yzDapqjdJq4y4xKDUATJlOPRIBodpGGeGt1n4I,Digital Poetry Journal,document,drive,C03kt1z99,2025-10-18T21:27:51-07:00,-2856812962461786835,2600:1700:9580:f4b0:2127:3b2:dd21:3806,False,,,,263492796725,Shared Drive 2,True,True,0AMhgLk82dhsuUkPXYZ,True,,0AMhgLk82dhsuUkPXYZ,Shared Drive 2,,,0AMhgLk82dhsuUkPXYZ,,access,people_with_link
edit,,user2@domain.com,,104066776037911136666,False,,True,,,1ZwHi_v-JVXH8W6zwgb7QYoUHrZD6NzIshJEqoTCaDD0,High School Scavenger Hunt,form,drive,C03kt1z99,2025-09-05T15:27:01-07:00,-1272095408714453395,50.204.178.246,False,,,,,Shared Drive 3,True,True,0AM8lpdkkJaKYUkPXYZ,True,,0AM8lpdkkJaKYUkPXYZ,Shared Drive 3,,,0AM8lpdkkJaKYUkPXYZ,,access,shared_internally
```
## Customer and user reports parameters
@@ -376,7 +378,7 @@ Select the users for whom information is desired.
* `showorgunit` - Add a column labelled `orgUnitPath` to the output; an additional API call is made to get the email addresses of the users in `<OrgUnitPath>`
* `select <UserTypeEntity>` - A selected collection of users, e.g., `select group staff@domain.com`; there is one API call per user
By default, when `user all` is specified (or no user specification in supplied), GAM backs up looking for data with a (basically) random user. If the randaom
By default, when `user all` is specified (or no user specification in supplied), GAM backs up looking for data with a (basically) random user. If the random
doesn't have any data, the command reports that no data was found. Use `allverifyuser <UserItem>` to specify a specific user to use to search for data.
Specify the report date; the default is today's date.
@@ -448,117 +450,117 @@ gam report users parameters accounts:drive_used_quota_in_mb,accounts:gmail_used_
```
Report on email activity for individual users.
```
$ gam report users select users testuser1,testuser2,testuser3 fields gmail:num_emails_received,gmail:num_emails_sent range 2023-07-01 2023-07-07
$ gam report users select users testuser1,testuser2,testuser3 fields gmail:num_emails_received,gmail:num_emails_sent range 2025-07-01 2025-07-07
Getting Reports for testuser1@rdschool.org (1/3)
Got 1 Report for testuser1@domain.com on 2023-07-01...
Got 1 Report for testuser1@domain.com on 2023-07-02...
Got 1 Report for testuser1@domain.com on 2023-07-03...
Got 1 Report for testuser1@domain.com on 2023-07-04...
Got 1 Report for testuser1@domain.com on 2023-07-05...
Got 1 Report for testuser1@domain.com on 2023-07-06...
Got 1 Report for testuser1@domain.com on 2023-07-07...
Got 1 Report for testuser1@domain.com on 2025-07-01...
Got 1 Report for testuser1@domain.com on 2025-07-02...
Got 1 Report for testuser1@domain.com on 2025-07-03...
Got 1 Report for testuser1@domain.com on 2025-07-04...
Got 1 Report for testuser1@domain.com on 2025-07-05...
Got 1 Report for testuser1@domain.com on 2025-07-06...
Got 1 Report for testuser1@domain.com on 2025-07-07...
Getting Reports for testuser2@domain.com (2/3)
Got 1 Report for testuser2@domain.com on 2023-07-01...
Got 1 Report for testuser2@domain.com on 2023-07-02...
Got 1 Report for testuser2@domain.com on 2023-07-03...
Got 1 Report for testuser2@domain.com on 2023-07-04...
Got 1 Report for testuser2@domain.com on 2023-07-05...
Got 1 Report for testuser2@domain.com on 2023-07-06...
Got 1 Report for testuser2@domain.com on 2023-07-07...
Got 1 Report for testuser2@domain.com on 2025-07-01...
Got 1 Report for testuser2@domain.com on 2025-07-02...
Got 1 Report for testuser2@domain.com on 2025-07-03...
Got 1 Report for testuser2@domain.com on 2025-07-04...
Got 1 Report for testuser2@domain.com on 2025-07-05...
Got 1 Report for testuser2@domain.com on 2025-07-06...
Got 1 Report for testuser2@domain.com on 2025-07-07...
Getting Reports for testuser3@domain.com (3/3)
Got 1 Report for testuser3@domain.com on 2023-07-01...
Got 1 Report for testuser3@domain.com on 2023-07-02...
Got 1 Report for testuser3@domain.com on 2023-07-03...
Got 1 Report for testuser3@domain.com on 2023-07-04...
Got 1 Report for testuser3@domain.com on 2023-07-05...
Got 1 Report for testuser3@domain.com on 2023-07-06...
Got 1 Report for testuser3@domain.com on 2023-07-07...
Got 1 Report for testuser3@domain.com on 2025-07-01...
Got 1 Report for testuser3@domain.com on 2025-07-02...
Got 1 Report for testuser3@domain.com on 2025-07-03...
Got 1 Report for testuser3@domain.com on 2025-07-04...
Got 1 Report for testuser3@domain.com on 2025-07-05...
Got 1 Report for testuser3@domain.com on 2025-07-06...
Got 1 Report for testuser3@domain.com on 2025-07-07...
email,date,gmail:num_emails_received,gmail:num_emails_sent
testuser1@domain.com,2023-07-01,10,1
testuser1@domain.com,2023-07-02,5,1
testuser1@domain.com,2023-07-03,14,3
testuser1@domain.com,2023-07-04,3,0
testuser1@domain.com,2023-07-05,35,4
testuser1@domain.com,2023-07-06,30,2
testuser1@domain.com,2023-07-07,20,0
testuser2@domain.com,2023-07-01,3,1
testuser2@domain.com,2023-07-02,1,0
testuser2@domain.com,2023-07-03,4,0
testuser2@domain.com,2023-07-04,1,0
testuser2@domain.com,2023-07-05,15,0
testuser2@domain.com,2023-07-06,14,0
testuser2@domain.com,2023-07-07,9,1
testuser3@domain.com,2023-07-01,14,0
testuser3@domain.com,2023-07-02,14,0
testuser3@domain.com,2023-07-03,20,0
testuser3@domain.com,2023-07-04,12,0
testuser3@domain.com,2023-07-05,37,2
testuser3@domain.com,2023-07-06,42,0
testuser3@domain.com,2023-07-07,20,0
testuser1@domain.com,2025-07-01,10,1
testuser1@domain.com,2025-07-02,5,1
testuser1@domain.com,2025-07-03,14,3
testuser1@domain.com,2025-07-04,3,0
testuser1@domain.com,2025-07-05,35,4
testuser1@domain.com,2025-07-06,30,2
testuser1@domain.com,2025-07-07,20,0
testuser2@domain.com,2025-07-01,3,1
testuser2@domain.com,2025-07-02,1,0
testuser2@domain.com,2025-07-03,4,0
testuser2@domain.com,2025-07-04,1,0
testuser2@domain.com,2025-07-05,15,0
testuser2@domain.com,2025-07-06,14,0
testuser2@domain.com,2025-07-07,9,1
testuser3@domain.com,2025-07-01,14,0
testuser3@domain.com,2025-07-02,14,0
testuser3@domain.com,2025-07-03,20,0
testuser3@domain.com,2025-07-04,12,0
testuser3@domain.com,2025-07-05,37,2
testuser3@domain.com,2025-07-06,42,0
testuser3@domain.com,2025-07-07,20,0
```
Report on email activity for individual users, aggregate by date across users.
```
$ gam report users select users testuser1,testuser2,testuser3@domain.com fields gmail:num_emails_received,gmail:num_emails_sent range 2023-07-01 2023-07-07 aggregatebydate
$ gam report users select users testuser1,testuser2,testuser3@domain.com fields gmail:num_emails_received,gmail:num_emails_sent range 2025-07-01 2025-07-07 aggregatebydate
Getting Reports for testuser1@domain.com (1/3)
Got 1 Report for testuser1@domain.com on 2023-07-01...
Got 1 Report for testuser1@domain.com on 2023-07-02...
Got 1 Report for testuser1@domain.com on 2023-07-03...
Got 1 Report for testuser1@domain.com on 2023-07-04...
Got 1 Report for testuser1@domain.com on 2023-07-05...
Got 1 Report for testuser1@domain.com on 2023-07-06...
Got 1 Report for testuser1@domain.com on 2023-07-07...
Got 1 Report for testuser1@domain.com on 2025-07-01...
Got 1 Report for testuser1@domain.com on 2025-07-02...
Got 1 Report for testuser1@domain.com on 2025-07-03...
Got 1 Report for testuser1@domain.com on 2025-07-04...
Got 1 Report for testuser1@domain.com on 2025-07-05...
Got 1 Report for testuser1@domain.com on 2025-07-06...
Got 1 Report for testuser1@domain.com on 2025-07-07...
Getting Reports for testuser2@domain.com (2/3)
Got 1 Report for testuser2@domain.com on 2023-07-01...
Got 1 Report for testuser2@domain.com on 2023-07-02...
Got 1 Report for testuser2@domain.com on 2023-07-03...
Got 1 Report for testuser2@domain.com on 2023-07-04...
Got 1 Report for testuser2@domain.com on 2023-07-05...
Got 1 Report for testuser2@domain.com on 2023-07-06...
Got 1 Report for testuser2@domain.com on 2023-07-07...
Got 1 Report for testuser2@domain.com on 2025-07-01...
Got 1 Report for testuser2@domain.com on 2025-07-02...
Got 1 Report for testuser2@domain.com on 2025-07-03...
Got 1 Report for testuser2@domain.com on 2025-07-04...
Got 1 Report for testuser2@domain.com on 2025-07-05...
Got 1 Report for testuser2@domain.com on 2025-07-06...
Got 1 Report for testuser2@domain.com on 2025-07-07...
Getting Reports for testuser3@domain.com (3/3)
Got 1 Report for testuser3@domain.com on 2023-07-01...
Got 1 Report for testuser3@domain.com on 2023-07-02...
Got 1 Report for testuser3@domain.com on 2023-07-03...
Got 1 Report for testuser3@domain.com on 2023-07-04...
Got 1 Report for testuser3@domain.com on 2023-07-05...
Got 1 Report for testuser3@domain.com on 2023-07-06...
Got 1 Report for testuser3@domain.com on 2023-07-07...
Got 1 Report for testuser3@domain.com on 2025-07-01...
Got 1 Report for testuser3@domain.com on 2025-07-02...
Got 1 Report for testuser3@domain.com on 2025-07-03...
Got 1 Report for testuser3@domain.com on 2025-07-04...
Got 1 Report for testuser3@domain.com on 2025-07-05...
Got 1 Report for testuser3@domain.com on 2025-07-06...
Got 1 Report for testuser3@domain.com on 2025-07-07...
date,gmail:num_emails_received,gmail:num_emails_sent
2023-07-01,27,2
2023-07-02,20,1
2023-07-03,38,3
2023-07-04,16,0
2023-07-05,87,6
2023-07-06,86,2
2023-07-07,49,1
2025-07-01,27,2
2025-07-02,20,1
2025-07-03,38,3
2025-07-04,16,0
2025-07-05,87,6
2025-07-06,86,2
2025-07-07,49,1
```
Report on email activity for individual users, aggregate by user across dates.
```
$ gam report users select users testuser1,testuser2,testuser3@domain.com fields gmail:num_emails_received,gmail:num_emails_sent range 2023-07-01 2023-07-07 aggregatebyuser
$ gam report users select users testuser1,testuser2,testuser3@domain.com fields gmail:num_emails_received,gmail:num_emails_sent range 2025-07-01 2025-07-07 aggregatebyuser
Getting Reports for testuser1@domain.com (1/3)
Got 1 Report for testuser1@domain.com on 2023-07-01...
Got 1 Report for testuser1@domain.com on 2023-07-02...
Got 1 Report for testuser1@domain.com on 2023-07-03...
Got 1 Report for testuser1@domain.com on 2023-07-04...
Got 1 Report for testuser1@domain.com on 2023-07-05...
Got 1 Report for testuser1@domain.com on 2023-07-06...
Got 1 Report for testuser1@domain.com on 2023-07-07...
Got 1 Report for testuser1@domain.com on 2025-07-01...
Got 1 Report for testuser1@domain.com on 2025-07-02...
Got 1 Report for testuser1@domain.com on 2025-07-03...
Got 1 Report for testuser1@domain.com on 2025-07-04...
Got 1 Report for testuser1@domain.com on 2025-07-05...
Got 1 Report for testuser1@domain.com on 2025-07-06...
Got 1 Report for testuser1@domain.com on 2025-07-07...
Getting Reports for testuser2@domain.com (2/3)
Got 1 Report for testuser2@domain.com on 2023-07-01...
Got 1 Report for testuser2@domain.com on 2023-07-02...
Got 1 Report for testuser2@domain.com on 2023-07-03...
Got 1 Report for testuser2@domain.com on 2023-07-04...
Got 1 Report for testuser2@domain.com on 2023-07-05...
Got 1 Report for testuser2@domain.com on 2023-07-06...
Got 1 Report for testuser2@domain.com on 2023-07-07...
Got 1 Report for testuser2@domain.com on 2025-07-01...
Got 1 Report for testuser2@domain.com on 2025-07-02...
Got 1 Report for testuser2@domain.com on 2025-07-03...
Got 1 Report for testuser2@domain.com on 2025-07-04...
Got 1 Report for testuser2@domain.com on 2025-07-05...
Got 1 Report for testuser2@domain.com on 2025-07-06...
Got 1 Report for testuser2@domain.com on 2025-07-07...
Getting Reports for testuser3@domain.com (3/3)
Got 1 Report for testuser3@domain.com on 2023-07-01...
Got 1 Report for testuser3@domain.com on 2023-07-02...
Got 1 Report for testuser3@domain.com on 2023-07-03...
Got 1 Report for testuser3@domain.com on 2023-07-04...
Got 1 Report for testuser3@domain.com on 2023-07-05...
Got 1 Report for testuser3@domain.com on 2023-07-06...
Got 1 Report for testuser3@domain.com on 2023-07-07...
Got 1 Report for testuser3@domain.com on 2025-07-01...
Got 1 Report for testuser3@domain.com on 2025-07-02...
Got 1 Report for testuser3@domain.com on 2025-07-03...
Got 1 Report for testuser3@domain.com on 2025-07-04...
Got 1 Report for testuser3@domain.com on 2025-07-05...
Got 1 Report for testuser3@domain.com on 2025-07-06...
Got 1 Report for testuser3@domain.com on 2025-07-07...
email,gmail:num_emails_received,gmail:num_emails_sent
testuser1@domain.com,117,11
testuser2@domain.com,47,2
@@ -566,7 +568,7 @@ testuser3@domain.com,159,2
```
## Monthly Report
### An example, running this on 3rd December 2020;-
### An example, running this on 3rd December 2025.
If combined with a scheduled task or cron job, this will produce an ongoing report with a new tab/sheet for each month.
```
$ gam report usage customer parameters meet:total_call_minutes,meet:total_meeting_minutes skipdaysofweek sat,sun previousmonths 1 todrive tdfileid <File ID> tdtitle "Meet Usage" tdtimeformat %Y-%m-%d tdaddsheet tdsheet "" tdsheettimeformat "%B %Y" tdsheetdaysoffset 6
@@ -575,9 +577,9 @@ $ gam report usage customer parameters meet:total_call_minutes,meet:total_meetin
* **gam report usage customer parameters meet:total_call_minutes,meet:total_meeting_minutes** - The GAM command
* **skipdaysofweek sat,sun** - exclude Sat & Sun, so only working days
* **previousmonths 1** - run against the previous months date range (regardless of how many days in the month, leap year etc)
* **todrive tdfileid <File ID> tdtitle "Meet Usage" tdtimeformat %Y-%m-%d** - write the data to an existing Google Sheet and append with current date, so it will be called "Meet Usage - 2020-12-03"
* **todrive tdfileid <File ID> tdtitle "Meet Usage" tdtimeformat %Y-%m-%d** - write the data to an existing Google Sheet and append with current date, so it will be called "Meet Usage - 2025-12-03"
* **tdaddsheet tdsheet ""** - Add a new tab/sheet with no name
* **tdsheettimeformat "%B %Y" tdsheetdaysoffset 6** - give the new tab/sheet a time stamp backdated by 6 days of 'Month Year', so for this example "November 2020", which will become the name of the new tab/sheet. The offset number must take you back in time into the previous month.
* **tdsheettimeformat "%B %Y" tdsheetdaysoffset 6** - give the new tab/sheet a time stamp backdated by 6 days of 'Month Year', so for this example "November 2025", which will become the name of the new tab/sheet. The offset number must take you back in time into the previous month.
**Notes**

View File

@@ -5,6 +5,8 @@
## Introduction
GAM7 can run on a Linux or Windows [Google Compute Engine (GCE)](https://cloud.google.com/products/compute) virtual machine and use the attached service account to access Google Workspace APIs. The advantage of this configuration is that no service account private key is accessible to GAM7 directly and [there is no risk of the key being stolen/lost](https://cloud.google.com/iam/docs/best-practices-for-managing-service-account-keys#alternatives).
**Note**: This method is recommended when running GAM **inside** Google Cloud. If you're running GAM **outside** Google Cloud (on-premises, other cloud providers, CI/CD systems), consider [Workload Identity Federation](https://github.com/GAM-team/GAM/wiki/Using-GAM7-with-keyless-authentication-Workload-Identity-Federation) instead - Google's officially recommended keyless authentication method for external environments.
## Setup Steps
1. Create a [GCP project](https://cloud.google.com/resource-manager/docs/creating-managing-projects).

View File

@@ -3,7 +3,8 @@
- [Query documentation](#query-documentation)
- [Definitions](#definitions)
- [Introduction](#introduction)
- [GUI API permission name mapping](#gui-api-permission-name-mapping)
- [API GUI permission name mapping](#api-gui-permission-name-mapping)
- [API GUI restriction name mapping](#api-gui-restriction-name-mapping)
- [Display Shared Drive themes](#display-shared-drive-themes)
- [Manage Shared Drives](#manage-shared-drives)
- [Create a Shared Drive](#create-a-shared-drive)
@@ -207,15 +208,8 @@
downloadrestrictedforwriters|downloadrestrictions.restrictedforwriters|
drivemembersonly|teammembersonly|
sharingfoldersrequiresorganizerpermission
Each pair of restrictions below are equivalent:
allowcontentmanagerstosharefolders true
sharingfoldersrequiresorganizerpermission false
allowcontentmanagerstosharefolders false
sharingfoldersrequiresorganizerpermission true
```
## Introduction
A domain administrator with the Drive and Docs administrator privilege can search for Shared Drives or update permissions for Shared Drives
owned by their organization, regardless of the admin's membership in any given Shared Drive.
@@ -225,15 +219,47 @@ Three forms of the commands are available:
* `gam <UserTypeEntity> action ... adminaccess` - The user named in `<UserTypeEntty>` is used, adminaccess indicates that the user is a domain administrator
* `gam <UserTypeEntity> action ...` - The user named in `<UserTypeEntty>` is used, access is limited to drives for which they are an organizer
## GUI API permission name mapping
## API GUI permission name mapping
| GUI setting | API setting |
|------------|------------|
| Manager | organizer |
| Content manager | fileOrganizer |
| Contributor | writer |
| Commenter | commenter |
| Viewer | reader |
| API setting | GUI setting |
|-------------|-------------|
| organizer | Manager |
| fileOrganizer | Content manager |
| writer | Contributor |
| commenter | Commenter |
| reader | Viewer |
## API GUI restriction name mapping
| API Setting | Description |
|-------------|-------------|
| adminManagedRestrictions | Whether administrative privileges on this shared drive are required to modify restrictions. |
| domainUsersOnly | Whether access to this shared drive and items inside this shared drive is restricted to users of the domain to which this shared drive belongs. |
| driveMembersOnly | Whether access to items inside this shared drive is restricted to its members. |
| allowContentManagersToShareFolders (GAM defined) | If true, users with either the organizer role or the file organizer role can share folders. If false, only users with the organizer role can share folders. |
| sharingFoldersRequiresOrganizerPermission | If true, only users with the organizer role can share folders. If false, users with either the organizer role or the file organizer role can share folders. |
| copyRequiresWriterPermission | Whether the options to copy, print, or download files inside this shared drive, should be disabled for readers and commenters. |
| downloadRestrictions.restrictedForWriters | Whether download and copy is restricted for writers. If true, download is also restricted for readers. |
| downloadRestrictions.restrictedForReaders | Whether download and copy is restricted for readers. |
| API Setting | False | True | GUI Setting | Checked | Unchecked |
|-------------|-------|------|-------------|---------|-----------|
| adminManagedRestrictions | X | | Shared drive settings can be modified | | |
| adminManagedRestrictions | | X | Shared drive settings can **not** be modified | | |
| | | | **Access** |
| domainUsersOnly | X | | Allow people outside of Domain name to access files | X | |
| domainUsersOnly | | X | Allow people outside of Domain name to access files | | X |
| driveMembersOnly | X | | Allow people who aren't shared drive members to access files | X | |
| driveMembersOnly | | X | Allow people who aren't shared drive members to access files | | X |
| | | | **Role permissions** |
| allowContentManagersToShareFolders | X | | Allow content managers to share folders | | X |
| allowContentManagersToShareFolders | | X | Allow content managers to share folders | X | |
| sharingFoldersRequiresOrganizerPermission | X | | Allow content managers to share folders | X | |
| sharingFoldersRequiresOrganizerPermission | | X | Allow content managers to share folders | | X |
| | | | **People who can download, copy, and print** |
| downloadRestrictions.restrictedForWriters | X | | Contributors and content managers | X | |
| downloadRestrictions.restrictedForWriters | | X | Contributors and content managers | | X |
| downloadRestrictions.restrictedForReaders | X | | Commenters and viewers | X | |
| downloadRestrictions.restrictedForReaders | | X | Commenters and viewers | | X |
## Display Shared Drive themes
```

View File

@@ -27,6 +27,8 @@ You can modify the default todrive behavior with options in `gam.cfg` or on the
## Definitions
```
<DateTimeFormat> ::= <String>
See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
<DriveFileID> ::= <String>
<DriveFolderID> ::= <String>
<TimeZone> ::= <String>
@@ -194,11 +196,11 @@ direct the uploaded file to a particular user and location and add a timestamp t
(tdreturnidonly [<Boolean>])|
(tdshare <EmailAddress> commenter|reader|writer)*|
(tdsheet (id:<Number>)|<String>)|
(tdsheettimestamp [<Boolean>] [tdsheettimeformat <String>])
(tdsheettimestamp [<Boolean>] [tdsheettimeformat <DateTimeFormat>])
(tdsheettitle <String>)|
(tdsubject <String>)|
([tdsheetdaysoffset <Number>] [tdsheethoursoffset <Number>])|
(tdtimestamp [<Boolean>] [tdtimeformat <String>]
(tdtimestamp [<Boolean>] [tdtimeformat <DateTimeFormat>]
([tddaysoffset <Number>] [tdhoursoffset <Number>])|
(tdtimezone <TimeZone>)|
(tdtitle <String>)|

View File

@@ -653,7 +653,7 @@ By default, Gam displays the information as an indented list of keys and values.
```
gam <UserTypeEntity> show events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek]
[countsonly] [formatjson]
[countsonly|formatjson]
```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
@@ -672,8 +672,8 @@ By default, Gam displays event details, use `countsonly` to display only the num
```
gam <UserTypeEntity> print events <UserCalendarEntity> [<EventEntity>] <EventDisplayProperty>*
[fields <EventFieldNameList>] [showdayofweek]
[countsonly]
[formatjson [quotechar <Character>]] [todrive <ToDriveAttribute>*]
(addcsvdata <FieldName> <String>)*
[eventrowfilter] [countsonly|(formatjson [quotechar <Character>])] [todrive <ToDriveAttribute>*]
```
In `<EventEntity>`, any `<EventSelectProperty>` options must precede all other options.
@@ -684,6 +684,9 @@ option `singleevents` to display all instances of a recurring event.
`showdayofweek` displays columns `start.dayOfWeek` and `end.dayOfWeek` when event start and end times are displayed.
Add additional columns of data from the command line to the output after the calendarId.
* `addcsvdata <FieldName> <String>`
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.

View File

@@ -44,6 +44,7 @@ Google requires that you have a Chat Bot configured in order to use the Chat API
## Set up a Chat Bot
* Run the command `gam setup chat`; it will point you to a URL to configure your Chat Bot.
* Uncheck "Build this chat app as a workspace add-on"
* Enter an App name and Description of your choosing.
* For the Avatar URL you can use `https://dummyimage.com/384x256/4d4d4d/0011ff.png&text=+GAM` or a public URL to an image of your own choosing.
* In Functionality, uncheck both "Receive 1:1 messages" and "Join spaces and group conversations"

View File

@@ -570,17 +570,12 @@ gam config auto_batch_min 1 csv_output_row_filter "owners.0.emailAddress:notrege
### Multiple parents
No existing parents are copied for source top/sub files/folders.
### Removed options
The following options will generate an error; they were removed in 6.23.00:
* `copysubfileparents` and `copysubfolderparents`.
### Move Folder Permissions
When a folder is moved by recreating it, its permissions are not copied; these options control copying permissions for folders.
When a folder is moved by recreating it, its permissions are not copied by the Drive API; these options control copying permissions for folders.
For options of the form `option [<Boolean>]`; if `<Boolean>` is omitted, `true` is assumed.
When recreated, a target folder inherits the permissions of its parent folder; these options control whether/how GAM copies the existing source folder permissions;
The default values of options introduced in version 6.14.00 are set to match the behavior of earlier versions.
When `mergewithparent` is `true`:
* `copymergewithparentfolderpermissions false` - The permissions of the source top folder are not not copied to the target folder; this is the default action.
@@ -594,7 +589,7 @@ When `duplicatefolders` is `merge` and a sub folder is a duplicate:
* `copymergedsubfolderpermissions false` - The permissions of the source sub folder are not not copied to the target folder.
* `copymergedsubfolderpermissions true` - The permissions of the source sub folder are copied to the target folder; this is the default action.
When `duplicatefolders` is `duplicatename` or `uniquename` and a top/sub folder is not a duplicate:
When `duplicatefolders` is `merge` or `duplicatename` or `uniquename` and a top/sub folder is not a duplicate:
* `copytopfolderpermissions true` - The permissions of the source top folder are copied to the target folder; this is the default action.
* `copytopfolderpermissions false` - The permissions of the source top folder are not not copied to the target folder.
* `copysubfolderpermissions true` - The permissions of the source sub folders are copied to the target folder; this is the default action.

View File

@@ -68,6 +68,8 @@
<ColorValue> ::= <ColorName>|<ColorHex>
```
```
<DateTimeFormat> ::= <String>
See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<DriveFileRevisionID> ::= <String>
@@ -178,7 +180,7 @@ gam <UserTypeEntity> create|add drivefile
[(localfile <FileName>|-)|(url <URL>)]
[(drivefilename|newfilename <DriveFileName>) | (replacefilename <REMatchPattern> <RESubstitution>)*]
[stripnameprefix <String>] [noduplicate]
[timestamp [<Boolean>]] [timeformat <String>]
[timestamp [<Boolean>]] [timeformat <DateTimeFormat>]
<DriveFileCreateAttribute>*
[(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) |
(returnidonly|returnlinkonly|returneditlinkonly|showdetails)]
@@ -478,7 +480,7 @@ gam <UserTypeEntity> update drivefile <DriveFileEntity> [copy] [returnidonly|ret
[(localfile <FileName>|-)|(url <URL>)]
[retainname | (newfilename <DriveFileName>) | (replacefilename <REMatchPattern> <RESubstitution>)*]
[stripnameprefix <String>]
[timestamp [<Boolean>]] [timeformat <String>]
[timestamp [<Boolean>]] [timeformat <DateTimeFormat>]
<DriveFileUpdateAttribute>*
[(gsheet|csvsheet <SheetEntity> [clearfilter])|(addsheet <String>)]
[charset <Charset>] [columndelimiter <Character>]

View File

@@ -10,12 +10,16 @@
- [Delete all ACLs except owner from a user's My Drive](#delete-all-acls-except-owner-from-a-users-my-drive)
- [Change shares to User1 to shares to User2](#change-shares-to-user1-to-shares-to-user2)
- [Map All ACLs from an old domain to a new domain](#map-all-acls-from-an-old-domain-to-a-new-domain)
- [Remove all ACLs for a specific user or group email address](#remove-all-ACLs-for-a-specific-user-or-group-email-address)
- [Remove anyone-anyoneWithLink ACLs](#remove-anyone-anyonewithlink-acls)
- [Remove ACLs for a specific user or group email address](#remove-ACLs-for-a-specific-user-or-group-email-address)
- [Remove ACLs for all users-groups in external domains](#remove-acls-for-all-users-groups-in-external-domains)
- [Remove domainCanFind-domainWithLink ACLs for internal domain](#remove-domaincanfind-domainwithlink-acls-for-internal-domain)
- [Remove My Drive ACLs for external domains](#remove-my-drive-acls-for-external-domains)
- [Remove anyoneCanFind-anyoneWithLink ACLs](#remove-anyonecanfind-anyonewithlink-acls)
## API documentation
* [Drive API - Permissions](https://developers.google.com/drive/api/v3/reference/permissions)
* [Shortcuts](https://developers.google.com/drive/api/guides/shortcuts)
* [Roles and permissions](https://developers.google.com/workspace/drive/api/guides/ref-roles)
* [Limited and Expansive Access](https://developers.google.com/workspace/drive/api/guides/limited-expansive-access)
## Definitions
@@ -25,6 +29,7 @@
```
<DomainName> ::= <String>(.<String>)+
<EmailAddress> ::= <String>@<DomainName>
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
<UniqueID> ::= id:<String>
<UserItem> ::= <EmailAddress>|<UniqueID>|<String>
@@ -176,6 +181,16 @@ gam <UserTypeEntity> transfer ownership <DriveFileEntity> <UserItem>
```
See: https://github.com/GAM-team/GAM/wiki/Users-Drive-Ownership#transfer-ownership-of-files-that-a-source-user-owns-to-a-target-user
If you specify `role owner`, Google requires that a notification message be sent to the new owner.
Google sends a preformatted message, use `emailmessage <String>` to include additional information in the message.
If you get the following error message from Google:
```
You are trying to invite user@domain.com. Since there is no Google account associated with this email address, you must check the "Notify people" box to invite this recipient."
```
Use the `sendemail` option and `emailmessage <String>` (if desired) to `check the "Notify people" box`.
The options `withlink|allowfilediscovery|discoverable` are only valid for ACLs to `anyone` or `domain`.
The option `expiration <Time>` is only valid for `role commenter|contributor|viewer` for files and `commenter|viewer` for folders.
@@ -265,6 +280,16 @@ From the Google Drive API documentation.
* `false` - Parents are not changed. The file is an orphan for the new owner. This is the default.
* `true` - The item is moved to the new owner's My Drive root folder and all prior parents removed. The file is an orphan for the old owner.
If you specify a pernission with `role owner`, Google requires that a notification message be sent to the new owner.
Google sends a preformatted message, use `emailmessage <String>` to include additional information in the message.
If you get the following error message from Google:
```
You are trying to invite user@domain.com. Since there is no Google account associated with this email address, you must check the "Notify people" box to invite this recipient."
```
Use the `sendemail` option and `emailmessage <String>` (if desired) to `check the "Notify people" box`.
Permission matching only applies when the `(json [charset <Charset>] <JSONData>)|(json file <FileName> [charset <Charset>])`
variant of `<DriveFilePermissionEntity>` and `<DriveFilePermissionIDEntity>` is used.
@@ -387,7 +412,7 @@ gam config csv_input_row_filter "permission.type:regex:user|group" redirect stdo
gam config csv_input_row_filter "permission.type:regex:domain" redirect stdout ./AddNewDomainACLsDomainShares.txt multiprocess redirect stderr stdout csv ./allUsersFiles.csv gam user "~Owner" create drivefileacl "~id" "~permission.type" "~permission.domain" role "~permission.role" allowfilediscovery "~permission.allowFileDiscovery" mappermissionsdomain olddomain.com newdomain.com
```
## Remove all ACLs for a specific user or group email address
## Remove ACLs for a specific user or group email address
### My Drives
@@ -400,12 +425,12 @@ gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv mult
Delete those My Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
Add My Drive ACLs with a different email address and the same role.
```
gam config num_threads 20 redirect stdout ./AddMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" add drivefleacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
gam config num_threads 20 redirect stdout ./AddMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" add drivefileacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
```
### Shared Drives
@@ -423,31 +448,44 @@ gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect
Delete those Shared Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
Add Shared Drive ACLs with a different email address and the same role.
```
gam config num_threads 20 redirect stdout ./ReplaceSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" add drivefleacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
gam config num_threads 20 redirect stdout ./ReplaceSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" add drivefileacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
```
## Remove anyone-anyoneWithLink ACLs
Here are the queries that will be used in these commands:
* anyone - query "visibility='anyoneCanFind'"
* anyoneWithLink - query "visibility='anyoneWithLink'"
* both - query "(visibility='anyoneCanFind' or visibility='anyoneWithLink')"
## Remove ACLs for all users-groups in external domains
### My Drives
Get My Drive anyone/anyoneWithLink ACLs
Get My Drive ACLs sharing to external domain users/groups.
Replace `<Types>` as required:
* `type user` - External domain users
* `type group` - External domain groups
* `typelist user,group` - External domain users and groups
Replace `<Domains>` with specification of external domain(s)
* `domain domain.com` - A single external domain
* `domainlist domain1.com,domain2.com,domain3.com...` - A list of external domains
If you want domains other than your internal domain(s)
* `notdomain domain.com` - A single internal domain
* `notdomainlist domain1.com,domain2.com,domain3.com...` - A list of internal domains
```
gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv multiprocess redirect stderr - multiprocess all users print filelist fields id,name,mimetype,basicpermissions <Query> pm type anyone em pmfilter oneitemperrow
gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv multiprocess redirect stderr - multiprocess all users print filelist fields id,name,mimetype,basicpermissions pm notrole owner <Types> <Domains> em pmfilter oneitemperrow
```
Delete those My Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
Add My Drive ACLs with a different email address and the same role.
```
gam config num_threads 20 redirect stdout ./AddMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" add drivefileacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
```
### Shared Drives
@@ -456,14 +494,123 @@ Get an organizer for each Shared Drive
gam redirect csv ./SharedDriveOrganizers.csv print shareddriveorganizers
```
Get Shared Drive anyone/anyoneWithLink ACLs
Get Shared Drive ACLs sharing to external domain users/groups.
Replace `<Types>` as required:
* `type user` - External domain users
* `type group` - External domain groups
* `typelist user,group` - External domain users and groups
Replace `<Domains>` with specification of external domain(s)
* `domain domain.com` - A single external domain
* `domainlist domain1.com,domain2.com,domain3.com...` - A list of external domains
If you want domains other than your internal domain(s)
* `notdomain domain.com` - A single internal domain
* `notdomainlist domain1.com,domain2.com,domain3.com...` - A list of internal domains
```
gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect csv ./SharedDriveShares.csv multiprocess redirect stderr - multiprocess csv SharedDriveOrganizers.csv gam user "~organizers" print filelist select shareddriveid "~id" fields id,name,mimetype,basicpermissions,driveid showdrivename pm <Types> <Domains> inherited false em pmfilter oneitemperrow
```
Delete those Shared Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
Add Shared Drive ACLs with a different email address and the same role.
```
gam config num_threads 20 redirect stdout ./ReplaceSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" add drivefileacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
```
## Remove domainCanFind-domainWithLink ACLs for internal domain
Replace `<Query>` below with one of these; they only apply to your internal domain:
* domainCanFind - query "visibility='domainCanFind'"
* domainWithLink - query "visibility='domainWithLink'"
* both - query "(visibility='domainCanFind' or visibility='domainWithLink')"
### My Drives
Get My Drive domainCanFind/domainWithLink ACLs for internal domain
```
gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv multiprocess redirect stderr - multiprocess all users print filelist fields id,name,mimetype,basicpermissions <Query> pm type domain em pmfilter oneitemperrow
```
Delete those My Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
### Shared Drives
Get an organizer for each Shared Drive
```
gam redirect csv ./SharedDriveOrganizers.csv print shareddriveorganizers
```
Get Shared Drive ACLs domainCanFind/domainWithLink ACLs for internal domain
* Replace `<Domain>` with actual domain name
```
gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect csv ./SharedDriveShares.csv multiprocess redirect stderr - multiprocess csv SharedDriveOrganizers.csv gam user "~organizers" print filelist select shareddriveid "~id" fields id,name,mimetype,basicpermissions,driveid showdrivename <Query> pm type domain inherited false em pmfilter oneitemperrow
```
Delete those Shared Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
## Remove My Drive ACLs for external domains
### My Drives
Get My Drive ACLs sharing to external domain(s)
Replace `<Domains>` with specification of external domain(s)
* `domain domain.com` - A single external domain
* `domainlist domain1.com,domain2.com,domain3.com...` - A list of external domains
If you want domains other than your internal domain(s)
* `notdomain domain.com` - A single internal domain
* `notdomainlist domain1.com,domain2.com,domain3.com...` - A list of internal domains
```
gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv multiprocess redirect stderr - multiprocess all users print filelist fields id,name,mimetype,basicpermissions pm type domain <Domains> em pmfilter oneitemperrow
```
Delete those My Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
## Remove anyoneCanFind-anyoneWithLink ACLs
Replace `<Query>` below with one of these:
* anyoneCanFind - query "visibility='anyoneCanFind'"
* anyoneWithLink - query "visibility='anyoneWithLink'"
* both - query "(visibility='anyoneCanFind' or visibility='anyoneWithLink')"
### My Drives
Get My Drive anyoneCanFind/anyoneWithLink ACLs
```
gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv multiprocess redirect stderr - multiprocess all users print filelist fields id,name,mimetype,basicpermissions <Query> pm type anyone em pmfilter oneitemperrow
```
Delete those My Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```
### Shared Drives
Get an organizer for each Shared Drive
```
gam redirect csv ./SharedDriveOrganizers.csv print shareddriveorganizers
```
Get Shared Drive anyoneCanFind/anyoneWithLink ACLs
```
gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect csv ./SharedDriveShares.csv multiprocess redirect stderr - multiprocess csv SharedDriveOrganizers.csv gam user "~organizers" print filelist select shareddriveid "~id" fields id,name,mimetype,basicpermissions,driveid showdrivename <Query> pm type anyone inherited false em pmfilter oneitemperrow
```
Delete those Shared Drive ACLs.
```
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
```

View File

@@ -11,6 +11,7 @@
## API documentation
* [Gmail API - Labels](https://developers.google.com/gmail/api/v1/reference/users.labels)
* [Gmail Labels](https://developers.google.com/workspace/gmail/api/guides/labels)
## Definitions
* [`<UserTypeEntity>`](Collections-of-Users)

View File

@@ -398,8 +398,8 @@ By default, Gam displays the information as an indented list of keys and values.
gam <UserTypeEntity> show contacts
<PeoplePrintShowUserContactSelection>
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
[countsonly|allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
[formatjson]
[allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
[countsonly|formatjson]
```
By default, Gam displays all of a user's people contacts.
* `query <String>` - Display contacts based on the data in their fields
@@ -416,8 +416,8 @@ By default, Gam displays the information as an indented list of keys and values.
gam <UserTypeEntity> print contacts [todrive <ToDriveAttribute>*]
<PeoplePrintShowUserContactSelection>
[orderby firstname|lastname|(lastmodified ascending)|(lastnodified descending)
[countsonly|allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
[formatjson [quotechar <Character>]]
[allfields|(fields <PeopleFieldNameList>)] [showgroups] [showmetadata]
[countsonly|(formatjson [quotechar <Character>])]
```
By default, Gam displays all of a user's people contacts.
* `query <String>` - Display contacts based on the data in their fields
@@ -547,8 +547,8 @@ User: user@domain.com, Delete maximum of 15 Other Contacts
```
gam <UserTypeEntity> show othercontacts
[<OtherContactsSelection>]
[countsonly|allfields|(fields <OtherContactsFieldNameList>)] [showmetadata]
[formatjson]
[allfields|(fields <OtherContactsFieldNameList>)] [showmetadata]
[countsonly|formatjson]
```
By default, Gam displays all of a user's Other Contacts; use
`<OtherContactsSelection>` to display a selection of Other Contacts.
@@ -563,8 +563,8 @@ By default, Gam displays the information as an indented list of keys and values.
```
gam <UserTypeEntity> print othercontacts [todrive <ToDriveAttribute>*]
[<OtherContactsSelection>]
[countsonly|allfields|(fields <OtherContactsFieldNameList>)] [showmetadata]
[formatjson [quotechar <Character>]]
[allfields|(fields <OtherContactsFieldNameList>)] [showmetadata]
[countsonly|(formatjson [quotechar <Character>])]
```
By default, Gam displays all of a user's Other Contacts; use
`<OtherContactsSelection>` to display a selection of Other Contacts.

View File

@@ -2,7 +2,8 @@
- [API documentation](#api-documentation)
- [Query documentation](#query-documentation)
- [Definitions](#definitions)
- [GUI API permission name mapping](#gui-api-permission-name-mapping)
- [API GUI permission name mapping](#api-gui-permission-name-mapping)
- [API GUI restriction name mapping](#api-gui-restriction-name-mapping)
- [Display Shared Drive themes](#display-shared-drive-themes)
- [Manage Shared Drives](#manage-shared-drives)
- [Create a Shared Drive](#create-a-shared-drive)
@@ -185,25 +186,49 @@
downloadrestrictedforwriters|downloadrestrictions.restrictedforwriters|
drivemembersonly|teammembersonly|
sharingfoldersrequiresorganizerpermission
Each pair of restrictions below are equivalent:
allowcontentmanagerstosharefolders true
sharingfoldersrequiresorganizerpermission false
allowcontentmanagerstosharefolders false
sharingfoldersrequiresorganizerpermission true
```
## GUI API permission name mapping
## API GUI permission name mapping
| GUI setting | API setting |
|------------|------------|
| Manager | organizer |
| Content manager | fileOrganizer |
| Contributor | writer |
| Commenter | commenter |
| Viewer | reader |
| API setting | GUI setting |
|-------------|-------------|
| organizer | Manager |
| fileOrganizer | Content manager |
| writer | Contributor |
| commenter | Commenter |
| reader | Viewer |
## API GUI restriction name mapping
| API Setting | Description |
|-------------|-------------|
| adminManagedRestrictions | Whether administrative privileges on this shared drive are required to modify restrictions. |
| domainUsersOnly | Whether access to this shared drive and items inside this shared drive is restricted to users of the domain to which this shared drive belongs. |
| driveMembersOnly | Whether access to items inside this shared drive is restricted to its members. |
| allowContentManagersToShareFolders (GAM defined) | If true, users with either the organizer role or the file organizer role can share folders. If false, only users with the organizer role can share folders. |
| sharingFoldersRequiresOrganizerPermission | If true, only users with the organizer role can share folders. If false, users with either the organizer role or the file organizer role can share folders. |
| copyRequiresWriterPermission | Whether the options to copy, print, or download files inside this shared drive, should be disabled for readers and commenters. |
| downloadRestrictions.restrictedForWriters | Whether download and copy is restricted for writers. If true, download is also restricted for readers. |
| downloadRestrictions.restrictedForReaders | Whether download and copy is restricted for readers. |
| API Setting | False | True | GUI Setting | Checked | Unchecked |
|-------------|-------|------|-------------|---------|-----------|
| adminManagedRestrictions | X | | Shared drive settings can be modified | | |
| adminManagedRestrictions | | X | Shared drive settings can **not** be modified | | |
| | | | **Access** |
| domainUsersOnly | X | | Allow people outside of Domain name to access files | X | |
| domainUsersOnly | | X | Allow people outside of Domain name to access files | | X |
| driveMembersOnly | X | | Allow people who aren't shared drive members to access files | X | |
| driveMembersOnly | | X | Allow people who aren't shared drive members to access files | | X |
| | | | **Role permissions** |
| allowContentManagersToShareFolders | X | | Allow content managers to share folders | | X |
| allowContentManagersToShareFolders | | X | Allow content managers to share folders | X | |
| sharingFoldersRequiresOrganizerPermission | X | | Allow content managers to share folders | X | |
| sharingFoldersRequiresOrganizerPermission | | X | Allow content managers to share folders | | X |
| | | | **People who can download, copy, and print** |
| downloadRestrictions.restrictedForWriters | X | | Contributors and content managers | X | |
| downloadRestrictions.restrictedForWriters | | X | Contributors and content managers | | X |
| downloadRestrictions.restrictedForReaders | X | | Commenters and viewers | X | |
| downloadRestrictions.restrictedForReaders | | X | Commenters and viewers | | X |
## Display Shared Drive themes
```

View File

@@ -122,7 +122,7 @@ gam <UserTypeEntity> show tasks [tasklists <TasklistEntity>]
[updatedmin <Time>]
[showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall]
[orderby completed|due|updated]
[countsonly|compact|formatjson]
[compact|countsonly|formatjson]
```
The API only supports dates in `duemin` and `duemax' but you must supply a null time:
* `duemin YYYY-MM-DDT00:00:00Z` - Specify the starting due date
@@ -152,7 +152,7 @@ gam <UserTypeEntity> print tasks [tasklists <TasklistEntity>] [todrive <ToDriveA
[updatedmin <Time>]
[showcompleted [<Boolean>]] [showdeleted [<Boolean>]] [showhidden [<Boolean>]] [showall]
[orderby completed|due|updated]
[countsonly | (formatjson [quotechar <Character>])]
[countsonly|(formatjson [quotechar <Character>])]
```
The API only supports dates in `duemin` and `duemax' but you must supply a null time:
* `duemin YYYY-MM-DDT00:00:00Z` - Specify the starting due date
@@ -230,7 +230,7 @@ By default, Gam displays the task lists as an indented list of keys and values.
```
gam <UserTypeEntity> print tasklists [todrive <ToDriveAttribute>*]
[countsonly | (formatjson [quotechar <Character>])]
[countsonly|(formatjson [quotechar <Character>])]
```
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.

View File

@@ -401,9 +401,10 @@ password "helloworld" nohash
```
## Password Notification
When creating a user or updating a user's password, you can send a message with details to an email address; this might be the user's secondary email address.
When creating a user or updating a user's password, you can send a message with details to an email address;'
this might be the user's secondary email address or their recovery email address.
```
[notify <EmailAddressList>
[[notify <EmailAddressList>] [notifyrecoveryemail]
[subject <String>]
[notifypassword <String>]
[from <EmailAaddress>]
@@ -416,6 +417,7 @@ When creating a user or updating a user's password, you can send a message with
[notifyonupdate [<Boolean>]]
```
* `notify <EmailAddressList>` - Specify recipients
* `notifyrecoveryemail` - Use the user's recovery email address (if defined) as a recipient
If subject is not specified, the following value will be used:
* create - `Welcome to #domain#`
@@ -653,7 +655,7 @@ gam update user <UserItem> [ignorenullpassword] <UserAttribute>*
[createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
[alias|aliases <EmailAddressList>]
[notify <EmailAddressList>
[[notify <EmailAddressList>] [notifyrecoveryemail]
[subject <String>]
[notifypassword <String>]
[from <EmailAaddress>]
@@ -675,7 +677,7 @@ gam update users <UserTypeEntity> [ignorenullpassword] <UserAttribute>*
[createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
[alias|aliases <EmailAddressList>]
[notify <EmailAddressList>
[[notify <EmailAddressList>] [notifyrecoveryemail]
[subject <String>]
[notifypassword <String>]
[from <EmailAddress>]
@@ -697,7 +699,7 @@ gam <UserTypeEntity> update users [ignorenullpassword] <UserAttribute>*
[createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
[alias|aliases <EmailAddressList>]
[notify <EmailAddressList>
[[notify <EmailAddressList>] [notifyrecoveryemail]
[subject <String>]
[notifypassword <String>]
[from <EmailAaddress>]
@@ -1057,7 +1059,7 @@ gam print users [todrive <ToDriveAttribute>*]
[userview] [allfields|basic|full|(<UserFieldName>*|fields <UserFieldNameList>)]
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
[issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
```
@@ -1068,6 +1070,7 @@ By default, users in all domains in the account are selected; these options allo
* `limittoou <OrgUnitPath>|<OrgUnitID>` - Limit users to those in the specified `<OrgUnitItem>>`
* `deleted_only|only_deleted` - Only display deleted users
* `issuspended <Boolean>` - Limit users based on their status
* `isarchived <Boolean>` - Limit users based on their status
### Print a header row and fields for users specified by `<UserTypeEntity>`
```
@@ -1082,7 +1085,7 @@ gam print users [todrive <ToDriveAttribute>*] select <UserTypeEntity>
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
[issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
gam <UserTypeEntity> print users [todrive <ToDriveAttribute>*]
@@ -1096,7 +1099,7 @@ gam <UserTypeEntity> print users [todrive <ToDriveAttribute>*]
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
[issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
```
@@ -1187,7 +1190,7 @@ gam print users countonly [todrive <ToDriveAttribute>*]
([domain|domains <DomainNameEntity>] [(query <QueryUser>)|(queries <QueryUserList>)]
[limittoou <OrgUnitItem>] [deleted_only|only_deleted])
[formatjson [quotechar <Character>]]
[issuspended <Boolean>]
[issuspended <Boolean>] [isarchived <Boolean>]
```
By default, users in all domains in the account are selected; these options allow selection of subsets of users:
* `domain|domains <DomainNameEntity>` - Limit users to those in the domains specified by `<DomainNameEntity>`
@@ -1196,6 +1199,7 @@ By default, users in all domains in the account are selected; these options allo
* `limittoou <OrgUnitPath>|<OrgUnitID>` - Limit users to those in the specified `<OrgUnitItem>>`
* `deleted_only|only_deleted` - Only display deleted users
* `issuspended <Boolean>` - Limit users based on their status
* `isarchived <Boolean>` - Limit users based on their status
### Print domain counts for users specified by `<UserTypeEntity>`
```
@@ -1323,7 +1327,7 @@ gam print users select <UserTypeEntity> showitemcountonly
gam print users
([domain|domains <DomainNameEntity>] [(query <QueryUser>)|(queries <QueryUserList>)]
[limittoou <OrgUnitItem>] [deleted_only|only_deleted])|[select <UserTypeEntity>]
[issuspended <Boolean>]
[issuspended <Boolean>] [isarchived <Boolean>]
showitemcountonly
```
Example

View File

@@ -5,6 +5,8 @@
- [FAQs](#faqs)
- [Setup Steps](#setup-steps)
**Alternative Approach**: For enhanced security and simplified operations when running GAM outside Google Cloud, consider [Workload Identity Federation](https://github.com/GAM-team/GAM/wiki/Using-GAM7-with-keyless-authentication-Workload-Identity-Federation) - Google's recommended keyless authentication method that eliminates the need for managing any long-lived credentials. If running GAM in Google Cloud, use [attached service accounts on GCE](https://github.com/GAM-team/GAM/wiki/Running-GAM7-securely-on-a-Google-Compute-Engine) instead.
## Thanks
Thanks to Jay Lee for the original version of this document.
@@ -69,4 +71,4 @@ gam user admin@example.com check serviceaccount
```
and see the YubiKey lights flash as the YubiKey interacts with GAM7 to sign the GAM7 authentication requests. If you look at the oauth2service.json file, you'll see it contains some new fields like yubikey_serial and yubikey_pin but no longer contains the private_key field where GAM7 would normally store the private key data.
7. As a last step, since YubiKey-stored private keys do not need to be and should not be rotated, you can remove the service account's permissions to change it's own key. Navigate to the [Cloud Console](https://console.cloud.google.com/iam-admin/serviceaccounts) select the correct project and service account and on the Permissions tab, edit and remove the "Service Account Key Admin" permission that the service account has to itself.
7. As a last step, since YubiKey-stored private keys do not need to be and should not be rotated, you can remove the service account's permissions to change it's own key. Navigate to the [Cloud Console](https://console.cloud.google.com/iam-admin/serviceaccounts) select the correct project and service account and on the Permissions tab, edit and remove the "Service Account Key Admin" permission that the service account has to itself.

View File

@@ -0,0 +1,290 @@
# Using GAM7 with Keyless Authentication - Workload Identity Federation
**Important**: This method is designed for running GAM7 **outside** of Google Cloud (on-premises, other cloud providers, CI/CD systems). If you're running GAM7 **inside** Google Cloud, use [attached service accounts on Google Compute Engine](Running-GAM7-securely-on-a-Google-Compute-Engine) instead, which provides the same keyless benefits with simpler configuration.
This guide explains how to configure GAM7 to use Google Cloud's Workload Identity Federation for keyless authentication. **This is Google's officially recommended authentication method** for enhanced security and simplified credential management.
## Table of Contents
- [Overview](#overview)
- [Prerequisites](#prerequisites)
- [Setup Steps](#setup-steps)
- [1. Enable Required APIs](#1-enable-required-apis)
- [2. Create Workload Identity Pool](#2-create-workload-identity-pool)
- [3. Create or Use Existing Service Account](#3-create-or-use-existing-service-account)
- [4. Grant Required Permissions](#4-grant-required-permissions)
- [AWS Configuration](#aws-configuration)
- [1. Create Workload Identity Provider for AWS](#1-create-workload-identity-provider-for-aws)
- [2. Allow AWS Identity to Impersonate Service Account](#2-allow-aws-identity-to-impersonate-service-account)
- [3. Create Credential Configuration File](#3-create-credential-configuration-file)
- [4. Configure GAM7 Environment for AWS](#4-configure-gam7-environment-for-aws)
- [5. Initialize GAM7](#5-initialize-gam7)
- [GitHub Actions Configuration](#github-actions-configuration)
- [1. Create Workload Identity Provider for GitHub Actions](#1-create-workload-identity-provider-for-github-actions)
- [2. Allow GitHub Actions to Impersonate Service Account](#2-allow-github-actions-to-impersonate-service-account)
- [3. GitHub Actions Workflow Configuration](#3-github-actions-workflow-configuration)
- [Clean Up](#clean-up)
- [Security Best Practices](#security-best-practices)
- [Troubleshooting](#troubleshooting)
- [Benefits](#benefits)
- [References](#references)
## Overview
Workload Identity Federation allows GAM7 to authenticate to Google Cloud services without storing long-lived service account keys. Instead, it uses short-lived tokens from external identity providers like AWS, Azure, or GitHub Actions, eliminating the security risks associated with managing static credentials.
## Prerequisites
- GAM7 [installed and configured](https://github.com/GAM-team/GAM/wiki/How-to-Install-GAM7)
- Run `gam config` to generate the `gam.cfg` file
- Run `gam create/use project` to generate the `oauth2service.json` file
- Optionally enable [DASA](https://github.com/GAM-team/GAM/wiki/Using-GAM7-with-a-delegated-admin-service-account) `gam config enable_dasa true admin_email admin@domain.com customer_id domain domain.com save`
- Google Cloud CLI (gcloud) installed and configured
- [Install gcloud CLI](https://cloud.google.com/sdk/docs/install)
- Run `gcloud auth login` to authenticate
- Run `gcloud config set project PROJECT_ID` to set your project
- **Alternative**: Use the [Google Cloud Console](https://console.cloud.google.com) web interface to perform the same operations
- Google Cloud project with appropriate APIs enabled
- External identity provider (AWS, Azure, GitHub Actions, etc.)
- Appropriate permissions to create Workload Identity Pools and manage IAM
## Setup Steps
### 1. Enable Required APIs
```bash
gcloud services enable iamcredentials.googleapis.com
gcloud services enable sts.googleapis.com
```
### 2. Create Workload Identity Pool
```bash
gcloud iam workload-identity-pools create POOL_ID \
--location="global" \
--description="Pool for GAM authentication"
```
### 3. Create or Use Existing Service Account
You can either create a new service account or reuse an existing one that has the necessary permissions.
#### Option A: Create New Service Account
```bash
gcloud iam service-accounts create SERVICE_ACCOUNT_ID \
--description="Service account for GAM operations" \
--display-name="GAM Service Account"
```
#### Option B: Use Existing Service Account
If you already have a service account with appropriate Google Workspace permissions (typically the one created during GAM7 initial setup), you can reuse it. Just note the service account email for the next steps.
```bash
# List existing service accounts to find the one you want to use
gcloud iam service-accounts list
```
### 4. Grant Required Permissions
```bash
# Grant necessary Google Workspace permissions
gcloud projects add-iam-policy-binding PROJECT_ID \
--member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
--role="roles/iam.serviceAccountTokenCreator"
```
## AWS Configuration
### 1. Create Workload Identity Provider for AWS
```bash
gcloud iam workload-identity-pools providers create-aws PROVIDER_ID \
--workload-identity-pool="POOL_ID" \
--account-id="YOUR_AWS_ACCOUNT_ID" \
--location="global"
```
### 2. Allow AWS Identity to Impersonate Service Account
```bash
gcloud iam service-accounts add-iam-policy-binding \
SERVICE_ACCOUNT_EMAIL \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.aws_role/arn:aws:sts::YOUR_AWS_ACCOUNT:assumed-role/YOUR_ROLE_NAME"
```
### 3. Create Credential Configuration File
Create a JSON file with your Workload Identity Federation configuration:
#### For AWS [IMDSv1](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html#instance-metadata-retrieval-examples-imdsv1)
```bash
gcloud iam workload-identity-pools create-cred-config \
projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
--service-account=SERVICE_ACCOUNT_EMAIL \
--service-account-token-lifetime-seconds=SERVICE_ACCOUNT_TOKEN_LIFETIME \
--aws \
--output-file=FILEPATH.json
```
#### For AWS [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html#instance-metadata-retrieval-examples)
```bash
gcloud iam workload-identity-pools create-cred-config \
projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
--service-account=SERVICE_ACCOUNT_EMAIL \
--aws \
--enable-imdsv2 \
--output-file=FILEPATH.json
```
### 4. Configure GAM7 Environment for AWS
Set the environment variable to use the credential file:
```bash
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/credential-configurations.json"
```
Open the `oauth2service.json` file, and set the `key_type` to `signjwt`.
```
...
"key_type": "signjwt",
...
```
### 5. Initialize GAM7
```bash
gam version
gam info user
```
## GitHub Actions Configuration
### 1. Create Workload Identity Provider for GitHub Actions
```bash
gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
--workload-identity-pool="POOL_ID" \
--issuer-uri="https://token.actions.githubusercontent.com" \
--attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository" \
--attribute-condition="assertion.repository_owner=='YOUR_GITHUB_ORGANIZATION'"
--location="global"
```
### 2. Allow GitHub Actions to Impersonate Service Account
```bash
gcloud iam service-accounts add-iam-policy-binding \
SERVICE_ACCOUNT_EMAIL \
--role="roles/iam.workloadIdentityUser" \
--member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.repository/YOUR_GITHUB_ORG/YOUR_REPO"
```
### 3. GitHub Actions Workflow Configuration
.github/workflows/example.yml
```yaml
name: GAM Operations
on: [push]
jobs:
gam-job:
runs-on: ubuntu-24.04
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v3
- name: Download and install GAM
run: |
bash <(curl -s -S -L https://git.io/gam-install) -l
- name: Copy GAM configs into target dir
# Make sure to remove the private key from oauth2service.json and set `key_type` to `signjwt`
run: |
cp ./gam.cfg ~/.gam/gam.cfg
cp ./oauth2service.json ~/.gam/oauth2service.json
# # For debugging GitHub identity tokens
# - name: Print out GitHub OIDC token
# uses: github/actions-oidc-debugger@2e9ba5d3f4bebaad1f91a2cede055115738b7ae8
# with:
# audience: https://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID
- id: 'auth'
name: 'Authenticate to Google Cloud'
uses: 'google-github-actions/auth@v1'
with:
create_credentials_file: true
workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID'
service_account: 'SERVICE_ACCOUNT_EMAIL'
- name: Run GAM commands
run: |
~/bin/gam7/gam info user
```
## Clean Up
After verifying that gam is working as expected, delete the old key if it's no longer in use.
```bash
gcloud iam service-accounts keys delete KEY_ID --iam-account=SERVICE_ACCOUNT_EMAIL
```
Also remove it from the `oauth2service.json` file.
```
...
"private_key": "",
"private_key_id": "",
...
```
## Security Best Practices
1. **Principle of Least Privilege**: Grant only necessary permissions to the service account
2. **Attribute Conditions**: Use attribute conditions to restrict access based on specific criteria
3. **Regular Auditing**: Regularly review and audit Workload Identity Federation configurations
4. **Token Lifetime**: Configure appropriate token lifetimes for your use case
## Troubleshooting
### Common Issues
1. **Authentication Errors**
- Verify the audience URL matches your Workload Identity Pool
- Check that the external identity has permission to impersonate the service account
2. **Permission Denied**
- Ensure the service account has necessary Google Workspace permissions
- Verify domain-wide delegation is configured if required
3. **Token Expiration**
- Tokens are automatically refreshed by the Google Auth libraries
- Check network connectivity to Google STS endpoints
### Debug Commands
```bash
# Test authentication
gcloud auth print-access-token
# Verify service account impersonation
gcloud auth print-access-token --impersonate-service-account=SERVICE_ACCOUNT_EMAIL
# Check GAM authentication
gam info user
```
## Benefits
- **Reduced Attack Surface**: Short-lived tokens minimize exposure window if compromised
- **Reduced Operational Cost**: Eliminates the overhead of managing and rotating service account keys
- **Improved Scalability**: Easily scale across multiple environments without distributing keys
- **Better Integration**: Native integration with cloud provider identity systems (AWS IAM, GitHub OIDC)
- **Compliance**: Meets security requirements for keyless authentication
## References
- [Google Cloud Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation)
- [Workload Identity Federation With Other Clouds](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-clouds)
- [Authenticate to Google Cloud from GitHub Actions](https://github.com/google-github-actions/auth/blob/main/README.md)
- [Service Account Impersonation](https://cloud.google.com/iam/docs/impersonating-service-accounts)

View File

@@ -3,6 +3,7 @@
- [Query documentation](#query-documentation)
- [Python Regular Expressions](Python-Regular-Expressions) Match function
- [Definitions](#definitions)
- [Special quoting](#special-quoting)
- [Vault Matters](#vault-matters)
- [Create Vault Matters](#create-vault-matters)
- [Manage Vault Matters](#manage-vault-matters)
@@ -21,9 +22,12 @@
- [Display Vault Holds](#display-vault-holds)
- [Display Vault Holds Affecting a User](#display-vault-holds-affecting-a-user)
- [Vault Saved Queries](#vault-saved-queries)
- [Create Vault Saved Queries](#create-vault-saved-queries)
- [Copy Vault Saved Queries](#copy-vault-saved-queries)
- [Delete Vault Saved Queries](#delete-vault-saved-queries)
- [Display Vault Saved Queries](#display-vault-saved-queries)
- [Takeout](#takeout)
- [Copy a Takeout Bucket](#copy-a-takeoutbucket)
- [Copy a Takeout Bucket](#copy-a-takeout-bucket)
- [Download a Takeout Bucket](#download-a-takeout-bucket)
## API documentation
@@ -54,6 +58,7 @@
<EmailAddressList> ::= "<EmailAddess>(,<EmailAddress>)*"
<EmailAddressEntity> ::= <EmailAddressList> | <FileSelector> | <CSVFileSelector> | <CSVkmdSelector> | <CSVDataSelector>
See: https://github.com/GAM-team/GAM/wiki/Collections-of-Items
<JSONData> ::= (json [charset <Charset>] <String>) | (json file <FileName> [charset <Charset>]) |
<TimeZone> ::= <String>
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
<UniqueID> ::= id:<String>
@@ -66,13 +71,17 @@
<ChatSpace> ::= spaces/<String> | space/<String> | <String>
<ChatSpaceList> ::= "<ChatSpace>(,<ChatSpace>)*"
<DriveFileID> ::= <String>
<DriveFileIDList> ::= "<DriveFileID>(,<DriveFileID>)*"
<ExportItem> ::= <UniqueID>|<String>
<ExportStatus> ::= completed|failed|inprogrsss
<ExportStatusList> ::= "<ExportStatus>(,<ExportStatus>)*"
<HoldItem> ::= <UniqueID>|<String>
<MatterItem> ::= <UniqueID>|<String>
<MatterItemList> ::= "<MatterItem>(,<MatterItem>)*"
<MatterState> ::= open|closed|deleted
<MatterStateList> ::= "<MatterState>(,<MatterState>)*"
<QueryItem> ::= <UniqueID>|<String>
<SharedDriveID> ::= <String>
<SharedDriveIDList> ::= "<SharedDriveID>(,<SharedDriveID>)*"
<URL> ::= <String>
@@ -135,9 +144,29 @@
<VaultQueryFieldNameList> ::= "<VaultQueryFieldName>(,<VaultQueryFieldName>)*"
```
You specify matters, exports and holds by ID (`<UniqueID>`) or name (`<String>`). The API requires an ID, so if you specify a name,
GAM has to make additional API calls to convert the name to an ID.
## Special quoting
You specify a single matter with `matter <MatterItem>` and a list of matters with `matters <MatterItemList>`.
As matter names can contain spaces, some care must be used when entering `<MatterItem>` and `<MatterItemList>` with names.
Suppose you have a matter `Foo Bar`. To get information about a specific export: `gam info vaultexport "Foo Bar" <ExportItem>`
The shell strips the `"` leaving a single argument `Foo Bar`; gam correctly processes the argument.
Suppose you enter the command: `gam show vaultexports matters "Foo Bar"`
The shell strips the `"` leaving a single argument `Foo Bar`; gam splits the argument on space leaving two items and then tries to process `Foo` and `Bar`, not what you want.
You must enter: `gam info show vaultexports matters "'Foo Bar'"`
The shell strips the `"` leaving a single argument `'Foo Bar'`; gam splits the argument on space while honoring the `'` leaving one item `Foo Bar` and correctly processes the item.
For quoting rules, see: [List Quoting Rules](Command-Line-Parsing)
## Vault Matters
## Create Vault Matters
Create a Google Vault matter.
@@ -201,11 +230,18 @@ Select fields to display:
* `fields <VaultMatterFieldNameList>` - Display selected fields; `matterId` and `name` are always displayed
## Display Vault Counts
Display item counts retained in Vault for the given users or groups.
### Display item counts retained in Vault using a saved Vault query.
```
gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem> <QueryItem>
[wait <Integer>]
```
### Display item counts retained in Vault for the given users or groups.
* The required argument `matter` specifies the matter name or ID (prefix with id:) where the count should be performed.
* The required argument `corpus` specifies whether Gmail mailbox data or Google Groups archives are queried.
* You need to specify one argument of accounts, orgunit or everyone to determine which users/groups to query.
* The `scope` argument specifies the data to be queried, `all_data` is the default and is recommended.
* You need to specify one argument of accounts, orgunit or everyone to determine which users/groups to query.
The command may take some time to complete; GAM makes repeated API calls until the operation is complete. By default,
GAM waits 15 seconds between API calls; use the `wait <Integer>` option to specify a different wait period.
@@ -213,26 +249,28 @@ GAM waits 15 seconds between API calls; use the `wait <Integer>` option to speci
This command can be useful for discovering legacy former employee accounts which no longer have any mail data retained by Vault.
```
gam print vaultcounts [todrive <ToDriveAttributes>*]
matter <MatterItem> corpus mail|groups
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
[(shareddrives|teamdrives (<TeamDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))]
[scope <all_data|held_data|unprocessed_data>]
matter <MatterItem>
corpus mail|groups
[scope all_data|held_data|unprocessed_data]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone|entireorg
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[excludedrafts <Boolean>]
[<JSONData>]
[wait <Integer>]
```
Specify the search method, this is optional:
* `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>`
* `orgunit|org|ou <OrgUnitPath>` - Search all accounts in the OU `<OrgUnitPath>`
* `everyone` - Search for all accounts in the organization
* `shareddrives|teamdrives <SharedDriveIDList>` - Search for all accounts in the Shared Drives specified in `<SharedDriveIDList>`
* `shareddrives|teamdrives select <FileSelector>|<CSVFileSelector>` - Search for all accounts in the Shared Drives specified in `<FileSelector>|<CSVFileSelector>`
* `rooms <ChatSpaceList>` - Search in the Room specified in the chat rooms specified in `<ChatSpaceList>`
* `rooms <ChatSpaceList>` - Search in the Room specified in the chat rooms specified in `<FileSelector>|<CSVFileSelector>`
* `sitesurl <URLList>` - Search the published site URLs of new Google Sites in `<URLList>`
* `sitesurl <URLList>` - Search the published site URLs of new Google Sites specified in `<FileSelector>|<CSVFileSelector>`
* `everyone|entireorg` - Search for all accounts in the organization
For `corpus mail|group`, you can specify search terms to limit the search.
* `terms <String>` - [Vault search](https://support.google.com/vault/answer/2474474)
For `corpus mail|group`, you can specify time limits on the search:
* `start|starttime <Date>|<Time>` - The start time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
* `end|endtime <Date>|<Time>` - The end time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
You can specify query options with `<JSONData>`.
Check the status of a previous count operation with the name from a previous command.
```
@@ -242,32 +280,48 @@ gam print vaultcounts [todrive <ToDriveAttributes>*]
## Vault Exports
## Create Vault Exports
Create a Google Vault export request.
### Create a Google Vault export request using a saved Vault query.
```
gam create vaultexport|export matter <MatterItem> [name <String>] corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(shareddrives|teamdrives (<TeamDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
gam create vaultexport|export matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[driveclientsideencryption any|encrypted|unencrypted]
[includeaccessinfo <Boolean>]
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
[format ics|mbox|pst|xml]
[region any|europe|us] [showdetails|returnidonly]
```
Create a Google Vault export request by specifying the query parameters.
```
gam create vaultexport|export matter <MatterItem> [name <String>]
corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
[scope all_data|held_data|unprocessed_data]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(documentids (<DriveFileIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
[driveversiondate <Date>|<Time>]
[includerooms <Boolean>]
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
[driveversiondate <Date>|<Time>] [includeaccessinfo <Boolean>]
(covereddata calllogs|textmessages|voicemails)*
[<JSONData>]
[driveclientsideencryption any|encrypted|unencrypted]
[includerooms <Boolean>]
[includeaccessinfo <Boolean>]
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
[covereddata calllogs|textmessages|voicemails]
[format ics|mbox|pst|xml]
[region any|europe|us] [showdetails|returnidonly]
```
<MatterItem> specifies the matter name or ID the export should be associated with.
Specify the name of the export:
* `name <String>` - The export will be named `<String>`
* `default` - The export will be named `GAM <corpus> Export - <Time>`
If `name <String>` is omitted, the export will be named `GAM <corpus> Export - <Time>`
## Vault Query options
Specify the corpus of data, this option is required:
* `calendar`
@@ -281,13 +335,15 @@ Specify the corpus of data, this option is required:
Specify the search method, this option is required:
* `accounts <EmailAddressEntity>` - Search all accounts specified in `<EmailAddressEntity>`
* `orgunit|org|ou <OrgUnitPath>` - Search all accounts in the OU `<OrgUnitPath>`
* `everyone` - Search for all accounts in the organization
* `everyone|entireorg` - Search for all accounts in the organization
* `documentids <DriveFileIDList>` - Search for all drive files specified in `<DriveFileIDList>`
* `documentids select <FileSelector>|<CSVFileSelector>` - Search for all drive files specified in `<FileSelector>|<CSVFileSelector>`
* `shareddrives|teamdrives <SharedDriveIDList>` - Search for all accounts in the Shared Drives specified in `<SharedDriveIDList>`
* `shareddrives|teamdrives select <FileSelector>|<CSVFileSelector>` - Search for all accounts in the Shared Drives specified in `<FileSelector>|<CSVFileSelector>`
* `rooms <ChatSpaceList>` - Search in the Room specified in the chat rooms specified in `<ChatSpaceList>`
* `rooms <ChatSpaceList>` - Search in the Room specified in the chat rooms specified in `<FileSelector>|<CSVFileSelector>`
* `sitesurl <URLList>` - Search the published site URLs of new Google Sites in `<URLList>`
* `sitesurl <URLList>` - Search the published site URLs of new Google Sites specified in `<FileSelector>|<CSVFileSelector>`
* `rooms <ChatSpaceList>` - Search in the Room specified in the chat rooms specified in `<ChatSpaceList>`
* `rooms <ChatSpaceList>` - Search in the Room specified in the chat rooms specified in `<FileSelector>|<CSVFileSelector>`
Specify the scope of data to include in the export:
* `all_data` - All available data; this is the default
@@ -320,10 +376,6 @@ For `corpus calendar`, you can specify advanced search options:
* Search the current version of the Calendar event, but export the contents of the last version saved before 12:00 AM UTC on the specified date.
* Enter the date in UTC.
For `corpus calendar`, you can specify the format of the exported data:
* `format ics` - Export in ICS format, this is the default
* `format pst` - Export in PST format
For `corpus drive`, you can specify advanced search options:
* `driveversiondate <Date>|<Time>` - Search the versions of the Drive file as of the reference date. These timestamps are in GMT and rounded down to the given date.
* `includeshareddrives False` - Mapped to `sharedrivesoption included_if_account_is_not_a_member`
@@ -331,6 +383,16 @@ For `corpus drive`, you can specify advanced search options:
* `sharedrivesoption included` - Resources in shared drives are included in the search
* `sharedrivesoption included_if_account_is_not_a_member` - Resources in shared drives where account is not a member are included in the search, this is the default
* `sharedrivesoption not_included` - Resources in shared drives are not included in the search
For `corpus hangouts_chat` you can specify advanced search options:
* `includerooms False` - Do not include rooms, this is the default
* `includerooms True` - Include rooms
You can specify query options with `<JSONData>`.
## Vault Export options
For `corpus drive`, you can specify advanced search options:
* `driveclientsideencryption any` - Include both client-side encrypted and unencrypted content in search, this is the default.
* `driveclientsideencryption encrypted` - Include client-side encrypted content only in search.
* `driveclientsideencryption unencrypted` - Include client-side unencrypted content only in search.
@@ -339,10 +401,6 @@ For `corpus drive`, you can specify whether to include access information for us
* `includeaccessinfo False` - Do not include access information for users with indirect access, this is the default
* `includeaccessinfo True` - Include access information for users with indirect access
For `corpus hangouts_chat` you can specify advanced search options:
* `includerooms False` - Do not include rooms, this is the default
* `includerooms True` - Include rooms
For `corpus mail`, you can specify advanced search options:
* `excludedrafts False` - Do not exclude drafts, this is the default
* `excludedrafts True` - Exclude drafts
@@ -365,18 +423,18 @@ For `corpus mail`, you can specify whether to enable exporting linked Drive file
See: https://support.google.com/vault/answer/4388708#new_gmail_export&zippy=%2Cfebruary-new-gmail-export-system-available
For `corpus calendar`, you can specify the format of the exported data:
* `format ics - Export in ICS format, this is the default
* `format ics` - Export in ICS format, this is the default
* `format pst` - Export in PST format
For `corpus drive`, you can not specify the format of the exported data,
For `corpus gemini`, `format xml` is the only format of the exported data,
For `corpus gemini`, `format xml` is the only supported format of the exported data,
For `corpus groups`, `corpus hangouts_chat`, `corpus mail` and `corpus voice`, you can specify the format of the exported data:
* `format mbox` - Export in MBOX format, this is the default
* `format pst` - Export in PST format
For `corpus voice` you can specify thet data covered by the export:
For `corpus voice` you can specify the data covered by the export, multiple values are allowed.:
* `covereddata calllogs` - Call logs
* `covereddata textmessages` - Voice text messages
* `covereddata voicemail` - Voicemail
@@ -606,13 +664,29 @@ The `shownames` argument controls whether account and org unit names are display
## Vault Holds
## Create Vault Holds
### Create a hold from a saved Vault query.
```
gam create vaulthold|hold matter <MatterItem> [name <String>] corpus calendar|drive|mail|groups|hangouts_chat|voice
gam create vaulthold|hold matter <MatterItem> [name <String>]
vaultquery <QueryItem>
[showdetails|returnidonly]
```
Specify the name of the hold:
* `name <String>` - The hold will be named `<String>`
* `default` - The hold will be named `GAM <corpus> Hold - <Time>`
Use the `showdetails` option to have the full details of the hold displayed.
Use the `returnidonly` option to have only the hold ID displayed.
### Create a hold from parameters.
```
gam create vaulthold|hold matter <MatterItem> [name <String>]
corpus calendar|drive|mail|groups|hangouts_chat|voice
[(accounts|groups|users <EmailItemList>) | (orgunit|org|ou <OrgUnit>)]
[query <QueryVaultCorpus>]
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[includerooms <Boolean>]
[covereddata calllogs|textmessages|voicemails]
(covereddata calllogs|textmessages|voicemails)*
[includeshareddrives <Boolean>]
[showdetails|returnidonly]
```
@@ -638,10 +712,10 @@ For `corpus drive`, you can specify advanced search options:
* `includeshareddrives False` - Files in shared drives are not included in the hold, this is the default
* `includeshareddrives True` - Files in shared drives are included in the hold
For `corpus mail`, you can specify search terms to limit the search.
For `corpus mail|group`, you can specify search terms to limit the search.
* `terms <String>` - [Vault search](https://support.google.com/vault/answer/2474474)
For `corpus mail`, you can specify time limits on the search:
For `corpus mail|group`, you can specify time limits on the search:
* `start|starttime <Date>|<Time>` - The start time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
* `end|endtime <Date>|<Time>` - The end time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
@@ -649,7 +723,8 @@ For `corpus hangouts_chat` you can specify advanced search options:
* `includerooms False` - Do not include rooms, this is the default
* `includerooms True` - Include rooms
For `corpus voice` you can specify the data covered by the hold:
For `corpus voice` you can specify the data covered by the hold,
multiple values are allowed.:
* `covereddata calllogs` - Call logs
* `covereddata textmessages` - Voice text messages
* `covereddata voicemail` - Voicemail
@@ -665,7 +740,7 @@ gam update vaulthold|hold <HoldItem> matter <MatterItem>
[query <QueryVaultCorpus>]
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
[includerooms <Boolean>]
[covereddata calllogs|textmessages|voicemails]
(covereddata calllogs|textmessages|voicemails)*
[includeshareddrives <Boolean>]
[showdetails]
```
@@ -673,10 +748,10 @@ For a hold with `corpus drive`, you can specify advanced search options:
* `includeshareddrives False` - Files in shared drives are not included in the hold, this is the default
* `includeshareddrives True` - Files in shared drives are included in the hold
For a hold with `corpus mail`, you can specify search terms to limit the search.
For a hold with `corpus mail|groups`, you can specify search terms to limit the search.
* `terms <String>` - [Vault search](https://support.google.com/vault/answer/2474474)
For a hold with `corpus mail`, you can specify time limits on the search:
For a hold with `corpus mai|groupsl`, you can specify time limits on the search:
* `start|starttime <Date>|<Time>` - The start time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
* `end|endtime <Date>|<Time>` - The end time range for the search query. These timestamps are in GMT and rounded down to the start of the given date.
@@ -684,7 +759,8 @@ For a hold with `corpus hangouts_chat` you can specify advanced search options:
* `includerooms False` - Do not include rooms, this is the default
* `includerooms True` - Include rooms
For a hold with `corpus voice` you can specify the data covered by the hold:
For a hold with `corpus voice` you can specify the data covered by the hold,
multiple values are allowed.:
* `covereddata calllogs` - Call logs
* `covereddata textmessages` - Voice text messages
* `covereddata voicemail` - Voicemail
@@ -752,6 +828,67 @@ gam <UserTypeEntity> show vaultholds|holds
```
## Vault Saved Queries
## Create Vault Saved Queries
```
gam create vaultquery <MatterItem> [name <String>]
corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
[scope all_data|held_data|unprocessed_data]
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
(documentids (<DriveFileIDList>|(select <FileSelector>|<CSVFileSelector>))) |
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
(sitesurl (<URLList>||(select <FileSelector>|<CSVFileSelector>)))
[driveversiondate <Date>|<Time>]
[includerooms <Boolean>]
(rooms (<ChatSpaceList>|(select <FileSelector>|<CSVFileSelector>))) |
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>] [timezone <TimeZone>]
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
(covereddata calllogs|textmessages|voicemails)*
[<JSONData>]
[shownames]
[showdetails|returnidonly|formatjson]
```
If `name <String>` is omitted, the query is named `GAM <corpus> Query - <Time>`
The `shownames` argument controls whether org unit and shared drive names are displayed in queries; additional API calls are required to get the names.
See: [Vault Query options](#vault-query-options)
Use the `showdetails` option to have the full details of the saved query displayed.
Use the `returnidonly` option to have only the saved query ID displayed.
Use the `formatjson` option to have only the saved query JSON displayed.
## Copy Vault Saved Queries
```
gam copy vaultquery <MatterItem> <QueryItem> [targetmatter <MatterItem>] [name <String>]
[shownames]
[showdetails|returnidonly|formatjson]
```
If `targetmatter <MatterItem>` is omitted, the query is copied in the source matter.
If `name <String>` is omitted:
* `targetmatter <MatterItem>` specified - The copied query has the same name as the source query
* `targetmatter <MatterItem>` omitted - The copied query is named `Copy of Source Query name`
The `shownames` argument controls whether org unit and shared drive names are displayed in queries; additional API calls are required to get the names.
Use the `showdetails` option to have the full details of the saved query displayed.
Use the `returnidonly` option to have only the saved query ID displayed.
Use the `formatjson` option to have only the saved query JSON displayed.
## Delete Vault Saved Queries
```
gam delete vaultquery <QueryItem> matter <MatterItem>
gam delete vaultquery <MatterItem> <QueryItem>
```
## Display Vault Saved Queries
```
gam info vaultquery <QueryItem> matter <MatterItem>
@@ -791,7 +928,7 @@ Select fields to display:
The `shownames` argument controls whether org unit and shared drive names are displayed in queries; additional API calls are required to get the names.
# Takeout
## Takeout
Many thanks to Jay for these commands and documentation.
GAM 6.42.00 and newer support copying and downloading Google Cloud Storage (GCS) buckets generated by [organization-wide Takeout](https://support.google.com/a/answer/100458?hl=en).

View File

@@ -3,10 +3,10 @@
Print the current version of Gam with details
```
gam version
GAM 7.20.01 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.23.07 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final
MacOS Sequoia 15.6.1 x86_64
macOS Tahoe 26.0.1 x86_64
Path: /Users/Admin/bin/gam7
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Time: 2023-06-02T21:10:00-07:00
@@ -15,10 +15,10 @@ Time: 2023-06-02T21:10:00-07:00
Print the current version of Gam with details and time offset information
```
gam version timeoffset
GAM 7.20.01 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.23.07 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final
MacOS Sequoia 15.6.1 x86_64
macOS Tahoe 26.0.1 x86_64
Path: /Users/Admin/bin/gam7
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Your system time differs from www.googleapis.com by less than 1 second
@@ -27,25 +27,29 @@ Your system time differs from www.googleapis.com by less than 1 second
Print the current version of Gam with extended details and SSL information
```
gam version extended
GAM 7.20.01 - https://github.com/GAM-team/GAM - pyinstaller
GAM 7.23.07 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final
MacOS Sequoia 15.6.1 x86_64
macOS Tahoe 26.0.1 x86_64
Path: /Users/Admin/bin/gam7
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Time: 2023-06-02T21:10:00-07:00
Your system time differs from admin.googleapis.com by less than 1 second
OpenSSL 3.5.2 5 ASug 2025
cryptography 43.0.3
filelock 3.16.1
google-api-python-client 2.149.0
OpenSSL 3.5.3 16 Sep 2025
arrow 1.3.0
chardet 5.2.0
cryptography 46.0.1
filelock 3.19.1
google-api-python-client 2.182.0
google-auth-httplib2 0.2.0
google-auth-oauthlib 1.2.1
google-auth 2.35.0
httplib2 0.22.0
google-auth-oauthlib 1.2.2
google-auth 2.40.3
lxml 6.0.1
httplib2 0.31.0
passlib 1.7.4
python-dateutil 2.9.0.post0
yubikey-manager 5.5.1
pathvalidate 3.3.1
pyscard 2.3.0
yubikey-manager 5.8.0
admin.googleapis.com connects using TLSv1.3 TLS_AES_256_GCM_SHA384
```
@@ -64,7 +68,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gam7
Version Check:
Current: 5.35.08
Latest: 7.20.01
Latest: 7.22.00
echo $?
1
```
@@ -72,7 +76,7 @@ echo $?
Print the current version number without details
```
gam version simple
7.20.01
7.22.00
```
In Linux/MacOS you can do:
```
@@ -82,10 +86,10 @@ echo $VER
Print the current version of Gam and address of this Wiki
```
gam help
GAM 7.20.01 - https://github.com/GAM-team/GAM
GAM 7.22.00 - https://github.com/GAM-team/GAM
GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.7 64-bit final
MacOS Sequoia 15.6.1 x86_64
macOS Tahoe 26.0.1 x86_64
Path: /Users/Admin/bin/gam7
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Time: 2023-06-02T21:10:00-07:00

View File

@@ -1,3 +1,5 @@
[FAQ](GAM7-FAQ)
Update History
* [GAM Updates](GamUpdates)
@@ -22,6 +24,7 @@ Configuration
* [Multiple Users-Projects on One Computer](https://github.com/GAM-team/GAM/wiki/gam.cfg#multiple-users-projects-on-one-computer)
* [Running GAM7 securely on a Google Compute Engine](Running-GAM7-securely-on-a-Google-Compute-Engine)
* [Using GAM7 with a delegated admin service account](Using-GAM7-with-a-delegated-admin-service-account)
* [Using GAM7 with keyless authentication - Workload Identity Federation](Using-GAM7-with-keyless-authentication-Workload-Identity-Federation)
* [Using GAM7 with a YubiKey](Using-GAM7-with-a-YubiKey)
* [GAM with minimal GCP rights](GAM-with-minimal-GCP-rights)
@@ -177,30 +180,3 @@ Service Account Access
* [Users - Tasks](Users-Tasks)
* [Users - YouTube](Users-YouTube)
* [Users - Web Resources and Sites](Users-Web-Resources-and-Sites)
GAM Tutorials
* [Account Auditing](l-ExamplesAccountAuditing)
* [Calendar Settings](l-CalendarExamples)
* [Chat Bot commands](Chat-Bot)
* [Chrome Browser Management](l-Chrome-Browser-Management)
* [Chrome Policy Settings](l-Chrome-Policy-Settings)
* [Context Aware Access levels](Context-Aware-Access-Levels)
* [Data Transfers](l-Data-Transfers)
* [Domain Verification](l-DomainVerification)
* [Google Drive Management](l-GoogleDriveManagement)
* [Group Settings](l-GAM3GroupSettings)
* [Inbound SSO Settings](l-Inbound-SSO-Settings)
* [Managing Admins](l-Managing-Admins)
* [Managing Classroom](l-Managing-Google-Classroom)
* [Managing Custom User Schemas](l-Custom-Schemas)
* [Managing Devices](l-Managing-Devices)
* [Managing Organizations](l-ExamplesOrganizations)
* [Managing Product Licenses](l-LicenseExamples)
* [Managing Users, Groups, Aliases, Domains, Mobile and Chrome Devices, and Resource Calendars](l-GAM3DirectoryCommands)
* [OAuth Authentication Related Commands](l-OAuthKeyManagement)
* [Print Users, Groups, Aliases, Mobile and Chrome OS devices, OUs, Licenses and Reports](l-GAM3CSVListings)
* [Printers](l-Printers)
* [Unmanaged Users and Invitations](l-UnmanagedUsersExamples)
* [User Email Settings](l-ExamplesEmailSettings)
* [User Security Settings](l-SecurityExamples)

View File

@@ -109,6 +109,11 @@ charset
Character set of gam batch, gam csv, gam loop files.
Default: utf-8
Environment variable: GAM_CHARSET
chat_max_results
When retrieving lists of Chat items from API,
how many should be retrieved in each API call
Default: 100
Range: 1 - 1000
classroom_max_results
When retrieving lists of Google Classroom items from API,
how many should be retrieved in each API call
@@ -551,8 +556,10 @@ timezone
to your local timezone. If you are running GAM on a remote computer or on a
cloud shell, "local" will mean the time at the remote/cloud shell computer,
not your location, Use "+|-hh:mm" to specify the timezone at your location.
Starting with version 7.21.00 you can use a timezone name.
See: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
Default: utc
Range: utc|Z|local|(+|-hh:mm)
Range: utc|z|local|(+|-hh:mm)I<ValidTimezoneName>
tls_max_version
Allowed values: '', tlsv1_2, tlsv1.2, tlsv1_3, tlsv1.3
The maximum TLS version to use in https connections

View File

@@ -1,54 +0,0 @@
# Intro
GAM can run on a Linux or Windows Google Compute Engine (GCE) VM and use the attached service account to access Google Workspace APIs. The advantage of this configuration is that no service account private key is accessible to GAM directly and there is no risk of the key being stolen/lost. To use GAM on GCE with a service account:
1. Create a [GCP project](https://cloud.google.com/resource-manager/docs/creating-managing-projects).
2. Create [a service account](https://cloud.google.com/iam/docs/creating-managing-service-accounts) which will be used by GAM. Continue steps 2 and 3 without granting the new service account any special access to the project and without granting users access to the service account.
3. Grant the service account rights to generate authentication tokens.
* go to [console.cloud.google.com](https://console.cloud.google.com).
* go to "IAM & Admin" > Service accounts
* click on the service account you created (not the default service account).
* copy the email address of your service account to the clipboard.
* click on the Permissions tab.
* click "Grant Access".
* In the "New principals text box, paste the service account email you copied.
* Give your service account the "Service Account Token Creator" and "View Service Accounts" roles.
4. [Create a Windows or Linux virtual machine](https://cloud.google.com/compute/docs/instances/create-start-instance).
* You can choose a region physically close to you though you may be limited in your choices if you want to use the free tier.
* GAM can run on the minimal `e2-micro` [free tier VM](https://cloud.google.com/free/docs/free-cloud-features#compute) though performance may suffer. If you are performing batch operations, raising the CPU count will help performance. If you have a very large and busy Workspace instance downloading reports or Drive file lists may require more RAM.
* [DO NOT use the default service account](https://cloud.google.com/iam/docs/best-practices-service-accounts#single-purpose). Choose the service account you created above instead.
* GAM does not use a significant amount of storage, unless you have specific storage needs the default disk size should suffice.
* leave other VM instance settings at their defaults unless you know what you are doing.
5. Install GAM on the VM with the command:
```
bash <(curl -s -S -L https://git.io/gam-install) -l
```
the `-l` argument causes GAM to be installed and SKIP the normal setup wizard.
6. Logout and log back in to the VM, you should now be able to run GAM commands like:
```
gam version
```
7. Create the special `oauth2service.json` file GAM will use:
```
gam create signjwtserviceaccount
```
If you'd like, take a look at the generated ```oauth2service.json``` file with:
```
cat ~/bin/gam/oauth2service.json
```
you'll notice that while the file has some fields similar to a normal service account file, there is no `private_key` attribute containing an RSA private key.
8. Enable the Google APIs GAM will use:
```
gam enable apis
```
you are given the option to enable them automatically or manually. Automatic enablement will ask you to authenticate to GAM. You should authenticate as a user with rights to manage project APIs, probably a project owner. If you are not the project owner you can choose manual enablement and GAM will provide two or more URLs which you can send to the project owner. When the owner opens these URLs, they'll be prompted to enable all the APIs GAM needs.
9. GAM is now installed, the last steps are to grant GAM permissions to your Google Workspace domain.
* If you want to manage user data, run ```gam user you@example.com check serviceaccount``` and follow the instructions to perform domain-wide delegation.
* If you want to perform admin actions (manage users, groups, etc) [you can configure delegated admin service account (DASA)](https://github.com/GAM-team/GAM/wiki/Using-GAM-with-a-delegated-admin-service-account-(DASA)).

View File

@@ -1,49 +0,0 @@
## Description
GAM supports using a [YubiKey](https://www.yubico.com/products/yubikey-5-overview/) to generate and store the service account's private RSA key. Private keys generated by the YubiKey cannot be exported even to the computer running GAM. When compared to the plain text oauth2service.json file with the private key stored in text, the YubiKey offers a more secure option that prevents digital theft and copying of the private key. Instead of reading the private key from the oauth2service.json file and signing requests itself, GAM will simply send signing requests to the YubiKey and get back the signature.
## FAQs
### Can I use a Google Titan or other brand security key?
No, while Titan keys are great as security keys / U2F / 2SV, that is not the protocol being used by GAM here. GAM uses the PIV app of YubiKeys to work with service accounts. You need to use [a genuine Yubikey.](https://yubico.com/genuine/).
### Does this protect the admin credentials GAM stores in oauth2.txt?
No, the admin credentials GAM stores in oauth2.txt are not protected by the YubiKey as they are not using RSA private keys. Only the service account credentials normally stored in oauth2service.json are protected. The service account credentials are used for domain-wide delegation operations like managing Workspace user data in Drive, Gmail and Calendar. Note that GAM also has the ability to perform admin actions as a delegated admin service account (DASA). See [instructions for setting up DASA](https://github.com/GAM-team/GAM/wiki/Using-GAM-with-a-delegated-admin-service-account-(DASA)) when DASA is setup, GAM will use the service account to authenticate which can be protected by the YubiKey.
### What if someone physically steals the YubiKey?
The YubiKey can be configured with a PIN that must be entered in order for it to sign data with the private key. GAM stores this PIN string in the oauth2service.json file so it can use it as needed. What this means is that an attacker would need to steal *both* the physical YubiKey and the PIN stored in oauth2service.json. The recommendation is to store oauth2service.json and the rest of the GAM directory on an encrypted partition. The YubiKey itself should also be kept in a secure location.
### Can I require a physical touch of the YubiKey before the private key can be used?
Yes but in practice this does not work very well with GAM. The YubiKey will need to be touched every time there is a GAM command running which for batch or cron jobs may be constant. GAM can use a PIN configured on the YubiKey in order to offer an additional layer of protection.
### If I use a YubiKey, do I need to rotate the private key regularly?
No, because the YubiKey generated the private key it cannot be digitally exported from the YubiKey so there is not chance for it to be copied and stolen. Instead you should physically secure the YubiKey from theft.
### What data does the service account private key have access to?
When using domain-wide delegation with GAM, the service account and anyone possessing the service account private key oauth2service.json file has access to the Gmail, Drive and Calendar data of ALL Workspace users in your domain. For this reason, whether using a YubiKey or not, you should take strong measures to protect the service account private key.
## Setup Steps
1. Upgrade to at least GAM 6.07. Best practice is to always use the [latest version of GAM](https://github.com/GAM-team/GAM).
2. Setup GAM according to the [Quick Start Guide](https://github.com/GAM-team/GAM#quick-start). Once setup you will have a service account created and it's private key credentials in the oauth2service.json file.
3. **If you are using a new YubiKey or don't care about the PIV app data on the YubiKey**
1. Tell GAM to reset and configure the PIV app data on the YubiKey. This wipes all existing keys and config and then configures a private key and PIN for GAM. Run:
```gam yubikey reset_piv```
2. During the PIV reset, GAM will print out a PIN for the private key, record this key.
4. **OR If you are already using the YubiKey and wish to preserve the PIV app data and keys**
1. You need to configure one of the PIV slots for a private key and certificate GAM can use. The full steps here are beyond this guide's scope but might include:
```
ykman piv keys generate -P some_pin --pin-policy ALWAYS --touch-policy NEVER --algorithm RSA2048 9c new_pubkey.txt
ykman piv certificates generate -P some_pin --subject "GAM Service Account" -d 36500 9c new_pubkey.txt
```
5. Now that you have a private key on your YubiKey, tell GAM to use that instead of the private_key stored in oauth2service.json. We can do that by rotating the key:
```
gam rotate sakey yubikey yubikey_pin yubikey_slot AUTHENTICATION
```
The yubikey argument tells GAM to use a private key on a plugged in YubiKey. The yubikey_pin argument tells GAM to prompt you to input the PIN that was set in the previous step. The yubikey_slot argument tells GAM which PIV slot to use on the YubiKey.
6. Now you should be able to run GAM commands like:
```
gam user admin@example.com check serviceaccount
```
and see the YubiKey lights flash as the YubiKey interacts with GAM to sign the GAM authentication requests. If you look at the oauth2service.json file, you'll see it contains some new fields like yubikey_serial and yubikey_pin but no longer contains the private_key field where GAM would normally store the private key data.
7. As a last step, since YubiKey-stored private keys do not need to be and should not be rotated, you can remove the service account's permissions to change it's own key. Navigate to the [Cloud Console](https://console.cloud.google.com/iam-admin/serviceaccounts) select the correct project and service account and on the Permissions tab, edit and remove the "Service Account Key Admin" permission that the service account has to itself.

Some files were not shown because too many files have changed in this diff Show More