Compare commits

...

116 Commits

Author SHA1 Message Date
Ross Scroggs
35fde0e48b Suppress missing credential file warnings on basic commands
gam checkconn
gam oauth|oauth2
gam version
2026-03-06 17:39:00 -08:00
Jay Lee
7c5e79f309 Update get-cacerts.yml 2026-03-06 13:47:27 -05:00
Jay Lee
71bac7c2eb Update build.yml
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 x86_64 macOS 26, macos-26-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Intel Windows, windows-2025-vs2026) (push) Has been cancelled
Build and test GAM / build (false, build, 14, 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, 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, 15, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 18, Test Python 3.13, ubuntu-24.04, 3.13) (push) Has been cancelled
Build and test GAM / build (false, test, 19, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 20, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-03-05 17:16:03 -05:00
Jay Lee
539b91a27e Update build.yml 2026-03-05 16:21:49 -05:00
Jay Lee
d71bf9b6cb [no ci] actions: only update VS when we are compiling OpenSSL/Python 2026-03-05 15:45:34 -05:00
Jay Lee
0c2fdeee6b Update build.yml 2026-03-05 15:44:00 -05:00
Jay Lee
33df3132b8 Update build.yml 2026-03-05 15:30:09 -05:00
Jay Lee
118e1e3ff5 Update build.yml 2026-03-05 15:22:28 -05:00
Jay Lee
2fdab61fc8 Update build.yml 2026-03-05 15:14:57 -05:00
Jay Lee
a883bf721f Update build.yml 2026-03-05 15:02:50 -05:00
Jay Lee
ca20bcbda0 Attempt to build win ARM64 Python with PGO 2026-03-05 13:29:05 -05:00
Jay Lee
a927dda9aa Update build.yml
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 x86_64 macOS 26, macos-26-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Intel Windows, windows-2025-vs2026) (push) Has been cancelled
Build and test GAM / build (false, build, 14, 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, 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, 15, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 18, Test Python 3.13, ubuntu-24.04, 3.13) (push) Has been cancelled
Build and test GAM / build (false, test, 19, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 20, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-03-05 11:52:49 -05:00
Jay Lee
a2d80cac46 Update build.yml 2026-03-05 10:44:08 -05:00
Jay Lee
fcf2712f3f [no ci] use native screenshoting 2026-03-05 10:25:17 -05:00
Jay Lee
8dc2b4bd64 [no ci] actions: remove dead code and deprecated screenshot tool 2026-03-05 10:22:12 -05:00
Jay Lee
679019fc3c Update build.yml 2026-03-05 10:09:12 -05:00
Jay Lee
c4da8110a3 actions: use PS_PYTHON_INSTALL_PATH 2026-03-05 10:04:29 -05:00
Jay Lee
7bcd0611c2 Update build.yml 2026-03-05 09:04:40 -05:00
Jay Lee
485cbb65bb Update build.yml
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 x86_64 macOS 26, macos-26-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Intel Windows, windows-2025-vs2026) (push) Has been cancelled
Build and test GAM / build (false, build, 14, 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, 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, 15, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 18, Test Python 3.13, ubuntu-24.04, 3.13) (push) Has been cancelled
Build and test GAM / build (false, test, 19, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 20, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-03-04 21:31:24 -05:00
Jay Lee
29a2e224bc Update build.yml 2026-03-04 20:51:43 -05:00
Ross Scroggs
ac25dd6557 Merge branch 'main' of https://github.com/GAM-team/GAM
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 x86_64 macOS 26, macos-26-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Intel Windows, windows-2025-vs2026) (push) Has been cancelled
Build and test GAM / build (false, build, 14, 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, 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, 15, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 18, Test Python 3.13, ubuntu-24.04, 3.13) (push) Has been cancelled
Build and test GAM / build (false, test, 19, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 20, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-03-04 17:39:20 -08:00
Ross Scroggs
673effa9f8 Update macOS version 2026-03-04 17:39:16 -08:00
Jay Lee
a936a5fa3d Update ssd.mjs 2026-03-04 20:28:03 -05:00
Jay Lee
a1b073cbdd Update ssd.mjs 2026-03-04 19:54:28 -05:00
Jay Lee
093015c617 Update ssd.mjs 2026-03-04 19:34:19 -05:00
Jay Lee
2bee44f7e9 Update ssd.mjs 2026-03-04 19:18:46 -05:00
Jay Lee
645155a2ea Update build.yml 2026-03-04 19:06:10 -05:00
Jay Lee
da2298ae23 Update build.yml 2026-03-04 18:52:50 -05:00
Jay Lee
02188e9c49 Update build.yml 2026-03-04 18:38:21 -05:00
Jay Lee
28b5ab34c3 Update build.yml 2026-03-04 17:52:58 -05:00
Jay Lee
b338e2da2f Update build.yml 2026-03-04 17:40:59 -05:00
Jay Lee
b1af32e487 Update ssd.mjs 2026-03-04 17:19:32 -05:00
Jay Lee
a32cc146ef [no ci] Update build.yml 2026-03-04 17:18:10 -05:00
Jay Lee
1ed1d8552b Update ssd.mjs 2026-03-04 17:02:08 -05:00
Jay Lee
4f58f7c967 [no ci] Update build.yml 2026-03-04 17:01:38 -05:00
Jay Lee
c41b94487e Update ssd.mjs 2026-03-04 16:52:29 -05:00
Jay Lee
7f95020e6f Update ssd.mjs 2026-03-04 16:40:50 -05:00
Jay Lee
9181a35c10 Update build.yml 2026-03-04 16:30:32 -05:00
Jay Lee
c95997e2d5 Archive PNG artifacts in build workflow
Add step to archive PNG artifacts on Windows.
2026-03-04 16:21:06 -05:00
Jay Lee
9348f57141 Update ssd.mjs 2026-03-04 16:10:37 -05:00
Jay Lee
dab6272d55 Refactor SSD app automation with PowerShell integration
Refactor Simply Sign Desktop app automation script to use native PowerShell for keystrokes and screenshots. Remove deprecated methods and improve error handling.
2026-03-04 15:58:17 -05:00
Jay Lee
f548d49e19 [no ci] actions: Comment out WinAppDriver and Appium installation steps
Comment out steps related to WinAppDriver installation and Appium setup.
2026-03-04 15:56:55 -05:00
Jay Lee
081965fa79 Implement performKeys function to handle key actions
Replaced the deprecated driver.sendKeys() method with a new helper function that uses the deprecated method due to WinAppDriver limitations.
2026-03-04 15:20:16 -05:00
Jay Lee
bcef6f9391 actions: Implement performKeys helper to replace sendKeys
Replaced deprecated driver.sendKeys() calls with a new helper function performKeys() for better key action handling.
2026-03-04 14:44:32 -05:00
Ross Scroggs
dfb4c88b69 Update GamUpdates.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 x86_64 macOS 26, macos-26-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Intel Windows, windows-2025-vs2026) (push) Has been cancelled
Build and test GAM / build (false, build, 14, 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, 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, 15, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 18, Test Python 3.13, ubuntu-24.04, 3.13) (push) Has been cancelled
Build and test GAM / build (false, test, 19, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 20, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-03-03 20:39:10 -08:00
Ross Scroggs
f10fca04c9 Windows MSI installer replaced with EXE installer 2026-03-03 20:35:06 -08:00
Ross Scroggs
096eef3f59 Update GamUpdates.md 2026-03-03 20:12:07 -08:00
Ross Scroggs
f9cd2f56d6 Update GamUpdates.md 2026-03-03 19:40:35 -08:00
Ross Scroggs
91559239ca Updated cacerts.pem 2026-03-03 19:15:35 -08:00
Ross Scroggs
a00256ee9f Updated cacerts.pem 2026-03-03 19:15:10 -08:00
Jay Lee
970697ec65 Remove curl command from build.yml
Removed unnecessary curl command from build workflow.
2026-03-03 21:39:27 -05:00
GitHub Action
06d131ec55 [ci skip] Updated cacerts.pem 2026-03-04 02:26:25 +00:00
Jay Lee
094616e482 Change runner to ubuntu-slim and update output file name 2026-03-03 21:25:57 -05:00
Jay Lee
cbfae9226a Enhance get-cacerts workflow for custom CA bundle
Updated the workflow to generate a custom certificate authority bundle using Let's Encrypt and Google roots.
2026-03-03 21:22:19 -05:00
Jay Lee
c35cdcf4c3 Also show cert SAN
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 x86_64 macOS 26, macos-26-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Intel Windows, windows-2025-vs2026) (push) Has been cancelled
Build and test GAM / build (false, build, 14, 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, 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, 15, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 18, Test Python 3.13, ubuntu-24.04, 3.13) (push) Has been cancelled
Build and test GAM / build (false, test, 19, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 20, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-03-03 19:57:31 -05:00
Jay Lee
d87ece177d further checkconn diagnostics data 2026-03-03 19:46:50 -05:00
Jay Lee
41535666b6 Add curl command to build workflow 2026-03-03 19:30:56 -05:00
Jay Lee
20d1b18009 Offer more specific cert errors on checkconn 2026-03-03 23:57:27 +00:00
Jay Lee
c27e48dd5c Update Python versions in build workflow 2026-03-03 17:04:37 -05:00
Jay Lee
44fe8a22e0 Refactor ISCC command for better readability 2026-03-03 16:27:03 -05:00
Jay Lee
21df315887 Update executable output path in build workflow
Change the output path for the executable files after signing.
2026-03-03 16:10:23 -05:00
Jay Lee
3a7c470e6e Refactor build workflow for executable handling
Updated the build workflow to move executable files and adjust artifact paths.
2026-03-03 15:45:02 -05:00
Jay Lee
22feec5136 Update paths for gam executable in build workflow 2026-03-03 15:19:53 -05:00
Jay Lee
a30f8c325f [no ci] Update output filename and architecture settings 2026-03-03 15:18:06 -05:00
Jay Lee
0770c20992 Update signing command in build workflow 2026-03-03 15:00:29 -05:00
Jay Lee
cc7fb0df7b Fix syntax for iscc command in build.yml 2026-03-03 14:44:43 -05:00
Jay Lee
fec061c250 Refactor Inno Setup command to use variable for signtool 2026-03-03 14:22:28 -05:00
Jay Lee
aef3b23061 fix quoting on $f 2026-03-03 14:04:27 -05:00
Jay Lee
3518fc8ad3 Replace MSI packaging with EXE packaging using Inno Setup #1886 2026-03-03 13:31:05 -05:00
Jay Lee
e5dab74336 Add initial Inno Setup script for GAM installer #1886 2026-03-03 13:20:03 -05:00
Jay Lee
3aef51781e Update InstallerVersion in gam.wxs to 500. Fixes #1885
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 x86_64 macOS 26, macos-26-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Intel Windows, windows-2025-vs2026) (push) Has been cancelled
Build and test GAM / build (false, build, 14, 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, 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, 15, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 18, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 19, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-03-02 18:49:09 -05:00
Ross Scroggs
23deb2526c Fixed bug in gam info policies <CIPolicyNameEntity> ... formatjson 2026-03-02 11:13:01 -08:00
Ross Scroggs
1a77bbf706 Merge branch 'main' of https://github.com/GAM-team/GAM 2026-03-02 11:11:37 -08:00
Ross Scroggs
40b8e58266 Fixed bug in gam info policies <CIPolicyNameEntity> ... formatjson 2026-03-02 11:11:33 -08:00
Jay Lee
733110120a Add support for Python 3.14 in classifiers
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 x86_64 macOS 26, macos-26-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Intel Windows, windows-2025-vs2026) (push) Has been cancelled
Build and test GAM / build (false, build, 14, 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, 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, 15, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 18, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 19, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-03-02 09:45:07 -05:00
Ross Scroggs
68b8c9108d Update Chrome-Printers.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 x86_64 macOS 26, macos-26-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Intel Windows, windows-2025-vs2026) (push) Has been cancelled
Build and test GAM / build (false, build, 14, 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, 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, 15, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 18, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 19, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-03-01 21:08:06 -08:00
Ross Scroggs
9ddeaba79b Update Chrome-Printers.md 2026-03-01 21:06:23 -08:00
Ross Scroggs
582c1e4fa2 Added option returnidonly to gam create|update printer 2026-03-01 20:55:18 -08:00
Ross Scroggs
28383c1391 Added option returnidonly to gam create|update printer 2026-03-01 19:52:51 -08:00
Jay Lee
7ab959f27c Fix command for printing user invitations in build.yml 2026-03-01 20:16:29 -05:00
Jay Lee
a877ca6139 Fix command syntax in build.yml for GAM commands 2026-03-01 20:00:28 -05:00
Jay Lee
33da8016a2 Update file paths in build.yml for GAM commands 2026-03-01 19:57:15 -05:00
Jay Lee
36b2849f20 Refactor gam command execution in build workflow 2026-03-01 19:40:52 -05:00
Jay Lee
377201614b Fix command substitution syntax in build.yml
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 x86_64 macOS 26, macos-26-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Intel Windows, windows-2025-vs2026) (push) Has been cancelled
Build and test GAM / build (false, build, 14, 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, 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, 15, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 18, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 19, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-03-01 19:05:30 -05:00
Jay Lee
ff11bf33d1 Fix command syntax for gam user query 2026-03-01 18:47:32 -05:00
Jay Lee
59463dcc9a Fix variable assignment syntax in build.yml 2026-03-01 18:35:34 -05:00
Jay Lee
23b5eb6fd6 Replace 'run_gam' with '$gam' in build.yml 2026-03-01 18:24:38 -05:00
Jay Lee
8f4aa19f13 Refactor GAM commands to use variable syntax 2026-03-01 18:01:25 -05:00
Jay Lee
6410691c0e Refactor GAM command execution and update workflows
Refactor GAM command executions to use a function for better readability and maintainability. Update artifact handling and VirusTotal scan steps.
2026-03-01 17:34:50 -05:00
Jay Lee
1ad1f9b96c Update artifact download and scan paths in build.yml 2026-03-01 12:43:30 -05:00
Ross Scroggs
636e8dd11e Updated gam-install.sh script for macOS/Linux #1883
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 x86_64 macOS 26, macos-26-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Intel Windows, windows-2025-vs2026) (push) Has been cancelled
Build and test GAM / build (false, build, 14, 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, 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, 15, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 18, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 19, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-02-27 18:18:43 -08:00
Ross Scroggs
caeab48dda Updated gam-install.sh script for macOS/Linux #1883
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 x86_64 macOS 26, macos-26-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Intel Windows, windows-2025-vs2026) (push) Has been cancelled
Build and test GAM / build (false, build, 14, 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, 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, 15, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 18, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 19, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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 / publish (push) Has been cancelled
2026-02-27 18:18:19 -08:00
Ross Scroggs
1364991e5d Fixed formatjson quotechar <Character> bug 2026-02-27 15:57:13 -08:00
Ross Scroggs
6bdea8fa54 Fixed formatjson quotechar <Character> bug 2026-02-27 15:56:55 -08:00
Ross Scroggs
da24220d87 Update Organizational-Units.md 2026-02-27 10:57:00 -08:00
Ross Scroggs
a7d537ebe2 Update Organizational-Units.md 2026-02-27 10:55:43 -08:00
Jay Lee
74b285959c actions: Add macOS 26 Intel, rebuild cache
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 x86_64 macOS 26, macos-26-intel) (push) Has been cancelled
Build and test GAM / build (false, build, 12, Build Arm MacOS 26, macos-26) (push) Has been cancelled
Build and test GAM / build (false, build, 13, Build Intel Windows, windows-2025-vs2026) (push) Has been cancelled
Build and test GAM / build (false, build, 14, 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, 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, 15, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (false, test, 16, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (false, test, 17, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (false, test, 18, Test Python 3.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 19, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-02-27 05:48:39 -05:00
Jay Lee
c138bc44f0 [no ci] actions: more info about Python builds. 2026-02-27 05:31:25 -05:00
Jay Lee
13f56afcd2 [no ci] actions: archive types based on OS
Updated conditions for artifact archiving based on OS.
2026-02-27 05:23:27 -05:00
Jay Lee
ba8242f480 Change job dependency from 'merge' to 'build' 2026-02-27 04:39:00 -05:00
Jay Lee
01985d4381 actions: Refactor artifact archiving in build workflow 2026-02-27 04:37:35 -05:00
Jay Lee
77511b79c9 actions: use newer action versions 2026-02-27 04:07:31 -05:00
Ross Scroggs
06f653db8f Update Users-Photo.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-vs2026) (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, 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.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-02-26 13:37:47 -08:00
Ross Scroggs
cea2099537 Updated gam <UserTypeEntity> update photo 2026-02-26 12:27:13 -08:00
Ross Scroggs
67a6d3f4de Updated gam <UserTypeEntity> update photo 2026-02-26 12:26:51 -08:00
Ross Scroggs
7987a94aab Update Users-Photo.md 2026-02-26 11:42:20 -08:00
Ross Scroggs
e6494b6747 Update Users-Photo.md 2026-02-26 11:40:42 -08:00
Ross Scroggs
401f5095e1 Update Users-Photo.md 2026-02-26 11:37:57 -08:00
Ross Scroggs
93323d12d3 Rebuild to avoid chardet induced error
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-vs2026) (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, 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.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-02-24 18:26:01 -08:00
Ross Scroggs
c3e23fabf1 Update pyproject.toml 2026-02-24 17:22:59 -08:00
Ross Scroggs
95eb36c5c2 Update to avoid requests error 2026-02-24 15:56:30 -08:00
Ross Scroggs
17105d51f1 Initial guest user support 2026-02-24 15:45:47 -08:00
Ross Scroggs
8dbc455407 Initial guest user support 2026-02-24 14:45:03 -08:00
Ross Scroggs
7e7b8416a4 Define guest user fields 2026-02-24 14:10:49 -08:00
Ross Scroggs
ed81501bf2 Define guest user fields
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-vs2026) (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, 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.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-02-24 14:10:13 -08:00
Ross Scroggs
428f8f5987 Added option copyfolderpermissions [<Boolean>] to gam <UserTypeEntity> copy|move drivefile
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-vs2026) (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, 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.15-dev, ubuntu-24.04, 3.15-dev) (push) Has been cancelled
Build and test GAM / build (true, test, 18, Test Python 3.14 freethread, ubuntu-24.04, 3.14) (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
2026-02-20 13:54:34 -08:00
23 changed files with 1051 additions and 519 deletions

View File

@@ -86,18 +86,23 @@ jobs:
freethreaded: false freethreaded: false
goal: build goal: build
name: Build x86_64 macOS 15 name: Build x86_64 macOS 15
- os: macos-26 - os: macos-26-intel
jid: 11 jid: 11
freethreaded: false freethreaded: false
goal: build goal: build
name: Build x86_64 macOS 26
- os: macos-26
jid: 12
freethreaded: false
goal: build
name: Build Arm MacOS 26 name: Build Arm MacOS 26
- os: windows-2025-vs2026 - os: windows-2025-vs2026
jid: 12 jid: 13
freethreaded: false freethreaded: false
goal: build goal: build
name: Build Intel Windows name: Build Intel Windows
- os: windows-11-arm - os: windows-11-arm
jid: 13 jid: 14
freethreaded: false freethreaded: false
goal: build goal: build
name: Build Arm Windows name: Build Arm Windows
@@ -105,36 +110,42 @@ jobs:
goal: test goal: test
python: "3.10" python: "3.10"
freethreaded: false freethreaded: false
jid: 14 jid: 15
name: Test Python 3.10 name: Test Python 3.10
- os: ubuntu-24.04 - os: ubuntu-24.04
goal: test goal: test
python: "3.11" python: "3.11"
freethreaded: false freethreaded: false
jid: 15 jid: 16
name: Test Python 3.11 name: Test Python 3.11
- os: ubuntu-24.04 - os: ubuntu-24.04
goal: test goal: test
python: "3.12" python: "3.12"
freethreaded: false freethreaded: false
jid: 16 jid: 17
name: Test Python 3.12 name: Test Python 3.12
- os: ubuntu-24.04
goal: test
python: "3.13"
freethreaded: false
jid: 18
name: Test Python 3.13
- os: ubuntu-24.04 - os: ubuntu-24.04
goal: test goal: test
python: "3.15-dev" python: "3.15-dev"
freethreaded: false freethreaded: false
jid: 17 jid: 19
name: Test Python 3.15-dev name: Test Python 3.15-dev
- os: ubuntu-24.04 - os: ubuntu-24.04
goal: test goal: test
python: "3.14" python: "3.14"
freethreaded: true freethreaded: true
jid: 18 jid: 20
name: Test Python 3.14 freethread name: Test Python 3.14 freethread
steps: steps:
- uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v5.0.0 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
fetch-depth: 0 fetch-depth: 0
@@ -148,12 +159,12 @@ jobs:
- name: Cache multiple paths - name: Cache multiple paths
if: matrix.goal == 'build' if: matrix.goal == 'build'
uses: actions/cache@638ed79f9dc94c1de1baef91bcab5edaa19451f4 # v4.2.4 uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
id: cache-python-ssl id: cache-python-ssl
with: with:
path: | path: |
cache.tar.xz cache.tar.xz
key: gam-${{ matrix.jid }}-20260213 key: gam-${{ matrix.jid }}-20260227
- name: Untar Cache archive - name: Untar Cache archive
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true' if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true'
@@ -163,7 +174,7 @@ jobs:
- name: Use pre-compiled Python for testing - name: Use pre-compiled Python for testing
if: matrix.python != '' if: matrix.python != ''
uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6.0.0 uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
with: with:
python-version: ${{ matrix.python }} python-version: ${{ matrix.python }}
allow-prereleases: true allow-prereleases: true
@@ -247,7 +258,7 @@ jobs:
- name: MacOS import developer certificates for signing - name: MacOS import developer certificates for signing
if: runner.os == 'macOS' if: runner.os == 'macOS'
uses: apple-actions/import-codesign-certs@11e1bb2d3771ad8ffa8459dfe527bc26b2dd4b62 # v5.0.3 uses: apple-actions/import-codesign-certs@b610f78488812c1e56b20e6df63ec42d833f2d14 # v6.0.0
with: with:
p12-file-base64: ${{ secrets.CERTIFICATES_P12 }} p12-file-base64: ${{ secrets.CERTIFICATES_P12 }}
p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }} p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }}
@@ -291,8 +302,9 @@ jobs:
fi fi
PYEXTERNALS_PATH=$(cygpath -u "${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_ARCH}") PYEXTERNALS_PATH=$(cygpath -u "${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_ARCH}")
LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${PYEXTERNALS_PATH}" LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:${PYEXTERNALS_PATH}"
echo "PYTHON=${PYTHON_SOURCE_PATH}/PCbuild/${PYEXTERNALS_ARCH}/python.exe" >> $GITHUB_ENV echo "PYTHON=${PYTHON_INSTALL_PATH}\python.exe" >> $GITHUB_ENV
echo "WIX_ARCH=${WIX_ARCH}" >> $GITHUB_ENV echo "WIX_ARCH=${WIX_ARCH}" >> $GITHUB_ENV
echo "PS_PYTHON_INSTALL_PATH=$(cygpath -w $PYTHON_INSTALL_PATH)" >> $GITHUB_ENV
fi fi
echo "We'll run make with: ${MAKEOPT}" echo "We'll run make with: ${MAKEOPT}"
echo "staticx=${staticx}" >> $GITHUB_ENV echo "staticx=${staticx}" >> $GITHUB_ENV
@@ -435,7 +447,7 @@ jobs:
pip install --upgrade sphinx pip install --upgrade sphinx
sphinx-build --version sphinx-build --version
- name: Windows Config/Build Python - name: Windows Config/Build/Install Python
if: matrix.goal == 'build' && runner.os == 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true' if: matrix.goal == 'build' && runner.os == 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true'
shell: powershell shell: powershell
run: | run: |
@@ -444,13 +456,16 @@ jobs:
Copy-Item -Path "${env:GITHUB_WORKSPACE}\src\tools\openssl.props" -Destination PCBuild\ -Verbose Copy-Item -Path "${env:GITHUB_WORKSPACE}\src\tools\openssl.props" -Destination PCBuild\ -Verbose
if (${env:RUNNER_ARCH} -eq "X64") { if (${env:RUNNER_ARCH} -eq "X64") {
$env:arch = "x64" $env:arch = "x64"
PCBuild\build.bat -c Release -p $env:arch --pgo #PCBuild\build.bat -c Release -p $env:arch --pgo
} elseif (${env:RUNNER_ARCH} -eq "ARM64") { } elseif (${env:RUNNER_ARCH} -eq "ARM64") {
$env:arch = "ARM64" $env:arch = "ARM64"
# TODO: figure out why Windows ARM64 isn't compat with PGO optimiazation # TODO: figure out why Windows ARM64 isn't compat with PGO optimiazation
# causes 10-20% slowdown in Python # causes 10-20% slowdown in Python
PCBuild\build.bat -c Release -p $env:arch #PCBuild\build.bat -c Release -p $env:arch
} }
PCBuild\build.bat -c Release -p $env:arch --pgo
.\python.bat PC\layout --precompile --preset-default --copy $env:PS_PYTHON_INSTALL_PATH
Get-ChildItem -Path $env:PS_PYTHON_INSTALL_PATH -File
- name: Mac/Linux Build Python - name: Mac/Linux Build Python
if: matrix.goal == 'build' && runner.os != 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true' if: matrix.goal == 'build' && runner.os != 'Windows' && steps.cache-python-ssl.outputs.cache-hit != 'true'
@@ -471,7 +486,7 @@ jobs:
- name: Run Python - name: Run Python
run: | run: |
"${PYTHON}" -V "${PYTHON}" -VV
"${PYTHON}" -c "import ssl; print(f'Using {ssl.OPENSSL_VERSION}')" "${PYTHON}" -c "import ssl; print(f'Using {ssl.OPENSSL_VERSION}')"
- name: Create and use Python venv - name: Create and use Python venv
@@ -656,28 +671,27 @@ jobs:
echo "GAM Version ${GAMVERSION}" echo "GAM Version ${GAMVERSION}"
echo "GAMVERSION=${GAMVERSION}" >> $GITHUB_ENV echo "GAMVERSION=${GAMVERSION}" >> $GITHUB_ENV
- name: Install WinAppDriver - name: Initialize Windows Desktop Shell
if: runner.os == 'Windows'
shell: pwsh
run: |
Write-Host "Checking for Windows Explorer shell..."
if (-not (Get-Process -Name explorer -ErrorAction SilentlyContinue)) {
Write-Host "Explorer not found. Booting the desktop shell..."
Start-Process explorer.exe
# Give the desktop a few seconds to fully render the taskbar
Start-Sleep -Seconds 10
} else {
Write-Host "Explorer is already running."
}
- name: Install NPM deps
if: runner.os == 'Windows' if: runner.os == 'Windows'
run: | run: |
choco install -y winappdriver #echo "Installing appium..."
#npm install -g appium
- name: Enabled dev mode for WinAppDriver
if: runner.os == 'Windows'
shell: cmd
run : |
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" /t REG_DWORD /f /v "AllowDevelopmentWithoutDevLicense" /d "1"
- name: Install appium and totp tools
if: runner.os == 'Windows'
run: |
echo "Installing appium..."
npm install -g appium
echo "Installing totp-generator..." echo "Installing totp-generator..."
npm install "totp-generator" npm install totp-generator
echo "Installing wdio..."
npm install @wdio/cli
echo "Installing appium win driver..."
appium driver install windows
- name: Install Certum MSI - name: Install Certum MSI
if: runner.os == 'Windows' if: runner.os == 'Windows'
@@ -699,18 +713,21 @@ jobs:
env: env:
TOTP_SECRET: ${{ secrets.TOTP_SECRET }} TOTP_SECRET: ${{ secrets.TOTP_SECRET }}
run: | run: |
# disable win private firewall that interferes with appium server
Set-NetFirewallProfile -Profile Private -Enabled False
$appiumCmd = Get-Command appium
$appiumPath = $appiumCmd.Path
Start-Process -Filepath "powershell.exe" -ArgumentList "-File", $appiumPath, "--address", "127.0.0.1", "--log-level", "error"
Start-Sleep -Seconds 10
write-host "appium started"
write-host "running SimplySignDesktop login..." write-host "running SimplySignDesktop login..."
node tools/ssd.mjs --log-level warn node tools/ssd.mjs --log-level warn
write-host "sleeping during login..." write-host "sleeping during login..."
Start-Sleep 10 Start-Sleep 10
- name: Archive png artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 7.0.0
if: runner.os == 'Windows'
with:
archive: true
name: images-${{ matrix.os }}
if-no-files-found: ignore
path: |
*.png
- name: Sign gam.exe - name: Sign gam.exe
if: runner.os == 'Windows' if: runner.os == 'Windows'
shell: pwsh shell: pwsh
@@ -732,7 +749,7 @@ jobs:
$gam create signjwtserviceaccount $gam create signjwtserviceaccount
- name: Attest gam executable was generated from this Action - name: Attest gam executable was generated from this Action
uses: actions/attest-build-provenance@0b6e9809265278d02c58acf52849a95818a5a306 # v3.0.0 uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
if: matrix.goal == 'build' if: matrix.goal == 'build'
with: with:
subject-path: ${{ env.gam }} subject-path: ${{ env.gam }}
@@ -753,11 +770,6 @@ jobs:
echo "GAM Archive ${GAM_ARCHIVE}" echo "GAM Archive ${GAM_ARCHIVE}"
tar -C "${gampath}/.." --create --verbose --exclude-from "${GITHUB_WORKSPACE}/.github/actions/package_exclusions.txt" --file $GAM_ARCHIVE --xz gam7 tar -C "${gampath}/.." --create --verbose --exclude-from "${GITHUB_WORKSPACE}/.github/actions/package_exclusions.txt" --file $GAM_ARCHIVE --xz gam7
- name: Install Wix on Win ARM64
if: runner.os == 'Windows' && runner.arch == 'ARM64'
run: |
choco install wixtoolset
- name: Windows package zip - name: Windows package zip
if: runner.os == 'Windows' && matrix.goal != 'test' if: runner.os == 'Windows' && matrix.goal != 'test'
run: | run: |
@@ -767,54 +779,52 @@ jobs:
GAM_ARCHIVE="${GITHUB_WORKSPACE}/gam-${GAMVERSION}-windows-${arch}.zip" GAM_ARCHIVE="${GITHUB_WORKSPACE}/gam-${GAMVERSION}-windows-${arch}.zip"
/c/Program\ Files/7-Zip/7z.exe a -tzip "$GAM_ARCHIVE" gam7 "-xr@${GITHUB_WORKSPACE}/.github/actions/package_exclusions.txt" -bb3 /c/Program\ Files/7-Zip/7z.exe a -tzip "$GAM_ARCHIVE" gam7 "-xr@${GITHUB_WORKSPACE}/.github/actions/package_exclusions.txt" -bb3
- name: Windows package MSI - name: Windows package exe with Inno Setup
if: runner.os == 'Windows' && matrix.goal != 'test' if: runner.os == 'Windows' && matrix.goal != 'test'
run: | run: |
export MSI_FILENAME="${GITHUB_WORKSPACE}/gam-${GAMVERSION}-windows-${arch}.msi" choco install innosetup
# auto-generate a lib.wxs based on the files PyInstaller created for the lib/ directory export signtool="C:\Program Files (x86)\Windows Kits\10\bin\10.0.26100.0\x64\signtool.exe"
/c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.14/bin/heat.exe dir "${gampath}/lib" -ke -srd -cg Lib -gg -dr lib -directoryid lib -out lib.wxs iscc \
$PYTHON tools/gen-wix-xml-filelist.py lib.wxs /S"gamsigntool=$signtool sign /sha1 $WINDOWS_CODESIGN_CERT_HASH /tr http://time.certum.pl /td SHA256 /fd SHA256 /v \$f" \
echo "-- begin lib.wxs --" /O"$GITHUB_WORKSPACE" \
cat lib.wxs gam.iss
echo "-- end lib.wxs --"
/c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.14/bin/candle.exe -arch "${WIX_ARCH}" gam.wxs lib.wxs
/c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.14/bin/light.exe -ext /c/Program\ Files\ \(x86\)/WiX\ Toolset\ v3.14/bin/WixUIExtension.dll gam.wixobj lib.wixobj -b "${gampath}/lib" -o "$MSI_FILENAME" || true;
rm -v -f *.wixpdb
rm -v -f *.wixobj
echo "MSI_FILENAME=${MSI_FILENAME}" >> $GITHUB_ENV
- name: Sign GAM MSI
if: runner.os == 'Windows'
shell: pwsh
run: |
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", "$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"
- name: Attest that gam package files were generated from this Action - name: Attest that gam package files were generated from this Action
uses: actions/attest-build-provenance@0b6e9809265278d02c58acf52849a95818a5a306 # v3.0.0 uses: actions/attest@59d89421af93a897026c735860bf21b6eb4f7b26 # v4.1.0
if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && matrix.goal == 'build' if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && matrix.goal == 'build'
with: with:
subject-path: | subject-path: |
gam*.tar.xz gam*.tar.xz
gam*.zip gam*.zip
gam*.msi gam*.exe
# gam*.msi
- name: Archive production artifacts - name: Archive tar.xz artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 7.0.0
#if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && matrix.goal != 'test' if: runner.os != 'Windows'
if: always()
with: with:
name: gam-binaries-${{ env.GAMOS }}-${{ env.arch }}-${{ matrix.jid }} archive: false
if-no-files-found: ignore
path: | path: |
gam*.tar.xz gam*.tar.xz
- name: Archive zip artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 7.0.0
if: runner.os == 'Windows'
with:
archive: false
if-no-files-found: ignore
path: |
gam*.zip gam*.zip
gam*.msi
*.png - name: Archive exe artifacts
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # 7.0.0
if: runner.os == 'Windows'
with:
archive: false
if-no-files-found: ignore
path: |
gam*.exe
- name: Basic Tests build jobs only - name: Basic Tests build jobs only
if: matrix.goal != 'test' && steps.cache-python-ssl.outputs.cache-hit != 'true' if: matrix.goal != 'test' && steps.cache-python-ssl.outputs.cache-hit != 'true'
@@ -839,19 +849,46 @@ jobs:
- name: Live API tests - name: Live API tests
if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') if: (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
run: | run: |
run_gam() {
local allowed_codes="0"
if [[ "$1" == "-a" ]]; then
allowed_codes="$2"
shift 2
fi
echo "::group::Executing: gam $*"
local exit_code=0
$gam "$@" || exit_code=$?
echo "::endgroup::"
allowed_codes="${allowed_codes//,/ }"
local passed=false
for code in $allowed_codes; do
if [ "$exit_code" -eq "$code" ]; then
passed=true
break
fi
done
if [ "$passed" = true ]; then
echo "| \`gam $*\` | 🟢 Pass | $exit_code |" >> $GITHUB_STEP_SUMMARY
return 0 # Mask the allowed non-zero exit code so GHA continues
else
echo "| \`gam $*\` | 🔴 Fail | $exit_code |" >> $GITHUB_STEP_SUMMARY
exit $exit_code # Hard fail the step for unapproved errors
fi
}
export gam_user="gam-gha-${JID}@pdl.jaylee.us" export gam_user="gam-gha-${JID}@pdl.jaylee.us"
echo "gam_user=${gam_user}" >> $GITHUB_ENV echo "gam_user=${gam_user}" >> $GITHUB_ENV
$gam config customer_id "C03uzfv2s" save run_gam config customer_id "C03uzfv2s" save
$gam config domain "pdl.jaylee.us" save run_gam config domain "pdl.jaylee.us" save
$gam config admin_email "${gam_user}" save run_gam config admin_email "${gam_user}" save
$gam config enable_dasa false save run_gam config enable_dasa false save
$gam oauth info run_gam oauth info
$gam oauth refresh run_gam oauth refresh
$gam config enable_dasa true save run_gam config enable_dasa true save
$gam checkconn run_gam checkconn
$gam user "$gam_user" check serviceaccount run_gam user "$gam_user" check serviceaccount
$gam info domain run_gam info domain
$gam info user run_gam info user
export tstamp=$($PYTHON -c "import time; print(time.time_ns())") export tstamp=$($PYTHON -c "import time; print(time.time_ns())")
export newbase="gha_test_${JID}_${tstamp}" export newbase="gha_test_${JID}_${tstamp}"
export newuser="${newbase}@pdl.jaylee.us" export newuser="${newbase}@pdl.jaylee.us"
@@ -861,23 +898,38 @@ jobs:
export newresource="${newbase}-resource" export newresource="${newbase}-resource"
export newou="aaaGithub Actions/${newbase}" export newou="aaaGithub Actions/${newbase}"
echo "### GAM Execution Report" >> $GITHUB_STEP_SUMMARY
echo "| Command | Status |" >> $GITHUB_STEP_SUMMARY
echo "| :--- | :---: |" >> $GITHUB_STEP_SUMMARY
# cleanup old runs # cleanup old runs
$gam config enable_dasa false save run_gam config enable_dasa false save
$gam config csv_output_row_filter "name:regex:gha_test_${JID}_" print vaultholds | $gam csv - gam delete vaulthold "id:~~holdId~~" matter "id:~~matterId~~" || if [ $? != 55 ]; then exit $?; fi run_gam config csv_output_row_filter "name:regex:gha_test_${JID}_" redirect csv ./vh.csv print vaultholds
$gam config csv_output_row_filter "name:regex:gha_test_${JID}_" print vaultmatters matterstate OPEN | $gam csv - gam update vaultmatter "id:~~matterId~~" action close run_gam -a "0 55" csv ./vh.csv gam delete vaulthold "id:~~holdId~~" matter "id:~~matterId~~"
$gam config csv_output_row_filter "name:regex:gha_test_${JID}_" print vaultmatters matterstate CLOSED | $gam csv - gam update vaultmatter "id:~~matterId~~" action delete run_gam config csv_output_row_filter "name:regex:gha_test_${JID}_" redirect csv ./vm-open.csv print vaultmatters matterstate OPEN
$gam config csv_output_row_filter "Emails.1.address:regex:^gha_test-${JID}_" print contacts | $gam csv - gam delete contact ~ContactID run_gam csv ./vm-open.csv gam update vaultmatter "id:~~matterId~~" action close
$gam config enable_dasa true save run_gam config csv_output_row_filter "name:regex:gha_test_${JID}_" redirect csv ./vm-closed.csv print vaultmatters matterstate CLOSED
$gam config csv_output_row_filter "name:regex:gha_test_${JID}_" print features | $gam csv - gam delete feature ~name run_gam csv ./vm-closed.csv gam update vaultmatter "id:~~matterId~~" action delete
$gam config csv_output_row_filter "name:regex:^gha_test_${JID}_" user $gam_user print shareddrives asadmin | $gam csv - gam user $gam_user delete shareddrive ~id nukefromorbit run_gam config csv_output_row_filter "Emails.1.address:regex:^gha_test-${JID}_" redirect csv ./contacts.csv print contacts
$gam print users query "gha.jid=$JID" | $gam csv - gam delete user ~primaryEmail run_gam csv ./contacts.csv gam delete contact ~ContactID
$gam config csv_output_row_filter "name:regex:^gha_test_${JID}_" print ous fromparent "aaaGithub Actions" | $gam csv - gam delete ou ~orgUnitId run_gam config enable_dasa true save
$gam config csv_output_row_filter "email:regex:^gha_test_${JID}_" print cigroups | $gam csv - gam delete cigroup ~email run_gam config csv_output_row_filter "name:regex:gha_test_${JID}_" redirect csv ./features.csv print features
$gam config csv_output_row_filter "resourceId:regex:^gha_test_${JID}_" print resources | $gam csv - gam delete resource ~resourceId run_gam csv ./features.csv gam delete feature ~name
$gam config csv_output_row_filter "buildingId:regex:^gha_test_${JID}_" print buildings | $gam csv - gam delete building ~buildingId run_gam config csv_output_row_filter "name:regex:^gha_test_${JID}_" redirect csv ./sd.csv user $gam_user print shareddrives asadmin
run_gam csv ./sd.csv gam user $gam_user delete shareddrive ~id nukefromorbit
run_gam redirect csv ./users.csv print users query "gha.jid=$JID"
run_gam csv ./users.csv gam delete user ~primaryEmail
run_gam config csv_output_row_filter "name:regex:^gha_test_${JID}_" redirect csv ./ous.csv print ous fromparent "aaaGithub Actions"
run_gam csv ./ous.csv gam delete ou ~orgUnitId
run_gam config csv_output_row_filter "email:regex:^gha_test_${JID}_" redirect csv ./cigroups.csv print cigroups
run_gam csv ./cigroups.csv gam delete cigroup ~email
run_gam config csv_output_row_filter "resourceId:regex:^gha_test_${JID}_" redirect csv ./resources.csv print resources
run_gam csv ./resources.csv gam delete resource ~resourceId
run_gam config csv_output_row_filter "buildingId:regex:^gha_test_${JID}_" redirect csv ./buildings.csv print buildings
run_gam csv ./buildings.csv gam delete building ~buildingId
echo "Creating OrgUnit ${newou}" echo "Creating OrgUnit ${newou}"
$gam create ou "${newou}" run_gam create ou "${newou}"
export GAM_THREADS=5 export GAM_THREADS=5
echo email > sample.csv; echo email > sample.csv;
for i in {1..10}; do for i in {1..10}; do
@@ -885,187 +937,183 @@ jobs:
done done
driveid=$($gam user $gam_user add shareddrive "${newbase}" returnidonly) driveid=$($gam user $gam_user add shareddrive "${newbase}" returnidonly)
echo "Created shared drive ${driveid}" echo "Created shared drive ${driveid}"
$gam create user $newuser firstname GHA lastname $JID displayname "Github Actions ${JID}" password random recoveryphone 12125121110 recoveryemail jay0lee@gmail.com gha.jid $JID languages en+,en-GB- ou "${newou}" run_gam create user $newuser firstname GHA lastname $JID displayname "Github Actions ${JID}" password random recoveryphone 12125121110 recoveryemail jay0lee@gmail.com gha.jid $JID languages en+,en-GB- ou "${newou}"
$gam user $newuser add license workspaceenterpriseplus run_gam user $newuser add license workspaceenterpriseplus
$gam user $newuser update photo https://dummyimage.com/98x98/000/fff.jpg run_gam user $newuser update photo https://dummyimage.com/98x98/000/fff.jpg
$gam user $newuser get photo run_gam user $newuser get photo
$gam user $newuser delete photo run_gam user $newuser delete photo
$gam create alias $newalias user $newuser run_gam create alias $newalias user $newuser
$gam create group $newgroup name "GHA $JID group" description "This is a description" isarchived true run_gam create group $newgroup name "GHA $JID group" description "This is a description" isarchived true
$gam user $gam_user sendemail recipient dev-null@pdl.jaylee.us subject "test message $newbase" message "GHA test message" run_gam user $gam_user sendemail recipient dev-null@pdl.jaylee.us subject "test message $newbase" message "GHA test message"
$gam config enable_dasa false save run_gam config enable_dasa false save
# don't expose policy output # don't expose policy output
$gam show policies > policies.csv run_gam show policies > policies.csv
$gam create contact firstname GHA lastname "$JID" email work "${newbase}@example.com" primary run_gam create contact firstname GHA lastname "$JID" email work "${newbase}@example.com" primary
$gam print contacts run_gam print contacts
$gam print privileges run_gam print privileges
$gam config enable_dasa true save run_gam config enable_dasa true save
$gam update cigroup $newgroup security memberrestriction 'member.type == 1 || member.customer_id == groupCustomerId()' run_gam update cigroup $newgroup security memberrestriction 'member.type == 1 || member.customer_id == groupCustomerId()'
$gam info cigroup $newgroup run_gam info cigroup $newgroup
$gam update group $newgroup add owner $gam_user run_gam update group $newgroup add owner $gam_user
$gam update group $newgroup add member $newuser run_gam update group $newgroup add member $newuser
$gam config enable_dasa false save run_gam config enable_dasa false save
# 9/17/24 temp disable due to Google API sluggishness to see new users for admin commands # 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 # run_gam create admin $newuser _GROUPS_EDITOR_ROLE CUSTOMER # condition nonsecuritygroup
# 9/13/25 temp disable due to hangs # 9/13/25 temp disable due to hangs
# $gam create admin $newgroup _HELP_DESK_ADMIN_ROLE org_unit "${newou}" # run_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" # run_gam config csv_output_row_filter "assignedToUser:regex:${newuser}" print admins | run_gam csv - gam delete admin "~roleAssignmentId"
# $gam config csv_output_row_filter "assignedToGroup:regex:${newgroup}" print admins | $gam csv - gam delete admin "~roleAssignmentId" # run_gam config csv_output_row_filter "assignedToGroup:regex:${newgroup}" print admins | run_gam csv - gam delete admin "~roleAssignmentId"
$gam config enable_dasa false save run_gam config enable_dasa false save
$gam csv sample.csv gam create user ~~email~~ firstname "GHA Bulk" lastname ~~email~~ gha.jid $JID ou "${newou}" run_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}" run_gam csv sample.csv gam update user ~~email~~ recoveryphone 12125121110 recoveryemail jay0lee@gmail.com password random displayname "GitHub Actions Bulk ${JID}"
$gam csv sample.csv gam update user ~~email~~ recoveryphone "" recoveryemail "" run_gam csv sample.csv gam update user ~~email~~ recoveryphone "" recoveryemail ""
$gam config enable_dasa false save run_gam config enable_dasa false save
$gam csv sample.csv gam user ~email add license workspaceenterpriseplus run_gam csv sample.csv gam user ~email add license workspaceenterpriseplus
#$gam user $newuser add contactdelegate "${newbase}-bulkuser-1" #run_gam user $newuser add contactdelegate "${newbase}-bulkuser-1"
#$gam user $newuser print contactdelegates #run_gam user $newuser print contactdelegates
$gam config enable_dasa true save run_gam config enable_dasa true save
$gam csv sample.csv gam user $gam_user sendemail recipient ~~email~~@pdl.jaylee.us subject "test message $newbase" message "GHA test message" run_gam csv sample.csv gam user $gam_user sendemail recipient ~~email~~@pdl.jaylee.us subject "test message $newbase" message "GHA test message"
$gam csv sample.csv gam update group $newgroup add member ~email run_gam csv sample.csv gam update group $newgroup add member ~email
$gam info group $newgroup run_gam info group $newgroup
$gam info cigroup $newgroup membertree run_gam info cigroup $newgroup membertree
# confirm mailbox is provisoned before continuing # confirm mailbox is provisoned before continuing
$gam user $newuser waitformailbox retries 50 run_gam user $newuser waitformailbox retries 50
$gam user $newuser imap on run_gam user $newuser imap on
$gam user $newuser show imap run_gam user $newuser show imap
$gam user $newuser show delegates run_gam user $newuser show delegates
export biohazard=$(echo -e '\xe2\x98\xa3') export biohazard=$(echo -e '\xe2\x98\xa3')
$gam user $newuser label "$biohazard unicode biohazard $biohazard" run_gam user $newuser label "$biohazard unicode biohazard $biohazard"
$gam user $newuser show labels run_gam user $newuser show labels
$gam user $newuser show labels > labels.txt run_gam user $newuser show labels > labels.txt
$gam user $gam_user importemail subject "GHA import $newbase" message "This is a test import" labels IMPORTANT,UNREAD,INBOX,STARRED run_gam user $gam_user importemail subject "GHA import $newbase" message "This is a test import" labels IMPORTANT,UNREAD,INBOX,STARRED
$gam user $gam_user insertemail subject "GHA insert $newbase" file gam.py labels INBOX,UNREAD # yep body is gam code run_gam user $gam_user insertemail subject "GHA insert $newbase" file gam.py labels INBOX,UNREAD # yep body is gam code
$gam user $gam_user sendemail recipient admin@pdl.jaylee.us subject "GHA send $gam_user $newbase" file gam.py run_gam user $gam_user sendemail recipient admin@pdl.jaylee.us subject "GHA send $gam_user $newbase" file gam.py
$gam user $gam_user draftemail subject "GHA draft $newbase" message "Draft message test" run_gam user $gam_user draftemail subject "GHA draft $newbase" message "Draft message test"
$gam csvfile sample.csv:email waitformailbox retries 20 run_gam csvfile sample.csv:email waitformailbox retries 20
$gam user $newuser delegate to "${newbase}-bulkuser-1" || if [ $? != 50 ]; then exit $?; fi # expect a 50 return code (delegation failed) run_gam user $newuser delegate to "${newbase}-bulkuser-1" || if [ $? != 50 ]; then exit $?; fi # expect a 50 return code (delegation failed)
$gam users "$gam_user $newbase-bulkuser-1 $newbase-bulkuser-2 $newbase-bulkuser-3" delete messages query in:anywhere maxtodelete 99999 doit || if [ $? != 60 ]; then exit $?; fi # expect a 60 return code (no messages) run_gam -a "0 60" users "$gam_user $newbase-bulkuser-1 $newbase-bulkuser-2 $newbase-bulkuser-3" delete messages query in:anywhere maxtodelete 99999 doit
$gam users "$newbase-bulkuser-4 $newbase-bulkuser-5 $newbase-bulkuser-6" trash messages query in:anywhere maxtotrash 99999 doit || if [ $? != 60 ]; then exit $?; fi # expect a 60 return code (no messages) run_gam -a "0 60" users "$newbase-bulkuser-4 $newbase-bulkuser-5 $newbase-bulkuser-6" trash messages query in:anywhere maxtotrash 99999 doit
$gam users "$newbase-bulkuser-7 $newbase-bulkuser-8 $newbase-bulkuser-9" modify messages query in:anywhere maxtomodify 99999 addlabel IMPORTANT addlabel STARRED doit || if [ $? != 60 ]; then exit $?; fi # expect a 60 return code (no messages) run_gam -a "0 60" users "$newbase-bulkuser-7 $newbase-bulkuser-8 $newbase-bulkuser-9" modify messages query in:anywhere maxtomodify 99999 addlabel IMPORTANT addlabel STARRED doit
$gam user $newuser delete label --ALL_LABELS-- run_gam user $newuser delete label --ALL_LABELS--
$gam config csv_output_row_filter "name:regex:gha-test-${JID}" print features | $gam csv - gam delete feature ~name run_gam config csv_output_row_filter "name:regex:gha-test-${JID}" redirect csv ./features.csv print features
$gam create feature name VC-$newbase run_gam csv ./features.csv gam delete feature ~name
$gam create feature name Whiteboard-$newbase run_gam create feature name VC-$newbase
$gam create building "My Building - $newbase" id $newbuilding floors 1,2,3,4,5,6,7,8,9,10,11,12,14,15 description "No 13th floor here..." run_gam create feature name Whiteboard-$newbase
$gam create resource $newresource "Resource Calendar $tstamp" capacity 25 features Whiteboard-$newbase,VC-$newbase building $newbuilding floor 15 type Room run_gam create building "My Building - $newbase" id $newbuilding floors 1,2,3,4,5,6,7,8,9,10,11,12,14,15 description "No 13th floor here..."
$gam info resource $newresource run_gam create resource $newresource "Resource Calendar $tstamp" capacity 25 features Whiteboard-$newbase,VC-$newbase building $newbuilding floor 15 type Room
$gam user $newuser add drivefile drivefilename "TPS Reports" mimetype gfolder run_gam info resource $newresource
$gam user $newuser show filelist run_gam user $newuser add drivefile drivefilename "TPS Reports" mimetype gfolder
$gam calendar $gam_user printacl | $gam csv - gam calendar $gam_user delete ~id # clear ACLs run_gam user $newuser show filelist
$gam calendar $gam_user add read domain run_gam redirect csv ./cal-acl.csv calendar $gam_user printacl
$gam calendar $gam_user add freebusy default run_gam csv ./cal-acl.csv gam calendar $gam_user delete ~id # clear ACLs
$gam calendar $gam_user add editor $newuser run_gam calendar $gam_user add read domain
$gam calendar $gam_user showacl run_gam calendar $gam_user add freebusy default
$gam calendar $gam_user printacl | $gam csv - gam calendar $gam_user delete ~id run_gam calendar $gam_user add editor $newuser
$gam calendar $gam_user addevent summary "GHA test event" start +1h end +2h attendee $newgroup hangoutsmeet guestscanmodify true sendupdates all run_gam calendar $gam_user showacl
$gam calendar $gam_user printevents after -0d run_gam redirect csv ./cal-acl.csv calendar $gam_user printacl
$gam config enable_dasa false save run_gam csv ./cal-acl.csv gam calendar $gam_user delete ~id
run_gam calendar $gam_user addevent summary "GHA test event" start +1h end +2h attendee $newgroup hangoutsmeet guestscanmodify true sendupdates all
run_gam calendar $gam_user printevents after -0d
run_gam config enable_dasa false save
matterid=uid:$($gam create vaultmatter name "GHA matter $newbase" description "test matter" returnidonly) matterid=uid:$($gam create vaultmatter name "GHA matter $newbase" description "test matter" returnidonly)
$gam create vaulthold matter $matterid name "GHA hold ${newbase}" corpus mail ou "$newou" run_gam create vaulthold matter "$matterid" name "GHA hold ${newbase}" corpus mail ou "$newou"
$gam print vaultmatters matterstate open run_gam print vaultmatters matterstate open
$gam print vaultholds matter $matterid run_gam print vaultholds matter $matterid
$gam print vaultcount matter $matterid corpus mail everyone todrive tdnobrowser run_gam print vaultcount matter $matterid corpus mail everyone todrive tdnobrowser
$gam create vaultexport matter $matterid name "GHA export $newbase" corpus mail ou "$newou" run_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~~ run_gam redirect csv ./exports.csv print exports matter $matterid
$gam config enable_dasa true save run_gam csv ./exports.csv gam info export $matterid id:~~id~~
$gam csv sample.csv gam user ~email add calendar id:$newresource run_gam config enable_dasa true save
$gam delete resource $newresource run_gam csv sample.csv gam user ~email add calendar id:$newresource
$gam delete feature Whiteboard-$newbase run_gam delete resource $newresource
$gam delete feature VC-$newbase run_gam delete feature Whiteboard-$newbase
$gam delete building $newbuilding run_gam delete feature VC-$newbase
$gam delete group $newgroup run_gam delete building $newbuilding
$gam config enable_dasa false save run_gam delete group $newgroup
run_gam config enable_dasa false save
echo start echo start
$gam user $newuser delete license workspaceenterpriseplus run_gam user $newuser delete license workspaceenterpriseplus
echo finish echo finish
$gam config enable_dasa true save run_gam config enable_dasa true save
$gam whatis $newuser || if [ $? != 20 ]; then exit $?; fi # expect a 20 return code (is a user) run_gam -a "0 20" whatis $newuser
$gam user $gam_user show tokens run_gam user $gam_user show tokens
$gam config enable_dasa false save run_gam config enable_dasa false save
download_dir="${RUNNER_TEMP}/TEMP_DELETE_ME" download_dir="${RUNNER_TEMP}/TEMP_DELETE_ME"
mkdir -v "$download_dir" mkdir -v "$download_dir"
$gam print exports matter $matterid | $gam csv - gam download export $matterid id:~~id~~ targetfolder "$download_dir" run_gam redirect csv ./exports.csv print exports matter $matterid
run_gam csv ./exports.csv gam download export $matterid id:~~id~~ targetfolder "$download_dir"
rm -rvf "$download_dir" rm -rvf "$download_dir"
$gam delete hold "GHA hold $newbase" matter $matterid run_gam delete hold "GHA hold $newbase" matter $matterid
$gam update matter $matterid action close run_gam update matter $matterid action close
$gam update matter $matterid action delete run_gam update matter $matterid action delete
# shakes off vault hold on user so we can delete # shakes off vault hold on user so we can delete
$gam print users query "email:${newuser}" orgunitpath | $gam csv - gam update user ~primaryEmail ou ~orgUnitPath run_gam redirect csv ./users.csv print users query "email:${newuser}" orgunitpath
$gam user $newuser show holds || if [ $? != 55 ]; then exit $?; fi # expect a 55 return code run_gam csv ./users.csv gam update user ~primaryEmail ou ~orgUnitPath
run_gam user $newuser show holds || if [ $? != 55 ]; then exit $?; fi # expect a 55 return code
export sn="$JID$JID$JID$JID-$(openssl rand -base64 32 | sed 's/[^a-zA-Z0-9]//g')" export sn="$JID$JID$JID$JID-$(openssl rand -base64 32 | sed 's/[^a-zA-Z0-9]//g')"
$gam create device serialnumber $sn devicetype android run_gam create device serialnumber $sn devicetype android
$gam delete contacts emailmatchpattern "^${newbase}@example.com$" run_gam delete contacts emailmatchpattern "^${newbase}@example.com$"
$gam config enable_dasa true save run_gam config enable_dasa true save
$gam print users query "gha.jid=$JID" | $gam csv - gam delete user ~primaryEmail || if [ $? != 50 ]; then exit $?; fi # expect a 50 return code (vault hold on user) run_gam redirect csv ./users.csv print users query "gha.jid=$JID"
$gam print mobile run_gam -a "0 50" csv ./users.csv gam delete user ~primaryEmail
$gam print devices clientstates run_gam print mobile
$gam print browsers run_gam print devices clientstates
$gam print cros allfields orderby serialnumber run_gam print browsers
$gam show crostelemetry storagepercentonly run_gam print cros allfields orderby serialnumber
$gam report usageparameters customer run_gam show crostelemetry storagepercentonly
$gam report usage customer parameters gmail:num_emails_sent,accounts:num_1day_logins run_gam report usageparameters customer
$gam report customer todrive tdnobrowser run_gam report usage customer parameters gmail:num_emails_sent,accounts:num_1day_logins
#$gam report users fields accounts:is_less_secure_apps_access_allowed,gmail:last_imap_time,gmail:last_pop_time filters "accounts:last_login_time>2025-01-01T00:00:00.000Z" todrive tdnobrowser run_gam report customer todrive tdnobrowser
$gam report users todrive tdnobrowser #run_gam report users fields accounts:is_less_secure_apps_access_allowed,gmail:last_imap_time,gmail:last_pop_time filters "accounts:last_login_time>2025-01-01T00:00:00.000Z" todrive tdnobrowser
$gam report admin start -3d todrive tdnobrowser run_gam report users todrive tdnobrowser
$gam print devices nopersonaldevices nodeviceusers filter "serial:$JID$JID$JID$JID-" | $gam csv - gam delete device id ~name run_gam report admin start -3d todrive tdnobrowser
$gam config enable_dasa false save run_gam redirect csv ./devices.csv print devices nopersonaldevices nodeviceusers filter "serial:$JID$JID$JID$JID-"
$gam print userinvitations run_gam csv ./devices.csv gam delete device id ~name
$gam print userinvitations | $gam csv - gam send userinvitation ~name run_gam config enable_dasa false save
$gam config enable_dasa false save run_gam print userinvitations
$gam create caalevel "zzz_${newbase}" basic condition ipsubnetworks 1.1.1.1/32,2.2.2.2/32 endcondition run_gam redirect csv ./invitations.csv print userinvitations
$gam print caalevels run_gam csv ./invitations.csv gam send userinvitation ~name
$gam delete caalevel "zzz_${newbase}" run_gam config enable_dasa false save
$gam user $gam_user add drivefile localfile gam.py parentid "${driveid}" run_gam create caalevel "zzz_${newbase}" basic condition ipsubnetworks 1.1.1.1/32,2.2.2.2/32 endcondition
$gam user $gam_user update shareddrive "${driveid}" ou "${newou}" run_gam print caalevels
$gam user $gam_user show shareddrives asadmin run_gam delete caalevel "zzz_${newbase}"
$gam user $gam_user update shareddrive "${driveid}" ou "aaaGithub Actions" # so we can delete our OU... run_gam user $gam_user add drivefile localfile gam.py parentid "${driveid}"
$gam user $gam_user delete shareddrive "${driveid}" nukefromorbit run_gam user $gam_user update shareddrive "${driveid}" ou "${newou}"
ssoprofile=$($gam config debug_level 1 create inboundssoprofile name "El Goog ${newbase}" loginurl https://www.google.com logouturl https://www.google.com changepasswordurl https://www.google.com entityid ElGoog return_name_only) run_gam user $gam_user show shareddrives asadmin
run_gam user $gam_user update shareddrive "${driveid}" ou "aaaGithub Actions" # so we can delete our OU...
run_gam user $gam_user delete shareddrive "${driveid}" nukefromorbit
ssoprofile=$(run_gam config debug_level 1 create inboundssoprofile name "El Goog ${newbase}" loginurl https://www.google.com logouturl https://www.google.com changepasswordurl https://www.google.com entityid ElGoog return_name_only)
if [ ${ssoprofile} != 'inProgress' ]; then if [ ${ssoprofile} != 'inProgress' ]; then
$gam create inboundssocredential profile "id:${ssoprofile}" generate_key run_gam create inboundssocredential profile "id:${ssoprofile}" generate_key
#$gam create inboundssoassignment profile "id:${ssoprofile}" orgunit "${newou}" mode SAML_SSO #run_gam create inboundssoassignment profile "id:${ssoprofile}" orgunit "${newou}" mode SAML_SSO
#$gam delete inboundssoassignment "orgunit:${newou}" #run_gam delete inboundssoassignment "orgunit:${newou}"
$gam delete inboundssoprofile "id:${ssoprofile}" run_gam delete inboundssoprofile "id:${ssoprofile}"
fi fi
echo "printer model count:" echo "printer model count:"
$gam print printermodels | wc -l run_gam print printermodels | wc -l
$gam print printers run_gam print printers
printerid=$($gam create printer displayname "${newbase}" uri ipp://localhost:631 driverless description "made by ${gam_user}" ou "${newou}" nodetails | awk '{print substr($2, 1, length($2)-1)}') printerid=$($gam create printer displayname "${newbase}" uri ipp://localhost:631 driverless description "made by ${gam_user}" ou "${newou}" returnIdOnly)
$gam info printer "$printerid" run_gam info printer "$printerid"
$gam delete printer "$printerid" run_gam delete printer "$printerid"
$gam delete ou "${newou}" run_gam delete ou "${newou}"
- name: Tar Cache archive - name: Tar Cache archive
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit != 'true' if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit != 'true'
working-directory: ${{ github.workspace }} working-directory: ${{ github.workspace }}
run: | run: |
if [[ "${RUNNER_OS}" == "Windows" ]]; then #if [[ "${RUNNER_OS}" == "Windows" ]]; then
tar_folders="src/cpython/ bin/ssl" # tar_folders="src/cpython/ bin/ssl"
else #else
tar_folders="bin/" # tar_folders="bin/"
fi #fi
tar_folders="bin/"
echo '.git*' > ./excludes.txt echo '.git*' > ./excludes.txt
tar cJvvf cache.tar.xz --exclude-from=excludes.txt $tar_folders 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')
runs-on: ubuntu-24.04
needs: build
permissions:
contents: write
packages: write
steps:
- name: Merge Artifacts
uses: actions/upload-artifact/merge@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: gam-binaries
pattern: gam-binaries-*
publish: publish:
if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch')
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
needs: merge needs: build
permissions: permissions:
contents: write contents: write
packages: write packages: write
@@ -1073,13 +1121,17 @@ jobs:
steps: steps:
- uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v5.0.0 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
fetch-depth: 0 fetch-depth: 0
- name: Download artifacts - name: Download artifacts
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # 5.0.0 uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0
with:
path: gam-binaries/
merge-multiple: true
skip-decompress: true
- name: VirusTotal Scan - name: VirusTotal Scan
uses: crazy-max/ghaction-virustotal@d34968c958ae283fe976efed637081b9f9dcf74f # 4.2.0 uses: crazy-max/ghaction-virustotal@d34968c958ae283fe976efed637081b9f9dcf74f # 4.2.0
@@ -1096,7 +1148,7 @@ jobs:
echo "dateversion=${dateversion}" >> $GITHUB_OUTPUT echo "dateversion=${dateversion}" >> $GITHUB_OUTPUT
- name: Publish draft release - name: Publish draft release
uses: softprops/action-gh-release@6cbd405e2c4e67a21c47fa9e383d020e4e28b836 # v2.3.3 uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
with: with:
draft: true draft: true
prerelease: false prerelease: false

View File

@@ -1,14 +1,9 @@
name: Check for Google Root CA Updates name: Check for Google Root CA Updates
on: on:
push:
paths-ignore:
- 'wiki/**'
pull_request:
paths-ignore:
- 'wiki/**'
schedule: schedule:
- cron: '23 23 * * *' - cron: '23 23 * * *'
workflow_dispatch:
defaults: defaults:
run: run:
@@ -17,9 +12,9 @@ defaults:
jobs: jobs:
check-certs: check-certs:
runs-on: ubuntu-latest runs-on: ubuntu-slim
steps: steps:
- uses: actions/checkout@ff7abcd0c3c05ccf6adc123a8cd1fd4fb30fb493 # v5.0.0 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal token
fetch-depth: 0 # otherwise, you will failed to push refs to dest repo fetch-depth: 0 # otherwise, you will failed to push refs to dest repo
@@ -30,9 +25,51 @@ jobs:
echo "Current hash is: ${CURRENT_HASH}" echo "Current hash is: ${CURRENT_HASH}"
echo "CURRENT_HASH=${CURRENT_HASH}" >> $GITHUB_ENV echo "CURRENT_HASH=${CURRENT_HASH}" >> $GITHUB_ENV
- name: Get latest cacerts.pem file from Google - name: Generate GAM-specific bundle with LE + Google roots
run: | run: |
curl -o ./cacerts.pem -vvvv https://pki.goog/roots.pem OUTPUT_FILE="cacerts.pem"
> "$OUTPUT_FILE"
process_cert() {
local url="$1"
local op_ca="$2"
local label="$3"
local tmp_cert=$(mktemp)
curl "$url" > "$tmp_cert"
local issuer=$(openssl x509 -noout -issuer -in "$tmp_cert" | sed -e 's/^issuer= *//')
local subject=$(openssl x509 -noout -subject -in "$tmp_cert" | sed -e 's/^subject= *//')
local serial_hex=$(openssl x509 -noout -serial -in "$tmp_cert" | sed -e 's/^serial=//')
local serial_dec=$(python3 -c "print(int('$serial_hex', 16))")
local md5=$(openssl x509 -noout -fingerprint -md5 -in "$tmp_cert" | sed -e 's/.*=//' | tr '[:upper:]' '[:lower:]')
local sha1=$(openssl x509 -noout -fingerprint -sha1 -in "$tmp_cert" | sed -e 's/.*=//' | tr '[:upper:]' '[:lower:]')
local sha256=$(openssl x509 -noout -fingerprint -sha256 -in "$tmp_cert" | sed -e 's/.*=//' | tr '[:upper:]' '[:lower:]')
echo "# Operating CA: $op_ca" >> "$OUTPUT_FILE"
echo "# Issuer: $issuer" >> "$OUTPUT_FILE"
echo "# Subject: $subject" >> "$OUTPUT_FILE"
echo "# Label: \"$label\"" >> "$OUTPUT_FILE"
echo "# Serial: $serial_dec" >> "$OUTPUT_FILE"
echo "# MD5 Fingerprint: $md5" >> "$OUTPUT_FILE"
echo "# SHA1 Fingerprint: $sha1" >> "$OUTPUT_FILE"
echo "# SHA256 Fingerprint: $sha256" >> "$OUTPUT_FILE"
cat "$tmp_cert" >> "$OUTPUT_FILE"
echo "" >> "$OUTPUT_FILE"
rm "$tmp_cert"
}
echo "#" >> "$OUTPUT_FILE"
echo "# This is a custom certificate authority bundle for GAM" >> "$OUTPUT_FILE"
echo "# It's composed of Let's Encrypt Root CAs and Google's" >> "$OUTPUT_FILE"
echo "# certificate bundle. This should be the minimal list of" >> "$OUTPUT_FILE"
echo "# CAs required to talk to Google and Github." >> "$OUTPUT_FILE"
echo"" >> "$OUTPUT_FILE"
echo "Processing Let's Encrypt ISRG Root X1..."
process_cert "https://letsencrypt.org/certs/isrgrootx1.pem" "Let's Encrypt" "ISRG Root X1"
echo "Processing Let's Encrypt ISRG Root X2..."
process_cert "https://letsencrypt.org/certs/isrg-root-x2.pem" "Let's Encrypt" "ISRG Root X2"
echo "Appending Google's roots.pem..."
curl -s https://pki.goog/roots.pem >> "$OUTPUT_FILE"
echo "Done! The new bundle has been saved to $OUTPUT_FILE."
- name: Compare hashes - name: Compare hashes
run: | run: |
@@ -51,6 +88,6 @@ jobs:
git diff --quiet && git diff --staged --quiet || git commit -am '[ci skip] Updated cacerts.pem' git diff --quiet && git diff --staged --quiet || git commit -am '[ci skip] Updated cacerts.pem'
- name: Push changes - name: Push changes
uses: ad-m/github-push-action@master uses: ad-m/github-push-action@77c5b412c50b723d2a4fbc6d71fb5723bcd439aa
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -11,7 +11,7 @@ authors = [
#significant compile dependencies. #significant compile dependencies.
dependencies = [ dependencies = [
"arrow>=1.3.0", "arrow>=1.3.0",
"chardet>=5.2.0", "chardet==5.2.0",
"cryptography>=46.0.5", "cryptography>=46.0.5",
"distro; sys_platform=='linux'", "distro; sys_platform=='linux'",
"filelock>=3.18.0", "filelock>=3.18.0",
@@ -31,11 +31,11 @@ requires-python = ">=3.10"
classifiers = [ classifiers = [
"Programming Language :: Python :: 3", "Programming Language :: Python :: 3",
"Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12", "Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13", "Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Operating System :: OS Independent", "Operating System :: OS Independent",
] ]
license = {text = "Apache License (2.0)"} license = {text = "Apache License (2.0)"}

View File

@@ -4568,8 +4568,8 @@ gam check ou|org <OrgUnitItem> [todrive <ToDriveAttribute>*]
usedriverlessconfig| usedriverlessconfig|
<PrinterFieldNameList> ::= "<PrinterFieldName>(,<PrinterFieldName>)*" <PrinterFieldNameList> ::= "<PrinterFieldName>(,<PrinterFieldName>)*"
gam create printer <PrinterAttribute>+ gam create printer <PrinterAttribute>+ [nodetails|returnidonly]
gam update printer <PrinterID> <PrinterAttribute>+ gam update printer <PrinterID> <PrinterAttribute>+ [nodetails|returnidonly]
gam delete printer gam delete printer
<PrinterIDList>| <PrinterIDList>|
<FileSelector>| <FileSelector>|
@@ -5693,6 +5693,7 @@ gam download storagefile <StorageBucketObjectName>
fullname| fullname|
gender| gender|
givenname|firstname| givenname|firstname|
guestaccountinfo|
id| id|
ims|im| ims|im|
includeinglobaladdresslist|gal| includeinglobaladdresslist|gal|
@@ -5700,6 +5701,7 @@ gam download storagefile <StorageBucketObjectName>
isdelegatedadmin|admin|isadmin| isdelegatedadmin|admin|isadmin|
isenforcedin2sv|is2svenforced| isenforcedin2sv|is2svenforced|
isenrolledin2sv|is2svenrolled| isenrolledin2sv|is2svenrolled|
isguestuser|
ismailboxsetup| ismailboxsetup|
keyword|keywords| keyword|keywords|
language|languages| language|languages|

View File

@@ -1,3 +1,74 @@
7.35.01
The following commands have been updated to not verify the existence of `gam.cfg` credentials files
as the WARNING messages about the missing files can be confusing to new users setting up GAM.
```
gam checkconn
gam oauth|oauth2
gam version
```
7.35.00
Windows `gam-7.wx.yz-x86_64.msi` has been replaced with `gam-7.wx.yz-x86_64.exe`.
Windows `gam-7.wx.yz-arm64.msi` has been replaced with `gam-7.wx.yz-arm64.exe`.
Updated cacerts.pem to avoid to following error in `gam checkconn`.
```
Checking raw.githubusercontent.com (185.199.110.133) (2)... ERROR
Certificate verification failed. If you are behind a firewall / proxy server that does TLS / SSL inspection you may need to point GAM at your certificate authority file by setting cacerts_pem = /path/to/your/certauth.pem in gam.cfg.
```
If you have customized cacerts.pem, update your version with the `Operating CA: Let's Encrypt` values from the GAM default version.
7.34.13
Fixed bug in `gam info policies <CIPolicyNameEntity> ... formatjson` where extraneous line
`Show Info 1 Policy` was displayed.
7.34.12
Fixed build errors that prevented Windows zip files from being created.
Added option `returnidonly` to `gam create|update printer` that causes GAM to return just the ID
of the printer.
7.34.11
Updated gam-install.sh script for macOS/Linux to properly config GAM when the answer to the following question is No.
```
Can you run a full browser on this machine? (usually Y for macOS, N for Linux if you SSH into this machine)
```
7.34.10
Fixed bug where `formatjson quotechar <Character>` on the command line did not override `redirect csv <FileName> multiprocess quotechar <Character>`.
7.34.09
Updated `gam <UserTypeEntity> update photo` to delete the user's existing photo
before performing the update as the API update will succeed but not replace a user's existing self-set photo.
7.34.08
Rebuild to avoid the following error:
```
requests/__init__.py:113: RequestsDependencyWarning: urllib3 (2.6.3) or chardet (6.0.0.post1)/charset_normalizer (3.4.4) doesn't match a supported version!
```
7.34.07
Added the following command to create a guest user.
* See: https://support.google.com/a/answer/16558545
```
gam create guestuser <EmailAddress>
```
Added the following items to `<UserFieldName>`:
* `guestaccountinfo` - Additional guest-related metadata fields
* `isguestuser` - Indicates if the inserted user is a guest
7.34.06 7.34.06
Added option `copyfolderpermissions [<Boolean>]` to `gam <UserTypeEntity> copy|move drivefile`. Added option `copyfolderpermissions [<Boolean>]` to `gam <UserTypeEntity> copy|move drivefile`.
@@ -1499,7 +1570,7 @@ Re-run the command specify a new service account name with: saname <ServiceAccou
Native support for Windows 11 Arm-based devices. Native support for Windows 11 Arm-based devices.
Renamed some MacOS and Linux binary installer files to align on terminology. Everything is "arm64" now, no "aarch64". Renamed some macOS and Linux binary installer files to align on terminology. Everything is "arm64" now, no "aarch64".
7.06.05 7.06.05
@@ -2108,7 +2179,7 @@ for `[R] 35) Meet API (supports readonly)` as it is a special case.
7.00.39 7.00.39
Supported MacOS versions are now in the download filename. Supported macOS versions are now in the download filename.
Minor code fixes. Minor code fixes.
@@ -3911,11 +3982,11 @@ See: https://github.com/taers232c/GAMADV-XTD3/wiki/Users-Drive-Files-Display#fil
6.65.12 6.65.12
Additional updates on MacOS when a `gam csv` command is interrupted with a contol-C. Additional updates on macOS when a `gam csv` command is interrupted with a contol-C.
6.65.11 6.65.11
Updated multiprocessing to handle the following error that occurs on MacOS when a `gam csv` command Updated multiprocessing to handle the following error that occurs on macOS when a `gam csv` command
is interrupted with a contol-C. is interrupted with a contol-C.
``` ```
multiprocessing/resource_tracker.py:224: UserWarning: resource_tracker: There appear to be N leaked semaphore objects to clean up at shutdown multiprocessing/resource_tracker.py:224: UserWarning: resource_tracker: There appear to be N leaked semaphore objects to clean up at shutdown
@@ -6076,7 +6147,7 @@ Improved code for `gam [<UserTypeEntity>] create teamdrive <Name> ou <OrgUnitIte
6.29.04 6.29.04
Updated multiprocessing on MacOS to use `spawn` instead of `fork` when starting subprocesses Updated multiprocessing on macOS to use `spawn` instead of `fork` when starting subprocesses
as `fork` was unreliable when large numbers (>20) of threads were used; subprocesses would as `fork` was unreliable when large numbers (>20) of threads were used; subprocesses would
hang and never complete. hang and never complete.
@@ -6198,7 +6269,7 @@ then filters the list to only those in `<PeopleContactGroupItem>`; quota limits
6.28.03 6.28.03
Build MacOS x86_64 and arm64 executables. Build macOS x86_64 and arm64 executables.
6.28.02 6.28.02
@@ -6436,7 +6507,7 @@ This addresses the following issue:
Updated `gam <UserTypeEntity> add|delete|update|print|show datastudiopermissions` to display an appropriate Updated `gam <UserTypeEntity> add|delete|update|print|show datastudiopermissions` to display an appropriate
error message, `The caller does not have permission`, when the user doesn't have permission to execute the command. error message, `The caller does not have permission`, when the user doesn't have permission to execute the command.
Previously, the following incorrect error message was displayed: Previously, the following incorrect error message was displayed:
`ERROR: Data Studio API not enabled. Please run "gam update project" and "gam user user@domain.com check serviceaccount"` `ERROR: Data Studio API not enabled. Please run "gam update project" and "gam user user@domain.com update serviceaccount"`
6.26.14 6.26.14
@@ -6545,7 +6616,7 @@ Added command that allows checking if a user is a member of specific groups and
6.26.00 6.26.00
Build MacOS universal version. Build macOS universal version.
* Upgraded to OpenSSL 3.0.5 where possible. * Upgraded to OpenSSL 3.0.5 where possible.
@@ -6718,7 +6789,7 @@ and display drive labels on files. Please test/experiment and report any issues.
To use these commands you must add the 'Drive Labels API' to your project and update your service account authorization. To use these commands you must add the 'Drive Labels API' to your project and update your service account authorization.
``` ```
gam update project gam update project
gam user user@domain.com check serviceaccount gam user user@domain.com update serviceaccount
``` ```
Supported editions for this feature: Business Standard and Business Plus; Enterprise; Education Standard and Education Plus; G Suite Business; Essentials. Supported editions for this feature: Business Standard and Business Plus; Enterprise; Education Standard and Education Plus; G Suite Business; Essentials.
@@ -6916,7 +6987,7 @@ ERROR: 403: permissionDenied - Google Forms API has not been used in project XXX
``` ```
is replaced with is replaced with
``` ```
ERROR: Forms API not enabled. Please run "gam update project" and "gam user user@domain.com check serviceaccount" ERROR: Forms API not enabled. Please run "gam update project" and "gam user user@domain.com update serviceaccount"
``` ```
6.23.00 6.23.00
@@ -9274,7 +9345,7 @@ To use this feature you must add the `People API` to your project and authorize
* `People API - Other Contacts - read only`: https://www.googleapis.com/auth/contacts.other.readonly * `People API - Other Contacts - read only`: https://www.googleapis.com/auth/contacts.other.readonly
``` ```
gam update project gam update project
gam user user@domain.com check serviceaccount gam user user@domain.com update serviceaccount
``` ```
Added commands to display user's contact groups using the People API. Added commands to display user's contact groups using the People API.
@@ -9315,7 +9386,7 @@ To use these features you must add the `People API` to your project and authoriz
``` ```
gam update project gam update project
gam oauth create gam oauth create
gam user user@domain.com check serviceaccount gam user user@domain.com update serviceaccount
``` ```
Following Jay's lead, added new license SKU `Cloud Search`. Following Jay's lead, added new license SKU `Cloud Search`.
@@ -9354,7 +9425,7 @@ Added commands to display Data Studio assets and display/manage Data Studio perm
To use these commands you must add the `Data Studio API` to your project and update your service account authorization. To use these commands you must add the `Data Studio API` to your project and update your service account authorization.
``` ```
gam update project gam update project
gam user user@domain.com check serviceaccount gam user user@domain.com update serviceaccount
``` ```
This is a first release from me, experiment and use with caution. This is a first release from me, experiment and use with caution.
@@ -10397,7 +10468,7 @@ Added commands to support the new Device Management API.
To use these commands you must update your service account authorization. To use these commands you must update your service account authorization.
``` ```
gam user user@domain.com check serviceaccount gam user user@domain.com update serviceaccount
``` ```
In the following places a Google Admin email address is required; by default the admin email address in `oauth2.txt` is used. In the following places a Google Admin email address is required; by default the admin email address in `oauth2.txt` is used.
@@ -11387,7 +11458,7 @@ ID of the created Team Drive as output. This will be useful in scripts that crea
want to perform subsequent GAM command on the Team Drive. This ID will only be valid when the return code want to perform subsequent GAM command on the Team Drive. This ID will only be valid when the return code
of the command is 0; program accordingly. of the command is 0; program accordingly.
``` ```
Linux/MacOS Linux/macOS
teamDriveId=`gam user user@domain.com create teamdrive ... returnidonly` teamDriveId=`gam user user@domain.com create teamdrive ... returnidonly`
Windows PowerShell Windows PowerShell
$teamDriveId = & gam user user@domain.com create teamdrive ... returnidonly` $teamDriveId = & gam user user@domain.com create teamdrive ... returnidonly`
@@ -11479,7 +11550,7 @@ file ID of the created file as output. This will be useful in scripts that creat
want to perform subsequent GAM command on the file. This file ID will only be valid when the return code want to perform subsequent GAM command on the file. This file ID will only be valid when the return code
of the command is 0; program accordingly. of the command is 0; program accordingly.
``` ```
Linux/MacOS Linux/macOS
fileId=`gam user user@domain.com create drivefile ... returnidonly` fileId=`gam user user@domain.com create drivefile ... returnidonly`
Windows PowerShell Windows PowerShell
$fileId = & gam user user@domain.com create drivefile ... returnidonly` $fileId = & gam user user@domain.com create drivefile ... returnidonly`
@@ -15562,7 +15633,7 @@ gam print group-members [todrive [<ToDriveAttribute>]]
4.55.44 4.55.44
Improve MacOS version of GAM's use of OpenSSL 1.0.2n. Improve macOS version of GAM's use of OpenSSL 1.0.2n.
Recode pyinstaller .spec files. Recode pyinstaller .spec files.
4.55.43 4.55.43
@@ -15589,7 +15660,7 @@ Fixed bug that made some gam print commands throw an exception.
4.55.40 4.55.40
Update MacOS version of GAM to use OpenSSL 1.0.2n. Update macOS version of GAM to use OpenSSL 1.0.2n.
4.55.39 4.55.39
@@ -18415,7 +18486,7 @@ Changed gam info user formatjson to show licenses in SKU ID (SKU Display Name) f
4.42.00 4.42.00
Fixed problem where control-C was not recognized when multiple processes were running via gam batch/csv. Fixed problem where control-C was not recognized when multiple processes were running via gam batch/csv.
Gam terminates cleanly on Linux/MacOS when you hit control-C in this situation; on Windows exceptions are Gam terminates cleanly on Linux/macOS when you hit control-C in this situation; on Windows exceptions are
thrown but Gam does terminate. thrown but Gam does terminate.
4.41.08 4.41.08

View File

@@ -10,7 +10,7 @@ OPTIONS:
-d Directory where gam folder will be installed. Default is \$HOME/bin/ -d Directory where gam folder will be installed. Default is \$HOME/bin/
-a Architecture to install (x86_64, arm64). Default is to detect your arch with "uname -m". -a Architecture to install (x86_64, arm64). Default is to detect your arch with "uname -m".
-o OS we are running (linux, macos). Default is to detect your OS with "uname -s". -o OS we are running (linux, macos). Default is to detect your OS with "uname -s".
-b OS version. Default is to detect on MacOS and Linux. -b OS version. Default is to detect on macOS and Linux.
-l Just upgrade GAM to latest version. Skips project creation and auth. -l Just upgrade GAM to latest version. Skips project creation and auth.
-p Profile update (true, false). Should script add gam command to environment. Default is true. -p Profile update (true, false). Should script add gam command to environment. Default is true.
-u Admin user email address to use with GAM. Default is to prompt. -u Admin user email address to use with GAM. Default is to prompt.
@@ -247,7 +247,7 @@ case $gamos in
archgrep="-arm64\|-aarch64" archgrep="-arm64\|-aarch64"
;; ;;
*) *)
echo_red "ERROR: this installer currently only supports x86_64 and arm64 MacOS. Looks like you're running on ${gamarch}. Exiting." echo_red "ERROR: this installer currently only supports x86_64 and arm64 macOS. Looks like you're running on ${gamarch}. Exiting."
exit exit
;; ;;
esac esac
@@ -256,19 +256,19 @@ case $gamos in
versionless_urls=$(echo -e "$gam_macos_urls" | \ versionless_urls=$(echo -e "$gam_macos_urls" | \
grep -e "-macos-") grep -e "-macos-")
if [ "$versionless_urls" == "" ]; then if [ "$versionless_urls" == "" ]; then
# versions after 7.00.38 include MacOS version info # versions after 7.00.38 include macOS version info
gam_macos_vers=$(echo -e "$gam_macos_urls" | \ gam_macos_vers=$(echo -e "$gam_macos_urls" | \
grep --only-matching -e '-macos[0-9\.]*' | \ grep --only-matching -e '-macos[0-9\.]*' | \
cut -c 7-10) cut -c 7-10)
for gam_mac_ver in $gam_macos_vers; do for gam_mac_ver in $gam_macos_vers; do
if version_gt $currentversion $gam_mac_ver; then if version_gt $currentversion $gam_mac_ver; then
download_url=$(echo -e "$gam_macos_urls" | grep "$gam_mac_ver") download_url=$(echo -e "$gam_macos_urls" | grep "$gam_mac_ver")
echo_green "You are running MacOS ${currentversion} Using GAM compiled against ${gam_mac_ver}" echo_green "You are running macOS ${currentversion} Using GAM compiled against ${gam_mac_ver}"
break break
fi fi
done done
if [ -z ${download_url+x} ]; then if [ -z ${download_url+x} ]; then
echo_red "Sorry, you are running MacOS ${osversion} but GAM on ${gamarch} requires MacOS ${gam_mac_ver} or newer. Exiting." echo_red "Sorry, you are running macOS ${osversion} but GAM on ${gamarch} requires macOS ${gam_mac_ver} or newer. Exiting."
exit exit
fi fi
else else
@@ -283,13 +283,13 @@ case $gamos in
esac esac
download_url=$(echo -e "$download_urls" | grep -e $archgrep) download_url=$(echo -e "$download_urls" | grep -e $archgrep)
if version_gt "$osversion" "$minimum_version"; then if version_gt "$osversion" "$minimum_version"; then
echo_green "You are running MacOS ${osversion}, good. Downloading GAM from ${download_url}." echo_green "You are running macOS ${osversion}, good. Downloading GAM from ${download_url}."
else else
echo_red "Sorry, you are running MacOS ${osversion} but GAM on ${gamarch} requires MacOS ${minimum_version}. Exiting." echo_red "Sorry, you are running macOS ${osversion} but GAM on ${gamarch} requires macOS ${minimum_version}. Exiting."
exit exit
fi fi
if [ -z ${download_url+x} ]; then if [ -z ${download_url+x} ]; then
echo_red "Sorry, you are running MacOS ${currentversion} but GAM on ${gamarch} requires MacOS ${minimum_version}. Exiting." echo_red "Sorry, you are running macOS ${currentversion} but GAM on ${gamarch} requires macOS ${minimum_version}. Exiting."
exit exit
fi fi
fi fi
@@ -302,7 +302,7 @@ case $gamos in
grep ".zip") grep ".zip")
;; ;;
*) *)
echo_red "Sorry, this installer currently only supports Linux and MacOS. Looks like you're running on ${gamos}. Exiting." echo_red "Sorry, this installer currently only supports Linux and macOS. Looks like you're running on ${gamos}. Exiting."
exit exit
;; ;;
esac esac
@@ -368,18 +368,15 @@ if [ "$upgrade_only" = true ]; then
exit exit
fi fi
# Set config command
#config_cmd="config no_browser false"
while true; do while true; do
read -p "Can you run a full browser on this machine? (usually Y for MacOS, N for Linux if you SSH into this machine) " yn read -p "Can you run a full browser on this machine? (usually Y for macOS, N for Linux if you SSH into this machine) " yn
case $yn in case $yn in
[Yy]*) [Yy]*)
"$target_gam" config no_browser false save
break break
;; ;;
[Nn]*) [Nn]*)
# config_cmd="config no_browser true" "$target_gam" config no_browser true save
touch "$target_folder/nobrowser.txt" > /dev/null 2>&1
break break
;; ;;
*) *)
@@ -397,7 +394,6 @@ while true; do
if [ "$adminuser" == "" ]; then if [ "$adminuser" == "" ]; then
read -p "Please enter your Google Workspace admin email address: " adminuser read -p "Please enter your Google Workspace admin email address: " adminuser
fi fi
# "$target_gam" $config_cmd create project $adminuser
"$target_gam" create project $adminuser "$target_gam" create project $adminuser
rc=$? rc=$?
if (( $rc == 0 )); then if (( $rc == 0 )); then
@@ -423,7 +419,6 @@ while $project_created; do
read -p "Are you ready to authorize GAM to perform Google Workspace management operations as your admin account? (yes or no) " yn read -p "Are you ready to authorize GAM to perform Google Workspace management operations as your admin account? (yes or no) " yn
case $yn in case $yn in
[Yy]*) [Yy]*)
# "$target_gam" $config_cmd oauth create $adminuser
"$target_gam" oauth create $adminuser "$target_gam" oauth create $adminuser
rc=$? rc=$?
if (( $rc == 0 )); then if (( $rc == 0 )); then
@@ -453,7 +448,6 @@ while $admin_authorized; do
read -p "Please enter the email address of a regular Google Workspace user: " regularuser read -p "Please enter the email address of a regular Google Workspace user: " regularuser
fi fi
echo_yellow "Great! Checking service account scopes.This will fail the first time. Follow the steps to authorize and retry. It can take a few minutes for scopes to PASS after they've been authorized in the admin console." echo_yellow "Great! Checking service account scopes.This will fail the first time. Follow the steps to authorize and retry. It can take a few minutes for scopes to PASS after they've been authorized in the admin console."
# "$target_gam" $config_cmd user $regularuser check serviceaccount
"$target_gam" user $regularuser check serviceaccount "$target_gam" user $regularuser check serviceaccount
rc=$? rc=$?
if (( $rc == 0 )); then if (( $rc == 0 )); then
@@ -475,7 +469,6 @@ while $admin_authorized; do
done done
echo_green "Here's information about your new GAM installation:" echo_green "Here's information about your new GAM installation:"
#"$target_gam" $config_cmd save version extended
"$target_gam" version extended "$target_gam" version extended
rc=$? rc=$?
if (( $rc != 0 )); then if (( $rc != 0 )); then

116
src/gam.iss Normal file
View File

@@ -0,0 +1,116 @@
; --- 1. PREPROCESSOR DEFINITIONS ---
#define AppVersion GetEnv("GAMVERSION")
#if AppVersion == ""
#define AppVersion "7.0.0"
#endif
; Pull architecture directly from GitHub Actions environment variable
#define RunnerArch GetEnv("RUNNER_ARCH")
[Setup]
; --- 2. CORE APPLICATION INFO ---
AppId={{D86B52B2-EFE9-4F9D-8BA3-9D84B9B2D319}
AppName=GAM7
AppVersion={#AppVersion}
AppPublisher=GAM Team - google-apps-manager@googlegroups.com
DefaultDirName={sd}\GAM7
LicenseFile=dist\gam\gam7\LICENSE
PrivilegesRequired=admin
ChangesEnvironment=yes
; Tell Inno Setup to use a custom signtool defined via the command line
SignTool=gamsigntool
; --- 3. COMPRESSION & OPTIMIZATION ---
Compression=lzma2/ultra64
SolidCompression=yes
; --- 4. DYNAMIC ARCHITECTURE CONFIGURATION ---
; GitHub Actions RUNNER_ARCH is typically uppercase "ARM64" or "X64"
#if RunnerArch == "ARM64" || RunnerArch == "arm64"
ArchitecturesAllowed=arm64
ArchitecturesInstallIn64BitMode=arm64
OutputBaseFilename=gam-{#AppVersion}-windows-arm64
#else
ArchitecturesAllowed=x64compatible
ArchitecturesInstallIn64BitMode=x64compatible
OutputBaseFilename=gam-{#AppVersion}-windows-x86_64
#endif
[Messages]
; Custom error if an admin tries to run the ARM64 installer on an Intel machine
#if RunnerArch == "ARM64" || RunnerArch == "arm64"
WindowsVersionNotSupported=You downloaded the ARM64 version of GAM, but this computer has an Intel or AMD processor.%n%nPlease go back to the release page and download the x86_64 installer instead.
#endif
[Files]
; --- 5. DYNAMIC FILE INCLUSION ---
Source: "dist\gam\gam7\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
[Registry]
; --- 6. PATH ENVIRONMENT VARIABLE ---
Root: HKLM; Subkey: "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"; \
ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};{app}"; \
Check: NeedsAddPath(ExpandConstant('{app}'))
[Code]
const
ERROR_SUCCESS = 0;
function MsiEnumRelatedProducts(lpUpgradeCode: string; dwReserved: Integer; iProductIndex: Integer; lpProductBuf: string): Integer;
external 'MsiEnumRelatedProductsW@msi.dll stdcall';
function UninstallWixMSI(): Boolean;
var
UpgradeCode: string;
ProductCode: string;
ResultCode: Integer;
begin
UpgradeCode := '{D86B52B2-EFE9-4F9D-8BA3-9D84B9B2D319}';
ProductCode := StringOfChar(' ', 39);
ResultCode := MsiEnumRelatedProducts(UpgradeCode, 0, 0, ProductCode);
if ResultCode = ERROR_SUCCESS then
begin
ProductCode := Trim(ProductCode);
Exec('msiexec.exe', '/x ' + ProductCode + ' /qn /norestart', '', SW_HIDE, ewWaitUntilTerminated, ResultCode);
end;
Result := True;
end;
function InitializeSetup(): Boolean;
begin
// --- Architecture Warning for Emulation ---
#if RunnerArch != "ARM64" && RunnerArch != "arm64"
if IsArm64() then
begin
if MsgBox('Notice: You are installing the Intel (x86_64) build of GAM on an ARM processor.' + #13#10#13#10 +
'While this will work via Windows emulation, it will perform worse than the native ARM64 version.' + #13#10#13#10 +
'Do you want to continue with the installation anyway?',
mbConfirmation, MB_YESNO) = idNo then
begin
Result := False;
Exit;
end;
end;
#endif
UninstallWixMSI();
Result := True;
end;
function NeedsAddPath(Param: string): boolean;
var
OrigPath: string;
begin
if not RegQueryStringValue(HKEY_LOCAL_MACHINE,
'SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
'Path', OrigPath)
then begin
Result := True;
exit;
end;
Result := Pos(';' + Param + ';', ';' + OrigPath + ';') = 0;
end;

View File

@@ -8,7 +8,7 @@
Manufacturer="GAM Team - google-apps-manager@googlegroups.com" Manufacturer="GAM Team - google-apps-manager@googlegroups.com"
UpgradeCode="D86B52B2-EFE9-4F9D-8BA3-9D84B9B2D319"> UpgradeCode="D86B52B2-EFE9-4F9D-8BA3-9D84B9B2D319">
<Package <Package
InstallerVersion="200" Compressed="yes" InstallScope="perMachine" /> InstallerVersion="500" Compressed="yes" InstallScope="perMachine" />
<MajorUpgrade <MajorUpgrade
DowngradeErrorMessage= DowngradeErrorMessage=

View File

@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
""" """
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>' __author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
__version__ = '7.34.06' __version__ = '7.35.01'
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)' __license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
# pylint: disable=wrong-import-position # pylint: disable=wrong-import-position
@@ -4349,7 +4349,8 @@ def SetGlobalVariables():
# warn if the json files are missing and return True # warn if the json files are missing and return True
if (Cmd.Location() == 1) or (Cmd.ArgumentsRemaining()): if (Cmd.Location() == 1) or (Cmd.ArgumentsRemaining()):
_chkCfgDirectories(sectionName) _chkCfgDirectories(sectionName)
_chkCfgFiles(sectionName) if not Cmd.PeekArgumentPresent(['checkconn', 'checkconnection', 'comment', 'oauth', 'oauth2', 'version']):
_chkCfgFiles(sectionName)
if status['errors']: if status['errors']:
sys.exit(CONFIG_ERROR_RC) sys.exit(CONFIG_ERROR_RC)
if GC.Values[GC.NO_CACHE]: if GC.Values[GC.NO_CACHE]:
@@ -4688,7 +4689,7 @@ def writeClientCredentials(creds, filename):
if filename != '-': if filename != '-':
writeFile(filename, json.dumps(creds_data, indent=2, sort_keys=True)+'\n') writeFile(filename, json.dumps(creds_data, indent=2, sort_keys=True)+'\n')
else: else:
writeStdout(json.dumps(creds_data, ensure_ascii=False, sort_keys=True, indent=2)+'\n') writeStdout(json.dumps(creds_data, ensure_ascii=False, indent=2, sort_keys=True)+'\n')
URL_SHORTENER_ENDPOINT = 'https://gam-shortn.appspot.com/create' URL_SHORTENER_ENDPOINT = 'https://gam-shortn.appspot.com/create'
@@ -9499,6 +9500,33 @@ def getOSPlatform():
pltfrm = platform.platform() pltfrm = platform.platform()
return f'{myos} {pltfrm}' return f'{myos} {pltfrm}'
def inspect_untrusted_cert(url):
"""Bypasses validation momentarily to extract the untrusted Issuer."""
parsed = urlparse(url if '://' in url else f'https://{url}')
host = parsed.hostname
port = parsed.port or 443
# Create an unverified context purely for diagnostic extraction
ctx = ssl.create_default_context()
ctx.check_hostname = False
ctx.verify_mode = ssl.CERT_NONE
try:
with socket.create_connection((host, port), timeout=5) as sock:
with ctx.wrap_socket(sock, server_hostname=host) as ssock:
der_cert = ssock.getpeercert(binary_form=True)
cert = x509.load_der_x509_certificate(der_cert, default_backend())
issuer = cert.issuer.rfc4514_string()
subject = cert.subject.rfc4514_string()
try:
san_ext = cert.extensions.get_extension_for_oid(x509.oid.ExtensionOID.SUBJECT_ALTERNATIVE_NAME)
# Loop through the list of SANs (DNS names, IP addresses, etc.)
sans = [str(name.value) for name in san_ext.value]
san_str = ", ".join(sans)
except x509.ExtensionNotFound:
san_str = "None"
return f"Untrusted Issuer: {issuer}\n Server Subject: {subject}\n SANs: {san_str}"
except Exception as e:
return f"Failed to retrieve diagnostic certificate: {e}"
# gam checkconnection # gam checkconnection
def doCheckConnection(): def doCheckConnection():
@@ -9534,6 +9562,10 @@ def doCheckConnection():
writeStdout(f'{not_okay}\n Connection reset by peer. {gen_firewall}\n') writeStdout(f'{not_okay}\n Connection reset by peer. {gen_firewall}\n')
except httplib2.error.ServerNotFoundError: except httplib2.error.ServerNotFoundError:
writeStdout(f'{not_okay}\n Failed to find server. Your DNS is probably misconfigured.\n') writeStdout(f'{not_okay}\n Failed to find server. Your DNS is probably misconfigured.\n')
except ssl.SSLCertVerificationError as e:
diag_info = inspect_untrusted_cert(host)
# e.verify_message contains the specific OpenSSL error string
writeStdout(f'{not_okay}\n Certificate verification failed: {e.verify_message}\n Diagnostic Info:\n {diag_info}\nIf you are behind a firewall / proxy server that does TLS / SSL inspection you may need to point GAM at your certificate authority file by setting cacerts_pem = /path/to/your/certauth.pem in gam.cfg.\n')
except ssl.SSLError as e: except ssl.SSLError as e:
if e.reason == 'SSLV3_ALERT_HANDSHAKE_FAILURE': if e.reason == 'SSLV3_ALERT_HANDSHAKE_FAILURE':
writeStdout(f'{not_okay}\n GAM expects to connect with TLS 1.3 or newer and that failed. If your firewall / proxy server is not compatible with TLS 1.3 then you can tell GAM to allow TLS 1.2 by setting tls_min_version = TLSv1.2 in gam.cfg.\n') writeStdout(f'{not_okay}\n GAM expects to connect with TLS 1.3 or newer and that failed. If your firewall / proxy server is not compatible with TLS 1.3 then you can tell GAM to allow TLS 1.2 by setting tls_min_version = TLSv1.2 in gam.cfg.\n')
@@ -9725,8 +9757,6 @@ def CSVFileQueueHandler(mpQueue, mpQueueStdout, mpQueueStderr, csvPF, datetimeNo
GC.Values[GC.TIMEZONE] = tzinfo GC.Values[GC.TIMEZONE] = tzinfo
GC.Values[GC.OUTPUT_TIMEFORMAT] = output_timeformat GC.Values[GC.OUTPUT_TIMEFORMAT] = output_timeformat
clearRowFilters = False clearRowFilters = False
# if sys.platform.startswith('win'):
# signal.signal(signal.SIGINT, signal.SIG_IGN)
if multiprocessing.get_start_method() != 'fork': if multiprocessing.get_start_method() != 'fork':
signal.signal(signal.SIGINT, signal.SIG_IGN) signal.signal(signal.SIGINT, signal.SIG_IGN)
Cmd = glclargs.GamCLArgs() Cmd = glclargs.GamCLArgs()
@@ -9776,7 +9806,7 @@ def CSVFileQueueHandler(mpQueue, mpQueueStdout, mpQueueStderr, csvPF, datetimeNo
GC.Values = dataItem GC.Values = dataItem
csvPF.SetColumnDelimiter(GC.Values[GC.CSV_OUTPUT_COLUMN_DELIMITER]) csvPF.SetColumnDelimiter(GC.Values[GC.CSV_OUTPUT_COLUMN_DELIMITER])
csvPF.SetNoEscapeChar(GC.Values[GC.CSV_OUTPUT_NO_ESCAPE_CHAR]) csvPF.SetNoEscapeChar(GC.Values[GC.CSV_OUTPUT_NO_ESCAPE_CHAR])
csvPF.SetQuoteChar(GC.Values[GC.CSV_OUTPUT_QUOTE_CHAR]) # csvPF.SetQuoteChar(GC.Values[GC.CSV_OUTPUT_QUOTE_CHAR])
csvPF.SetSortHeaders(GC.Values[GC.CSV_OUTPUT_SORT_HEADERS]) csvPF.SetSortHeaders(GC.Values[GC.CSV_OUTPUT_SORT_HEADERS])
csvPF.SetTimestampColumn(GC.Values[GC.CSV_OUTPUT_TIMESTAMP_COLUMN]) csvPF.SetTimestampColumn(GC.Values[GC.CSV_OUTPUT_TIMESTAMP_COLUMN])
csvPF.SetHeaderFilter(GC.Values[GC.CSV_OUTPUT_HEADER_FILTER]) csvPF.SetHeaderFilter(GC.Values[GC.CSV_OUTPUT_HEADER_FILTER])
@@ -9843,8 +9873,6 @@ def StdQueueHandler(mpQueue, stdtype, gmGlobals, gcValues):
except IOError as e: except IOError as e:
systemErrorExit(FILE_ERROR_RC, fdErrorMessage(fd, GM.Globals[stdtype][GM.REDIRECT_NAME], e)) systemErrorExit(FILE_ERROR_RC, fdErrorMessage(fd, GM.Globals[stdtype][GM.REDIRECT_NAME], e))
# if sys.platform.startswith('win'):
# signal.signal(signal.SIGINT, signal.SIG_IGN)
if multiprocessing.get_start_method() != 'fork': if multiprocessing.get_start_method() != 'fork':
signal.signal(signal.SIGINT, signal.SIG_IGN) signal.signal(signal.SIGINT, signal.SIG_IGN)
GM.Globals = gmGlobals.copy() GM.Globals = gmGlobals.copy()
@@ -9938,7 +9966,6 @@ def ProcessGAMCommandMulti(pid, numItems, logCmd, mpQueueCSVFile, mpQueueStdout,
with mplock: with mplock:
initializeLogging() initializeLogging()
# if sys.platform.startswith('win'):
if multiprocessing.get_start_method() != 'fork': if multiprocessing.get_start_method() != 'fork':
signal.signal(signal.SIGINT, signal.SIG_IGN) signal.signal(signal.SIGINT, signal.SIG_IGN)
GM.Globals[GM.API_CALLS_RETRY_DATA] = {} GM.Globals[GM.API_CALLS_RETRY_DATA] = {}
@@ -12480,7 +12507,7 @@ def checkServiceAccount(users):
saScopes[API.DRIVE2] = saScopes[API.DRIVE3] saScopes[API.DRIVE2] = saScopes[API.DRIVE3]
GM.Globals[GM.OAUTH2SERVICE_JSON_DATA][API.OAUTH2SA_SCOPES] = saScopes GM.Globals[GM.OAUTH2SERVICE_JSON_DATA][API.OAUTH2SA_SCOPES] = saScopes
writeFile(GC.Values[GC.OAUTH2SERVICE_JSON], writeFile(GC.Values[GC.OAUTH2SERVICE_JSON],
json.dumps(GM.Globals[GM.OAUTH2SERVICE_JSON_DATA], ensure_ascii=False, sort_keys=True, indent=2), json.dumps(GM.Globals[GM.OAUTH2SERVICE_JSON_DATA], ensure_ascii=False, indent=2, sort_keys=True),
continueOnError=False) continueOnError=False)
checkScopes = sorted(checkScopesSet) checkScopes = sorted(checkScopesSet)
jcount = len(checkScopes) jcount = len(checkScopes)
@@ -12967,7 +12994,7 @@ def doProcessSvcAcctKeys(mode=None, iam=None, projectId=None, clientEmail=None,
except (IndexError, KeyError, SyntaxError, TypeError, ValueError) as e: except (IndexError, KeyError, SyntaxError, TypeError, ValueError) as e:
invalidOauth2serviceJsonExit(str(e)) invalidOauth2serviceJsonExit(str(e))
GM.Globals[GM.OAUTH2SERVICE_JSON_DATA][API.OAUTH2SA_SCOPES] = GM.Globals[GM.SVCACCT_SCOPES] GM.Globals[GM.OAUTH2SERVICE_JSON_DATA][API.OAUTH2SA_SCOPES] = GM.Globals[GM.SVCACCT_SCOPES]
oauth2service_data = json.dumps(GM.Globals[GM.OAUTH2SERVICE_JSON_DATA], ensure_ascii=False, sort_keys=True, indent=2) oauth2service_data = json.dumps(GM.Globals[GM.OAUTH2SERVICE_JSON_DATA], ensure_ascii=False, indent=2, sort_keys=True)
writeFile(GC.Values[GC.OAUTH2SERVICE_JSON], oauth2service_data, continueOnError=False) writeFile(GC.Values[GC.OAUTH2SERVICE_JSON], oauth2service_data, continueOnError=False)
Act.Set(Act.UPDATE) Act.Set(Act.UPDATE)
entityActionPerformed([Ent.OAUTH2SERVICE_JSON_FILE, GC.Values[GC.OAUTH2SERVICE_JSON], entityActionPerformed([Ent.OAUTH2SERVICE_JSON_FILE, GC.Values[GC.OAUTH2SERVICE_JSON],
@@ -13133,7 +13160,7 @@ def doCreateGCPServiceAccount():
except GAPI.invalid as e: except GAPI.invalid as e:
systemErrorExit(API_ACCESS_DENIED_RC, str(e)) systemErrorExit(API_ACCESS_DENIED_RC, str(e))
sa_info['client_id'] = token_info['issued_to'] sa_info['client_id'] = token_info['issued_to']
sa_output = json.dumps(sa_info, ensure_ascii=False, sort_keys=True, indent=2) sa_output = json.dumps(sa_info, ensure_ascii=False, indent=2, sort_keys=True)
writeStdout(f'Writing SignJWT service account data:\n\n{sa_output}\n') writeStdout(f'Writing SignJWT service account data:\n\n{sa_output}\n')
writeFile(GC.Values[GC.OAUTH2SERVICE_JSON], sa_output, continueOnError=False) writeFile(GC.Values[GC.OAUTH2SERVICE_JSON], sa_output, continueOnError=False)
@@ -31661,6 +31688,7 @@ UPDATE_PRINTER_JSON_SKIP_FIELDS = ['id', 'name', 'createTime', 'orgUnitId', 'org
def _getPrinterAttributes(cd, jsonDeleteFields): def _getPrinterAttributes(cd, jsonDeleteFields):
'''get printer attributes for create/update commands''' '''get printer attributes for create/update commands'''
body = {} body = {}
returnIdOnly = False
showDetails = True showDetails = True
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
@@ -31679,13 +31707,15 @@ def _getPrinterAttributes(cd, jsonDeleteFields):
body['useDriverlessConfig'] = getBoolean() body['useDriverlessConfig'] = getBoolean()
elif myarg == 'nodetails': elif myarg == 'nodetails':
showDetails = False showDetails = False
elif myarg == 'returnidonly':
returnIdOnly = True
elif myarg == 'json': elif myarg == 'json':
body.update(getJSON(jsonDeleteFields)) body.update(getJSON(jsonDeleteFields))
else: else:
unknownArgumentExit() unknownArgumentExit()
if body.get('makeAndModel'): if body.get('makeAndModel'):
body.pop('useDriverlessConfig', None) body.pop('useDriverlessConfig', None)
return (body, showDetails) return (body, showDetails, returnIdOnly)
PRINTER_FIELDS_CHOICE_MAP = { PRINTER_FIELDS_CHOICE_MAP = {
'auxiliarymessages': 'auxiliaryMessages', 'auxiliarymessages': 'auxiliaryMessages',
@@ -31731,33 +31761,39 @@ def _showPrinter(cd, printer, FJQC, orgUnitId=None, showInherited=False, i=0, co
showJSON(None, printer, timeObjects=PRINTER_TIME_OBJECTS) showJSON(None, printer, timeObjects=PRINTER_TIME_OBJECTS)
Ind.Decrement() Ind.Decrement()
# gam create printer <PrinterAttribute>+ [nodetails] # gam create printer <PrinterAttribute>+ [nodetails|returnidonly]
def doCreatePrinter(): def doCreatePrinter():
cd = buildGAPIObject(API.DIRECTORY) cd = buildGAPIObject(API.DIRECTORY)
parent = _getCustomersCustomerIdWithC() parent = _getCustomersCustomerIdWithC()
body, showDetails = _getPrinterAttributes(cd, CREATE_PRINTER_JSON_SKIP_FIELDS) body, showDetails, returnIdOnly = _getPrinterAttributes(cd, CREATE_PRINTER_JSON_SKIP_FIELDS)
if not body.get('orgUnitId'): if not body.get('orgUnitId'):
missingArgumentExit('orgunit') missingArgumentExit('orgunit')
try: try:
printer = callGAPI(cd.customers().chrome().printers(), 'create', printer = callGAPI(cd.customers().chrome().printers(), 'create',
throwReasons=[GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED], throwReasons=[GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
parent=parent, body=body) parent=parent, body=body)
if returnIdOnly:
writeStdout(f"{printer['id']}\n")
return
entityActionPerformed([Ent.PRINTER, printer['id']]) entityActionPerformed([Ent.PRINTER, printer['id']])
if showDetails: if showDetails:
_showPrinter(cd, printer, None) _showPrinter(cd, printer, None)
except (GAPI.invalidArgument, GAPI.permissionDenied) as e: except (GAPI.invalidArgument, GAPI.permissionDenied) as e:
entityActionFailedWarning([Ent.PRINTER, None], str(e)) entityActionFailedWarning([Ent.PRINTER, None], str(e))
# gam update printer <PrinterID> <PrinterAttribute>+ [nodetails] # gam update printer <PrinterID> <PrinterAttribute>+ [nodetails|returnidonly]
def doUpdatePrinter(): def doUpdatePrinter():
name, printerId, cd = _getPrinterID() name, printerId, cd = _getPrinterID()
body, showDetails = _getPrinterAttributes(cd, UPDATE_PRINTER_JSON_SKIP_FIELDS) body, showDetails, returnIdOnly = _getPrinterAttributes(cd, UPDATE_PRINTER_JSON_SKIP_FIELDS)
updateMask = ','.join(list(body.keys())) updateMask = ','.join(list(body.keys()))
# note clearMask seems unnecessary. Updating field to '' clears it. # note clearMask seems unnecessary. Updating field to '' clears it.
try: try:
printer = callGAPI(cd.customers().chrome().printers(), 'patch', printer = callGAPI(cd.customers().chrome().printers(), 'patch',
throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED], throwReasons=[GAPI.NOT_FOUND, GAPI.INVALID_ARGUMENT, GAPI.PERMISSION_DENIED],
name=name, updateMask=updateMask, body=body) name=name, updateMask=updateMask, body=body)
if returnIdOnly:
writeStdout(f"{printer['id']}\n")
return
entityActionPerformed([Ent.PRINTER, printerId]) entityActionPerformed([Ent.PRINTER, printerId])
if showDetails: if showDetails:
_showPrinter(cd, printer, None) _showPrinter(cd, printer, None)
@@ -37770,8 +37806,7 @@ def _cleanPolicy(policy, add_warnings, no_appnames,
def _showPolicy(policy, FJQC, i=0, count=0): def _showPolicy(policy, FJQC, i=0, count=0):
if FJQC is not None and FJQC.formatJSON: if FJQC is not None and FJQC.formatJSON:
printLine(json.dumps(cleanJSON(policy, timeObjects=CIPOLICY_TIME_OBJECTS), printLine(json.dumps(cleanJSON(policy, timeObjects=CIPOLICY_TIME_OBJECTS),
ensure_ascii=False, ensure_ascii=False, sort_keys=True))
sort_keys=True))
return return
printEntity([Ent.POLICY, policy['name']], i, count) printEntity([Ent.POLICY, policy['name']], i, count)
Ind.Increment() Ind.Increment()
@@ -37784,10 +37819,11 @@ def _showPolicies(policies, FJQC, add_warnings, no_appnames,
groupEmailPattern, orgUnitPathPattern, groupEmailPattern, orgUnitPathPattern,
cd, groups_ci): cd, groups_ci):
count = len(policies) count = len(policies)
if groupEmailPattern is None and orgUnitPathPattern is None: if FJQC is None or not FJQC.formatJSON:
performActionNumItems(count, Ent.POLICY) if groupEmailPattern is None and orgUnitPathPattern is None:
else: performActionNumItems(count, Ent.POLICY)
performActionModifierNumItems(Msg.MAXIMUM_OF, count, Ent.POLICY) else:
performActionModifierNumItems(Msg.MAXIMUM_OF, count, Ent.POLICY)
Ind.Increment() Ind.Increment()
i = 0 i = 0
for policy in policies: for policy in policies:
@@ -37998,8 +38034,7 @@ def doPrintShowCIPolicies():
elif csvPF.CheckRowTitles(row): elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({'name': policy['name'], csvPF.WriteRowNoFilter({'name': policy['name'],
'JSON': json.dumps(cleanJSON(policy, timeObjects=CIPOLICY_TIME_OBJECTS), 'JSON': json.dumps(cleanJSON(policy, timeObjects=CIPOLICY_TIME_OBJECTS),
ensure_ascii=False, ensure_ascii=False, sort_keys=True)})
sort_keys=True)})
_checkPoliciesWithDASA() _checkPoliciesWithDASA()
ci = buildGAPIObject(API.CLOUDIDENTITY_POLICY) ci = buildGAPIObject(API.CLOUDIDENTITY_POLICY)
@@ -39636,8 +39671,7 @@ def doPrintShowBuildings():
else: else:
if (not csvPF.rowFilter and not csvPF.rowDropFilter) or csvPF.CheckRowTitles(row): if (not csvPF.rowFilter and not csvPF.rowDropFilter) or csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({'buildingId': building['buildingId'], csvPF.WriteRowNoFilter({'buildingId': building['buildingId'],
'JSON': json.dumps(cleanJSON(building), 'JSON': json.dumps(cleanJSON(building), ensure_ascii=False, sort_keys=True)})
ensure_ascii=False, sort_keys=True)})
if csvPF: if csvPF:
csvPF.writeCSVfile('Buildings') csvPF.writeCSVfile('Buildings')
@@ -40545,8 +40579,8 @@ def _printShowCalendarACLs(cal, user, entityType, calId, i, count, csvPF, FJQC,
if not FJQC.formatJSON: if not FJQC.formatJSON:
csvPF.WriteRowTitles(row) csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row): elif csvPF.CheckRowTitles(row):
row = {'calendarId': calId, 'JSON': json.dumps(cleanJSON(rule), row = {'calendarId': calId,
ensure_ascii=False, sort_keys=False)} 'JSON': json.dumps(cleanJSON(rule), ensure_ascii=False, sort_keys=False)}
if user: if user:
row['primaryEmail'] = user row['primaryEmail'] = user
if addCSVData: if addCSVData:
@@ -40565,8 +40599,8 @@ def _printShowCalendarACLs(cal, user, entityType, calId, i, count, csvPF, FJQC,
if not FJQC.formatJSON: if not FJQC.formatJSON:
csvPF.WriteRowTitles(row) csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row): elif csvPF.CheckRowTitles(row):
row = {'resourceId': user, 'resourceEmail': calId, 'JSON': json.dumps(cleanJSON(rule), row = {'resourceId': user, 'resourceEmail': calId,
ensure_ascii=False, sort_keys=False)} 'JSON': json.dumps(cleanJSON(rule), ensure_ascii=False, sort_keys=False)}
if addCSVData: if addCSVData:
row.update(addCSVData) row.update(addCSVData)
csvPF.WriteRowNoFilter(row) csvPF.WriteRowNoFilter(row)
@@ -46009,10 +46043,13 @@ def doCreateGuestUser():
checkForExtraneousArguments() checkForExtraneousArguments()
try: try:
result = callGAPI(cd.users(), 'createGuest', result = callGAPI(cd.users(), 'createGuest',
throwReasons=[GAPI.FAILED_PRECONDITION], throwReasons=[GAPI.FAILED_PRECONDITION, GAPI.INVALID_ARGUMENT],
body=body) body=body)
entityActionPerformed([Ent.GUEST_USER, result['primaryGuestEmail']]) entityActionPerformed([Ent.GUEST_USER, body['primaryGuestEmail']])
except (GAPI.failedPrecondition) as e: Ind.Increment()
showJSON(None, result)
Ind.Decrement()
except (GAPI.failedPrecondition, GAPI.invalidArgument) as e:
entityActionFailedExit([Ent.GUEST_USER, body['primaryGuestEmail']], str(e)) entityActionFailedExit([Ent.GUEST_USER, body['primaryGuestEmail']], str(e))
# gam <UserTypeEntity> update user <UserAttribute>* # gam <UserTypeEntity> update user <UserAttribute>*
@@ -46624,8 +46661,9 @@ USER_FIELDS_CHOICE_MAP = {
'firstname': 'name.givenName', 'firstname': 'name.givenName',
'fullname': 'name.fullName', 'fullname': 'name.fullName',
'gal': 'includeInGlobalAddressList', 'gal': 'includeInGlobalAddressList',
'givenname': 'name.givenName',
'gender': ['gender.type', 'gender.customGender', 'gender.addressMeAs'], 'gender': ['gender.type', 'gender.customGender', 'gender.addressMeAs'],
'givenname': 'name.givenName',
'guestaccountinfo': 'guestAccountInfo',
'id': 'id', 'id': 'id',
'im': 'ims', 'im': 'ims',
'ims': 'ims', 'ims': 'ims',
@@ -46635,6 +46673,7 @@ USER_FIELDS_CHOICE_MAP = {
'isdelegatedadmin': ['isAdmin', 'isDelegatedAdmin'], 'isdelegatedadmin': ['isAdmin', 'isDelegatedAdmin'],
'isenforcedin2sv': 'isEnforcedIn2Sv', 'isenforcedin2sv': 'isEnforcedIn2Sv',
'isenrolledin2sv': 'isEnrolledIn2Sv', 'isenrolledin2sv': 'isEnrolledIn2Sv',
'isguestuser': 'isGuestUser',
'is2svenforced': 'isEnforcedIn2Sv', 'is2svenforced': 'isEnforcedIn2Sv',
'is2svenrolled': 'isEnrolledIn2Sv', 'is2svenrolled': 'isEnrolledIn2Sv',
'ismailboxsetup': 'isMailboxSetup', 'ismailboxsetup': 'isMailboxSetup',
@@ -48318,8 +48357,7 @@ def doPrintShowInboundSSOProfiles():
csvPF.WriteRowTitles(row) csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row): elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({'name': profile['name'], csvPF.WriteRowNoFilter({'name': profile['name'],
'JSON': json.dumps(cleanJSON(profile), 'JSON': json.dumps(cleanJSON(profile), ensure_ascii=False, sort_keys=True)})
ensure_ascii=False, sort_keys=True)})
if csvPF: if csvPF:
csvPF.writeCSVfile('Inbound SSO Profiles') csvPF.writeCSVfile('Inbound SSO Profiles')
@@ -48800,8 +48838,7 @@ def doPrintShowInboundSSOAssignments():
csvPF.WriteRowTitles(row) csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row): elif csvPF.CheckRowTitles(row):
csvPF.WriteRowNoFilter({'name': assignment['name'], csvPF.WriteRowNoFilter({'name': assignment['name'],
'JSON': json.dumps(cleanJSON(assignment), 'JSON': json.dumps(cleanJSON(assignment), ensure_ascii=False, sort_keys=True)})
ensure_ascii=False, sort_keys=True)})
if csvPF: if csvPF:
csvPF.writeCSVfile('Inbound SSO Assignments') csvPF.writeCSVfile('Inbound SSO Assignments')
@@ -68168,8 +68205,7 @@ def printShowDriveLabelPermissions(users, useAdminAccess=False):
csvPF.WriteRowTitles(row) csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row): elif csvPF.CheckRowTitles(row):
row = {'User': user, 'name': labelperm['name']} row = {'User': user, 'name': labelperm['name']}
row['JSON'] = json.dumps(cleanJSON(labelperm), row['JSON'] = json.dumps(cleanJSON(labelperm), ensure_ascii=False, sort_keys=True)
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowNoFilter(row) csvPF.WriteRowNoFilter(row)
except (GAPI.permissionDenied, GAPI.notFound) as e: except (GAPI.permissionDenied, GAPI.notFound) as e:
entityActionFailedWarning(kvList, str(e), j, jcount) entityActionFailedWarning(kvList, str(e), j, jcount)
@@ -70905,8 +70941,7 @@ def printShowGroupTree(users):
row = {'User': user, 'Group': groupEmail, 'Name': group['name']} row = {'User': user, 'Group': groupEmail, 'Name': group['name']}
if rolesSet: if rolesSet:
row['Role'] = role row['Role'] = role
row['JSON'] = json.dumps(cleanJSON(groupInfo), row['JSON'] = json.dumps(cleanJSON(groupInfo), ensure_ascii=False, sort_keys=True)
ensure_ascii=False, sort_keys=True)
csvPF.WriteRowNoFilter(row) csvPF.WriteRowNoFilter(row)
Ind.Decrement() Ind.Decrement()
if csvPF: if csvPF:
@@ -71335,6 +71370,13 @@ def updatePhoto(users):
continue continue
body = {'photoData': base64.urlsafe_b64encode(image_data).decode(UTF8)} body = {'photoData': base64.urlsafe_b64encode(image_data).decode(UTF8)}
try: try:
try:
callGAPI(cd.users().photos(), 'delete',
bailOnInternalError=True,
throwReasons=[GAPI.USER_NOT_FOUND, GAPI.FORBIDDEN, GAPI.PHOTO_NOT_FOUND, GAPI.INTERNAL_ERROR],
userKey=user)
except (GAPI.photoNotFound, GAPI.internalError):
pass
callGAPI(cd.users().photos(), 'update', callGAPI(cd.users().photos(), 'update',
throwReasons=[GAPI.USER_NOT_FOUND, GAPI.FORBIDDEN, GAPI.INVALID_INPUT, GAPI.CONDITION_NOT_MET], throwReasons=[GAPI.USER_NOT_FOUND, GAPI.FORBIDDEN, GAPI.INVALID_INPUT, GAPI.CONDITION_NOT_MET],
userKey=user, body=body, fields='') userKey=user, body=body, fields='')
@@ -78628,7 +78670,8 @@ def _showTask(tasklist, task, j=0, jcount=0, FJQC=None, compact=False):
task['tasklistId'] = tasklist task['tasklistId'] = tasklist
task['taskId'] = f"{tasklist}/{task['id']}" task['taskId'] = f"{tasklist}/{task['id']}"
if FJQC is not None and FJQC.formatJSON: if FJQC is not None and FJQC.formatJSON:
printLine(json.dumps(cleanJSON(task, skipObjects=TASK_SKIP_OBJECTS, timeObjects=TASK_TIME_OBJECTS), ensure_ascii=False, sort_keys=True)) printLine(json.dumps(cleanJSON(task, skipObjects=TASK_SKIP_OBJECTS, timeObjects=TASK_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True))
return return
printEntity([Ent.TASK, task['taskId']], j, jcount) printEntity([Ent.TASK, task['taskId']], j, jcount)
Ind.Increment() Ind.Increment()
@@ -78972,7 +79015,8 @@ TASKLIST_TIME_OBJECTS = ['updated']
def _showTasklist(tasklist, j=0, jcount=0, FJQC=None): def _showTasklist(tasklist, j=0, jcount=0, FJQC=None):
if FJQC is not None and FJQC.formatJSON: if FJQC is not None and FJQC.formatJSON:
printLine(json.dumps(cleanJSON(tasklist, skipObjects=TASKLIST_SKIP_OBJECTS, timeObjects=TASKLIST_TIME_OBJECTS), ensure_ascii=False, sort_keys=True)) printLine(json.dumps(cleanJSON(tasklist, skipObjects=TASKLIST_SKIP_OBJECTS, timeObjects=TASKLIST_TIME_OBJECTS),
ensure_ascii=False, sort_keys=True))
return return
printEntity([Ent.TASKLIST, tasklist['id']], j, jcount) printEntity([Ent.TASKLIST, tasklist['id']], j, jcount)
Ind.Increment() Ind.Increment()

View File

@@ -1,3 +1,72 @@
#
# This is a custom certificate authority bundle for GAM
# It's composed of Let's Encrypt Root CAs and Google's
# certificate bundle. This should be the minimal list of
# CAs required to talk to Google and Github.
# Operating CA: Let's Encrypt
# Issuer: C = US, O = Internet Security Research Group, CN = ISRG Root X1
# Subject: C = US, O = Internet Security Research Group, CN = ISRG Root X1
# Label: "ISRG Root X1"
# Serial: 172886928669790476064670243504169061120
# MD5 Fingerprint: 0c:d2:f9:e0:da:17:73:e9:ed:86:4d:a5:e3:70:e7:4e
# SHA1 Fingerprint: ca:bd:2a:79:a1:07:6a:31:f2:1d:25:36:35:cb:03:9d:43:29:a5:e8
# SHA256 Fingerprint: 96:bc:ec:06:26:49:76:f3:74:60:77:9a:cf:28:c5:a7:cf:e8:a3:c0:aa:e1:1a:8f:fc:ee:05:c0:bd:df:08:c6
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
# Operating CA: Let's Encrypt
# Issuer: C = US, O = Internet Security Research Group, CN = ISRG Root X2
# Subject: C = US, O = Internet Security Research Group, CN = ISRG Root X2
# Label: "ISRG Root X2"
# Serial: 87493402998870891108772069816698636114
# MD5 Fingerprint: d3:9e:c4:1e:23:3c:a6:df:cf:a3:7e:6d:e0:14:e6:e5
# SHA1 Fingerprint: bd:b1:b9:3c:d5:97:8d:45:c6:26:14:55:f8:db:95:c7:5a:d1:53:af
# SHA256 Fingerprint: 69:72:9b:8e:15:a8:6e:fc:17:7a:57:af:b7:17:1d:fc:64:ad:d2:8c:2f:ca:8c:f1:50:7e:34:45:3c:cb:14:70
-----BEGIN CERTIFICATE-----
MIICGzCCAaGgAwIBAgIQQdKd0XLq7qeAwSxs6S+HUjAKBggqhkjOPQQDAzBPMQsw
CQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFyY2gg
R3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMjAeFw0yMDA5MDQwMDAwMDBaFw00
MDA5MTcxNjAwMDBaME8xCzAJBgNVBAYTAlVTMSkwJwYDVQQKEyBJbnRlcm5ldCBT
ZWN1cml0eSBSZXNlYXJjaCBHcm91cDEVMBMGA1UEAxMMSVNSRyBSb290IFgyMHYw
EAYHKoZIzj0CAQYFK4EEACIDYgAEzZvVn4CDCuwJSvMWSj5cz3es3mcFDR0HttwW
+1qLFNvicWDEukWVEYmO6gbf9yoWHKS5xcUy4APgHoIYOIvXRdgKam7mAHf7AlF9
ItgKbppbd9/w+kHsOdx1ymgHDB/qo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0T
AQH/BAUwAwEB/zAdBgNVHQ4EFgQUfEKWrt5LSDv6kviejM9ti6lyN5UwCgYIKoZI
zj0EAwMDaAAwZQIwe3lORlCEwkSHRhtFcP9Ymd70/aTSVaYgLXTWNLxBo1BfASdW
tL4ndQavEi51mI38AjEAi/V3bNTIZargCyzuFJ0nN6T5U6VR5CmD1/iQMVtCnwr1
/q4AaOeMSQ+2b1tbFfLn
-----END CERTIFICATE-----
# Operating CA: DigiCert # Operating CA: DigiCert
# Issuer: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com # 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 # Subject: CN=DigiCert Assured ID Root CA O=DigiCert Inc OU=www.digicert.com

View File

@@ -6,7 +6,7 @@
\deftab720 \deftab720
\pard\pardeftab720\sl276\slmult1\sa200\qc\partightenfactor0 \pard\pardeftab720\sl276\slmult1\sa200\qc\partightenfactor0
\f0\fs22 \cf0 Copyright 2025 Jay Lee\ \f0\fs22 \cf0 Copyright 2026 Jay Lee\
\pard\pardeftab720\sa200\qc\partightenfactor0 \pard\pardeftab720\sa200\qc\partightenfactor0
\f1\b \cf0 Licensed under the Apache License, Version 2.0 (the "License");\ \f1\b \cf0 Licensed under the Apache License, Version 2.0 (the "License");\

View File

@@ -1,128 +1,147 @@
// Node.js script that implements an Appium client which will launch // Node.js script to launch Simply Sign Desktop app and log a user in
// Simply Sign Desktop app and log a user in. Once logged in it should // using native Windows keystrokes and screenshot-desktop for reliable CI imaging.
// be possible to use tools like signtool.exe to sign Windows EXE/MSI files
// with the Certum certificate.
import { Key, remote } from 'webdriverio'; import { execSync, spawn } from 'child_process';
import { exec } from 'child_process';
import { TOTP } from 'totp-generator'; import { TOTP } from 'totp-generator';
import path from 'path';
async function screenshot(driver, filename) { import fs from 'fs';
// uncomment to save .png screenshots
await driver.saveScreenshot(filename);
return
}
function sleep(ms) { function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms)); return new Promise(resolve => setTimeout(resolve, ms));
} }
async function executeCommand(command) { // Native PowerShell Keystroke Sender
function sendKeys(keys) {
const script = `$wshell = New-Object -ComObject wscript.shell; $wshell.SendKeys('${keys}')`;
execSync(`powershell -Command "${script}"`);
}
// Native PowerShell Desktop Clear
function minimizeAllWindows() {
console.log('Minimizing all rogue background windows...');
const script = `$shell = New-Object -ComObject "Shell.Application"; $shell.MinimizeAll()`;
try { try {
let { stdout, stderr } = await exec(command); execSync(`powershell -Command "${script}"`);
return stdout; } catch (err) {
} catch (error) { console.log('Minimize command failed silently.');
console.error(`Error executing command: ${command}`);
console.error(`Error details: ${error}`);
throw error;
} }
} }
async function runSSD() { async function takeScreenshot(filename) {
const opts = { const workspace = process.env.GITHUB_WORKSPACE || process.cwd();
port: 4723, const fullPath = path.join(workspace, filename);
logLevel: "silent",
capabilities: {
platformName: "Windows",
"appium:app": "C:\\Program Files\\Certum\\SimplySign Desktop\\SimplySignDesktop.exe",
"appium:automationName": "Windows",
},
};
let driver; const psScript = `
try { Add-Type -AssemblyName System.Windows.Forms;
driver = await remote(opts); Add-Type -AssemblyName System.Drawing;
$Screen = [System.Windows.Forms.SystemInformation]::VirtualScreen;
// Github Actions Win ARM64 is stuck on a OOB screen that steals focus if ($Screen.Width -eq 0 -or $Screen.Height -eq 0) {
// These enter / escapes should dismiss it. Write-Error "Screen dimensions are 0x0. Desktop not fully initialized.";
const runner_arch = process.env.RUNNER_ARCH; exit 1;
if ( runner_arch === "ARM64" ) {
console.log('Running on ARM64...');
await sleep(3000); // Pause execution for 3 seconds
await screenshot(driver, 'oob1.png');
await driver.sendKeys([Key.Enter]);
await sleep(3000); // Pause execution for 3 seconds
await screenshot(driver, 'oob2.png');
await driver.sendKeys([Key.Enter]);
await sleep(3000); // Pause execution for 3 seconds
await screenshot(driver, 'oob3.png');
await driver.sendKeys([Key.Escape]);
await screenshot(driver, 'oob6.png');
} else {
console.log('NOT running on ARM64');
}
// Execute SSD again to open login dialog
exec('"C:\\Program Files\\Certum\\SimplySign Desktop\\SimplySignDesktop.exe"', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
});
await sleep(3000);
// Login
const windows = await driver.getWindowHandles();
const login_window = windows[0]
await driver.switchWindow(login_window);
await screenshot(driver, 'login01.png');
const id_value = 'jay0lee@gmail.com';
const id_arr = [...id_value];
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 { 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]);
// TODO: it's expected that on successful login the window
// will close and these screenshots will error out. Figure
// out how to handle that gracefully.
await screenshot(driver, 'login04.png');
await sleep(500);
await screenshot(driver, 'login05.png');
await sleep(500);
await screenshot(driver, 'login06.png');
await sleep(500);
await screenshot(driver, 'login07.png');
await sleep(500);
await screenshot(driver, 'login08.png');
await sleep(500);
await screenshot(driver, 'login09.png');
await sleep(500);
await screenshot(driver, 'login10.png');
await sleep(500);
await screenshot(driver, 'login11.png');
await sleep(500);
await screenshot(driver, 'login12.png');
} catch (error) {
console.error(error);
//console.error("Error during Appium run:");
} }
// INTENTIONAL Keep driver open so tray icon for Certum doesn't close $bitmap = New-Object System.Drawing.Bitmap $Screen.Width, $Screen.Height;
// finally { $graphic = [System.Drawing.Graphics]::FromImage($bitmap);
// if (driver) { $graphic.CopyFromScreen($Screen.Left, $Screen.Top, 0, 0, $bitmap.Size);
// await driver.deleteSession(); // Close the Appium session $bitmap.Save('${fullPath}');
// } `;
//}
try {
execSync(`powershell -Command "${psScript}"`);
console.log(`Saved screenshot: ${fullPath}`);
} catch (err) {
console.error(`Failed to save screenshot ${fullPath}:`, err.message);
}
}
// Fire and forget application launcher
function launchSSD() {
const child = spawn('C:\\Program Files\\Certum\\SimplySign Desktop\\SimplySignDesktop.exe', [], {
detached: true,
stdio: 'ignore'
});
child.unref();
}
async function runSSD() {
await takeScreenshot('001.png');
minimizeAllWindows();
await sleep(2000);
await takeScreenshot('002.png');
sendKeys('{ESC}');
await sleep(2000);
await takeScreenshot('003.png');
//sendKeys('{ESC}');
//await sleep(2000);
//await takeScreenshot('004.png');
//sendKeys('{ESC}');
//await sleep(2000);
//await takeScreenshot('005.png');
//sendKeys('%{F4}');
//await sleep(2000);
//await takeScreenshot('006.png');
//sendKeys('%{F4}');
//await sleep(2000);
//await takeScreenshot('007.png');
// Re-execute SSD to open login dialog
launchSSD();
await sleep(3000);
await takeScreenshot('008.png');
launchSSD();
await sleep(3000);
await takeScreenshot('009.png');
// 2. Login Flow
console.log('Typing credentials...');
// Type Email
sendKeys('jay0lee@gmail.com');
await sleep(500);
await takeScreenshot('010.png');
// Tab to next field
sendKeys('{TAB}');
await sleep(500);
// Generate and type TOTP
console.log(`Our secret is ${process.env.TOTP_SECRET.length} characters.`);
const { otp } = await TOTP.generate(process.env.TOTP_SECRET, {algorithm: 'SHA-256'});
console.log(`Our token is ${otp.length} characters.`);
sendKeys(otp);
await sleep(500);
await takeScreenshot('011.png');
// Submit
sendKeys('{ENTER}');
console.log('Login sequence complete.');
// Screenshot cascade to monitor the window closing
await takeScreenshot('012.png');
await sleep(500);
await takeScreenshot('013.png');
await sleep(500);
await takeScreenshot('014.png');
await sleep(500);
console.log('Exiting script, leaving SimplySign running in background.');
// Verification block to list all PNGs in the workspace
console.log('\n--- Screenshot Verification ---');
const workspace = process.env.GITHUB_WORKSPACE || process.cwd();
try {
const files = fs.readdirSync(workspace);
const pngFiles = files.filter(f => f.endsWith('.png'));
console.log(`Target Directory: ${workspace}`);
console.log(`Found ${pngFiles.length} .png files:`);
pngFiles.forEach(f => console.log(` - ${f}`));
} catch (err) {
console.error(`Error reading directory ${workspace}:`, err.message);
}
console.log('-------------------------------\n');
} }
runSSD(); runSSD();

View File

@@ -99,14 +99,25 @@ Typically, you will enclose the entire list in double quotes and quote each item
## Manage printers ## Manage printers
When creating a printer you must specify: `displayname`, `ou`, `uri` and `makeandmodel` or `driverless`. When creating a printer you must specify: `displayname`, `ou`, `uri` and `makeandmodel` or `driverless`.
``` ```
gam create printer <PrinterAttribute>+ [nodetails] gam create printer <PrinterAttribute>+ [nodetails|returnidonly]
gam update printer <PrinterID> <PrinterAttribute>+ [nodetails] gam update printer <PrinterID> <PrinterAttribute>+ [nodetails|returnidonly]
gam delete printer gam delete printer
<PrinterIDList>| <PrinterIDList>|
<FileSelector>| <FileSelector>|
<CSVFileSelector> <CSVFileSelector>
``` ```
By default, when a printer is created/updated, GAM outputs details of the printer; the `nodetails` option suppresses this output. By default, when a printer is created/updated, GAM outputs details of the printer.
* `nodetails` - Suppress the datails output.
* `returnidonly` - Display just the printer ID of the created printer as output
To retrieve the printer ID with `returnidonly`:
```
Linux/MacOS
printerId=$(gam create printer ... returnidonly)
Windows PowerShell
$printerId = & gam create printer ... returnidonly
```
The printer ID will only be valid when the return code of the command is 0; program accordingly.
## Display printers ## Display printers
Display information about a single printer. Display information about a single printer.

View File

@@ -25,41 +25,41 @@ start a new terminal session and reissue the command from above.
## Executable, Manual ## Executable, Manual
* Executable Archive, Manual, Linux/Google Cloud Shell * Executable Archive, Manual, Linux/Google Cloud Shell
- `gam-7.wx.yz-linux-x86_64-glibc2.36.tar.xz` - `gam-7.wx.yz-linux-x86_64-glibc2.35.tar.xz`
- `gam-7.wx.yz-linux-x86_64-glibc2.39.tar.xz` - `gam-7.wx.yz-linux-x86_64-glibc2.39.tar.xz`
- `gam-7.wx.yz-linux-x86_64-legacy.tar.xz` - `gam-7.wx.yz-linux-x86_64-legacy.tar.xz`
- Download the archive, extract the contents into some directory. - Download the archive, extract the contents into some directory.
- Start a terminal session. - Start a terminal session.
* Executable Archive, Manual, Raspberry Pi/ChromeOS ARM devices * Executable Archive, Manual, Raspberry Pi/ChromeOS ARM devices
- `gam-7.wx.yz-linux-arm64-glibc2.36.tar.xz` - `gam-7.wx.yz-linux-arm64-glibc2.35.tar.xz`
- `gam-7.wx.yz-linux-arm64-glibc2.39.tar.xz` - `gam-7.wx.yz-linux-arm64-glibc2.39.tar.xz`
- `gam-7.wx.yz-linux-arm64-legacy.tar.xz` - `gam-7.wx.yz-linux-arm64-legacy.tar.xz`
- Download the archive, extract the contents into some directory. - Download the archive, extract the contents into some directory.
- Start a terminal session. - Start a terminal session.
* Executable Archive, Manual, Mac OS versions Sonoma, Sequoia - M1/M2 * Executable Archive, Manual, Mac OS versions Sonoma, Sequoia - M1/M2
- `gam-7.wx.yz-macos14.7-arm64.tar.xz` - `gam-7.wx.yz-macos14.8-arm64.tar.xz`
- Download the archive, extract the contents into some directory. - Download the archive, extract the contents into some directory.
- Start a terminal session. - Start a terminal session.
* Executable Archive, Manual, Mac OS versions Sequoia - M2/M3 * Executable Archive, Manual, Mac OS versions Sequoia - M2/M3
- `gam-7.wx.yz-macos15.6-arm64.tar.xz` - `gam-7.wx.yz-macos15.7-arm64.tar.xz`
- Download the archive, extract the contents into some directory.
- Start a terminal session.
* 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. - Download the archive, extract the contents into some directory.
- Start a terminal session. - Start a terminal session.
* Executable Archive, Manual, Mac OS, versions Sequoia, Tahoe - Intel * Executable Archive, Manual, Mac OS, versions Sequoia, Tahoe - Intel
- `gam-7.wx.yz-macos15.6-x86_64.tar.xz` - `gam-7.wx.yz-macos15.7-x86_64.tar.xz`
- Download the archive, extract the contents into some directory.
- Start a terminal session.
* Executable Archive, Manual, Mac OS versions Tahoe - M2/M3/M4
- `gam-7.wx.yz-macos26.3-arm64.tar.xz`
- Download the archive, extract the contents into some directory.
- Start a terminal session.
* Executable Archive, Manual, Mac OS versions Tahoe - Intel
- `gam-7.wx.yz-macos26.3-x86_64.tar.xz`
- Download the archive, extract the contents into some directory. - Download the archive, extract the contents into some directory.
- Start a terminal session. - Start a terminal session.
@@ -69,7 +69,7 @@ start a new terminal session and reissue the command from above.
- Start a Command Prompt/PowerShell session. - Start a Command Prompt/PowerShell session.
* Executable Installer, Manual, Windows 64 bit * Executable Installer, Manual, Windows 64 bit
- `gam-7.wx.yz-windows-x86_64.msi` - `gam-7.wx.yz-windows-x86_64.exe`
- Download the installer and run it. - Download the installer and run it.
- Start a Command Prompt/PowerShell session. - Start a Command Prompt/PowerShell session.
@@ -79,7 +79,7 @@ start a new terminal session and reissue the command from above.
- Start a Command Prompt/PowerShell session. - Start a Command Prompt/PowerShell session.
* Executable Installer, Manual, Windows 11 ARM * Executable Installer, Manual, Windows 11 ARM
- `gam-7.wx.yz-windows-arm64.msi` - `gam-7.wx.yz-windows-arm64.exe`
- Download the installer and run it. - Download the installer and run it.
- Start a Command Prompt/PowerShell session. - Start a Command Prompt/PowerShell session.

View File

@@ -10,6 +10,87 @@ 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 See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Installs) for Windows or other options, including manual installation
### 7.35.00
Windows `gam-7.wx.yz-x86_64.msi` has been replaced with `gam-7.wx.yz-x86_64.exe`.
Windows `gam-7.wx.yz-arm64.msi` has been replaced with `gam-7.wx.yz-arm64.exe`.
Updated cacerts.pem to avoid to following error in `gam checkconn`.
```
Checking raw.githubusercontent.com (185.199.110.133) (2)... ERROR
Certificate verification failed. If you are behind a firewall / proxy server that does TLS / SSL inspection you may need to point GAM at your certificate authority file by setting cacerts_pem = /path/to/your/certauth.pem in gam.cfg.
```
If you have customized cacerts.pem, update your version with the `Operating CA: Let's Encrypt` values from the GAM default version.
### 7.34.13
Fixed bug in `gam info policies <CIPolicyNameEntity> ... formatjson` where extraneous line
`Show Info 1 Policy` was displayed.
### 7.34.12
Fixed build errors that prevented Windows zip files from being created.
Added option `returnidonly` to `gam create|update printer` that causes GAM to return just the ID
of the printer.
### 7.34.11
Updated gam-install.sh script for macOS/Linux to properly config GAM when the answer to the following question is No.
```
Can you run a full browser on this machine? (usually Y for macOS, N for Linux if you SSH into this machine)
```
### 7.34.10
Fixed bug where `formatjson quotechar <Character>` on the command line did not override `redirect csv <FileName> multiprocess quotechar <Character>`.
### 7.34.09
Updated `gam <UserTypeEntity> update photo` to delete the user's existing photo
before performing the update as the API update will succeed but not replace a user's existing self-set photo.
### 7.34.08
Rebuild to avoid the following error:
```
requests/__init__.py:113: RequestsDependencyWarning: urllib3 (2.6.3) or chardet (6.0.0.post1)/charset_normalizer (3.4.4) doesn't match a supported version!
```
### 7.34.07
Added the following command to create a guest user.
* See: https://support.google.com/a/answer/16558545
```
gam create guestuser <EmailAddress>
```
Added the following items to `<UserFieldName>`:
* `guestaccountinfo` - Additional guest-related metadata fields
* `isguestuser` - Indicates if the inserted user is a guest
### 7.34.06
Added option `copyfolderpermissions [<Boolean>]` to `gam <UserTypeEntity> copy|move drivefile`.
When `copyfolderpermissions false` is specified, no folder permissions are copied; this simplifies
disabling all folder permission copying.
When not specified or `copyfolderpermissions [true]` is specified, folder permissions are copied based on the following options:
```
copymergewithparentfolderpermissions [<Boolean>]
copymergedtopfolderpermissions [<Boolean>]
copytopfolderpermissions [<Boolean>]
copytopfolderiheritedpermissions [<Boolean>]
copytopfoldernoniheritedpermissions never|always|syncallfolders|syncupdatedfolders
copymergedsubfolderpermissions [<Boolean>]
copysubfolderpermissions [<Boolean>]
copysubfolderinheritedpermissions [<Boolean>]
copysubfoldernoniheritedpermissions never|always|syncallfolders|syncupdatedfolders
```
### 7.34.05 ### 7.34.05
Updated `gam report <ActivityApplictionName>` to perform a reverse chronological sort Updated `gam report <ActivityApplictionName>` to perform a reverse chronological sort

View File

@@ -129,7 +129,7 @@ See: [Downloads-Installs-GAM7](Downloads-Installs-GAM7)
### Update to latest version, use current path `C:\GAMADV-XTD3`. ### Update to latest version, use current path `C:\GAMADV-XTD3`.
You don't have to update path or scripts. You don't have to update path or scripts.
* Executable Installer, Manual, Windows 64 bit * Executable Installer, Manual, Windows 64 bit
- `gam-7.wx.yz-windows-x86_64.msi` - `gam-7.wx.yz-windows-x86_64.exe`
- Download the installer and run it. When prompted for the Destination Foler, enter `C:\GAMADV-XTD3`. - Download the installer and run it. When prompted for the Destination Foler, enter `C:\GAMADV-XTD3`.
* Executable Archive, Manual, Windows 64 bit * Executable Archive, Manual, Windows 64 bit
- `gam-7.wx.yz-windows-x86_64.zip` - `gam-7.wx.yz-windows-x86_64.zip`
@@ -139,7 +139,7 @@ Your update is complete.
### Update to latest version, use new path `C:\GAM7`. ### Update to latest version, use new path `C:\GAM7`.
* Executable Installer, Manual, Windows 64 bit * Executable Installer, Manual, Windows 64 bit
- `gam-7.wx.yz-windows-x86_64.msi` - `gam-7.wx.yz-windows-x86_64.exe`
- Download the installer and run it. - Download the installer and run it.
- Start a Command Prompt/PowerShell session. - Start a Command Prompt/PowerShell session.
* Executable Archive, Manual, Windows 64 bit * Executable Archive, Manual, Windows 64 bit

View File

@@ -252,10 +252,10 @@ writes the credentials into the file oauth2.txt.
gamteam@server:/Users/gamteam$ rm -f /Users/gamteam/GAMConfig/oauth2.txt gamteam@server:/Users/gamteam$ rm -f /Users/gamteam/GAMConfig/oauth2.txt
gamteam@server:/Users/gamteam$ gam version gamteam@server:/Users/gamteam$ gam version
WARNING: Config File: /Users/gamteam/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/gamteam/GAMConfig/oauth2.txt, Not Found WARNING: Config File: /Users/gamteam/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/gamteam/GAMConfig/oauth2.txt, Not Found
GAM 7.34.05 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.35.00 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.14.3 64-bit final Python 3.14.3 64-bit final
macOS Tahoe 26.3 arm64 macOS Tahoe 26.3.1 arm64
Path: /Users/gamteam/bin/gam7 Path: /Users/gamteam/bin/gam7
Config File: /Users/gamteam/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com Config File: /Users/gamteam/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
@@ -1036,7 +1036,7 @@ writes the credentials into the file oauth2.txt.
C:\>del C:\GAMConfig\oauth2.txt C:\>del C:\GAMConfig\oauth2.txt
C:\>gam version C:\>gam version
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
GAM 7.34.05 - https://github.com/GAM-team/GAM - pythonsource GAM 7.35.00 - https://github.com/GAM-team/GAM - pythonsource
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.14.3 64-bit final Python 3.14.3 64-bit final
Windows 11 10.0.26200 AMD64 Windows 11 10.0.26200 AMD64

View File

@@ -1,6 +1,7 @@
# Organizational Units # Organizational Units
- [API documentation](#api-documentation) - [API documentation](#api-documentation)
- [Definitions](#definitions) - [Definitions](#definitions)
- [Special character issues](#special-character-issues)
- [Special quoting](#special-quoting) - [Special quoting](#special-quoting)
- [Manage organizational units](#manage-organizational-units) - [Manage organizational units](#manage-organizational-units)
- [Add users to an organizational unit](#add-users-to-an-organizational-unit) - [Add users to an organizational unit](#add-users-to-an-organizational-unit)
@@ -50,6 +51,15 @@ For `<UserTypeEntity>`, see: [Collections of Users](Collections-Of-Users)
For `<CrOSTypeEntity>`, see: [Collections of ChromeOS Devices](Collections-of-ChromeOS-Devices) For `<CrOSTypeEntity>`, see: [Collections of ChromeOS Devices](Collections-of-ChromeOS-Devices)
## Special character issues
If an organizational unit name contains a `#` or a `+`, these commands will not work due to a bug
that Google does not plan to fix.
```
gam update org|ou <OrgUnitPath>
gam delete org|ou <OrgUnitPath>
gam info org|ou <OrgUnitPath>
```
## Special quoting ## Special quoting
You specify a single organizational unit with `org <OrgUnitPath>` and a list of organizationsl units with `orgs <OrgUnitList>`. You specify a single organizational unit with `org <OrgUnitPath>` and a list of organizationsl units with `orgs <OrgUnitList>`.
As organizational unit paths can contain spaces, some care must be used when entering `<OrgUnitPath>` and `<OrgUnitList>`. As organizational unit paths can contain spaces, some care must be used when entering `<OrgUnitPath>` and `<OrgUnitList>`.

View File

@@ -120,6 +120,7 @@ gam <UserTypeEntity> copy drivefile <DriveFileEntity>
[copyfilepermissions [<Boolean>]] [copyfilepermissions [<Boolean>]]
[copyfileinheritedpermissions [<Boolean>] [copyfileinheritedpermissions [<Boolean>]
[copyfilenoninheritedpermissions [<Boolean>] [copyfilenoninheritedpermissions [<Boolean>]
[copyfolderpermissions [<Boolean>]]
[copymergewithparentfolderpermissions [<Boolean>]] [copymergewithparentfolderpermissions [<Boolean>]]
[copymergedtopfolderpermissions [<Boolean>]] [copymergedtopfolderpermissions [<Boolean>]]
[copytopfolderpermissions [<Boolean>]] [copytopfolderpermissions [<Boolean>]]
@@ -294,6 +295,8 @@ When a folder is copied, its permissions are not copied; these options control c
of the form `option [<Boolean>]`; if `<Boolean>` is omitted, `true` is assumed. of the form `option [<Boolean>]`; if `<Boolean>` is omitted, `true` is assumed.
When copied, a target folder inherits the permissions of its parent folder; these options control whether/how GAM copies the existing source folder permissions. When copied, a target folder inherits the permissions of its parent folder; these options control whether/how GAM copies the existing source folder permissions.
* `copyfolderpermissions false` - The permissions of the source folders are not copied to the target folder.
* `copyfolderpermissions true` - The permissions of the source folders are copied to the target folder based on the following options; this is the default action.
When `mergewithparent` is `true`: 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. * `copymergewithparentfolderpermissions false` - The permissions of the source top folder are not not copied to the target folder; this is the default action.
@@ -571,6 +574,7 @@ gam <UserTypeEntity> move drivefile <DriveFileEntity> [newfilename <DriveFileNam
[createshortcutsfornonmovablefiles [<Boolean>]] [createshortcutsfornonmovablefiles [<Boolean>]]
[duplicatefiles overwriteolder|overwriteall|duplicatename|uniquename|skip] [duplicatefiles overwriteolder|overwriteall|duplicatename|uniquename|skip]
[duplicatefolders merge|duplicatename|uniquename|skip] [duplicatefolders merge|duplicatename|uniquename|skip]
[copyfolderpermissions [<Boolean>]]
[copymergewithparentfolderpermissions [<Boolean>]] [copymergewithparentfolderpermissions [<Boolean>]]
[copymergedtopfolderpermissions [<Boolean>]] [copymergedtopfolderpermissions [<Boolean>]]
[copytopfolderpermissions [<Boolean>]] [copytopfolderpermissions [<Boolean>]]
@@ -660,6 +664,8 @@ When a folder is moved by recreating it, its permissions are not copied by the D
For options of the form `option [<Boolean>]`; if `<Boolean>` is omitted, `true` is assumed. 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; When recreated, a target folder inherits the permissions of its parent folder; these options control whether/how GAM copies the existing source folder permissions;
* `copyfolderpermissions false` - The permissions of the source folders are not copied to the target folder.
* `copyfolderpermissions true` - The permissions of the source folders are copied to the target folder based on the following options; this is the default action.
When `mergewithparent` is `true`: 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. * `copymergewithparentfolderpermissions false` - The permissions of the source top folder are not not copied to the target folder; this is the default action.

View File

@@ -1,5 +1,6 @@
# Users - Photo # Users - Photo
- [API documentation](#api-documentation) - [API documentation](#api-documentation)
- [Notes](#notes)
- [Definitions](#definitions) - [Definitions](#definitions)
- [Upload a user's photo from a default file](#upload-a-users-photo-from-a-default-file) - [Upload a user's photo from a default file](#upload-a-users-photo-from-a-default-file)
- [Upload a user's photo specifying file name](#upload-a-users-photo-specifying-file-name) - [Upload a user's photo specifying file name](#upload-a-users-photo-specifying-file-name)
@@ -7,11 +8,16 @@
- [Upload a user's photo specifying a Google Drive owner and file name](#upload-a-users-photo-specifying-a-google-drive-owner-and-file-name) - [Upload a user's photo specifying a Google Drive owner and file name](#upload-a-users-photo-specifying-a-google-drive-owner-and-file-name)
- [Download a user's photo](#download-a-users-photo) - [Download a user's photo](#download-a-users-photo)
- [Delete a user's photo](#delete-a-users-photo) - [Delete a user's photo](#delete-a-users-photo)
- [Update photo fails to change user's photo](#update-photo-fails-to-change-users-photo)
- [Download a user's profile photo](Users-Profile-Photo) - [Download a user's profile photo](Users-Profile-Photo)
## API documentation ## API documentation
* [Directory API - Users Photos](https://developers.google.com/admin-sdk/directory/reference/rest/v1/users.photos) * [Directory API - Users Photos](https://developers.google.com/admin-sdk/directory/reference/rest/v1/users.photos)
## Notes
As of version 7.34.09, `gam <UserTypeEntity> update photo` was updated to delete the user's existing photo
before performing the update as the API update will succeed but not replace a user's existing self-set photo.
## Definitions ## Definitions
* [`<DriveFileEntity>`](Drive-File-Selection) * [`<DriveFileEntity>`](Drive-File-Selection)
* [`<UserTypeEntity>`](Collections-of-Users) * [`<UserTypeEntity>`](Collections-of-Users)
@@ -81,3 +87,7 @@ By default, the Base64 encoded data is dumped to stdout.
``` ```
gam <UserTypeEntity> delete|del photo gam <UserTypeEntity> delete|del photo
``` ```
## Update photo fails to change user's photo
If you use `gam <UserTypeEntity> update photo ...` to change a user's photo and the command succeeds
but the photo doesn't change, use `gam <UserTypeEntity> delete photo` first and then do the update.

View File

@@ -40,6 +40,7 @@
- [Print user list](#print-user-list) - [Print user list](#print-user-list)
- [Display user counts](#display-user-counts) - [Display user counts](#display-user-counts)
- [Verify domain membership](#verify-domain-membership) - [Verify domain membership](#verify-domain-membership)
- [Guest Users](#guest-users)
## API documentation ## API documentation
* [Directory API - Users](https://developers.google.com/admin-sdk/directory/reference/rest/v1/users) * [Directory API - Users](https://developers.google.com/admin-sdk/directory/reference/rest/v1/users)
@@ -169,6 +170,7 @@ queries "`"orgUnitPath=\'/Students/Lower\ School/2027\'`",`"orgUnitPath=\'/Stude
fullname| fullname|
gender| gender|
givenname|firstname| givenname|firstname|
guestaccountinfo|
id| id|
ims|im| ims|im|
includeinglobaladdresslist|gal| includeinglobaladdresslist|gal|
@@ -176,6 +178,7 @@ queries "`"orgUnitPath=\'/Students/Lower\ School/2027\'`",`"orgUnitPath=\'/Stude
isdelegatedadmin|admin|isadmin| isdelegatedadmin|admin|isadmin|
isenforcedin2sv|is2svenforced| isenforcedin2sv|is2svenforced|
isenrolledin2sv|is2svenrolled| isenrolledin2sv|is2svenrolled|
isguestuser|
ismailboxsetup| ismailboxsetup|
keyword|keywords| keyword|keywords|
language|languages| language|languages|
@@ -1384,3 +1387,11 @@ testuser1@domain.com,118080758787650801331,True,Test User 1
testuserxxx@domain.com,,False,Test User XXX testuserxxx@domain.com,,False,Test User XXX
testuser2@domain.com,107344800159717682514,True,Test User 2 testuser2@domain.com,107344800159717682514,True,Test User 2
``` ```
## Guest Users
* See: https://support.google.com/a/answer/16558545
```
gam create guestuser <EmailAddress>
```
Guest users are in the OU "/Workspace guests".

View File

@@ -11,7 +11,7 @@ It's important to confirm you are always running an official GAM7 release. The f
# GitHub Attestation (Linux/MacOS/Windows) # GitHub Attestation (Linux/MacOS/Windows)
GitHub offers [artifict attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds) which prove if a given GAM binary or archive was built by the [GAM-team/GAM](https://gitHub.com/GAM-team/GAM) project and links to the build job. This offers you certainty that the GAM executable you are running or the GAM package you downloaded were officially generated by the [GAM-team/GAM](https://gitHub.com/GAM-team/GAM) project. GitHub offers [artifict attestations](https://docs.github.com/en/actions/security-for-github-actions/using-artifact-attestations/using-artifact-attestations-to-establish-provenance-for-builds) which prove if a given GAM binary or archive was built by the [GAM-team/GAM](https://gitHub.com/GAM-team/GAM) project and links to the build job. This offers you certainty that the GAM executable you are running or the GAM package you downloaded were officially generated by the [GAM-team/GAM](https://gitHub.com/GAM-team/GAM) project.
To verify a given GAM executable file or package (.zip, .msi or .tar.xz) is legitimate, use the following steps: To verify a given GAM executable file or package (.zip, .exe or .tar.xz) is legitimate, use the following steps:
1. Install the [GitHub CLI command line tool](https://github.com/cli/cli#installation). 1. Install the [GitHub CLI command line tool](https://github.com/cli/cli#installation).
2. Login to the tool with the command. You need a [free GitHub account](https://gitHub.com/join) for this. 2. Login to the tool with the command. You need a [free GitHub account](https://gitHub.com/join) for this.
``` ```
@@ -27,7 +27,7 @@ gh attestation verify --repo GAM-team/GAM --format=json \
4. If the GAM file or package is legit you'll see output like: 4. If the GAM file or package is legit you'll see output like:
``` ```
Loaded digest sha256:a63dc5e71c0b3335865877fc7dc9248bbf7481d22995c18253a2ae71fcb9793a for file://gam-7.00.00-windows-x86_64.msi Loaded digest sha256:a63dc5e71c0b3335865877fc7dc9248bbf7481d22995c18253a2ae71fcb9793a for file://gam-7.00.00-windows-x86_64.exe
Loaded 1 attestation from GitHub API Loaded 1 attestation from GitHub API
✓ Verification succeeded! ✓ Verification succeeded!
@@ -77,7 +77,7 @@ origin=Developer ID Application: Jay Lee (GZ85H2DRLM)
If you do not see "accepted" and "Jay Lee" as the developer ID, there may be a problem. Please report any suspicious files or concerns to the [GAM Group](https://groups.google.com/g/google-apps-manager) or the [GAM Chat Space](https://git.io/gam-chat). If you do not see "accepted" and "Jay Lee" as the developer ID, there may be a problem. Please report any suspicious files or concerns to the [GAM Group](https://groups.google.com/g/google-apps-manager) or the [GAM Chat Space](https://git.io/gam-chat).
# Windows Code Sign # Windows Code Sign
On Windows, Official gam.exe files and MSI installer packages are signed by a [Certum Open Source code signing certificate](https://shop.certum.eu/open-source-code-signing.html). You can validate the signature and thus be sure you are running official GAM7 from the command line and GUI: On Windows, Official gam.exe files and EXE installer packages are signed by a [Certum Open Source code signing certificate](https://shop.certum.eu/open-source-code-signing.html). You can validate the signature and thus be sure you are running official GAM7 from the command line and GUI:
# Command Line # Command Line
From PowerShell, run the following command: From PowerShell, run the following command:
@@ -113,6 +113,6 @@ SignerCertificate : [Subject]
confirm that status is "Valid" and the SignerCertificate says "Open Source Developer, James Lee" (yes, James is Jay's legal name, now you know). confirm that status is "Valid" and the SignerCertificate says "Open Source Developer, James Lee" (yes, James is Jay's legal name, now you know).
## GUI ## GUI
From File Manager, you can right click on gam.exe or the MSI package and go to the Digital Signatures tab. From there you'll see the signing certificate which should show "Open Source Developer, James Lee". From File Manager, you can right click on gam.exe or the EXE installer package and go to the Digital Signatures tab. From there you'll see the signing certificate which should show "Open Source Developer, James Lee".
![image](https://github.com/user-attachments/assets/dceb8cb8-36e0-4ed7-8b03-09322b49b06a) ![image](https://github.com/user-attachments/assets/dceb8cb8-36e0-4ed7-8b03-09322b49b06a)

View File

@@ -1,12 +1,12 @@
# Version and Help \# Version and Help
Print the current version of Gam with details Print the current version of Gam with details
``` ```
gam version gam version
GAM 7.34.05 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.35.00 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.14.3 64-bit final Python 3.14.3 64-bit final
macOS Tahoe 26.3 arm64 macOS Tahoe 26.3.1 arm64
Path: /Users/gamteam/bin/gam7 Path: /Users/gamteam/bin/gam7
Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Time: 2026-02-15T07:51:00-08:00 Time: 2026-02-15T07:51:00-08:00
@@ -15,10 +15,10 @@ Time: 2026-02-15T07:51:00-08:00
Print the current version of Gam with details and time offset information Print the current version of Gam with details and time offset information
``` ```
gam version timeoffset gam version timeoffset
GAM 7.34.05 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.35.00 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.14.3 64-bit final Python 3.14.3 64-bit final
macOS Tahoe 26.3 arm64 macOS Tahoe 26.3.1 arm64
Path: /Users/gamteam/bin/gam7 Path: /Users/gamteam/bin/gam7
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com 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 Your system time differs from www.googleapis.com by less than 1 second
@@ -27,10 +27,10 @@ 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 Print the current version of Gam with extended details and SSL information
``` ```
gam version extended gam version extended
GAM 7.34.05 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.35.00 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.14.3 64-bit final Python 3.14.3 64-bit final
macOS Tahoe 26.3 arm64 macOS Tahoe 26.3.1 arm64
Path: /Users/gamteam/bin/gam7 Path: /Users/gamteam/bin/gam7
Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Time: 2026-02-15T07:51:00-08:00 Time: 2026-02-15T07:51:00-08:00
@@ -68,7 +68,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/gamteam/bin/gam7 Path: /Users/gamteam/bin/gam7
Version Check: Version Check:
Current: 5.35.08 Current: 5.35.08
Latest: 7.34.05 Latest: 7.35.00
echo $? echo $?
1 1
``` ```
@@ -76,7 +76,7 @@ echo $?
Print the current version number without details Print the current version number without details
``` ```
gam version simple gam version simple
7.34.05 7.35.00
``` ```
In Linux/MacOS you can do: In Linux/MacOS you can do:
``` ```
@@ -86,10 +86,10 @@ echo $VER
Print the current version of Gam and address of this Wiki Print the current version of Gam and address of this Wiki
``` ```
gam help gam help
GAM 7.34.05 - https://github.com/GAM-team/GAM GAM 7.35.00 - https://github.com/GAM-team/GAM
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.14.3 64-bit final Python 3.14.3 64-bit final
macOS Tahoe 26.3 arm64 macOS Tahoe 26.3.1 arm64
Path: /Users/gamteam/bin/gam7 Path: /Users/gamteam/bin/gam7
Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com Config File: /Users/gamteam/GamConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
Time: 2026-02-15T07:51:00-08:00 Time: 2026-02-15T07:51:00-08:00