Compare commits

...

31 Commits

Author SHA1 Message Date
Ross Scroggs
e95fcbaa38 Deleted commands to display Analytic UA properties; the API has been deprecated.
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
2025-04-25 15:10:59 -07:00
Ross Scroggs
a7b31550f3 Updated gam print group-members and gam print cigroup-members
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-04-25 12:29:11 -07:00
Jay Lee
ed19f877a5 Improved checkconn
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
checkconn now works from a base set of hosts and then builds it's full
list based on our discovery APIs and the host in their discovery document.
2025-04-24 18:55:45 +00:00
Jay Lee
0ab08c968e use a string for env var 2025-04-24 15:27:21 +00:00
Jay Lee
02a7a1a106 Merge branch 'main' of https://github.com/GAM-team/GAM 2025-04-24 15:18:04 +00:00
Jay Lee
170a2e593b disable legacy openssl for cryptography 2025-04-24 15:17:59 +00:00
Jay Lee
8339b92537 actions: disable building cryptography from source for now 2025-04-24 10:50:37 -04:00
Jay Lee
ce16aa252e Update build.yml 2025-04-24 09:58:24 -04:00
Jay Lee
8a70470281 actions: install few more linux packages 2025-04-24 09:08:33 -04:00
Jay Lee
981301a878 actions: list packages 2025-04-24 09:00:50 -04:00
Jay Lee
13cfb77811 actions: install packaging 2025-04-24 08:55:10 -04:00
Jay Lee
458e08645d Merge branch 'main' of https://github.com/GAM-team/GAM 2025-04-24 12:10:15 +00:00
Jay Lee
98d4d3c06f fix hostname for analytics API 2025-04-24 12:10:00 +00:00
Jay Lee
2204c35193 actions: install rust, fix cryptography install 2025-04-24 07:53:48 -04:00
Jay Lee
87827badb8 actions: disable legacy ssl for cryptography
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-04-24 07:39:47 -04:00
Ross Scroggs
319bedd338 Update Users-Chat.md 2025-04-23 20:47:30 -07:00
Ross Scroggs
b3e4541b9d Merge branch 'main' of https://github.com/GAM-team/GAM
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-04-23 15:17:29 -07:00
Ross Scroggs
9d17ea2d68 Added the following license SKU: 1010020034 2025-04-23 15:17:26 -07:00
Jay Lee
9c4b348909 [no ci] remove errant ' 2025-04-23 14:54:44 -04:00
Jay Lee
a8fafd0dcc [no ci] actions: attest wheels uploaded to PyPi 2025-04-23 14:52:02 -04:00
Ross Scroggs
ac31042576 Merge branch 'main' of https://github.com/GAM-team/GAM 2025-04-23 07:34:56 -07:00
Ross Scroggs
a0d695c57d Added gemini and geminiforworkspace to <ActivityApplicationName> for use in gam report <ActivityApplicationName>. 2025-04-23 07:34:08 -07:00
Jay Lee
bf742ec88a GAM 7.06.09 2025-04-23 14:30:13 +00:00
Jay Lee
f2206d02e4 Add gemini reports and support new reports dynamically. Fixes #1773 2025-04-23 13:31:15 +00:00
Jay Lee
c3add48f2a Update pyproject.toml
Some checks failed
Build and test GAM / build (build, 1, Build Intel Ubuntu Jammy, ubuntu-22.04) (push) Has been cancelled
Build and test GAM / build (build, 10, Build Intel Windows, windows-2022) (push) Has been cancelled
Build and test GAM / build (build, 11, Build Arm Windows, windows-11-arm) (push) Has been cancelled
Build and test GAM / build (build, 2, Build Intel Ubuntu Noble, ubuntu-24.04) (push) Has been cancelled
Build and test GAM / build (build, 3, Build Arm Ubuntu Noble, ubuntu-24.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 4, Build Arm Ubuntu Jammy, ubuntu-22.04-arm) (push) Has been cancelled
Build and test GAM / build (build, 5, Build Intel StaticX Legacy, ubuntu-22.04, yes) (push) Has been cancelled
Build and test GAM / build (build, 6, Build Arm StaticX Legacy, ubuntu-22.04-arm, yes) (push) Has been cancelled
Build and test GAM / build (build, 7, Build Intel MacOS, macos-13) (push) Has been cancelled
Build and test GAM / build (build, 8, Build Arm MacOS 14, macos-14) (push) Has been cancelled
Build and test GAM / build (build, 9, Build Arm MacOS 15, macos-15) (push) Has been cancelled
Build and test GAM / build (test, 12, Test Python 3.10, ubuntu-24.04, 3.10) (push) Has been cancelled
Build and test GAM / build (test, 13, Test Python 3.11, ubuntu-24.04, 3.11) (push) Has been cancelled
Build and test GAM / build (test, 14, Test Python 3.12, ubuntu-24.04, 3.12) (push) Has been cancelled
Build and test GAM / build (test, 15, Test Python 3.14-dev, ubuntu-24.04, 3.14-dev) (push) Has been cancelled
Build and test GAM / merge (push) Has been cancelled
Build and test GAM / publish (push) Has been cancelled
CodeQL / Analyze (python) (push) Has been cancelled
Check for Google Root CA Updates / check-apis (push) Has been cancelled
Push wiki / pushwiki (push) Has been cancelled
2025-04-22 19:20:28 -04:00
Jay Lee
119047bf2b [no ci] Update setup.cfg 2025-04-22 19:20:08 -04:00
Ross Scroggs
662b7d857c Fixed problem where Yubikeys caused a trap. 2025-04-22 15:38:18 -07:00
Ross Scroggs
3bb9724e50 Update Downloads-Installs.md 2025-04-22 14:30:32 -07:00
Ross Scroggs
b450716c23 Update Downloads-Installs.md 2025-04-22 14:06:24 -07:00
Ross Scroggs
73333f921d Updated gam create|use|update project 2025-04-22 13:50:04 -07:00
Jay Lee
c5d194489f [no ci] actions: fix description of possible arch choices 2025-04-22 16:01:09 -04:00
24 changed files with 304 additions and 218 deletions

View File

@@ -28,6 +28,8 @@ env:
OPENSSL_SOURCE_PATH: ${{ github.workspace }}/src/openssl OPENSSL_SOURCE_PATH: ${{ github.workspace }}/src/openssl
PYTHON_INSTALL_PATH: ${{ github.workspace }}/bin/python PYTHON_INSTALL_PATH: ${{ github.workspace }}/bin/python
PYTHON_SOURCE_PATH: ${{ github.workspace }}/src/cpython PYTHON_SOURCE_PATH: ${{ github.workspace }}/src/cpython
CRYPTOGRAPHY_BUILD_OPENSSL_NO_LEGACY: 1
CRYPTOGRAPHY_OPENSSL_NO_LEGACY: 1
jobs: jobs:
build: build:
@@ -124,7 +126,7 @@ jobs:
with: with:
path: | path: |
cache.tar.xz cache.tar.xz
key: gam-${{ matrix.jid }}-20250408-01 key: gam-${{ matrix.jid }}-20250422
- 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'
@@ -197,7 +199,7 @@ jobs:
run: | run: |
echo "RUNNING: apt update..." echo "RUNNING: apt update..."
sudo apt-get -qq --yes update sudo apt-get -qq --yes update
sudo apt-get -qq --yes install swig libpcsclite-dev libxslt1-dev libsqlite3-dev sudo apt-get -qq --yes install swig libpcsclite-dev libxslt1-dev libsqlite3-dev libffi-dev pkg-config
- name: MacOS install tools - name: MacOS install tools
if: runner.os == 'macOS' if: runner.os == 'macOS'
@@ -450,6 +452,9 @@ jobs:
"$PYTHON" -m pip install --upgrade pip "$PYTHON" -m pip install --upgrade pip
"$PYTHON" -m pip install --upgrade wheel "$PYTHON" -m pip install --upgrade wheel
"$PYTHON" -m pip install --upgrade setuptools "$PYTHON" -m pip install --upgrade setuptools
"$PYTHON" -m pip install --upgrade importlib-metadata
"$PYTHON" -m pip install --upgrade setuptools-scm
"$PYTHON" -m pip list
- name: Custom wheels for Win arm64 - name: Custom wheels for Win arm64
if: runner.os == 'Windows' && runner.arch == 'ARM64' if: runner.os == 'Windows' && runner.arch == 'ARM64'
@@ -463,6 +468,13 @@ jobs:
curl -O -L "$latest_crypt_whl" curl -O -L "$latest_crypt_whl"
"$PYTHON" -m pip install cryptography*.whl "$PYTHON" -m pip install cryptography*.whl
- uses: actions-rust-lang/setup-rust-toolchain@v1
# - name: Compile cryptography from source (no legacy)
# if: runner.os != 'Windows' || runner.arch != 'ARM64'
# run: |
# pip install --no-binary ":all:" --force cryptography
- name: Install pip requirements - name: Install pip requirements
run: | run: |
echo "before anything..." echo "before anything..."

View File

@@ -31,3 +31,5 @@ jobs:
- name: Publish package distributions to PyPI - name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1 uses: pypa/gh-action-pypi-publish@release/v1
with:
attestation: true

View File

@@ -7,19 +7,21 @@ authors = [
{ name="Jay Lee", email="jay0lee@gmail.com" }, { name="Jay Lee", email="jay0lee@gmail.com" },
{ name="Ross Scroggs", email="Ross.Scroggs@gmail.com" }, { name="Ross Scroggs", email="Ross.Scroggs@gmail.com" },
] ]
# # The following files should be edited to match: setup.cfg, requirements.txt
dependencies = [ dependencies = [
"chardet", "chardet>=5.2.0",
"cryptography", "cryptography>=44.0.2",
"distro; sys_platform=='linux'", "distro; sys_platform=='linux'",
"filelock", "filelock>=3.18.0",
"google-api-python-client>=2.1", "google-api-python-client>=2.167.0",
"google-auth-httplib2", "google-auth-httplib2>=0.2.0",
"google-auth-oauthlib>=0.4.1", "google-auth-oauthlib>=1.2.2",
"google-auth>=2.3.2", "google-auth>=2.39.0",
"httplib2>=0.17.0", "httplib2>=0.22.0",
"lxml", "lxml>=5.4.0",
"passlib>=1.7.2", "passlib>=1.7.4",
"pathvalidate", "pathvalidate>=3.2.3",
"pyscard==2.2.1",
"python-dateutil", "python-dateutil",
] ]
description = "CLI tool to manage Google Workspace" description = "CLI tool to manage Google Workspace"
@@ -39,7 +41,7 @@ license = {text = "Apache License (2.0)"}
license-files = ["LICEN[CS]E*"] license-files = ["LICEN[CS]E*"]
[project.optional-dependencies] [project.optional-dependencies]
yubikey = ["yubikey-manager>=5.0"] yubikey = ["yubikey-manager>=5.6.1"]
[project.scripts] [project.scripts]
gam = "gam.__main__:main" gam = "gam.__main__:main"

View File

@@ -322,7 +322,8 @@ If an item contains spaces, it should be surrounded by ".
wsess | workspaceesentials | gsuiteessentials | essentials | d4e | driveenterprise | drive4enterprise | 1010060001 | Google Workspace Essentials | wsess | workspaceesentials | gsuiteessentials | essentials | d4e | driveenterprise | drive4enterprise | 1010060001 | Google Workspace Essentials |
wsessplus | workspaceessentialsplus | 1010060005 | Google Workspace Essentials Plus | wsessplus | workspaceessentialsplus | 1010060005 | Google Workspace Essentials Plus |
wsflw | workspacefrontline | workspacefrontlineworker | 1010020030 | Google Workspace Frontline Starter | wsflw | workspacefrontline | workspacefrontlineworker | 1010020030 | Google Workspace Frontline Starter |
wsflwstan | workspacefrontlinestan | workspacefrontlineworkerstan | 1010020031 | Google Workspace Frontline Standard wsflwstan | workspacefrontlinestan | workspacefrontlineworkerstan | 1010020031 | Google Workspace Frontline Standard |
wsflwplus | workspacefrontlineplus | workspacefrontlineworkerplus | 1010020034 | Google Workspace Frontline Plus
## Items built from primitives ## Items built from primitives
@@ -782,7 +783,7 @@ Items, separated by spaces, with spaces, commas or single quotes in the items th
## Collections of ChromeOS Devices ## Collections of ChromeOS Devices
Specify a collection of ChromeOS devices by directly specifying them or by specifiying items that will yield a list of ChromeOS devices. Specify a collection of ChromeOS devices by directly specifying them or by specifying items that will yield a list of ChromeOS devices.
<CrOSTypeEntity> ::= <CrOSTypeEntity> ::=
(all cros)| (all cros)|
@@ -865,7 +866,7 @@ Specify a collection of ChromeOS devices by directly specifying them or by speci
## Collections of Users ## Collections of Users
Specify a collection of Users by directly specifying them or by specifiying items that will yield a list of users. Specify a collection of Users by directly specifying them or by specifying items that will yield a list of users.
<UserTypeEntity> ::= <UserTypeEntity> ::=
(all users|users_ns|users_susp|users_ns_susp)| (all users|users_ns|users_susp|users_ns_susp)|
@@ -1522,17 +1523,6 @@ gam print alias|aliases [todrive <ToDriveAttribute>*]
gam whatis <EmailItem> [noinfo] [noinivitablecheck] gam whatis <EmailItem> [noinfo] [noinivitablecheck]
# Analytics UA
gam <UserTypeEntity> print analyticuaproperties [todrive <ToDriveAttribute>*]
accountid [accounts/]<String>
[maxresults <Integer>]
[formatjson [quotechar <Character>]]
gam <UserTypeEntity> show analyticuaproperties
accountid [accounts/]<String>
[maxresults <Integer>]
[formatjson]
# Analytics Admin # Analytics Admin
gam <UserTypeEntity> print analyticaccounts [todrive <ToDriveAttribute>*] gam <UserTypeEntity> print analyticaccounts [todrive <ToDriveAttribute>*]
@@ -4458,6 +4448,7 @@ gam report usage customer [todrive <ToDriveAttribute>*]
domain| domain|
drive|doc|docs| drive|doc|docs|
gcp| gcp|
gemini|geminiforworkspace|
groups|group| groups|group|
groupsenterprise|enterprisegroups| groupsenterprise|enterprisegroups|
jamboard| jamboard|

View File

@@ -1,7 +1,51 @@
7.06.12
Deleted commands to display Analytic UA properties; the API has been deprecated.
```
gam <UserTypeEntity> print|show analyticuaproperties
```
7.06.11
Improved `gam checkconn`.
Updated `gam print group-members` and `gam print cigroup-members` to recognize members
that are groups representing chat spaces. For now, these groups are not expanded when
`recursive` is specified.
7.06.10
Added the following license SKU.
```
1010020034 - Google Workspace Frontline Plus
```
7.06.09
Added `gemini` and `geminiforworkspace` to `<ActivityApplicationName>` for use in
`gam report <ActivityApplicationName>`.
7.06.08
Fixed problem where Yubikeys caused a trap.
7.06.07
Updated private key rotation progress messages in `gam create|use|update project`
and `gam upload sakey`.
Updated `gam use project` to display the following error message when the specifed project
already has a service account.
```
Re-run the command specify a new service account name with: saname <ServiceAccountName>'
```
7.06.06 7.06.06
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".
7.06.05 7.06.05
Updated code in `gam delete|update chromepolicy` to handle the `policyTargetKey[additionalTargetKeys]` Updated code in `gam delete|update chromepolicy` to handle the `policyTargetKey[additionalTargetKeys]`

View File

@@ -8,7 +8,7 @@ GAM installation script.
OPTIONS: OPTIONS:
-h show help. -h show help.
-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 (i386, x86_64, x86_64_legacy, arm, 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.

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.06.06' __version__ = '7.06.12'
__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
@@ -95,6 +95,8 @@ import wsgiref.simple_server
import wsgiref.util import wsgiref.util
import zipfile import zipfile
# disable legacy stuff we don't use and isn't secure
os.environ['CRYPTOGRAPHY_OPENSSL_NO_LEGACY'] = "1"
from cryptography import x509 from cryptography import x509
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives import hashes, serialization
@@ -9358,32 +9360,9 @@ def getOSPlatform():
# gam checkconnection # gam checkconnection
def doCheckConnection(): def doCheckConnection():
hosts = ['api.github.com',
'raw.githubusercontent.com', def check_host(host):
'accounts.google.com', nonlocal try_count, okay, not_okay, success_count
'workspace.google.com',
'oauth2.googleapis.com',
'www.googleapis.com']
fix_hosts = {'calendar-json.googleapis.com': 'www.googleapis.com',
'storage-api.googleapis.com': 'storage.googleapis.com'}
api_hosts = ['apps-apis.google.com',
'sites.google.com',
'versionhistory.googleapis.com',
'www.google.com']
for host in API.PROJECT_APIS:
host = fix_hosts.get(host, host)
if host not in api_hosts and host not in hosts:
api_hosts.append(host)
hosts.extend(sorted(api_hosts))
host_count = len(hosts)
httpObj = getHttpObj(timeout=30)
httpObj.follow_redirects = False
headers = {'user-agent': GAM_USER_AGENT}
okay = createGreenText('OK')
not_okay = createRedText('ERROR')
try_count = 0
success_count = 0
for host in hosts:
try_count += 1 try_count += 1
dns_err = None dns_err = None
ip = 'unknown' ip = 'unknown'
@@ -9393,12 +9372,12 @@ def doCheckConnection():
dns_err = f'{not_okay}\n DNS failure: {str(e)}\n' dns_err = f'{not_okay}\n DNS failure: {str(e)}\n'
except Exception as e: except Exception as e:
dns_err = f'{not_okay}\n Unknown DNS failure: {str(e)}\n' dns_err = f'{not_okay}\n Unknown DNS failure: {str(e)}\n'
check_line = f'Checking {host} ({ip}) ({try_count}/{host_count})...' check_line = f'Checking {host} ({ip}) ({try_count})...'
writeStdout(f'{check_line:<100}') writeStdout(f'{check_line:<100}')
flushStdout() flushStdout()
if dns_err: if dns_err:
writeStdout(dns_err) writeStdout(dns_err)
continue return
gen_firewall = 'You probably have security software or a firewall on your machine or network that is preventing GAM from making Internet connections. Check your network configuration or try running GAM on a hotspot or home network to see if the problem exists only on your organization\'s network.' gen_firewall = 'You probably have security software or a firewall on your machine or network that is preventing GAM from making Internet connections. Check your network configuration or try running GAM on a hotspot or home network to see if the problem exists only on your organization\'s network.'
try: try:
if host.startswith('http'): if host.startswith('http'):
@@ -9427,7 +9406,54 @@ def doCheckConnection():
writeStdout(f'{not_okay}\n Timed out trying to connect to host\n') writeStdout(f'{not_okay}\n Timed out trying to connect to host\n')
except Exception as e: except Exception as e:
writeStdout(f'{not_okay}\n {str(e)}\n') writeStdout(f'{not_okay}\n {str(e)}\n')
if success_count == host_count:
try_count = 0
httpObj = getHttpObj(timeout=30)
httpObj.follow_redirects = False
headers = {'user-agent': GAM_USER_AGENT}
okay = createGreenText('OK')
not_okay = createRedText('ERROR')
success_count = 0
initial_hosts = ['api.github.com',
'raw.githubusercontent.com',
'accounts.google.com',
'oauth2.googleapis.com',
'www.googleapis.com']
for host in initial_hosts:
check_host(host)
api_hosts = ['apps-apis.google.com',
'www.google.com']
for host in api_hosts:
check_host(host)
# For v2 discovery APIs, GAM gets discovery file from <api>.googleapis.com so
# add those domains.
disc_hosts = []
for api, config in API._INFO.items():
if config.get('v2discovery') and not config.get('localdiscovery'):
if mapped_api := config.get('mappedAPI'):
api = mapped_api
host = f'{api}.googleapis.com'
if host not in disc_hosts:
disc_hosts.append(host)
for host in disc_hosts:
check_host(host)
checked_hosts = initial_hosts + api_hosts + disc_hosts
# now we need to "build" each API and check it's base URL host
# if we haven't already. This may not be any hosts at all but
# to ensure we are checking all hosts GAM may use we should
# keep this.
for api in API._INFO:
if api in [API.CONTACTS, API.EMAIL_AUDIT]:
continue
svc = getService(api, httpObj)
base_url = svc._rootDesc.get('baseUrl')
parsed_base_url = urlparse(base_url)
base_host = parsed_base_url.netloc
if base_host not in checked_hosts:
writeStdout(f'Checking {base_host} for {api}\n')
check_host(base_host)
checked_hosts.append(base_host)
if success_count == try_count:
writeStdout(createGreenText('All hosts passed!\n')) writeStdout(createGreenText('All hosts passed!\n'))
else: else:
systemErrorExit(3, createYellowText('Some hosts failed to connect! Please follow the recommendations for those hosts to correct any issues and try again.')) systemErrorExit(3, createYellowText('Some hosts failed to connect! Please follow the recommendations for those hosts to correct any issues and try again.'))
@@ -11384,25 +11410,26 @@ def _waitForSvcAcctCompletion(i):
sys.stdout.write(Msg.WAITING_FOR_ITEM_CREATION_TO_COMPLETE_SLEEPING.format(Ent.Singular(Ent.SVCACCT), sleep_time)) sys.stdout.write(Msg.WAITING_FOR_ITEM_CREATION_TO_COMPLETE_SLEEPING.format(Ent.Singular(Ent.SVCACCT), sleep_time))
time.sleep(sleep_time) time.sleep(sleep_time)
def _grantRotateRights(iam, projectId, service_account, email, account_type='serviceAccount'): def _grantRotateRights(iam, projectId, service_account, account_type='serviceAccount'):
body = {'policy': {'bindings': [{'role': 'roles/iam.serviceAccountKeyAdmin', body = {'policy': {'bindings': [{'role': 'roles/iam.serviceAccountKeyAdmin',
'members': [f'{account_type}:{email}']}]}} 'members': [f'{account_type}:{service_account}']}]}}
maxRetries = 10 maxRetries = 10
printEntityMessage([Ent.PROJECT, projectId, Ent.SVCACCT, email], kvList = [Ent.PROJECT, projectId, Ent.SVCACCT, service_account]
Msg.HAS_RIGHTS_TO_ROTATE_OWN_PRIVATE_KEY.format(email, service_account)) printEntityMessage(kvList, Msg.GRANTING_RIGHTS_TO_ROTATE_ITS_OWN_PRIVATE_KEY.format('Granting'))
for retry in range(1, maxRetries+1): for retry in range(1, maxRetries+1):
try: try:
callGAPI(iam.projects().serviceAccounts(), 'setIamPolicy', callGAPI(iam.projects().serviceAccounts(), 'setIamPolicy',
throwReasons=[GAPI.INVALID_ARGUMENT], throwReasons=[GAPI.INVALID_ARGUMENT],
resource=f'projects/{projectId}/serviceAccounts/{service_account}', body=body) resource=f'projects/{projectId}/serviceAccounts/{service_account}', body=body)
printEntityMessage(kvList, Msg.GRANTING_RIGHTS_TO_ROTATE_ITS_OWN_PRIVATE_KEY.format('Granted'))
return True return True
except GAPI.invalidArgument as e: except GAPI.invalidArgument as e:
entityActionFailedWarning([Ent.PROJECT, projectId, Ent.SVCACCT, service_account], str(e)) entityActionFailedWarning(kvList, str(e))
if 'does not exist' not in str(e) or retry == maxRetries: if 'does not exist' not in str(e) or retry == maxRetries:
return False return False
_waitForSvcAcctCompletion(retry) _waitForSvcAcctCompletion(retry)
except Exception as e: except Exception as e:
entityActionFailedWarning([Ent.PROJECT, projectId, Ent.SVCACCT, service_account], str(e)) entityActionFailedWarning(kvList, str(e))
return False return False
def _createOauth2serviceJSON(httpObj, projectInfo, svcAcctInfo, create_key=True): def _createOauth2serviceJSON(httpObj, projectInfo, svcAcctInfo, create_key=True):
@@ -11420,6 +11447,7 @@ def _createOauth2serviceJSON(httpObj, projectInfo, svcAcctInfo, create_key=True)
return False return False
except GAPI.alreadyExists as e: except GAPI.alreadyExists as e:
entityActionFailedWarning([Ent.PROJECT, projectInfo['projectId'], Ent.SVCACCT, svcAcctInfo['name']], str(e)) entityActionFailedWarning([Ent.PROJECT, projectInfo['projectId'], Ent.SVCACCT, svcAcctInfo['name']], str(e))
writeStderr(Msg.RERUN_THE_COMMAND_AND_SPECIFY_A_NEW_SANAME)
return False return False
GM.Globals[GM.SVCACCT_SCOPES_DEFINED] = False GM.Globals[GM.SVCACCT_SCOPES_DEFINED] = False
if create_key and not doProcessSvcAcctKeys(mode='retainexisting', iam=iam, if create_key and not doProcessSvcAcctKeys(mode='retainexisting', iam=iam,
@@ -11428,7 +11456,7 @@ def _createOauth2serviceJSON(httpObj, projectInfo, svcAcctInfo, create_key=True)
clientId=service_account['uniqueId']): clientId=service_account['uniqueId']):
return False return False
sa_email = service_account['name'].rsplit('/', 1)[-1] sa_email = service_account['name'].rsplit('/', 1)[-1]
return _grantRotateRights(iam, projectInfo['projectId'], sa_email, sa_email) return _grantRotateRights(iam, projectInfo['projectId'], sa_email)
def _createClientSecretsOauth2service(httpObj, login_hint, appInfo, projectInfo, svcAcctInfo, create_key=True): def _createClientSecretsOauth2service(httpObj, login_hint, appInfo, projectInfo, svcAcctInfo, create_key=True):
def _checkClientAndSecret(csHttpObj, client_id, client_secret): def _checkClientAndSecret(csHttpObj, client_id, client_secret):
@@ -11921,9 +11949,7 @@ def doUpdateProject():
continue continue
iam = getAPIService(API.IAM, httpObj) iam = getAPIService(API.IAM, httpObj)
_getSvcAcctData() # needed to read in GM.OAUTH2SERVICE_JSON_DATA _getSvcAcctData() # needed to read in GM.OAUTH2SERVICE_JSON_DATA
_grantRotateRights(iam, projectId, _grantRotateRights(iam, projectId, GM.Globals[GM.OAUTH2SERVICE_JSON_DATA]['client_email'])
GM.Globals[GM.OAUTH2SERVICE_JSON_DATA]['client_email'],
GM.Globals[GM.OAUTH2SERVICE_JSON_DATA]['client_email'])
Ind.Decrement() Ind.Decrement()
# gam delete project [[admin] <EmailAddress>] [<ProjectIDEntity>] # gam delete project [[admin] <EmailAddress>] [<ProjectIDEntity>]
@@ -12786,7 +12812,7 @@ def doUploadSvcAcctKeys():
iam = getAPIService(API.IAM, httpObj) iam = getAPIService(API.IAM, httpObj)
if doProcessSvcAcctKeys(mode='upload', iam=iam): if doProcessSvcAcctKeys(mode='upload', iam=iam):
sa_email = GM.Globals[GM.OAUTH2SERVICE_JSON_DATA]['client_email'] sa_email = GM.Globals[GM.OAUTH2SERVICE_JSON_DATA]['client_email']
_grantRotateRights(iam, GM.Globals[GM.OAUTH2SERVICE_JSON_DATA]['project_id'], sa_email, sa_email) _grantRotateRights(iam, GM.Globals[GM.OAUTH2SERVICE_JSON_DATA]['project_id'], sa_email)
sys.stdout.write(Msg.YOUR_GAM_PROJECT_IS_CREATED_AND_READY_TO_USE) sys.stdout.write(Msg.YOUR_GAM_PROJECT_IS_CREATED_AND_READY_TO_USE)
# gam delete sakeys <ServiceAccountKeyList> # gam delete sakeys <ServiceAccountKeyList>
@@ -13491,6 +13517,8 @@ REPORT_CHOICE_MAP = {
'drive': 'drive', 'drive': 'drive',
'enterprisegroups': 'groups_enterprise', 'enterprisegroups': 'groups_enterprise',
'gcp': 'gcp', 'gcp': 'gcp',
'gemini': 'gemini_for_workspace',
'geminiforworkspace': 'gemini_for_workspace',
'gplus': 'gplus', 'gplus': 'gplus',
'google+': 'gplus', 'google+': 'gplus',
'group': 'groups', 'group': 'groups',
@@ -13788,6 +13816,20 @@ def doReport():
csvPF.WriteRow(row) csvPF.WriteRow(row)
return (True, lastDate) return (True, lastDate)
# dynamically extend our choices with other reports Google dynamically adds
rep = buildGAPIObject(API.REPORTS)
dyn_choices = rep._rootDesc \
.get('resources', {}) \
.get('activities', {}) \
.get('methods', {}) \
.get('list', {}) \
.get('parameters', {}) \
.get('applicationName', {}) \
.get('enum', [])
for dyn_choice in dyn_choices:
if dyn_choice.replace('_', '') not in REPORT_CHOICE_MAP and \
dyn_choice not in REPORT_CHOICE_MAP.values():
REPORT_CHOICE_MAP[dyn_choice.replace('_', '')] = dyn_choice
report = getChoice(REPORT_CHOICE_MAP, mapChoice=True) report = getChoice(REPORT_CHOICE_MAP, mapChoice=True)
if report == 'usage': if report == 'usage':
doReportUsage() doReportUsage()
@@ -13795,7 +13837,6 @@ def doReport():
if report == 'usageparameters': if report == 'usageparameters':
doReportUsageParameters() doReportUsageParameters()
return return
rep = buildGAPIObject(API.REPORTS)
customerId = GC.Values[GC.CUSTOMER_ID] customerId = GC.Values[GC.CUSTOMER_ID]
if customerId == GC.MY_CUSTOMER: if customerId == GC.MY_CUSTOMER:
customerId = None customerId = None
@@ -15763,27 +15804,13 @@ ANALYTIC_ENTITY_MAP = {
'pageSize': 50, 'pageSize': 50,
'maxPageSize': 200, 'maxPageSize': 200,
}, },
Ent.ANALYTIC_UA_PROPERTY:
{'titles': ['User', 'accountId', 'name', 'id', 'created', 'updated'],
'JSONtitles': ['User', 'accountId', 'name', 'id', 'JSON'],
'timeObjects': ['created', 'updated'],
'items': 'items',
'pageSize': 50,
'maxPageSize': 200,
},
} }
def printShowAnalyticItems(users, entityType): def printShowAnalyticItems(users, entityType):
analyticEntityMap = ANALYTIC_ENTITY_MAP[entityType] analyticEntityMap = ANALYTIC_ENTITY_MAP[entityType]
csvPF = CSVPrintFile(analyticEntityMap['titles'], 'sortall') if Act.csvFormat() else None csvPF = CSVPrintFile(analyticEntityMap['titles'], 'sortall') if Act.csvFormat() else None
FJQC = FormatJSONQuoteChar(csvPF) FJQC = FormatJSONQuoteChar(csvPF)
if entityType != Ent.ANALYTIC_UA_PROPERTY: kwargs = {'pageSize': analyticEntityMap['pageSize']}
kwargs = {'pageSize': analyticEntityMap['pageSize']}
api = API.ANALYTICS_ADMIN
else:
# kwargs = {'webPropertyId': '~all'}
kwargs = {}
api = API.ANALYTICS
if entityType in {Ent.ANALYTIC_ACCOUNT, Ent.ANALYTIC_PROPERTY}: if entityType in {Ent.ANALYTIC_ACCOUNT, Ent.ANALYTIC_PROPERTY}:
kwargs['showDeleted'] = False kwargs['showDeleted'] = False
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
@@ -15796,16 +15823,12 @@ def printShowAnalyticItems(users, entityType):
kwargs['showDeleted'] = getBoolean() kwargs['showDeleted'] = getBoolean()
elif entityType == Ent.ANALYTIC_PROPERTY and myarg == 'filter': elif entityType == Ent.ANALYTIC_PROPERTY and myarg == 'filter':
kwargs['filter'] = getString(Cmd.OB_STRING) kwargs['filter'] = getString(Cmd.OB_STRING)
elif entityType == Ent.ANALYTIC_UA_PROPERTY and myarg == 'accountid':
kwargs['accountId'] = getString(Cmd.OB_STRING).replace('accounts/', '')
elif entityType == Ent.ANALYTIC_DATASTREAM and myarg == 'parent': elif entityType == Ent.ANALYTIC_DATASTREAM and myarg == 'parent':
kwargs['parent'] = getString(Cmd.OB_STRING) kwargs['parent'] = getString(Cmd.OB_STRING)
else: else:
FJQC.GetFormatJSONQuoteChar(myarg, True) FJQC.GetFormatJSONQuoteChar(myarg, True)
if entityType == Ent.ANALYTIC_PROPERTY and 'filter' not in kwargs: if entityType == Ent.ANALYTIC_PROPERTY and 'filter' not in kwargs:
missingArgumentExit('filter') missingArgumentExit('filter')
if entityType == Ent.ANALYTIC_UA_PROPERTY and 'accountId' not in kwargs:
missingArgumentExit('accountid')
if entityType == Ent.ANALYTIC_DATASTREAM and 'parent' not in kwargs: if entityType == Ent.ANALYTIC_DATASTREAM and 'parent' not in kwargs:
missingArgumentExit('parent') missingArgumentExit('parent')
if csvPF and FJQC.formatJSON: if csvPF and FJQC.formatJSON:
@@ -15813,7 +15836,7 @@ def printShowAnalyticItems(users, entityType):
i, count, users = getEntityArgument(users) i, count, users = getEntityArgument(users)
for user in users: for user in users:
i += 1 i += 1
user, analytics = buildGAPIServiceObject(api, user, i, count) user, analytics = buildGAPIServiceObject(API.ANALYTICS_ADMIN, user, i, count)
if not analytics: if not analytics:
continue continue
if entityType == Ent.ANALYTIC_ACCOUNT: if entityType == Ent.ANALYTIC_ACCOUNT:
@@ -15822,11 +15845,8 @@ def printShowAnalyticItems(users, entityType):
service = analytics.accountSummaries() service = analytics.accountSummaries()
elif entityType == Ent.ANALYTIC_DATASTREAM: elif entityType == Ent.ANALYTIC_DATASTREAM:
service = analytics.properties().dataStreams() service = analytics.properties().dataStreams()
elif entityType == Ent.ANALYTIC_PROPERTY: else: # entityType == Ent.ANALYTIC_PROPERTY:
service = analytics.properties() service = analytics.properties()
else: #Ent.ANALYTIC_UA_PROPERTY:
service = analytics.management().webproperties()
# service = analytics.management().profiles()
if csvPF: if csvPF:
printGettingAllEntityItemsForWhom(entityType, user, i, count) printGettingAllEntityItemsForWhom(entityType, user, i, count)
pageMessage = getPageMessageForWhom() pageMessage = getPageMessageForWhom()
@@ -15867,10 +15887,7 @@ def printShowAnalyticItems(users, entityType):
if not FJQC.formatJSON: if not FJQC.formatJSON:
csvPF.WriteRowTitles(row) csvPF.WriteRowTitles(row)
elif csvPF.CheckRowTitles(row): elif csvPF.CheckRowTitles(row):
if entityType != Ent.ANALYTIC_UA_PROPERTY: row = {'User': user, 'name': item['name'], 'displayName': item['displayName']}
row = {'User': user, 'name': item['name'], 'displayName': item['displayName']}
else:
row = {'User': user, 'accountId': item['accountId'], 'id': item['id'], 'name': item['name']}
for field in analyticEntityMap['JSONtitles'][2:-1]: for field in analyticEntityMap['JSONtitles'][2:-1]:
row[field] = item[field] row[field] = item[field]
row['JSON'] = json.dumps(cleanJSON(item, timeObjects=analyticEntityMap['timeObjects']), row['JSON'] = json.dumps(cleanJSON(item, timeObjects=analyticEntityMap['timeObjects']),
@@ -15908,17 +15925,6 @@ def printShowAnalyticAccountSummaries(users):
def printShowAnalyticProperties(users): def printShowAnalyticProperties(users):
printShowAnalyticItems(users, Ent.ANALYTIC_PROPERTY) printShowAnalyticItems(users, Ent.ANALYTIC_PROPERTY)
# gam <UserTypeEntity> print analyticuaproperties [todrive <ToDriveAttribute>*]
# accountid [accounts/]<String>
# [maxresults <Integer>]
# [formatjson [quotechar <Character>]]
# gam <UserTypeEntity> show analyticuaproperties
# accountid [accounts/]<String>
# [maxresults <Integer>]
# [formatjson]
def printShowAnalyticUAProperties(users):
printShowAnalyticItems(users, Ent.ANALYTIC_UA_PROPERTY)
# gam <UserTypeEntity> print analyticdatastreams [todrive <ToDriveAttribute>*] # gam <UserTypeEntity> print analyticdatastreams [todrive <ToDriveAttribute>*]
# parent <String> # parent <String>
# [maxresults <Integer>] # [maxresults <Integer>]
@@ -34164,7 +34170,8 @@ def getGroupMembers(cd, groupEmail, memberRoles, membersList, membersSet, i, cou
elif memberOptions[MEMBEROPTION_NODUPLICATES]: elif memberOptions[MEMBEROPTION_NODUPLICATES]:
groupMemberList = [] groupMemberList = []
for member in groupMembers: for member in groupMembers:
if member['type'] != Ent.TYPE_GROUP: namespace = member['email'].find('@') == -1
if member['type'] != Ent.TYPE_GROUP or namespace:
if ((member['type'] in typesSet and if ((member['type'] in typesSet and
checkMemberMatch(member, memberOptions) and checkMemberMatch(member, memberOptions) and
_checkMemberRoleIsSuspendedIsArchived(member, validRoles, memberOptions[MEMBEROPTION_ISSUSPENDED], memberOptions[MEMBEROPTION_ISARCHIVED]) and _checkMemberRoleIsSuspendedIsArchived(member, validRoles, memberOptions[MEMBEROPTION_ISSUSPENDED], memberOptions[MEMBEROPTION_ISARCHIVED]) and
@@ -34193,7 +34200,8 @@ def getGroupMembers(cd, groupEmail, memberRoles, membersList, membersSet, i, cou
memberOptions, memberDisplayOptions, level+1, typesSet) memberOptions, memberDisplayOptions, level+1, typesSet)
else: else:
for member in groupMembers: for member in groupMembers:
if member['type'] != Ent.TYPE_GROUP: namespace = member['email'].find('@') == -1
if member['type'] != Ent.TYPE_GROUP or namespace:
if ((member['type'] in typesSet) and if ((member['type'] in typesSet) and
checkMemberMatch(member, memberOptions) and checkMemberMatch(member, memberOptions) and
_checkMemberRoleIsSuspendedIsArchived(member, validRoles, _checkMemberRoleIsSuspendedIsArchived(member, validRoles,
@@ -36292,7 +36300,8 @@ def getCIGroupMembers(ci, groupName, memberRoles, membersList, membersSet, i, co
for member in groupMembers: for member in groupMembers:
getCIGroupMemberRoleFixType(member) getCIGroupMemberRoleFixType(member)
memberName = member.get('preferredMemberKey', {}).get('id', '') memberName = member.get('preferredMemberKey', {}).get('id', '')
if member['type'] != Ent.TYPE_GROUP: namespace = member.get('preferredMemberKey', {}).get('namespace', '')
if member['type'] != Ent.TYPE_GROUP or namespace:
if (member['type'] in typesSet and if (member['type'] in typesSet and
checkCIMemberMatch(member, memberOptions) and checkCIMemberMatch(member, memberOptions) and
_checkMemberRole(member, validRoles) and _checkMemberRole(member, validRoles) and
@@ -36320,7 +36329,8 @@ def getCIGroupMembers(ci, groupName, memberRoles, membersList, membersSet, i, co
for member in groupMembers: for member in groupMembers:
getCIGroupMemberRoleFixType(member) getCIGroupMemberRoleFixType(member)
memberName = member.get('preferredMemberKey', {}).get('id', '') memberName = member.get('preferredMemberKey', {}).get('id', '')
if member['type'] != Ent.TYPE_GROUP: namespace = member.get('preferredMemberKey', {}).get('namespace', '')
if member['type'] != Ent.TYPE_GROUP or namespace:
if (member['type'] in typesSet and if (member['type'] in typesSet and
checkCIMemberMatch(member, memberOptions) and checkCIMemberMatch(member, memberOptions) and
_checkMemberRole(member, validRoles) and _checkMemberRole(member, validRoles) and
@@ -76671,7 +76681,6 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_ANALYTICACCOUNTSUMMARY: printShowAnalyticAccountSummaries, Cmd.ARG_ANALYTICACCOUNTSUMMARY: printShowAnalyticAccountSummaries,
Cmd.ARG_ANALYTICDATASTREAM: printShowAnalyticDatastreams, Cmd.ARG_ANALYTICDATASTREAM: printShowAnalyticDatastreams,
Cmd.ARG_ANALYTICPROPERTY: printShowAnalyticProperties, Cmd.ARG_ANALYTICPROPERTY: printShowAnalyticProperties,
Cmd.ARG_ANALYTICUAPROPERTY: printShowAnalyticUAProperties,
Cmd.ARG_ASP: printShowASPs, Cmd.ARG_ASP: printShowASPs,
Cmd.ARG_BACKUPCODE: printShowBackupCodes, Cmd.ARG_BACKUPCODE: printShowBackupCodes,
Cmd.ARG_CALENDAR: printShowCalendars, Cmd.ARG_CALENDAR: printShowCalendars,
@@ -76778,7 +76787,6 @@ USER_COMMANDS_WITH_OBJECTS = {
Cmd.ARG_ANALYTICACCOUNTSUMMARY: printShowAnalyticAccountSummaries, Cmd.ARG_ANALYTICACCOUNTSUMMARY: printShowAnalyticAccountSummaries,
Cmd.ARG_ANALYTICDATASTREAM: printShowAnalyticDatastreams, Cmd.ARG_ANALYTICDATASTREAM: printShowAnalyticDatastreams,
Cmd.ARG_ANALYTICPROPERTY: printShowAnalyticProperties, Cmd.ARG_ANALYTICPROPERTY: printShowAnalyticProperties,
Cmd.ARG_ANALYTICUAPROPERTY: printShowAnalyticUAProperties,
Cmd.ARG_ASP: printShowASPs, Cmd.ARG_ASP: printShowASPs,
Cmd.ARG_BACKUPCODE: printShowBackupCodes, Cmd.ARG_BACKUPCODE: printShowBackupCodes,
Cmd.ARG_CALENDAR: printShowCalendars, Cmd.ARG_CALENDAR: printShowCalendars,
@@ -76991,7 +76999,6 @@ USER_COMMANDS_OBJ_ALIASES = {
Cmd.ARG_ANALYTICACCOUNTSUMMARIES: Cmd.ARG_ANALYTICACCOUNTSUMMARY, Cmd.ARG_ANALYTICACCOUNTSUMMARIES: Cmd.ARG_ANALYTICACCOUNTSUMMARY,
Cmd.ARG_ANALYTICDATASTREAMS: Cmd.ARG_ANALYTICDATASTREAM, Cmd.ARG_ANALYTICDATASTREAMS: Cmd.ARG_ANALYTICDATASTREAM,
Cmd.ARG_ANALYTICPROPERTIES: Cmd.ARG_ANALYTICPROPERTY, Cmd.ARG_ANALYTICPROPERTIES: Cmd.ARG_ANALYTICPROPERTY,
Cmd.ARG_ANALYTICUAPROPERTIES: Cmd.ARG_ANALYTICUAPROPERTY,
Cmd.ARG_ASPS: Cmd.ARG_ASP, Cmd.ARG_ASPS: Cmd.ARG_ASP,
Cmd.ARG_BACKUPCODES: Cmd.ARG_BACKUPCODE, Cmd.ARG_BACKUPCODES: Cmd.ARG_BACKUPCODE,
Cmd.ARG_CALENDARS: Cmd.ARG_CALENDAR, Cmd.ARG_CALENDARS: Cmd.ARG_CALENDAR,

View File

@@ -22,7 +22,6 @@
# APIs # APIs
ACCESSCONTEXTMANAGER = 'accesscontextmanager' ACCESSCONTEXTMANAGER = 'accesscontextmanager'
ALERTCENTER = 'alertcenter' ALERTCENTER = 'alertcenter'
ANALYTICS = 'analytics'
ANALYTICS_ADMIN = 'analyticsadmin' ANALYTICS_ADMIN = 'analyticsadmin'
CALENDAR = 'calendar' CALENDAR = 'calendar'
CBCM = 'cbcm' CBCM = 'cbcm'
@@ -162,7 +161,6 @@ PROJECT_APIS = [
'accesscontextmanager.googleapis.com', 'accesscontextmanager.googleapis.com',
'admin.googleapis.com', 'admin.googleapis.com',
'alertcenter.googleapis.com', 'alertcenter.googleapis.com',
'analytics.googleapis.com',
'analyticsadmin.googleapis.com', 'analyticsadmin.googleapis.com',
# 'audit.googleapis.com', # 'audit.googleapis.com',
'calendar-json.googleapis.com', 'calendar-json.googleapis.com',
@@ -201,7 +199,6 @@ PROJECT_APIS = [
_INFO = { _INFO = {
ACCESSCONTEXTMANAGER: {'name': 'Access Context Manager API', 'version': 'v1', 'v2discovery': True}, ACCESSCONTEXTMANAGER: {'name': 'Access Context Manager API', 'version': 'v1', 'v2discovery': True},
ALERTCENTER: {'name': 'AlertCenter API', 'version': 'v1beta1', 'v2discovery': True}, ALERTCENTER: {'name': 'AlertCenter API', 'version': 'v1beta1', 'v2discovery': True},
ANALYTICS: {'name': 'Analytics API', 'version': 'v3', 'v2discovery': False},
ANALYTICS_ADMIN: {'name': 'Analytics Admin API', 'version': 'v1beta', 'v2discovery': True}, ANALYTICS_ADMIN: {'name': 'Analytics Admin API', 'version': 'v1beta', 'v2discovery': True},
CALENDAR: {'name': 'Calendar API', 'version': 'v3', 'v2discovery': True, 'mappedAPI': 'calendar-json'}, CALENDAR: {'name': 'Calendar API', 'version': 'v3', 'v2discovery': True, 'mappedAPI': 'calendar-json'},
CBCM: {'name': 'Chrome Browser Cloud Management API', 'version': 'v1.1beta1', 'v2discovery': True, 'localjson': True}, CBCM: {'name': 'Chrome Browser Cloud Management API', 'version': 'v1.1beta1', 'v2discovery': True, 'localjson': True},
@@ -244,7 +241,7 @@ _INFO = {
EMAIL_AUDIT: {'name': 'Email Audit API', 'version': 'v1', 'v2discovery': False}, EMAIL_AUDIT: {'name': 'Email Audit API', 'version': 'v1', 'v2discovery': False},
FORMS: {'name': 'Forms API', 'version': 'v1', 'v2discovery': True}, FORMS: {'name': 'Forms API', 'version': 'v1', 'v2discovery': True},
GMAIL: {'name': 'Gmail API', 'version': 'v1', 'v2discovery': True}, GMAIL: {'name': 'Gmail API', 'version': 'v1', 'v2discovery': True},
GROUPSMIGRATION: {'name': 'Groups Migration API', 'version': 'v1', 'v2discovery': False}, GROUPSMIGRATION: {'name': 'Groups Migration API', 'version': 'v1', 'v2discovery': True},
GROUPSSETTINGS: {'name': 'Groups Settings API', 'version': 'v1', 'v2discovery': True}, GROUPSSETTINGS: {'name': 'Groups Settings API', 'version': 'v1', 'v2discovery': True},
IAM: {'name': 'Identity and Access Management API', 'version': 'v1', 'v2discovery': True}, IAM: {'name': 'Identity and Access Management API', 'version': 'v1', 'v2discovery': True},
IAM_CREDENTIALS: {'name': 'Identity and Access Management Credentials API', 'version': 'v1', 'v2discovery': True}, IAM_CREDENTIALS: {'name': 'Identity and Access Management Credentials API', 'version': 'v1', 'v2discovery': True},
@@ -532,10 +529,6 @@ _SVCACCT_SCOPES = [
'api': ALERTCENTER, 'api': ALERTCENTER,
'subscopes': [], 'subscopes': [],
'scope': 'https://www.googleapis.com/auth/apps.alerts'}, 'scope': 'https://www.googleapis.com/auth/apps.alerts'},
{'name': 'Analytics API - read only',
'api': ANALYTICS,
'subscopes': [],
'scope': 'https://www.googleapis.com/auth/analytics.readonly'},
{'name': 'Analytics Admin API - read only', {'name': 'Analytics Admin API - read only',
'api': ANALYTICS_ADMIN, 'api': ANALYTICS_ADMIN,
'subscopes': [], 'subscopes': [],

View File

@@ -423,8 +423,6 @@ class GamCLArgs():
ARG_ANALYTICDATASTREAMS = 'analyticdatastreams' ARG_ANALYTICDATASTREAMS = 'analyticdatastreams'
ARG_ANALYTICPROPERTY = 'analyticproperty' ARG_ANALYTICPROPERTY = 'analyticproperty'
ARG_ANALYTICPROPERTIES = 'analyticproperties' ARG_ANALYTICPROPERTIES = 'analyticproperties'
ARG_ANALYTICUAPROPERTY = 'analyticuaproperty'
ARG_ANALYTICUAPROPERTIES = 'analyticuaproperties'
ARG_API = 'api' ARG_API = 'api'
ARG_APIS = 'apis' ARG_APIS = 'apis'
ARG_APIPROJECT = 'apiproject' ARG_APIPROJECT = 'apiproject'

View File

@@ -61,7 +61,6 @@ class GamEntity():
ANALYTIC_ACCOUNT_SUMMARY = 'anas' ANALYTIC_ACCOUNT_SUMMARY = 'anas'
ANALYTIC_DATASTREAM = 'anad' ANALYTIC_DATASTREAM = 'anad'
ANALYTIC_PROPERTY = 'anap' ANALYTIC_PROPERTY = 'anap'
ANALYTIC_UA_PROPERTY = 'anau'
API = 'api ' API = 'api '
APP_ACCESS_SETTINGS = 'apps' APP_ACCESS_SETTINGS = 'apps'
APP_ID = 'appi' APP_ID = 'appi'
@@ -412,7 +411,6 @@ class GamEntity():
ANALYTIC_ACCOUNT_SUMMARY: ['Analytic Account Summaries', 'Analytic Account Summary'], ANALYTIC_ACCOUNT_SUMMARY: ['Analytic Account Summaries', 'Analytic Account Summary'],
ANALYTIC_DATASTREAM: ['Analytic Datastreams', 'Analytic Datastream'], ANALYTIC_DATASTREAM: ['Analytic Datastreams', 'Analytic Datastream'],
ANALYTIC_PROPERTY: ['Analytic GA4 Properties', 'Analytic GA4 Property'], ANALYTIC_PROPERTY: ['Analytic GA4 Properties', 'Analytic GA4 Property'],
ANALYTIC_UA_PROPERTY: ['Analytic UA Properties', 'Analytic UA Property'],
API: ['APIs', 'API'], API: ['APIs', 'API'],
APP_ACCESS_SETTINGS: ['Application Access Settings', 'Application Access Settings'], APP_ACCESS_SETTINGS: ['Application Access Settings', 'Application Access Settings'],
APP_ID: ['Application IDs', 'Application ID'], APP_ID: ['Application IDs', 'Application ID'],

View File

@@ -72,7 +72,7 @@ Please go to:
24. Paste it at the "Enter your Client Secret: " prompt in your terminal 24. Paste it at the "Enter your Client Secret: " prompt in your terminal
25. Press return/enter in your terminal 25. Press return/enter in your terminal
26. Switch back to the browser 26. Switch back to the browser
27. Click "CANCEL" 27. Click "OK"
28. These steps are complete 28. These steps are complete
''' '''
ENTER_YOUR_CLIENT_ID = '\nEnter your Client ID: ' ENTER_YOUR_CLIENT_ID = '\nEnter your Client ID: '
@@ -287,6 +287,7 @@ GAM_OUT_OF_MEMORY = 'GAM has run out of memory. If this is a large Google Worksp
GENERATING_NEW_PRIVATE_KEY = 'Generating new private key' GENERATING_NEW_PRIVATE_KEY = 'Generating new private key'
GETTING = 'Getting' GETTING = 'Getting'
GETTING_ALL = 'Getting all' GETTING_ALL = 'Getting all'
GRANTING_RIGHTS_TO_ROTATE_ITS_OWN_PRIVATE_KEY = '{0} rights to rotate its own private key'
GOOGLE_DELEGATION_ERROR = 'Google delegation error, delegator and delegate both exist and are valid for delegation' GOOGLE_DELEGATION_ERROR = 'Google delegation error, delegator and delegate both exist and are valid for delegation'
GOT = 'Got' GOT = 'Got'
GROUP_MAPS_TO_MULTIPLE_OUS = 'File: {0}, Group: {1} references multiple OUs: {2}' GROUP_MAPS_TO_MULTIPLE_OUS = 'File: {0}, Group: {1} references multiple OUs: {2}'
@@ -294,13 +295,12 @@ GROUP_MAPS_TO_OU_INVALID_ROW = 'File: {0}, Invalid row, must contain non-blank <
GUARDIAN_INVITATION_STATUS_NOT_PENDING = 'Guardian invitation status is not PENDING' GUARDIAN_INVITATION_STATUS_NOT_PENDING = 'Guardian invitation status is not PENDING'
HAS_CHILD_ORGS = 'Has child {0}' HAS_CHILD_ORGS = 'Has child {0}'
HAS_INVALID_FORMAT = '{0}: {1}, Has invalid format' HAS_INVALID_FORMAT = '{0}: {1}, Has invalid format'
HAS_RIGHTS_TO_ROTATE_OWN_PRIVATE_KEY = 'Giving account {0} rights to rotate {1} private key'
HEADER_NOT_FOUND_IN_CSV_HEADERS = 'Header "{0}" not found in CSV headers of "{1}".' HEADER_NOT_FOUND_IN_CSV_HEADERS = 'Header "{0}" not found in CSV headers of "{1}".'
HELP_SYNTAX = 'Help: Syntax in file {0}\n' HELP_SYNTAX = 'Help: Syntax in file {0}\n'
HELP_WIKI = 'Help: Documentation is at {0}\n' HELP_WIKI = 'Help: Documentation is at {0}\n'
IGNORED = 'Ignored' IGNORED = 'Ignored'
INSTRUCTIONS_CLIENT_SECRETS_JSON = 'Please run\n\ngam create|use project\ngam oauth create\n\nto create and authorize a Client account.\n' INSTRUCTIONS_CLIENT_SECRETS_JSON = 'Please run\n\ngam create|use project\ngam oauth create\n\nto create and authorize a Client account.\n'
INSTRUCTIONS_OAUTH2SERVICE_JSON = 'Please run\n\ngam create|use project\ngam user <user> check serviceaccount\n\nto create and authorize a Service account.\n' INSTRUCTIONS_OAUTH2SERVICE_JSON = 'Please run\n\ngam create|use project\ngam user <user> update serviceaccount\n\nto create and authorize a Service account.\n'
INSUFFICIENT_PERMISSIONS_TO_PERFORM_TASK = 'Insufficient permissions to perform this task' INSUFFICIENT_PERMISSIONS_TO_PERFORM_TASK = 'Insufficient permissions to perform this task'
INTER_BATCH_WAIT_INCREASED = 'inter_batch_wait increased to {0:.2f}' INTER_BATCH_WAIT_INCREASED = 'inter_batch_wait increased to {0:.2f}'
INVALID = 'Invalid' INVALID = 'Invalid'
@@ -468,6 +468,10 @@ REFUSING_TO_DEPROVISION_DEVICES = 'Refusing to deprovision {0} devices because a
REPLY_TO_CUSTOM_REQUIRES_EMAIL_ADDRESS = 'replyto REPLY_TO_CUSTOM requires customReplyTo <EmailAddress>' REPLY_TO_CUSTOM_REQUIRES_EMAIL_ADDRESS = 'replyto REPLY_TO_CUSTOM requires customReplyTo <EmailAddress>'
REQUEST_COMPLETED_NO_FILES = 'Request completed but no results/files were returned, try requesting again' REQUEST_COMPLETED_NO_FILES = 'Request completed but no results/files were returned, try requesting again'
REQUEST_NOT_COMPLETE = 'Request needs to be completed before downloading, current status is: {0}' REQUEST_NOT_COMPLETE = 'Request needs to be completed before downloading, current status is: {0}'
RERUN_THE_COMMAND_AND_SPECIFY_A_NEW_SANAME = """
Re-run the command specify a new service account name with: saname <ServiceAccountName>
See: https://github.com/GAM-team/GAM/wiki/Authorization#advanced-use
"""
RESOURCE_CAPACITY_FLOOR_REQUIRED = 'Options "capacity <Number>" (<Number> > 0) and "floor <String>" required' RESOURCE_CAPACITY_FLOOR_REQUIRED = 'Options "capacity <Number>" (<Number> > 0) and "floor <String>" required'
RESOURCE_FLOOR_REQUIRED = 'Option "floor <String>" required' RESOURCE_FLOOR_REQUIRED = 'Option "floor <String>" required'
RESULTS_TOO_LARGE_FOR_GOOGLE_SPREADSHEET = 'Results are too large for Google Spreadsheets. Uploading as a regular CSV file.' RESULTS_TOO_LARGE_FOR_GOOGLE_SPREADSHEET = 'Results are too large for Google Spreadsheets. Uploading as a regular CSV file.'

View File

@@ -144,6 +144,8 @@ _SKUS = {
'product': 'Google-Apps', 'aliases': ['wsflw', 'workspacefrontline', 'workspacefrontlineworker'], 'displayName': 'Google Workspace Frontline Starter'}, 'product': 'Google-Apps', 'aliases': ['wsflw', 'workspacefrontline', 'workspacefrontlineworker'], 'displayName': 'Google Workspace Frontline Starter'},
'1010020031': { '1010020031': {
'product': 'Google-Apps', 'aliases': ['wsflwstan', 'workspacefrontlinestan', 'workspacefrontlineworkerstan'], 'displayName': 'Google Workspace Frontline Standard'}, 'product': 'Google-Apps', 'aliases': ['wsflwstan', 'workspacefrontlinestan', 'workspacefrontlineworkerstan'], 'displayName': 'Google Workspace Frontline Standard'},
'1010020034': {
'product': 'Google-Apps', 'aliases': ['wsflwplus', 'workspacefrontlineplus', 'workspacefrontlineworkerplus'], 'displayName': 'Google Workspace Frontline Plus'},
'1010340001': { '1010340001': {
'product': '101034', 'aliases': ['gseau', 'enterprisearchived', 'gsuiteenterprisearchived'], 'displayName': 'Google Workspace Enterprise Plus - Archived User'}, 'product': '101034', 'aliases': ['gseau', 'enterprisearchived', 'gsuiteenterprisearchived'], 'displayName': 'Google Workspace Enterprise Plus - Archived User'},
'1010340002': { '1010340002': {

View File

@@ -20,14 +20,19 @@
""" """
GAM_VER_LIBS = ['cryptography', GAM_VER_LIBS = [
'filelock', 'chardet',
'google-api-python-client', 'cryptography',
'google-auth-httplib2', 'filelock',
'google-auth-oauthlib', 'google-api-python-client',
'google-auth', 'google-auth-httplib2',
'httplib2', 'google-auth-oauthlib',
'passlib', 'google-auth',
'python-dateutil', 'lxml',
'yubikey-manager', 'httplib2',
] 'passlib',
'pathvalidate',
'pyscard',
'python-dateutil',
'yubikey-manager',
]

Binary file not shown.

View File

@@ -1,14 +1,15 @@
chardet chardet>=5.2.0
cryptography cryptography>=44.0.2
distro; sys_platform=='linux' distro; sys_platform=='linux'
filelock filelock>=3.18.0
google-api-python-client>=2.166.0 google-api-python-client>=2.167.0
google-auth-httplib2>=0.2.0 google-auth-httplib2>=0.2.0
google-auth-oauthlib>=1.2.1 google-auth-oauthlib>=1.2.2
google-auth>=2.38.0 google-auth>=2.39.0
httplib2>=0.22.0 httplib2>=0.22.0
lxml lxml>=5.4.0
passlib>=1.7.4 passlib>=1.7.4
pathvalidate pathvalidate>=3.2.3
pyscard==2.2.1
python-dateutil python-dateutil
yubikey-manager[yubikey]>=5.6.1 yubikey-manager>=5.6.1

View File

@@ -17,26 +17,29 @@ classifiers =
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
License :: OSI Approved :: Apache License License :: OSI Approved :: Apache License
[options] [options]
packages = find: packages = find:
python_requires = >= 3.8 python_requires = >= 3.9
# The following files should be edited to match: pyproject.toml, requirements.txt
install_requires = install_requires =
chardet chardet >= 5.2.0
cryptography cryptography >= 44.0.2
distro; sys_platform == 'linux' distro; sys_platform == 'linux'
filelock filelock >= 3.18.0
google-api-python-client >= 2.36 google-api-python-client >= 2.167.0
google-auth-httplib2 google-auth-httplib2 >= 0.2.0
google-auth-oauthlib >= 0.4.6 google-auth-oauthlib >= 1.2.2
google-auth >= 2.3.3 google-auth >= 2.39.0
httplib2 >= 0.20.2 httplib2 >= 0.22.0
lxml lxml >= 5.4.0
passlib >= 1.7.4 passlib >= 1.7.4
pathvalidate pathvalidate >= 3.2.3
pyscard == 2.2.1
python-dateutil python-dateutil
yubikey-manager >= 5.0 yubikey-manager >= 5.6.1
[options.package_data] [options.package_data]
* = *.pem * = *.pem

View File

@@ -24,18 +24,19 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
- 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-aarch64-glibc2.35.tar.xz` - `gam-7.wx.yz-linux-arm64-glibc2.35.tar.xz`
- `gam-7.wx.yz-linux-aarch64-legacy.tar.xz` - `gam-7.wx.yz-linux-arm64-glibc2.39.tar.xz`
- `gam-7.wx.yz-linux-arm64-legacy.tar.xz`
- Download the archive, extract the contents into some directory. - 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-aarch64.tar.xz` - `gam-7.wx.yz-macos14.7-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 - M3 * Executable Archive, Manual, Mac OS versions Sequoia - M3
- `gam-7.wx.yz-macos15.2-aarch64.tar.xz` - `gam-7.wx.yz-macos15.4-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.
@@ -54,6 +55,16 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
- 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 11 ARM
- `gam-7.wx.yz-windows-arm64.zip`
- Download the archive, extract the contents into some directory.
- Start a Command Prompt/PowerShell session.
* Executable Installer, Manual, Windows 11 ARM
- `gam-7.wx.yz-windows-arm64.msi`
- Download the installer and run it.
- Start a Command Prompt/PowerShell session.
* Source, all platforms * Source, all platforms
- `Source code(zip)` - `Source code(zip)`
- `Source code(tar.gz)` - `Source code(tar.gz)`

View File

@@ -10,6 +10,54 @@ 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.06.12
Deleted commands to display Analytic UA properties; the API has been deprecated.
```
gam <UserTypeEntity> print|show analyticuaproperties
```
### 7.06.11
Improved `gam checkconn`.
Updated `gam print group-members` and `gam print cigroup-members` to recognize members
that are groups representing chat spaces. For now, these groups are not expanded when
`recursive` is specified.
### 7.06.10
Added the following license SKU.
```
1010020034 - Google Workspace Frontline Plus
```
### 7.06.09
Added `gemini` and `geminiforworkspace` to `<ActivityApplicationName>` for use in
`gam report <ActivityApplicationName>`.
### 7.06.08
Fixed problem where Yubikeys caused a trap.
### 7.06.07
Updated private key rotation progress messages in `gam create|use|update project`
and `gam upload sakey`.
Updated `gam use project` to display the following error message when the specifed project
already has a service account.
```
Re-run the command specify a new service account name with: saname <ServiceAccountName>'
```
### 7.06.06
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".
### 7.06.05 ### 7.06.05
Updated code in `gam delete|update chromepolicy` to handle the `policyTargetKey[additionalTargetKeys]` Updated code in `gam delete|update chromepolicy` to handle the `policyTargetKey[additionalTargetKeys]`

View File

@@ -251,7 +251,7 @@ writes the credentials into the file oauth2.txt.
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
admin@server:/Users/admin$ gam version admin@server:/Users/admin$ gam version
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
GAM 7.06.05 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.06.12 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.3 64-bit final Python 3.13.3 64-bit final
MacOS Sequoia 15.4.1 x86_64 MacOS Sequoia 15.4.1 x86_64
@@ -989,7 +989,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.06.05 - https://github.com/GAM-team/GAM - pythonsource GAM 7.06.12 - https://github.com/GAM-team/GAM - pythonsource
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.3 64-bit final Python 3.13.3 64-bit final
Windows-10-10.0.17134 AMD64 Windows-10-10.0.17134 AMD64

View File

@@ -110,6 +110,7 @@
| Google Workspace for Education: Teaching and Learning Upgrade | 1010370001 | gwetlu | | Google Workspace for Education: Teaching and Learning Upgrade | 1010370001 | gwetlu |
| Google Workspace Frontline Starter | 1010020030 | wsflw | | Google Workspace Frontline Starter | 1010020030 | wsflw |
| Google Workspace Frontline Standard | 1010020031 | wsflwstan | | Google Workspace Frontline Standard | 1010020031 | wsflwstan |
| Google Workspace Frontline Plus | 1010020034 | wsflwplus |
| Google Workspace Government | Google-Apps-For-Government | gsuitegov | | Google Workspace Government | Google-Apps-For-Government | gsuitegov |
| Google Workspace Labs | 1010470002 | gwlabs | workspacelabs | | Google Workspace Labs | 1010470002 | gwlabs | workspacelabs |

View File

@@ -51,6 +51,7 @@ config csv_output_row_filter "'\"accounts:used_quota_in_mb\":count>15000'"
domain| domain|
drive|doc|docs| drive|doc|docs|
gcp| gcp|
gemini|geminiforworkspace|
groups|group| groups|group|
groupsenterprise|enterprisegroups| groupsenterprise|enterprisegroups|
jamboard| jamboard|

View File

@@ -6,14 +6,13 @@
- [Display Analytic Account Summaries](#display-analytic-account-summaries) - [Display Analytic Account Summaries](#display-analytic-account-summaries)
- [Display Analytic Properties](#display-analytic-properties) - [Display Analytic Properties](#display-analytic-properties)
- [Display Analytic Datastreams](#display-analytic-datastreams) - [Display Analytic Datastreams](#display-analytic-datastreams)
- [Display Analytic UA Properties](#display-analytic-ua-properties)
- [Examples](#examples) - [Examples](#examples)
## API documentation ## API documentation
* [Analytics Admin API](https://developers.google.com/analytics/devguides/config/admin/v1/rest) * [Analytics Admin API](https://developers.google.com/analytics/devguides/config/admin/v1/rest)
## Notes ## Notes
To use these commands you must add 'Analytics API' and 'Analytics Admin API' to your project and update your service account authorization. To use these commands you must add 'Analytics Admin API' to your project and update your service account authorization.
``` ```
gam update project gam update project
gam user user@domain.com update serviceaccount gam user user@domain.com update serviceaccount
@@ -142,37 +141,6 @@ When using the `formatjson` option, double quotes are used extensively in the da
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output. The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used. `quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
## Display Analytic UA Properties
```
gam <UserTypeEntity> show analyticuaproperties
accountid [accounts/]<String>
[maxresults <Integer>]
[formatjson]
```
The required `accountid <String>` can be in the format: 'accounts/123' or '123'.
By default, GAM asks the API for 50 properties per page of results,
* `maxresults` - Maximum number of results per page; range is 1-200; the default is 50.
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
```
gam <UserTypeEntity> print analyticuaproperties [todrive <ToDriveAttribute>*]
accountid [accounts/]<String>
[maxresults <Integer>]
[formatjson [quotechar <Character>]]
```
The required `accountid <String>` can be in the format: 'accounts/123' or '123'.
By default, GAM asks the API for 50 properties per page of results,
* `maxresults` - Maximum number of results per page; range is 1-200; the default is 50.
By default, when writing CSV files, Gam uses a quote character of double quote `"`. The quote character is used to enclose columns that contain
the quote character itself, the column delimiter (comma by default) and new-line characters. Any quote characters within the column are doubled.
When using the `formatjson` option, double quotes are used extensively in the data resulting in hard to read/process output.
The `quotechar <Character>` option allows you to choose an alternate quote character, single quote for instance, that makes for readable/processable output.
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
## Examples ## Examples
Get all analytic accounts Get all analytic accounts
@@ -189,8 +157,3 @@ Get all analytic account properties (GA4)
``` ```
gam redirect stdout - multiprocess redirect stderr stdout redirect csv ./GA4AnalyticAccountProperties.csv multiprocess csv AnalyticAccounts.csv gam user "~User" print analyticproperties filter "parent:~~name~~" gam redirect stdout - multiprocess redirect stderr stdout redirect csv ./GA4AnalyticAccountProperties.csv multiprocess csv AnalyticAccounts.csv gam user "~User" print analyticproperties filter "parent:~~name~~"
``` ```
Get all analytic account properties (UA)
```
gam redirect stdout - multiprocess redirect stderr stdout redirect csv ./UAAnalyticAccountProperties.csv multiprocess csv AnalyticAccounts.csv gam user "~User" print analyticuaproperties accountid "~~name~~"
```

View File

@@ -42,12 +42,12 @@ Google requires that you have a Chat Bot configured in order to use the Chat API
## Set up a Chat Bot ## Set up a Chat Bot
* Run the command `gam setup chat`; it will point you to a URL to configure your Chat Bot; this is required to use the Chat API. * Run the command `gam setup chat`; it will point you to a URL to configure your Chat Bot.
* Enter an App name and Description of your choosing. * Enter an App name and Description of your choosing.
* For the Avatar URL you can use `https://dummyimage.com/384x256/4d4d4d/0011ff.png&text=+GAM` or a public URL to an image of your own choosing. * For the Avatar URL you can use `https://dummyimage.com/384x256/4d4d4d/0011ff.png&text=+GAM` or a public URL to an image of your own choosing.
* In Functionality, uncheck both "Receive 1:1 messages" and "Join spaces and group conversations" * In Functionality, uncheck both "Receive 1:1 messages" and "Join spaces and group conversations"
* In Connection settings, choose "Cloud Pub/Sub" and enter "no-topic" for the topic name. GAM doesn't yet listen to pub/sub so this option is not used. * In Connection settings, choose "Cloud Pub/Sub" and enter `projects/<ProjectID>/topics/no-topic` for the topic name. Replace `<ProjectID>` with your GAM project ID. GAM doesn't yet listen to pub/sub so this option is not used.
* In Visibility, uncheck "Make this Chat app available to specific people and groups in Domain Workspace". * In Visibility, uncheck "Make this Chat app available to specific people and groups in Domain Workspace".
* Click Save. * Click Save.
## API documentation ## API documentation

View File

@@ -4,7 +4,7 @@ k
Print the current version of Gam with details Print the current version of Gam with details
``` ```
gam version gam version
GAM 7.06.05 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.06.12 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.3 64-bit final Python 3.13.3 64-bit final
MacOS Sequoia 15.4.1 x86_64 MacOS Sequoia 15.4.1 x86_64
@@ -16,7 +16,7 @@ Time: 2023-06-02T21:10:00-07: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.06.05 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.06.12 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.3 64-bit final Python 3.13.3 64-bit final
MacOS Sequoia 15.4.1 x86_64 MacOS Sequoia 15.4.1 x86_64
@@ -28,7 +28,7 @@ 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.06.05 - https://github.com/GAM-team/GAM - pyinstaller GAM 7.06.12 - https://github.com/GAM-team/GAM - pyinstaller
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.3 64-bit final Python 3.13.3 64-bit final
MacOS Sequoia 15.4.1 x86_64 MacOS Sequoia 15.4.1 x86_64
@@ -65,7 +65,7 @@ MacOS High Sierra 10.13.6 x86_64
Path: /Users/Admin/bin/gam7 Path: /Users/Admin/bin/gam7
Version Check: Version Check:
Current: 5.35.08 Current: 5.35.08
Latest: 7.06.05 Latest: 7.06.12
echo $? echo $?
1 1
``` ```
@@ -73,7 +73,7 @@ echo $?
Print the current version number without details Print the current version number without details
``` ```
gam version simple gam version simple
7.06.05 7.06.12
``` ```
In Linux/MacOS you can do: In Linux/MacOS you can do:
``` ```
@@ -83,7 +83,7 @@ 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.06.05 - https://github.com/GAM-team/GAM GAM 7.06.12 - https://github.com/GAM-team/GAM
GAM Team <google-apps-manager@googlegroups.com> GAM Team <google-apps-manager@googlegroups.com>
Python 3.13.3 64-bit final Python 3.13.3 64-bit final
MacOS Sequoia 15.4.1 x86_64 MacOS Sequoia 15.4.1 x86_64