Updated `gam report <ActivityApplicationName>` to display `id:<actor.profileId>` in the `emailAddress` column
when `actor.email` is empty. This typically occurs when the actor is not in your workspace.
Updated `gam <UserTypeEntity> copy drivefile` to ignore ACLs referencing deleted user/groups.
We currently only have 13 JID accounts available for testing but after Linux arm64 changes needed 14 runners.
I'm disabling Python 3.9 tests for now since it's the oldest and due for deprecation in October.
If there's any concerns we can re-enable and disable something else or else Jay can rebuild the auth files to add a 14th JID Google account and credentials (not hard but cumbersome and time consuming).
Updated `gam <UserTypeEntity> claim|transfer ownership` to show `Got N Drive Files/Folders that matched query` messages
as files/folders are being identified for processing.
Added option `<JSONData>` to `gam create|update caalevel`.
todrive actions for reports often only need to create drive files, not read
other files. drive.file scope limits GAM to being able to create files and
read just those files.
Ensure live Google API tests run on test runners so we are exercising our code against Python versions other than the version used by GAM binaries.
These runners generally finish fastest anyway since they never need to compile OpenSSL, Python or PyInstaller.
@@ -32,7 +32,7 @@ There is a public chat room hosted in Google Chat. [Instructions to join](https:
# Author
GAM is maintained by [Jay Lee](mailto:jay0lee@gmail.com). Please direct "how do I?" questions to [Google Groups].
GAM is maintained by [Jay (James) Lee](mailto:jay0lee@gmail.com) and [Ross Scroggs](mailto:ross.scroggs@gmail.com). Please direct "how do I?" questions to [Google Groups].
You can download the current GAMADV-XTD3 release from the [GitHub Releases](https://github.com/taers232c/GAMADV-XTD3/releases) page. Choose one of the following:
By default, a folder, `gamadv-xtd3`, is created in the default or specified path and the files are downloaded into that folder.
Add the `-s` option to the end of the above commands to suppress creating the `gamadv-xtd3` folder; the files are downloaded directly into the default or specified path.
- [Installation - First time GAM installation](#installation---first-time-gam-installation)
- [Installation - Upgrading from a GAM version other than a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3](#installation---upgrading-from-a-gam-version-other-than-a-prior-version-of-gamadv-x-or-gamadv-xtd-or-gamadv-xtd3)
- [Installation - Upgrading from a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3](#installation---upgrading-from-a-prior-version-of-gamadv-x-or-gamadv-xtd-or-gamadv-xtd3)
# Introduction
GAMADV-XTD3 is a free, open source command line tool for Google Workspace Administrators to manage domain and user settings quickly and easily.
GAMADV-XTD3 is built with Python 3; as Python 2 support ends on 2020-01-01, this is the version of Advanced GAM that new/existing users should install.
This page provides simple instructions for downloading, installing and starting to use GAMADV-XTD3.
GAMADV-XTD3 requires paid, or Education/Non-profit, editions of Google Workspace. G Suite Legacy Free Edition has limited API support and not all GAM commands work.
GAMADV-XTD3 is a rewrite/extension of Jay Lee's [GAM], without his efforts, this version wouldn't exist.
GAMADV-XTD3 is backwards compatible with [GAM], meaning that if your command works with regular GAM, it will also work with GAMADV-XTD3. There may be differences in output, but the syntax is compatible.
# Documentation
Basic GAM documentation is hosted in the [GitHub Wiki]. Documentation specifically for GAMADV-XTD3 is hosted in the [GitHub GAMADV-XTD3 Wiki] and in Gam*.txt files.
# Mailing List / Discussion group
The GAM mailing list / discussion group is hosted on [Google Groups]. You can join the list and interact via email, or just post from the web itself.
# Source Repository
The official GAMADV-XTD3 source repository is on [GitHub] in the master branch.
# Author
GAMADV-XTD3 is maintained by <a href="mailto:ross.scroggs@gmail.com">Ross Scroggs</a>.
# Requirements
To run all commands properly, GAMADV-XTD3 requires three things:
* An API project which identifies your install of GAMADV-XTD3 to Google and keeps track of API quotas.
* Authorization to act as your Google Workspace Administrator in order to perform management functions like add users, modify group settings and membership and pull domain reports.
* A special service account that is authorized to act on behalf of your users in order to modify user-specific settings and data such as Drive files, Calendars and Gmail messages and settings like signatures.
# Installation - First time GAM installation
Use these steps if you have never used any version of GAM in your domain. They will create a GAM project
and all necessary authentications.
* Download: [Downloads](Downloads)
* Configuration: [GAM Configuration](gam.cfg)
* Install: [How to Install Advanced GAM](How-to-Install-Advanced-GAM)
# Installation - Upgrading from a GAM version other than a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3
Use these steps if you have used any version of GAM in your domain. They will update your GAM project
and all necessary authentications.
* Download: [Downloads](Downloads)
* Configuration: [GAM Configuration](gam.cfg)
* Upgrade: [How to Upgrade from Standard GAM](How-to-Upgrade-from-Standard-GAM)
# Installation - Upgrading from a prior version of GAMADV-X or GAMADV-XTD or GAMADV-XTD3
Use these steps if you already use GAMADV-X or GAMADV-XTD or GAMADV-XTD3. The updates may tell you to update your GAM project
or authentications because new features have been included.
* Updates: [GAM Updates]
* Download: [Downloads](Downloads)
You can install multiple versions of GAM and GAMADV-XTD3 in different parallel directories.
GAMADV-XTD3 is a free, open source command line tool for Google Workspace (formerly G Suite) Administrators to manage domain and user settings quickly and easily.
GAMADV-XTD3 is built with Python 3.
This page provides simple instructions for downloading, installing and starting to use GAMADV-XTD3.
GAMADV-XTD3 runs on all versions of Google Workspace; Google Apps Free Edition has limited API support and not all GAM commands work.
GAMADV-XTD3 is a rewrite/extension of Jay Lee's [GAM], without his efforts, this version wouldn't exist.
GAMADV-XTD3 is backwards compatible with [GAM], meaning that if your command works with regular GAM, it will also work with GAMADV-XTD3. There may be differences in output, but the syntax is compatible.
# Documentation
Documentation for GAMADV-XTD3 is hosted in the [GitHub GAMADV-XTD3 Wiki] and in Gam*.txt files.
# Mailing List / Discussion group
The GAM mailing list / discussion group is hosted on [Google Groups]. You can join the list and interact via email, or just post from the web itself.
# Source Repository
The official GAMADV-XTD3 source repository is on [GitHub] in the master branch.
# Author
GAMADV-XTD3 is maintained by <a href="mailto:ross.scroggs@gmail.com">Ross Scroggs</a>.
# Requirements
To run all commands properly, GAMADV-XTD3 requires three things:
* An API project which identifies your install of GAMADV-XTD3 to Google and keeps track of API quotas.
* Authorization to act as your G Suite Administrator in order to perform management functions like add users, modify group settings and membership and pull domain reports.
* A special service account that is authorized to act on behalf of your users in order to modify user-specific settings and data such as Drive files, Calendars and Gmail messages and settings like signatures.
# Installation - First time GAM installation
Use these steps if you have never used any version of GAM in your domain. They will create a GAM project
and all necessary authentications.
| [Downloads] | [Configuration] | [Install] |
| :---: | :---: | :---: |
# Installation - Update Advanced GAM
Use these steps to update your version of GAMADV-XTD3.
# Running GAMADV-XTD3 securely on a Google Compute Engine
- [thanks](#thanks)
- [Introduction](#introduction)
- [Setup Steps](#setup-steps)
## Thanks
Thanks to Jay Lee for the original version of this document.
## Introduction
GAMADV-XTD3 can run on a Linux or Windows Google Compute Engine (GCE) VM and use the attached service account to access Google Workspace APIs. The advantage of this configuration is that no service account private key is accessible to GAMADV-XTD3 directly and there is no risk of the key being stolen/lost.
GAMADV-XTD3 version 6.50.00 or higher is required.
## Setup Steps
1. Create a [GCP project](https://cloud.google.com/resource-manager/docs/creating-managing-projects).
2. Create [a service account](https://cloud.google.com/iam/docs/creating-managing-service-accounts) which will be used by GAMADV-XTD3. Continue steps 2 and 3 without granting the new service account any special access to the project and without granting users access to the service account.
3. Grant the service account rights to generate authentication tokens.
* go to [console.cloud.google.com](https://console.cloud.google.com).
* go to "IAM & Admin" > Service accounts
* click on the service account you created (not the default service account).
* copy the email address of your service account to the clipboard.
* click on the Permissions tab.
* click "Grant Access".
* In the "New principals text box, paste the service account email you copied.
* Give your service account the "Service Account Key Admin", "Service Account Token Creator" and "View Service Accounts" roles.
4. [Create a Windows or Linux virtual machine](https://cloud.google.com/compute/docs/instances/create-start-instance).
* You can choose a region physically close to you though you may be limited in your choices if you want to use the free tier.
* GAMADV-XTD3 can run on the minimal `e2-micro` [free tier VM](https://cloud.google.com/free/docs/free-cloud-features#compute) though performance may suffer. If you are performing batch operations, raising the CPU count will help performance. If you have a very large and busy Workspace instance downloading reports or Drive file lists may require more RAM.
* [DO NOT use the default service account](https://cloud.google.com/iam/docs/best-practices-service-accounts#single-purpose). Choose the service account you created above instead.
* GAMADV-XTD3 does not use a significant amount of storage, unless you have specific storage needs the default disk size should suffice.
* leave other VM instance settings at their defaults unless you know what you are doing.
6. Logout and log back in to the VM, you should now be able to run GAMADV-XTD3 commands like:
```
gam version
```
7. Create the special `oauth2service.json` file GAMADV-XTD3 will use:
```
gam create gcpserviceaccount
```
If you'd like, take a look at the generated ```oauth2service.json``` file;
you'll notice that while the file has some fields similar to a normal service account file, there is no `private_key` attribute containing an RSA private key.
8. Enable the Google APIs GAMADV-XTD3 will use:
```
gam enable apis
```
You are given the option to enable them automatically or manually. Automatic enablement will ask you to authenticate to GAMADV-XTD3. You should authenticate as a user with rights to manage project APIs, probably a project owner. If you are not the project owner you can choose manual enablement and GAMADV-XTD3 will provide two or more URLs which you can send to the project owner. When the owner opens these URLs, they'll be prompted to enable all the APIs GAMADV-XTD3 needs.
To use these commands you must update your service account authorization.
```
gam user user@domain.com update serviceaccount
[*] 3) Chat API - Memberships (supports readonly)
[*] 4) Chat API - Messages (supports readonly)
[*] 5) Chat API - Spaces (supports readonly)
[*] 6) Chat API - Spaces Delete
```
Google requires that you have a Chat Bot configured in order to use the Chat API; set up a Chat Bot as described in the next section.
## 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.
* Enter an App name and Description of your choosing.
* For the Avatar URL you can use `https://dummyimage.com/384x256/4d4d4d/0011ff.png&text=+GAM` or a public URL to an image of your own choosing.
* In Functionality, uncheck both "Receive 1:1 messages" and "Join spaces and group conversations"
* 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 Visibility, uncheck "Make this Chat app available to specific people and groups in Domain Workspace".
* Click Save.
## Definitions
* [`<UserTypeEntity>`](Collections-of-Users)
* [Drive File Selection](Drive-File-Selection) for symbols not listed here, such as `<DriveFileIDEntity>`
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
*`formatjson` - Display the fields in JSON format.
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.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
*`formatjson` - Display the fields in JSON format.
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.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
*`formatjson` - Display the fields in JSON format.
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.
By default, only `JOINED` members are displayed; use `showinvited` to also display `INVITED` members.
Use `filter <String>` to filter memberships by a member's `role `and `member.type`.
* To filter by role, set role to ROLE_MEMBER or ROLE_MANAGER.
* To filter by type, set member.type to HUMAN or BOT.
* To filter by both role and type, use the AND operator.
* To filter by either role or type, use the OR operator.
For example, the following queries are valid:
```
role = "ROLE_MANAGER" OR role = "ROLE_MEMBER"
member.type = "HUMAN" AND role = "ROLE_MANAGER"
```
The following queries are invalid:
```
member.type = "HUMAN" AND member.type = "BOT"
role = "ROLE_MANAGER" AND role = "ROLE_MEMBER"
```
### Delete a user from their `space` and `groupchat` spaces
There is no way to delete a user from a directmessage space.
```
gam redirect csv ./UserChatSpaces.csv user user@domain.com print chatspaces types space,groupchat
gam redirect stdout ./DeleteUserChatMemberships.txt multiprocess redirect stderr stdout csv ./UserChatSpaces.csv gam user "~User" delete chatmember "~name" user "~User"
```
## Manage Chat Messages
### Create a chat message in a space
Messages are limited to 4,096 characters and will be trimmed to that length.
Chat supports [simple formatting](https://developers.google.com/chat/reference/message-formats/basic#using_formatted_text_in_messages) allowing you to bold, underline, italics and strikethrough your text.
*`textfile <FileName> [charset <Charset>]` - The message is read from a local file
*`gdoc <UserGoogleDoc>` - The message is read from a Google Doc.
*`gcsdoc <StorageBucketObjectName>` - The message is read from a Google Cloud Storage file.
By default, a new message thread is created; use `thread <ChatThread>` or `threadkey <String>` to create the message as a reply to an existing thread.
Use `replyoption` to specify what happens if the specified thread does not exist:
*`fail` - If the thread soes not exiat, a `Not Found` error is generated
*`fallbacktonew` - If the thread does not exist, start a new thread
The first time you reply to a thread you must use `thread <ChatThread>`; if you also specify `threadkey <String>`
then you can use just `threadkey <String>` in subsequent replies.
If you specify `thread` or `threadkey` but not `replyoption`, the default is `fail'.
By default, details about the chatmessage are displayed.
* `returnidonly` - Display the chatmessage name only
### Examples
This example creates a new chat message in the given room.
```
gam user user@domain.com create chatmessage space spaces/iEMj8AAAAAE text "Hello Chat"
```
This example creates a formatted message and posts it to an existing thread
```
gam user user@domain.com create chatmessage space spaces/AAAADi-pvqc thread spaces/AAAADi-pvqc/threads/FMNw-iE9jN4 text "*Bold* _Italics_ ~Strikethrough~"
```
This example reads the MotD.txt file and posts its contents to Chat.
```
gam user user@domain.com create chatmessage spaces spaces/AAAADi-pvqc textfile MotD.txt
```
This example reads the Google Doc MotD and posts its contents to Chat.
```
gam user user@domain.com create chatmessage spaces spaces/AAAADi-pvqc gdoc announcements@domain.com name "MotD"
```
### Update a Chat Message
Updates and rewrites an existing Chat message. Message will show as edited and no notification will be sent to members.
```
gam <UserTypeEntity> update chatmessage name <ChatMessage>
<ChatContent>
```
Specify the text of the message: `<ChatContent>`
* `text <String>` - The message is `<String>`
* `textfile <FileName> [charset <Charset>]` - The message is read from a local file
* `gdoc <UserGoogleDoc>` - The message is read from a Google Doc.
* `gcsdoc <StorageBucketObjectName>` - The message is read from a Google Cloud Storage file.
### Example
This example updates an existing chat message with new text.
```
gam user user@domain.com update chatmessage name spaces/AAAADi-pvqc/messages/PKJrx90ooIU.PKJrx90ooIU text "HELLO CHAT?"
```
### Delete a Chat Message
Deletes the given Chat message. Members will no longer see the message.
```
gam <UserTypeEntity> delete chatmessage name <ChatMessage>
```
### Example
```
gam user user@domain.com delete chatmessage name spaces/AAAADi-pvqc/messages/PKJrx90ooIU.PKJrx90ooIU
```
## Display Chat Messages
Display a specific Chat message.
```
gam <UserTypeEntity> info chatmessage name <ChatMessage>
[filter <String>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
### Example
```
gam user user@domain.com info chatmessage name spaces/AAAADi-pvqc/messages/PKJrx90ooIU.PKJrx90ooIU
```
### Display information about all chat messages in a chat space
```
gam <UserTypeEntity> show chatmessages <ChatSpace>
[showdeleted [<Boolean>]] [filter <String>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
* `formatjson` - Display the fields in JSON format.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
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.
By default, deleted messages are not displayed; use `showdeleted` to also display deleted messages.
Use `filter <String>` to filter messages by `createTime` and `thread.name`.
To filter messages by the date they were created, specify the createTime with a timestamp in RFC-3339 format and double quotation marks. For example, "2023-04-21T11:30:00-04:00".
* Use the greater than operator `>` to list messages that were created after a timestamp.
* Use the less than operator `<` to list messages that were created before a timestamp.
* To filter messages within a time interval, use the AND operator between two timestamps.
* To filter by thread, specify the thread.name, formatted as spaces/{space}/threads/{thread}. You can only specify one thread.name per query.
* To filter by both thread and date, use the AND operator in your query.
For example, the following queries are valid on Linux/MacOS:
```
filter 'createTime > "2012-04-21T11:30:00-04:00"'
filter 'createTime > "2012-04-21T11:30:00-04:00" AND thread.name = spaces/AAAAAAAAAAA/threads/123'
filter 'createTime > "2012-04-21T11:30:00+00:00" AND createTime < "2013-01-01T00:00:00+00:00" AND thread.name = spaces/AAAAAAAAAAA/threads/123'
To use these commands you must add the 'Drive Labels API' to your project and update your service account authorization.
```
gam update project
gam user user@domain.com check serviceaccount
```
Supported editions for this feature: Business Standard and Business Plus; Enterprise; Education Standard and Education Plus; G Suite Business; Essentials.
A domain administrator with the Drive and Docs administrator privilege can search for Shared Drives or update permissions for Shared Drives
owned by their organization, regardless of the admin's membership in any given Shared Drive.
Three forms of the commands are available:
*`gam action ...` - The administrator named in oauth2.txt is used, domain administrator access implied and labels of type `SHARED` and `ADMIN`can be written
*`gam <UserTypeEntity> action ... adminaccess` - The user named in `<UserTypeEntty>` is used, adminaccess indicates that labels of type `SHARED` and `ADMIN`can be written
*`gam <UserTypeEntity> action ...` - The user named in `<UserTypeEntty>` is used, access is limited, onlylabels of type `SHARED` can be written
## Display Drive Labels
```
gam [<UserTypeEntity>] info drivelabels <DriveLabelNameEntity>
[[basic|full] [languagecode <BCP47LanguageCode>]
[formatjson] [adminaccess|asadmin]
```
* `basic` - Display fields: name,id,revisionId,labelType,properties.*; this is the default
*`full` - Display all possible fields
*`languagecode <BCP47LanguageCode>` - The BCP-47 language code to use for evaluating localized Field labels. When not specified, values in the default configured language will be used.
*`adminaccess|asadmin` - Use the user's admin credentials. This will return all Labels within the customer.
By default, Gam displays the information as an indented list of keys and values.
*`formatjson` - Display the fields in JSON format.
* `basic` - Display fields: name,id,revisionId,labelType,properties.*; this is the default
*`full` - Display all possible fields
*`languagecode <BCP47LanguageCode>` - The BCP-47 language code to use for evaluating localized Field labels. When not specified, values in the default configured language will be used.
*`minimumrole applier|editor|organizer|reader` - Specifies the level of access the user must have on the returned Labels. Defaults to READER.
*`adminaccess|asadmin` - Use the user's admin credentials. This will return all Labels within the customer.
By default, Gam displays the information as an indented list of keys and values.
*`formatjson` - Display the fields in JSON format.
* `basic` - Display fields: name,id,revisionId,labelType,properties.*; this is the default
*`full` - Display all possible fields
*`languagecode <BCP47LanguageCode>` - The BCP-47 language code to use for evaluating localized Field labels. When not specified, values in the default configured language will be used.
*`minimumrole applier|editor|organizer|reader` - Specifies the level of access the user must have on the returned Labels. Defaults to READER.
*`adminaccess|asadmin` - Use the user's admin credentials. This will return all Labels within the customer.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
*`formatjson` - Display the fields in JSON format.
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.
## Process File Drive Labels
`<DriveLabelID>`, `<DriveLabelFieldID>` and `<DriveLabelSelectionID>` values are obtained from the commands above.
```
gam <UserTypeEntity> process filedrivelabels <DriveFileEntity>
Thanks to Jay Lee for the original version of this document.
## Introduction
GAMADV-XTD3 supports using a [YubiKey](https://www.yubico.com/products/yubikey-5-overview/) to generate and store the service account's private RSA key. Private keys generated by the YubiKey cannot be exported even to the computer running GAMADV-XTD3. When compared to the plain text oauth2service.json file with the private key stored in text, the YubiKey offers a more secure option that prevents digital theft and copying of the private key. Instead of reading the private key from the oauth2service.json file and signing requests itself, GAMADV-XTD3 will simply send signing requests to the YubiKey and get back the signature.
GAMADV-XTD3 version 6.50.01 or higher is required. Best practice is to always use the [latest version of GAMADV-XTD3](https://github.com/taers232c/GAMADV-XTD3/wiki/How-to-Update-Advanced-GAM).
## FAQs
### Can I use a Google Titan or other brand security key?
No, while Titan keys are great as security keys / U2F / 2SV, that is not the protocol being used by GAMADV-XTD3 here. GAMADV-XTD3 uses the PIV app of YubiKeys to work with service accounts. You need to use [a genuine Yubikey.](https://yubico.com/genuine/).
### Does this protect the admin credentials GAMADV-XTD3 stores in oauth2.txt?
No, the admin credentials GAMADV-XTD3 stores in oauth2.txt are not protected by the YubiKey as they are not using RSA private keys. Only the service account credentials normally stored in oauth2service.json are protected. The service account credentials are used for domain-wide delegation operations like managing Workspace user data in Drive, Gmail and Calendar. Note that GAMADV-XTD3 also has the ability to perform admin actions as a delegated admin service account (DASA). See [instructions for setting up DASA](https://github.com/taers232c/GAMADV-XTD3/wiki/Using-GAMADV-XTD3-with-a-delegated-admin-service-account.md). When DASA is setup, GAMADV-XTD3 will use the service account to authenticate which can be protected by the YubiKey.
### What if someone physically steals the YubiKey?
The YubiKey can be configured with a PIN that must be entered in order for it to sign data with the private key. GAMADV-XTD3 stores this PIN string in the oauth2service.json file so it can use it as needed. What this means is that an attacker would need to steal *both* the physical YubiKey and the PIN stored in oauth2service.json. The recommendation is to store oauth2service.json and the rest of the GAM directory on an encrypted partition. The YubiKey itself should also be kept in a secure location.
### Can I require a physical touch of the YubiKey before the private key can be used?
Yes but in practice this does not work very well with GAMADV-XTD3. The YubiKey will need to be touched every time there is a GAMADV-XTD3 command running which for batch or cron jobs may be constant. GAMADV-XTD3 can use a PIN configured on the YubiKey in order to offer an additional layer of protection.
### If I use a YubiKey, do I need to rotate the private key regularly?
No, because the YubiKey generated the private key it cannot be digitally exported from the YubiKey so there is not chance for it to be copied and stolen. Instead you should physically secure the YubiKey from theft.
### What data does the service account private key have access to?
When using domain-wide delegation with GAMADV-XTD3, the service account and anyone possessing the service account private key oauth2service.json file has access to the Gmail, Drive and Calendar data of ALL Workspace users in your domain. For this reason, whether using a YubiKey or not, you should take strong measures to protect the service account private key.
## Setup Steps
1. Upgrade to at least GAMADV-XTD3 6.50.01.
2.**If you are using a new YubiKey or don't care about the PIV app data on the YubiKey**
1. Tell GAMADV-XTD3 to reset and configure the PIV app data on the YubiKey. This wipes all existing keys and configuration and then configures a private key and PIN for GAMADV-XTD3.
* Use `9a` for the `AUTHENTICATION` slot, `9c` for the `SIGNATURE` slot
5. Now that you have a private key on your YubiKey, tell GAMADV-XTD3 to use that instead of the private_key stored in oauth2service.json. We can do that by rotating the key:
The yubikey argument tells GAMADV-XTD3 to use a private key on a plugged in YubiKey. The yubikey_pin argument tells GAMADV-XTD3 to prompt you to input the PIN that was set in the previous step. The yubikey_slot argument tells GAMADV-XTD3 which PIV slot to use on the YubiKey.
If there are problems, you can go back to the original oauth2service.json.
```
copy oauth2service.json to oauth2service.yk
copy oauth2service.save to oauth2service.json
```
6. Now you should be able to run GAMADV-XTD3 commands like:
```
gam user admin@example.com check serviceaccount
```
and see the YubiKey lights flash as the YubiKey interacts with GAMADV-XTD3 to sign the GAMADV-XTD3 authentication requests. If you look at the oauth2service.json file, you'll see it contains some new fields like yubikey_serial and yubikey_pin but no longer contains the private_key field where GAMADV-XTD3 would normally store the private key data.
7. As a last step, since YubiKey-stored private keys do not need to be and should not be rotated, you can remove the service account's permissions to change it's own key. Navigate to the [Cloud Console](https://console.cloud.google.com/iam-admin/serviceaccounts) select the correct project and service account and on the Permissions tab, edit and remove the "Service Account Key Admin" permission that the service account has to itself.
# Issuer: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only
# Subject: CN=Entrust Root Certification Authority - EC1 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2012 Entrust, Inc. - for authorized use only
# Issuer: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only
# Subject: CN=Entrust Root Certification Authority - G2 O=Entrust, Inc. OU=See www.entrust.net/legal-terms/(c) 2009 Entrust, Inc. - for authorized use only
"Responses with Content-Type of application/json",
"Media download with context-dependent Content-Type",
"Responses with Content-Type of application/x-protobuf"
],
"location":"query",
"type":"string"
},
"callback":{
"description":"JSONP",
"location":"query",
"type":"string"
},
"fields":{
"description":"Selector specifying which fields to include in a partial response.",
"location":"query",
"type":"string"
},
"key":{
"description":"API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
"location":"query",
"type":"string"
},
"oauth_token":{
"description":"OAuth 2.0 token for the current user.",
"location":"query",
"type":"string"
},
"prettyPrint":{
"default":"true",
"description":"Returns response with indentations and line breaks.",
"location":"query",
"type":"boolean"
},
"quotaUser":{
"description":"Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.",
"location":"query",
"type":"string"
},
"uploadType":{
"description":"Legacy upload protocol for media (e.g. \"media\", \"multipart\").",
"location":"query",
"type":"string"
},
"upload_protocol":{
"description":"Upload protocol for media (e.g. \"raw\", \"multipart\").",
"description":"Asset identifier as annotated by the administrator or specified during enrollment.",
"type":"string"
},
"annotatedLocation":{
"description":"Address or location of the device as annotated by the administrator.",
"type":"string"
},
"annotatedNotes":{
"description":"Notes about this device as annotated by the administrator",
"type":"string"
},
"annotatedUser":{
"description":"User of the device as annotated by the administrator.",
"type":"string"
},
"deviceId":{
"annotations":{
"required":[
"cbcm.chromebrowsers.update"
]
},
"description":"The unique ID of the device.",
"type":"string"
}
},
"type":"object"
},
"ChromeBrowsers":{
"id":"ChromeBrowsers",
"properties":{
"browsers":{
"description":"List of Chrome browser objects.",
"items":{
"$ref":"ChromeBrowser"
},
"type":"array"
},
"etag":{
"description":"ETag of the resource.",
"type":"string"
},
"kind":{
"default":"admin#directory#chromeosdevices",
"description":"Kind of resource this is.",
"type":"string"
},
"nextPageToken":{
"description":"Token used to access the next page of this result. To access the next page, use this token's value in the `pageToken` query string of this request.",
"description":"Token used to access the next page of this result. To access the next page, use this token's value in the `pageToken` query string of this request.",
"type":"string"
}
},
"type":"object"
},
"CreateEnrollmentTokenRequest":{
"id":"CreateEnrollmentTokenRequest",
"type":"object",
"properties":{
"org_unit_path":{
"description":"The full path of the organizational unit or its unique ID.",
"type":"string"
},
"expire_time":{
"description":"Expiration Time.",
"type":"string"
},
"token_type":{
"id":"token_type",
"annotations":{
"required":[
"cbcm.enrollmentTokens.create"
]
},
"description":"CHROME_BROWSER.",
"type":"string"
}
}
},
"MoveChromeBrowsersRequest":{
"id":"MoveChromeBrowsersRequest",
"type":"object",
"properties":{
"org_unit_path":{
"annotations":{
"required":[
"cbcm.chromebrowsers.moveChromeBrowsersToOu"
]
},
"description":"Destination organization unit to move devices to. Full path of the organizational unit or its ID prefixed with id:",
"type":"string"
},
"resource_ids":{
"annotations":{
"required":[
"cbcm.chromebrowsers.moveChromeBrowsersToOu"
]
},
"description":"List of unique device IDs of Chrome Browser Devices to move. A maximum of 600 browsers may be moved per request.",
"description":"The Contact Delegation API allows Admins to delegate access of one user's, called the delegator, contacts to another user, called the delegate.",
"Responses with Content-Type of application/json",
"Media download with context-dependent Content-Type",
"Responses with Content-Type of application/x-protobuf"
],
"location":"query",
"type":"string"
},
"callback":{
"description":"JSONP",
"location":"query",
"type":"string"
},
"fields":{
"description":"Selector specifying which fields to include in a partial response.",
"location":"query",
"type":"string"
},
"key":{
"description":"API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
"location":"query",
"type":"string"
},
"oauth_token":{
"description":"OAuth 2.0 token for the current user.",
"location":"query",
"type":"string"
},
"prettyPrint":{
"default":"true",
"description":"Returns response with indentations and line breaks.",
"location":"query",
"type":"boolean"
},
"quotaUser":{
"description":"Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.",
"location":"query",
"type":"string"
},
"uploadType":{
"description":"Legacy upload protocol for media (e.g. \"media\", \"multipart\").",
"location":"query",
"type":"string"
},
"upload_protocol":{
"description":"Upload protocol for media (e.g. \"raw\", \"multipart\").",
"description":"Token used to access the next page of this result. To access the next page, use this token's value in the `pageToken` query string of this request.",
"description":"Date the asset was last viewed by me.",
"format":"google-datetime"
},
"owner":{
"type":"string",
"description":"The owner of the asset."
},
"name":{
"type":"string",
"description":"The name of the asset."
},
"trashed":{
"type":"boolean",
"description":"Value indicating if the asset is in the trash."
},
"updateTime":{
"format":"google-datetime",
"description":"Date the asset was last modified.",
"type":"string"
},
"updateByMeTime":{
"description":"Date the asset was last modified by me.",
"type":"string",
"format":"google-datetime"
},
"assetType":{
"enumDescriptions":[
"Asset type not specified.",
"A report asset.",
"A data Source asset."
],
"enum":[
"ASSET_TYPE_UNSPECIFIED",
"REPORT",
"DATA_SOURCE"
],
"description":"The type of the asset.",
"type":"string"
}
},
"description":"A Data Studio asset.",
"type":"object"
},
"SearchAssetsResponse":{
"id":"SearchAssetsResponse",
"properties":{
"assets":{
"items":{
"$ref":"Asset"
},
"type":"array",
"description":"The list of assets."
},
"nextPageToken":{
"type":"string",
"description":"A token to retrieve next page of results. Pass this value in the SearchAssetsRequest.page_token field in the subsequent call to `SearchAssets` method to retrieve the next page of results."
}
},
"description":"Response message for DataStudioService.SearchAssets",
"type":"object"
},
"UpdatePermissionsRequest":{
"description":"Request message for DataStudioService.UpdatePermissions",
"properties":{
"updateMask":{
"description":"The list of fields to be updated. Currently not supported.",
"type":"string",
"format":"google-fieldmask"
},
"permissions":{
"description":"The permissions object to update.",
"$ref":"Permissions"
}
},
"id":"UpdatePermissionsRequest",
"type":"object"
},
"AddMembersRequest":{
"properties":{
"members":{
"type":"array",
"items":{
"type":"string"
},
"description":"Required. The members to add to the role. The format of a member is one of - user:alice@example.com - group:admins@example.com - domain:google.com - serviceAccount:my-app@appspot.gserviceaccount.com"
},
"role":{
"type":"string",
"enumDescriptions":[
"Role not specified.",
"A viewer.",
"An editor.",
"An owner.",
"Link shared viewer.",
"Link shared editor."
],
"enum":[
"ROLE_UNSPECIFIED",
"VIEWER",
"EDITOR",
"OWNER",
"LINK_VIEWER",
"LINK_EDITOR"
],
"description":"Required. The role to add members to."
}
},
"type":"object",
"id":"AddMembersRequest",
"description":"Request message for DataStudioService.AddMembers"
},
"Permissions":{
"type":"object",
"id":"Permissions",
"description":"A Data Studio asset's Permissions.",
"properties":{
"permissions":{
"description":"A map from a Role to a list of members. Role is a string representation of the Role enum. One of: - OWNER - EDITOR - VIEWER",
"additionalProperties":{
"$ref":"Members"
},
"type":"object"
},
"etag":{
"format":"byte",
"description":"etag to detect and fail concurrent modifications",
"type":"string"
}
}
},
"RevokeAllPermissionsRequest":{
"description":"Request message for DataStudioService.RevokeAllPermissions",
"id":"RevokeAllPermissionsRequest",
"type":"object",
"properties":{
"members":{
"description":"Required. The members that are having their access revoked. The format of a member is one of - user:alice@example.com - group:admins@example.com - domain:google.com - serviceAccount:my-app@appspot.gserviceaccount.com",
"items":{
"type":"string"
},
"type":"array"
}
}
},
"Members":{
"description":"A wrapper message for a list of members.",
"properties":{
"members":{
"description":"Format of string is one of - user:alice@example.com - group:admins@example.com - domain:google.com - serviceAccount:my-app@appspot.gserviceaccount.com",
"description":"Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.",
"type":"string"
},
"prettyPrint":{
"location":"query",
"type":"boolean",
"description":"Returns response with indentations and line breaks.",
"default":"true"
},
"callback":{
"location":"query",
"type":"string",
"description":"JSONP"
},
"uploadType":{
"description":"Legacy upload protocol for media (e.g. \"media\", \"multipart\").",
"type":"string",
"location":"query"
},
"upload_protocol":{
"type":"string",
"location":"query",
"description":"Upload protocol for media (e.g. \"raw\", \"multipart\")."
},
"$.xgafv":{
"enumDescriptions":[
"v1 error format",
"v2 error format"
],
"description":"V1 error format.",
"location":"query",
"type":"string",
"enum":[
"1",
"2"
]
},
"oauth_token":{
"type":"string",
"location":"query",
"description":"OAuth 2.0 token for the current user."
},
"alt":{
"type":"string",
"enum":[
"json",
"media",
"proto"
],
"location":"query",
"description":"Data format for response.",
"enumDescriptions":[
"Responses with Content-Type of application/json",
"Media download with context-dependent Content-Type",
"Responses with Content-Type of application/x-protobuf"
],
"default":"json"
},
"fields":{
"description":"Selector specifying which fields to include in a partial response.",
"location":"query",
"type":"string"
},
"access_token":{
"type":"string",
"description":"OAuth access token.",
"location":"query"
},
"key":{
"type":"string",
"location":"query",
"description":"API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token."
}
},
"servicePath":"",
"kind":"discovery#restDescription",
"resources":{
"assets":{
"methods":{
"getPermissions":{
"parameters":{
"name":{
"type":"string",
"location":"path",
"description":"Required. The name of the asset.",
"required":true
},
"role":{
"enumDescriptions":[
"Role not specified.",
"A viewer.",
"An editor.",
"An owner.",
"Link shared viewer.",
"Link shared editor."
],
"type":"string",
"location":"query",
"description":"The role of the permssion.",
"enum":[
"ROLE_UNSPECIFIED",
"VIEWER",
"EDITOR",
"OWNER",
"LINK_VIEWER",
"LINK_EDITOR"
]
}
},
"id":"datastudio.assets.getPermissions",
"response":{
"$ref":"Permissions"
},
"flatPath":"v1/assets/{name}/permissions",
"path":"v1/assets/{name}/permissions",
"description":"Gets the asset's permission for a given role.",
"parameterOrder":[
"name"
],
"httpMethod":"GET"
},
"updatePermissions":{
"id":"datastudio.assets.updatePermissions",
"parameterOrder":[
"name"
],
"flatPath":"v1/assets/{name}/permissions",
"description":"Updates a permission.",
"request":{
"$ref":"UpdatePermissionsRequest"
},
"path":"v1/assets/{name}/permissions",
"parameters":{
"name":{
"description":"Required. The name of the asset.",
"location":"path",
"type":"string",
"required":true
}
},
"response":{
"$ref":"Permissions"
},
"httpMethod":"PATCH"
},
"get":{
"path":"v1/{+name}",
"id":"datastudio.assets.get",
"parameterOrder":[
"name"
],
"description":"Gets the asset by name.",
"parameters":{
"name":{
"description":"Required. The name of the asset. Format: assets/{asset}",
"location":"path",
"required":true,
"pattern":"^assets/[^/]+$",
"type":"string"
}
},
"flatPath":"v1/assets/{assetsId}",
"response":{
"$ref":"Asset"
},
"httpMethod":"GET"
},
"search":{
"response":{
"$ref":"SearchAssetsResponse"
},
"path":"v1/assets:search",
"parameters":{
"pageToken":{
"type":"string",
"location":"query",
"description":"A token identifying a page of results the server should return. Use the value of SearchAssetsResponse.next_page_token returned from the previous call to `SearchAssets` method."
},
"assetTypes":{
"type":"string",
"repeated":true,
"description":"Exactly one AssetType must be specified.",
"enumDescriptions":[
"Asset type not specified.",
"A report asset.",
"A data Source asset."
],
"location":"query",
"enum":[
"ASSET_TYPE_UNSPECIFIED",
"REPORT",
"DATA_SOURCE"
]
},
"title":{
"description":"The title of assets to include. Not an exact match, works the same as search from the UI.",
"location":"query",
"type":"string"
},
"owner":{
"type":"string",
"location":"query",
"description":"The email of the owner of the asset."
},
"pageSize":{
"description":"Requested page size. If unspecified, server will pick an appropriate default.",
"location":"query",
"type":"integer",
"format":"int32"
},
"orderBy":{
"location":"query",
"description":"How the results should be ordered. Valid options are: - title",
"type":"string"
},
"includeTrashed":{
"location":"query",
"type":"boolean",
"description":"Value indicating if assets in trash should be included."
read -p "Please enter the email address of a regular Google Workspace user: " regularuser
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."
# "$target_dir/$target_gam" $config_cmd user $regularuser check serviceaccount
"$target_dir/$target_gam" user $regularuser check serviceaccount
# "$target_gam" $config_cmd user $regularuser check serviceaccount
"$target_gam" user $regularuser check serviceaccount
1. Choose "Desktop App" or "Other" for "Application type".
2. Enter"GAM" or another desired value for "Name".
3. Click the blue "Create" button.
4. Copy your "Client ID" value that shows on the next page.
1. If "+ CREATE CLIENT" is on the screen, skip to step 14
2. Click"GET STARTED"
3. Under "App Information", enter {1} or another value in "App name *"
4. Under "App Information", enter {2} in "User support email *"
5. Click "NEXT"
6. Under "Audience", choose INTERNAL
7. Click "NEXT"
8. Under, "Contact Information", enter an email address in "Email addresses *"
9. Click "NEXT"
10. Under "Finish", click "I agree to the Google API Services: User Data Policy."
11. Click "CONTINUE"
12. Click "CREATE"
13. Click "Clients" in the left-hand column
14. Click "+ CREATE CLIENT"
15. Choose "Desktop App" for "Application type"
16. Enter {1} or another value in "Name *"
17. Click "Create"
18. Under "Name", click your client name
19. Copy the "Client ID" value under "Additional information"
20. Paste it at the "Enter your Client ID: " prompt in your terminal
21. Press return/enter in your terminal
22. Switch back to the browser
23. Copy the "Client secret" value under "Client Secrets"
24. Paste it at the "Enter your Client Secret: " prompt in your terminal
25. Press return/enter in your terminal
26. Switch back to the browser
27. Click "OK"
28. These steps are complete
'''
ENTER_YOUR_CLIENT_ID='\nEnter your Client ID: '
GO_BACK_TO_YOUR_BROWSER_AND_COPY_YOUR_CLIENT_SECRET_VALUE='\n5. Go back to your browser and copy your "Client Secret" value.\n'
ENTER_YOUR_CLIENT_SECRET='\nEnter your Client Secret: '
GO_BACK_TO_YOUR_BROWSER_AND_CLICK_OK_TO_CLOSE_THE_OAUTH_CLIENT_POPUP='\n6. Go back to your browser and click OK to close the "OAuth client" popup if it\'s still open.\n'
@@ -148,8 +184,9 @@ ALREADY_EXISTS_USE_MERGE_ARGUMENT = 'Already exists; use the "merge" argument to
API_ACCESS_DENIED='API access Denied'
API_CALLS_RETRY_DATA='API calls retry data\n'
API_CHECK_CLIENT_AUTHORIZATION='Please make sure the Client ID: {0} is authorized for the appropriate API or scopes:\n{1}\n\nRun: gam oauth create\n'
API_CHECK_SVCACCT_AUTHORIZATION='Please make sure the Service Account Client name: {0} is authorized for the appropriate API or scopes:\n{1}\n\nRun: gam user {2}check serviceaccount\n'
API_CHECK_SVCACCT_AUTHORIZATION='Please make sure the Service Account Client ID: {0} is authorized for the appropriate API or scopes:\n{1}\n\nRun: gam user {2}update serviceaccount\n'
API_ERROR_SETTINGS='API error, some settings not set'
ARE_BOTH_REQUIRED='Arguments {0} and {1} are both required'
ARE_MUTUALLY_EXCLUSIVE='Arguments {0} and {1} are mutually exclusive'
CALLING_GCLOUD_FOR_REAUTH='Calling gcloud for reauth credentials..."\n'
CAN_NOT_DELETE_USER_WITH_VAULT_HOLD='{0}: The user may be (or have recently been) on Google Vault Hold and thus not eligible for deletion. You can check holds with "gam user {1} show vaultholds".'
CAN_NOT_BE_SPECIFIED_MORE_THAN_ONCE='Argument {0} can not be specified more than once'
CHAT_ADMIN_ACCESS_LIMITED_TO_ONE_USER='Chat adminaccess|asadmin limited to one user, {0} specified'
CHROME_TARGET_VERSION_FORMAT=r'^([a-z]+)-(\d+)$ or ^(\d{1,4}\.){1,4}$'
COLUMN_DOES_NOT_MATCH_ANY_INPUT_COLUMNS='{0} column "{1}" does not match any input columns'
COLUMN_DOES_NOT_MATCH_ANY_OUTPUT_COLUMNS='{0} column "{1}" does not match any output columns'
GAM_LATEST_VERSION_NOT_AVAILABLE='GAM Latest Version information not available'
GAM_OUT_OF_MEMORY='GAM has run out of memory. If this is a large Google Workspace instance, you should use a 64-bit version of GAM on Windows or a 64-bit version of Python on other systems.'
GENERATING_NEW_PRIVATE_KEY='Generating new private key'
GETTING='Getting'
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'
GUARDIAN_INVITATION_STATUS_NOT_PENDING='Guardian invitation status is not PENDING'
HAS_CHILD_ORGS='Has child {0}'
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}".'
HELP_SYNTAX='Help: Syntax in file {0}\n'
HELP_WIKI='Help: Documentation is at {0}\n'
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_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'
INTER_BATCH_WAIT_INCREASED='inter_batch_wait increased to {0:.2f}'
INVALID='Invalid'
@@ -281,7 +322,7 @@ INVALID_NUMBER_OF_CHAT_SPACE_MEMBERS = '{0} type {1} number of members, {2}, mus
INVALID_ORGUNIT='Invalid Organizational Unit'
INVALID_PATH='Invalid Path'
INVALID_PERMISSION_ATTRIBUTE_TYPE='permission attribute {0} not allowed with type {1}'
'product':'101034','aliases':['gseau','enterprisearchived','gsuiteenterprisearchived'],'displayName':'Google Workspace Enterprise Plus - Archived User'},
'1010340002':{
@@ -130,14 +158,16 @@ _SKUS = {
'product':'101034','aliases':['wsbizstarterarchived','workspacebusinessstarterarchived'],'displayName':'Google Workspace Business Starter - Archived User'},
'1010340006':{
'product':'101034','aliases':['wsbizstanarchived','workspacebusinessstanarchived'],'displayName':'Google Workspace Business Standard - Archived User'},
'1010340007':{
'product':'101034','aliases':['gwefau','gwefarchived','workspaceeducationfundamentalsarchived'],'displayName':'Google Workspace for Education Fundamentals - Archived User'},
"Responses with Content-Type of application/json",
"Media download with context-dependent Content-Type",
"Responses with Content-Type of application/x-protobuf"
],
"location":"query",
"type":"string"
},
"callback":{
"description":"JSONP",
"location":"query",
"type":"string"
},
"fields":{
"description":"Selector specifying which fields to include in a partial response.",
"location":"query",
"type":"string"
},
"key":{
"description":"API key. Your API key identifies your project and provides you with API access, quota, and reports. Required unless you provide an OAuth 2.0 token.",
"location":"query",
"type":"string"
},
"oauth_token":{
"description":"OAuth 2.0 token for the current user.",
"location":"query",
"type":"string"
},
"prettyPrint":{
"default":"true",
"description":"Returns response with indentations and line breaks.",
"location":"query",
"type":"boolean"
},
"quotaUser":{
"description":"Available to use for quota purposes for server-side applications. Can be any arbitrary string assigned to a user, but should not exceed 40 characters.",
"location":"query",
"type":"string"
},
"uploadType":{
"description":"Legacy upload protocol for media (e.g. \"media\", \"multipart\").",
"location":"query",
"type":"string"
},
"upload_protocol":{
"description":"Upload protocol for media (e.g. \"raw\", \"multipart\").",
"location":"query",
"type":"string"
}
},
"protocol":"rest",
"resources":{
"serviceaccounts":{
"methods":{
"lookup":{
"description":"Lookup",
"flatPath":"metadata/x509/{account}",
"httpMethod":"GET",
"id":"serviceaccountslookup.lookup",
"parameterOrder":[
"account"
],
"parameters":{
"account":{
"description":"Email or ID of the service account.",
- [Authorize a super admin to create projects](#authorize-a-super-admin-to-create-projects)
- [Authorize Service Account Key Uploads](#authorize-service-account-key-uploads)
- [Authorize GAM to create projects](#authorize-gam-to-create-projects)
- [Create a new GCP project folder](#create-a-new-gcp-project-folder)
- [Create a new project for GAM authorization](#create-a-new-project-for-gam-authorization)
@@ -30,6 +30,7 @@
- [Update an existing Service Account key](#update-an-existing-service-account-key)
- [Replace all existing Service Account keys](#replace-all-existing-service-account-keys)
- [Delete Service Account keys](#delete-service-account-keys)
- [Upload a Service Account key to a service account with no keys](#upload-a-service-account-key-to-a-service-account-with-no-keys)
- [Display Service Account keys](#display-service-account-keys)
- [Manage Service Account access](#manage-service-account-access)
- [Full Service Account access](#full-service-account-access)
@@ -44,6 +45,7 @@
- [Install GAM on the limited users computer](#install-gam-on-the-limited-users-computer)
- [Test Client and Service Account access on the non-administrator computer](#test-client-and-service-account-access-on-the-non-administrator-computer)
- [Unselect limited section on your computer.](#unselect-limited-section-on-your-computer)
- [Delete old versions of GAM from Configured Apps](#delete-old-versions-of-gam-from-configured-apps)
## Introduction
GAM requires authorization to perform tasks on your domain; the tasks break down into two categories:
@@ -89,6 +91,20 @@ If you run a Google Workspace Education SKU, verify that the super admin you'll
* Choose "All users are 18 or older"
* Click "SAVE"
Based on your domain policies, you may have to mark GAM as a trusted app. These steps are performed after a project is created.
* Access the admin console and go to Security -> Access and data control -> API controls
* Click Manage third-party app access
* Click Configure new app
* Paste client_id value from client_secrets.json in Search for app
* Click Search
* Click the line referencing GAM
* Keep the default scope All in domain.com (all users) or select an org unit that includes your GAM admin
* Click Continue
* Click Trusted: App can request access to all Google data
* Click Continue
* Click Finish
* Press Confirm if Confirm parental consent pops up
Verify whether the super admin you'll be using is in an OU where reauthentication is required.
* Access the admin console and go to Security -> Overview
* Scroll down and open Google Cloud session control section
@@ -96,23 +112,11 @@ Verify whether the super admin you'll be using is in an OU where reauthenticatio
* If Require reauthentication is selected and Exempt Trusted apps is not checked, you'll have to do `gam oauth create` at whatever frequency is specified
* If that sounds unappealing, check Exempt Trusted apps
* Click "OVERRIDE"
* Follow the steps below to mark GAM as a trusted app
Based on your domain policies, you may have to mark GAM as a trusted app. These steps are performed after a project is created.
* Access the admin console and go to Security -> Access and data control -> API controls
* Check Trust internal, domain-owned apps
* Click **Manage third-party app access**
* Click Add app and select **OAuth App Name Or Client ID**
* Paste client_id value from client_secrets.json
* Click Search
* Click Select at right end of line referencing GAM
* Check box to the left of the line with GAM client ID
* Click Select
* Keep the default scope domain.com (all users) or select an org unit that includes your GAM admin
* Click Next/Continue
* Click Trusted: App can request access to all Google data
* Click Next/Continue
* Click Finish
Additional steps may be required if errors are encountered.
* [Authorize a super admin to create projects](#authorize-a-super-admin-to-create-projects)
* [Authorize Service Account Key Uploads](#authorize-service-account-key-uploads)
* [Authorize GAM to create projects](#authorize-gam-to-create-projects)
## Headless computers and Cloud Shells
With many thanks to Jay, `gam oauth create` now uses a new client access authentication flow
@@ -120,25 +124,6 @@ as required by Google for headless computers/cloud shells; this is required as o
Must match this Python Regular Expression: [a-zA-Z0-9 '"!-]{4,30}
<ServiceAccountName> ::= <String>
@@ -176,12 +161,11 @@ gam oauth update
```
## Manage Projects
In all of the project commands, the Google Workspace admin/GCP project manager `<EmailAddress>` can be omitted; you will be prompted for a value.
You must enter a full address, i.e., user@domain.com; you will be required to enter the password.
You must enter a full address, i.e., user@domain.com; you will be required to authenticate.
For `print|show projects`, you can eliminate the password requirement by enabling the following scope in `gam update serviceaccount`;
GAM will then use Service Account access to display projects.
For `print|show projects`, you can eliminate the password prompt and authentication requirement by specifying the super admin emailaddress used in `gam oauth create`.
```
[*] 9) Cloud Resource Manager API v3
gam print projects admin admin@domain.com
```
## Authorize a super admin to create projects
@@ -191,7 +175,7 @@ perform these steps and then retry the create project command.
* Login as an existing super admin at console.cloud.google.com
* In the upper left click the three lines to the left of Google Cloud and select IAM & Admin
* Under IAM & Admin select IAM
* Click the down arrow in the box to the right of Google Cloud
* Click in the box to the right of Google Cloud
* Click the three dots at the right and select IAM/Permissions
* Now you should be at "Permissions for organization ..."
* Click on Grant Access
@@ -199,8 +183,58 @@ perform these steps and then retry the create project command.
* Click in the Select a role box
* Type project creator in the Filter box
* Click Project Creator
* Click + Add Another Role
* Type orgpolicy.policyAdmin in the Filter box
* Click Organization Policy Administrator
* Click Save
## Authorize Service Account Key Uploads
If you try to create a project and get an error saying that Constraint `constraints/iam.disableServiceAccountKeyUpload violated for service account projects/gam-project-xxxxx`,
perform these steps and then you should be able to authorize and use your project.
* Login as an existing super admin at console.cloud.google.com
* In the upper left click the three lines to the left of Google Cloud and select IAM & Admin
* Under IAM & Admin select IAM
* Click in the box to the right of Google Cloud
* Click the three dots at the right and select IAM/Permissions
* Now you should be at "Permissions for organization ..."
* Click on Grant Access
* Enter the new admin address in Principals
* Click in the Select a role box
* Type orgpolicy.policyAdmin in the Filter box
* Click Organization Policy Administrator
* Click Save
* In the upper left click the three lines to the left of Google Cloud and select IAM & Admin
* Under IAM & Admin select IAM
* Click in the box to the right of Google Cloud
* Click the three dots at the right and select Manage Resources
* Click the three dots at the end of the line for the GAM project just created
* Click Settings
* Click Organization Policies in the left column
* Now you should be at "Policies for Gam Project"
* Click in the Filter box
* Enter iam.managed.disableServiceAccountKeyUpload
* Click the three dots at the end of the Disable service account key upload/iam.managed.disableServiceAccountKeyUpload line
* Choose Edit policy
* Click Override parent's policy
* Click Add A Rule
* Select Enforcement/Off
* Click Done
* Click Set Policy
* Click the three dots at the end of the Disable Service Account Key Upload/iam.disableServiceAccountKeyUpload line
* Choose Edit policy
* Click Override parent's policy
* Click Add A Rule
* Select Enforcement/Off
* Click Done
* Click Set Policy
Wait a couple of minutes for the policy updates to complete and then do the following to upload the service account key:
```
gam upload sakey [admin <EmailAddress>]
```
## Authorize GAM to create projects
If you try to create a project and get an error saying "This app has been blocked on your domain for either being
insecure or non-edutational"; you'll have to mark the GAM Project Creation app as trusted.
@@ -243,13 +277,13 @@ You can skip these steps if you know that untrusted third-party apps are allowed
### Default values
* `<AppName>` - "GAM"
* `<ProjectID>` - "gam-project-abc-def-jki" where "abc-def-ghi" are randomly generated
* `<ProjectID>` - "gam-project-a1b2c" where "a1b2c" are randomly generated
* `sadisplayname <ServiceAccountDisplayName>` - Service account display name
* `sadescription <ServiceAccountDescription>` - Service account description
You can optionally specify the type of service account key with `algorithm|localkeysize|yubikey`: [Manage Service Account keys](#manage-service-account-keys)
Use `nokey` if you do not want a service account key created for the project.
## Use an existing project for GAM authorization
Use an existing project to create and download two files: `client_secrets.json` for the Client and `oauth2service.json` for the Service Account.
@@ -284,23 +326,30 @@ Use an existing project to create and download two files: `client_secrets.json`
* `sadisplayname <ServiceAccountDisplayName>` - Service account display name
* `sadescription <ServiceAccountDescription>` - Service account description
You can optionally specify the type of service account key with `algorithm|localkeysize|yubikey`: [Manage Service Account keys](#manage-service-account-keys)
## Update an existing project for GAM authorization
This command is used when GAM has added new capabilities that require additional APIs to be added to your project.
[] 23) Cloud Storage API (Read/Write, Vault/Takeout Copy/Download, Cloud Storage)
[*] 24) Contact Delegation API (supports readonly)
[*] 25) Contacts API - Domain Shared Contacts and GAL
[*] 26) Data Transfer API (supports readonly)
[*] 27) Directory API - Chrome OS Devices (supports readonly)
[*] 28) Directory API - Customers (supports readonly)
[*] 29) Directory API - Domains (supports readonly)
[*] 30) Directory API - Groups (supports readonly)
[*] 31) Directory API - Mobile Devices Directory (supports readonly and action)
[*] 32) Directory API - Organizational Units (supports readonly)
[*] 33) Directory API - Resource Calendars (supports readonly)
[*] 34) Directory API - Roles (supports readonly)
[*] 35) Directory API - User Schemas (supports readonly)
[*] 36) Directory API - User Security
[*] 37) Directory API - Users (supports readonly)
[ ] 38) Email Audit API
[*] 39) Groups Migration API
[*] 40) Groups Settings API
[*] 41) License Manager API
[*] 42) People API (supports readonly)
[*] 43) People Directory API - read only
[] 44) Pub / Sub API
[*] 45) Reports API - Audit Reports
[*] 46) Reports API - Usage Reports
[ ] 47) Reseller API
[*] 48) Site Verification API
[ ] 49) Sites API
[*] 50) Vault API (supports readonly)
s) Select all scopes
u) Unselect all scopes
e) Exit without changes
c) Continue to authorization
Please enter 0-42[a|r] or s|u|e|c:
Select an unselected scope [ ] by entering a number; yields [*]
For scopes that support readonly, enter a number and an 'r' to grant read-only access; yields [R]
For scopes that support action, enter a number and an 'a' to grant action-only access; yields [A]
Clear read-only access [R] or action-only access [A] from a scope by entering a number; yields [*]
Unselect a selected scope [*] by entering a number; yields [ ]
Select all default scopes by entering an 's'; yields [*] for default scopes, [ ] for others
Unselect all scopes by entering a 'u'; yields [ ] for all scopes
Exit without changes/authorization by entering an 'e'
Continue to authorization by entering a 'c'
Note, if all scopes are selected, Google will probably generate an authorization error
Please enter 0-50[a|r] or s|u|e|c: c
Enter your Google Workspace admin email address? admin@domain.com
@@ -565,8 +636,6 @@ gam select bbb oauth update
```
## Refresh Client credentials
If necessary, update `oauth2.txt` from versions of GAM before `5.00.00`.
Refresh the expiration time in `oauth2.txt`.
```
gam oauth refresh
@@ -601,13 +670,9 @@ Export `oauth2.txt` in JSON form.
```
gam oauth|oauth2 export [<FileName>]
```
For GAM version `5.00.00` and later:
* If `<FileName>` is omitted, the JSON data is written to `oauth2.txt`.
* If `<FileName>` is `-`, the JSON data is written to stdout.
For GAM versions before `5.00.00`:
* If `<FileName>` is omitted, the JSON data is written to stdout.
## Manage Service Accounts
In all of the service account commands, the Google Workspace admin/GCP project manager `<EmailAddress>` can be omitted; you will be prompted for a value.
You must enter a full address, i.e., user@domain.com; you will be required to enter the password.
@@ -625,11 +690,14 @@ file or define a new section in `gam.cfg` that references a different `oauth2ser
* `<EmailAddress>` - Google Workspace admin/GCP project manager; if omitted, you will be prompted for the address
Use these options to select projects.
* `current` - The project referenced in `client_secret.json`; this is the default
* `current` - The project referenced in `client_secrets.json`; this is the default
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
@@ -639,6 +707,8 @@ Use these options to select user-specified values..
* `sadisplayname <ServiceAccountDisplayName>` - Service account display name
* `sadescription <ServiceAccountDescription>` - Service account description
You can optionally specify the type of service account key with `algorithm|localkeysize|yubikey`: [Manage Service Account keys](#manage-service-account-keys)
After adding an additional service account, you can select specific access APIs for it.
[Selective Service Account access](#selective-service-account-access)
* `all` - All projects accessible by the administrator; this is the default
* `current` - The project referenced in `client_secret.json`
* `current` - The project referenced in `client_secrets.json`
* `gam` - Projects accessible by the administrator that were created by Gam, i.e, their project ID begins with `gam-project-`
* `<ProjectID>` - A Google API project ID
* `filter <String>` - A filter to select projects accessible by the administrator; see the API documentation
@@ -695,6 +765,7 @@ There are several methods for generating private keys:
* `localkeysize 1024` - Gam generates a 1024 bit key; this is not recommended
* `localkeysize 2048` - Gam generates a 2048 bit key; this is the default
* `localkeysize 4096` - Gam generates a 4096 bit key
* `yubikey yubikey_pin yubikey_slot AUTHENTICATION|SIGNATURE yubikey_serialnumber <Number>)]` - [Using GAM7 with a YubiKey](Using-GAM7-with-a-YubiKey)
When `localkeysize` is specified, the optional argument `validityhours <Number>` sets the length of time during which the key will be valid and should be used when the [GCP constraints/iam.serviceAccountKeyExpiryHours organization policy](https://cloud.google.com/resource-manager/docs/organization-policy/restricting-service-accounts#limit_key_expiry) is in use. Note that in order to account for system clock skew, GAM sets the key to be valid two minutes earlier than the current system time and thus it will also expire two minutes earlier.
@@ -716,20 +787,16 @@ The `oauth2service.json` file is updated with the new private key.
Keep a good record of where each Service Account key is used as the keys themselves do not record this information.
The two forms of the command are equivalent; the second form is used by Basic Gam.
The two forms of the command are equivalent; the second form is used by Legacy GAM.
* `noescapechar <Boolean>` - Should `\` be ignored as an escape character; if not specified, the value of `csv_input_no_escape_char` from `gam.cfg` will be used
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings.
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `(matchfield|skipfield <FieldName> <RESearchPattern>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `showcmds` - Write `timestamp,command number/number of commands,command` to stderr when each command starts; write `timestamp, command number/numberof commands,complete` to stderr when command completes
* `skiprows <Integer>` - Skip filtered rows from the CSV file/Google Sheet.
* `skiprows 0` - All rows are processed, this is the default
@@ -119,7 +121,7 @@ Put a space in front of the `~`: `targetfolder " ~/Documents/GamWork"` to avoid
* You want a note field that shows their email address as name AT domain.com
* You have a CSV file Users.csv with columns: primaryEmail,Street,City,State,ZIP
```
gam csv Users.csv gam update user ~primaryEmail address type work unstructured "~~Street~~, ~~City~~, ~~State~~~~ZIP~~" primary note text_plain "~~primaryEmail~!~^(.+)@(.+)$~!~\1 AT \2~~"
gam csv Users.csv gam update user "~primaryEmail" address type work unstructured "~~Street~~, ~~City~~, ~~State~~~~ZIP~~" primary note text_plain "~~primaryEmail~!~^(.+)@(.+)$~!~\1 AT \2~~"
- [Saving filters in gam.cfg](#saving-filters-in-gamcfg)
There are five values in `gam.cfg` that can be used to filter the output from `gam print` commands.
There are seven values in `gam.cfg` that can be used to filter the output from `gam print` commands.
* `csv_output_header_filter` - A list of `<RegularExpressions>` used to select specific column headers to include
* `csv_output_header_drop_filter` - A list of `<RegularExpressions>` used to select specific column headers to exclude
* `csv_output_header_force` - A list of <Strings> used to specify the exact column headers to include
* `csv_output_header_order` - A list of <Strings> used to specify the column header order; any headers in the file but not in the list will appear after the headers in the list.
* `csv_output_row_filter` - A list or JSON dictionary used to include specific rows based on column values
* `csv_output_row_drop_filter` - A list or JSON dictionary used to exclude specific rows based on column values
* `csv_output_row_limit` - A limit on the number of rows written
If you define a value for `csv_output_header_filter`, `csv_output_header_drop_filter`, `csv_output_row_filter`, `csv_output_row_drop_filter` or `csv_output_row_limit` in the `[DEFAULT]` section of `gam.cfg`,
If you define a value for `csv_output_header_filter`, `csv_output_header_drop_filter`,`csv_output_header_force`, `csv_output_header_order`,`csv_output_row_filter`, `csv_output_row_drop_filter` or `csv_output_row_limit` in the `[DEFAULT]` section of `gam.cfg`,
it will apply to every `gam print` command which is probably not desirable. You can store them in `gam.cfg` in named sections.
@@ -343,7 +361,7 @@ If none of the following options are selected, all events are selected.
* `<EventSelectProperty>* <EventMatchProperty>*` - Properties used to select events
The Google Calendar API processes `<EventSelectProperty>*`; you may specify none or multiple properties.
* `after|starttime|timemin <Time>` - Lower bound (inclusive) for an event's end time to filter by. If timeMax is set, timeMin must be smaller than timeMax.
* `after|starttime|timemin <Time>` - Lower bound (exclusive) for an event's end time to filter by. If timeMax is set, timeMin must be smaller than timeMax.
* `before|endtime|timemax <Time>` - Upper bound (exclusive) for an event's start time to filter by. If timeMin is set, timeMax must be greater than timeMin.
* `eventtypes <EventTypeList>` - Select events based on their type.
* `query <QueryCalendar>` - Free text search terms to find events that match these terms in any field, except for extended properties
@@ -356,26 +374,34 @@ The Google Calendar API processes `<EventSelectProperty>*`; you may specify none
GAM processes `<EventMatchProperty>*`; you may specify none or multiple properties.
* `matchfield attendees <EmailAddressEntity>` - All of the attendees in `<EmailAddressEntity>` must be present
* `matchfield attendeespattern <RegularExpression>` - Some attendee must match `<RegularExpression>`
* `matchfield attendeesonlydomainlist <DomainNameList>` - All attendee's email addresses must be in a domain in `<DomainNameList>`
* For example, this lets you look for events with all attendees in your internal domains. You should include `resource.calendar.google.com`
in `<DomainNameList>` if the events use resources.
* `matchfield attendeesdomainlist <DomainNameList>` - Some attendee's email address must be in a domain in `<DomainNameList>`
* For example, this lets you look for events with attendees in specific external domains
* `matchfield attendeesnotdomainlist <DomainNameList>` - Some attendee's email address must be in a domain not in `<DomainNameList>`
* For example, this lets you look for events with attendees not in your internal domains. You should include `resource.calendar.google.com`
in `<DomainNameList>` if the events use resources.
* `matchfield attendeespattern <RESearchPattern>` - Some attendee's email address must match `<RESearchPattern>`
* `matchfield attendeesstatus [<AttendeeAttendance>] [<AttendeeStatus>] <EmailAddressEntity>` - All of the attendees in `<EmailAddressEntity>` must be present
and must have the specified values.
* `<AttendeeAttendance>` - Default is `required`
* `<AttendanceStatus>` - Default is`needsaction`
* `matchfield creatoremail <RegularExpression>` - The creator email address must match `<RegularExpression>`
* `matchfield creatorname <RegularExpression>` - The creator name must match `<RegularExpression>`
* `matchfield description <RegularExpression>` - The description (summary) must match `<RegularExpression>`
* `matchfield location <RegularExpression>` - The location must match `<RegularExpression>`
* `matchfield organizeremail <RegularExpression>` - The organizer email address must match `<RegularExpression>`
* `matchfield organizername <RegularExpression>` - The orgainzer name must match `<RegularExpression>`
* `matchfield status <RegularExpression>` - The summary must match `<RegularExpression>`. The API documented values are:
* `matchfield creatoremail <RESearchPattern>` - The creator email address must match `<RESearchPattern>`
* `matchfield creatorname <RESearchPattern>` - The creator name must match `<RESearchPattern>`
* `matchfield description <RESearchPattern>` - The description (summary) must match `<RESearchPattern>`
* `matchfield location <RESearchPattern>` - The location must match `<RESearchPattern>`
* `matchfield organizeremail <RESearchPattern>` - The organizer email address must match `<RESearchPattern>`
* `matchfield organizername <RESearchPattern>` - The orgainzer name must match `<RESearchPattern>`
* `matchfield status <RESearchPattern>` - The summary must match `<RESearchPattern>`. The API documented values are:
* `confirmed`
* `tentative`
* `cancelled`
* `matchfield summary <RegularExpression>` - The summary must match `<RegularExpression>`
* `matchfield transparency <RegularExpression>` - The summary must match `<RegularExpression>`. The API documented values are:
* `matchfield summary <RESearchPattern>` - The summary must match `<RESearchPattern>`
* `matchfield transparency <RESearchPattern>` - The summary must match `<RESearchPattern>`. The API documented values are:
* `opaque` - Busy. The API does not seem to return this value; use `"(^$)|opaque"` to match no value or `opaque`.
* `transparent` - Free/Available
* `matchfield visibility <RegularExpression>` - The summary must match `<RegularExpression>`. The API documented values are:
* `matchfield visibility <RESearchPattern>` - The summary must match `<RESearchPattern>`. The API documented values are:
* `default` - The API does not seem to return this value; use `"(^$)|default"` to match no value or `default`.
* `public` - The API does not seem to return this value if it is the default; use `"(^$)|public"` to match no value or `public`.
* `private` - The API does not seem to return this value if it is the default; use `"(^$)|private"` to match no value or `private`.
@@ -414,6 +440,7 @@ You can specify attendees in the following ways:
@@ -581,8 +608,19 @@ 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.
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
### Special character processing
When outputting events with `formatjson` with the goal of adding the events to another calendar,
use these options at the beginning of the command:
Since GAM 6.04.00, GAM is capable of acting as a Chat Bot and sending messages to Chat Rooms or direct messages to users. You first need to configure your Chat Bot.
@@ -55,7 +109,7 @@ Since GAM 6.04.00, GAM is capable of acting as a Chat Bot and sending messages t
* Enter an App name and Description of your choosing.
* For the Avatar URL you can use `https://dummyimage.com/384x256/4d4d4d/0011ff.png&text=+GAM` or a public URL to an image of your own choosing.
* In Functionality, uncheck both "Receive 1:1 messages" and "Join spaces and group conversations"
* 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".
* Click Save.
@@ -69,6 +123,7 @@ At first you'll have no spaces listed. Try [finding your bot and chatting it](ht
### Display information about a specific chat space
```
gam info chatspace space <ChatSpace>
[fields <ChatSpaceFieldNameList>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
@@ -77,6 +132,7 @@ By default, Gam displays the information as an indented list of keys and values.
### Display information about all chat spaces
```
gam show chatspaces
[fields <ChatSpaceFieldNameList>]
[formatjson]
```
By default, Gam displays the information as an indented list of keys and values.
@@ -84,11 +140,12 @@ By default, Gam displays the information as an indented list of keys and values.
* [Chrome Management API - Count Devices that Need Attention](https://developers.google.com/chrome/management/reference/rest/v1/customers.reports/countChromeDevicesThatNeedAttention)
## Notes
To use these features you must add the `Chrome Management API` to your project and authorize
Use these options to select Chrome profiles; if none are chosen, all Chrome profiles in the account are selected:
* `filter <String>` - Limit profiles to those that match a query
The first two columns will always `name,profileId`; the remaining field names will be sorted if `sortheaders` is specified;
otherwise, the remaining field names will appear in the order specified.
Select the fields to be displayed:
* `<ChromeProfileFieldName>* [fields <ChromeProfileFieldNameList>]` - Display a selected list of fields
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format:
* `formatjson` - Display the fields in JSON format.
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.
## Profile Query Searchable Fields
These are the fields that can be used in a filter:
```
affiliationState
browserChannel
browserVersion
displayName
extensionCount
firstEnrollmentTime
identityProvider
lastActivityTime
lastPolicySyncTime
lastStatusReportTime
osPlatformType
osVersion
ouId
policyCount
profileId
userEmail
```
Any of the above fields can be used to specify a filter, and filtering by multiple fields is supported with AND operator.
String type fields and enum type fields support '=' and '!=' operators. Wildcard '*' can be used with a string type field filter.
The integer type and the timestamp type fields support '=', '!=', '<', '>', '<=' and '>=' operators.
Timestamps expect an RFC-3339 formatted string (e.g. 2012-04-21T11:30:00-04:00).
In addition, string literal filtering is also supported, for example, 'ABC' as a filter maps to a filter that checks if any of the filterable string type fields contains 'ABC'.
Organization unit number can be used as a filtering criteria here by specifying 'ouId = <String>', please note that only single OU ID matching is supported.
### Examples
For Windows PowerShell, replace `\"` with ``` `" ```.
Print information about Chrome profiles synced more than 30 days ago:
@@ -105,7 +103,10 @@ The second form is backwards compatible with Standard GAM and selection with `<C
annotatedlocation|location|
annotateduser|user|
autoupdateexpiration|
autoupdatethrough|
backlightinfo|
bootmode|
cpuinfo|
cpustatusreports|
deprovisionreason|
devicefiles|
@@ -115,6 +116,9 @@ The second form is backwards compatible with Standard GAM and selection with `<C
dockmacaddress|
ethernetmacaddress|
ethernetmacaddress0|
extendedsupporteligible|
extendedsupportstart|
extendedsupportenabled|
firmwareversion|
firstenrollmenttime|
lastdeprovisiontimestamp|
@@ -247,6 +251,9 @@ Enter `id:` as the operator. For example, if you are searching for the serial nu
Partial serial number searches are supported, as long as you enter at least three characters in the serial number.
All serial number searches are partial, be careful that you don't enter a partial serial number by mistake
when actioning/modifying devices as you will affect multiple devices rather than the single desired device.
### Status
To view all provisioned or deprovisioned devices, select the status from the left drop-down, and all of the devices that fit this criterion will appear in the view. Alternatively, you can do the following searches from the All devices view:
@@ -358,7 +365,7 @@ If you have a CSV file, UpdateCrOS.csv with two columns: deviceId,notes
this command will add a new line of notes to the front of the existing notes:
Remove user profile data from the device; the device will remain enrolled and connected.
User data not synced to the Cloud including Downloads, Android app data and Crostini Linux VMs will be permanently lost.
Commands with issuecommand directly after gam will work with standard GAM & GAMADV-XTD3, whereas commands where the issuecommand is after the cros <CrOSTypeEntity> will work only with GAMADV-XTD3.
Commands with issuecommand directly after gam will work with Legacy GAM & GAM7, whereas commands where the issuecommand is after the cros <CrOSTypeEntity> will work only with GAM7.
```
gam issuecommand cros dd1d659a-0ea4-4e94-905e-4726c7a5f1e9 command wipe_users doit
```
@@ -467,7 +474,7 @@ Remove profiles using the annotatedAssetID, which is a user editable field, in t
```
gam cros_query "asset_id:CB1234" issuecommand command wipe_users doit
```
For multiple devices you can sepatete each asset ID with a comma
For multiple devices you can separate each asset ID with a comma
```
gam cros_queries "asset_id:CB1234,asset_id:CB5678" issuecommand command wipe_users doit
@@ -593,6 +601,9 @@ otherwise, the remaining field names will appear in the order specified.
- `timerangeorder descending` - Change the `activetimeranges` order from ascending (oldest to newest) to descending (newest to oldest); this makes it easy to get the `N` most recent values with `timeranges listlimit N timerangeorder descending`.
- `showdvrsfp` - Display a field `diskVolumeReports.volumeInfo.storageFreePercentage` which is calculated as: `(diskVolumeReports.volumeInfo.storageFree/diskVolumeReports.volumeInfo.storageTotal)*100`
Add additional columns of data from the command line to the output
* `addcsvdata <FieldName> <String>`
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format:
- `formatjson` - Display the fields in JSON format.
@@ -643,6 +655,9 @@ otherwise, the remaining field names will appear in the order specified.
- `timerangeorder descending` - Change the `activetimeranges` order from ascending (oldest to newest) to descending (newest to oldest); this makes it easy to get the `N` most recent values with `timeranges listlimit N timerangeorder descending`.
- `showdvrsfp` - Display a field `diskVolumeReports.volumeInfo.storageFreePercentage` which is calculated as: `(diskVolumeReports.volumeInfo.storageFree/diskVolumeReports.volumeInfo.storageTotal)*100`
Add additional columns of data from the command line to the output
* `addcsvdata <FieldName> <String>`
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format:
- `formatjson` - Display the fields in JSON format.
* [Google Classroom API - Courses Students](https://developers.google.com/classroom/reference/rest/v1/courses.students)
* [Google Classroom API - Courses Teachers](https://developers.google.com/classroom/reference/rest/v1/courses.teachers)
* [Google Classroom API - Announcements](https://developers.google.com/classroom/reference/rest/v1/courses.announcements/list)
* [Google Classroom API - Topics](https://developers.google.com/classroom/reference/rest/v1/courses.topics/list)
* [Google Classroom API - Course Work](https://developers.google.com/classroom/reference/rest/v1/courses.courseWork/list)
* [Google Classroom API - Course Work Materials](https://developers.google.com/classroom/reference/rest/v1/courses.courseWorkMaterials/list)
* [Google Classroom API - Course Work Student Submissions](https://developers.google.com/classroom/reference/rest/v1/courses.courseWork.studentSubmissions/list)
## Notes
In this document, `course materials` refers to stand-alone materials, not the materials associated with
@@ -44,54 +44,60 @@ gam user user@domain.com check|update serviceaccount
`copyfrom <CourseID>` allows copying of course announcements, work, topics and members from one course to another.
* Accouncements - By default, no course announcements are copied
* `announcementstates <CourseAnnouncementStateList>` - Copy class announcements with the specified states
* `individualstudentannouncements copy` - Copy individual student announcements; this is the default. You will get an error if a student is not a member of the course
* `individualstudentannouncements maptoall` - Map individual student announcements to all student announcements
* Materials - By default, no course materials are copied
* `materialstates <CourseMaterialsStateList>` - Copy class materials with the specified states
* `individualstudentmaterials copy` - Copy individual student materials; this is the default. You will get an error if a student is not a member of the course
* `individualstudentmaterials maptoall` - Map individual student materials to all student materials
* Work - By default, no course work is copied
* `workstates <CourseWorkStateList>` - Copy class work with the specified states
* `individualstudentcoursework copy` - Copy individual student coursework; this is the default. You will get an error if the student is not a member of the course
If `role` is not specified, `student` will be used.
You can only invite a co-teacher to be an owner of a course.
By default, classroom invitations are issued by the owner of the course, the `adminaccess` option causes the invitations to be issued by the admin named in `oauth2.txt`.
By default, when an invitation is created, GAM outputs details of the invitation as indented keywords and values.
* `csv|csvformat [todrive <ToDriveAttribute>*] [formatjson [quotechar <Character>]]` - Output the details in CSV format.
### Example
Suppose you have a CSV file CourseStudent.csv with two columns: Course,Student.
Select invitations to delete by role. By default, invitations for all roles will be deleted; you can limit the deletions to invitations of a specific role.
## Display classroom invitations by course
```
gam show classroominvitations (course|class <CourseEntity>)*|([teacher <UserItem>] [student <UserItem>] [states <CourseStateList>])
By default, all types of members (cbcmbrowser, chromeosdevice, customer, group, serviceaccount, user) in the group are displayed; this option modifies that behavior:
By default, members that are groups are displayed as a single entry of type GROUP; this option recursively expands group members to display their user members.
* `recursive` - Recursively expand group members
When `recursive` is specified, the default is to only display type user members; this option modifies those behaviors:
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be displayed; others will not be displayed
* `memberemailskippattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will not be displayed; others will be displayed
* `memberemaildisplaypattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be displayed; others will not be displayed
* `memberemailskippattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will not be displayed; others will be displayed
By default, the ID, role, email address, type, createTime, updateTime and expireTime of each member is displayed along with the group email address;
these options specify which fields to display:
* `<CIGroupMembersFieldName>*` - Individual field names
* `fields <CIGroupMembersFieldNameList>` - A comma separated list of field names
* `full` - Fields displayed: group, type, id, role, email, createTime, updateTime, expireTime; this is the default
By default, the group email address is always shown, you can suppress it with the `nogroupemail` option.
By default, members that are groups are displayed as a single entry of type GROUP; this option recursively expands group members to display their user members.
* `recursive` - Recursively expand group members
The `recursive` option does not expand or display members of type CUSTOMER.
The `recursive` option adds two columns, level and subgroup, to the output:
* `level` - At what level of the expansion does the user appear; level 0 is the top level
* `subgroup` - The group that contained the user
@@ -421,13 +432,13 @@ The `quotechar <Character>` option allows you to choose an alternate quote chara
By default, all types of members (cbcmbrowser, chromeosdevice, customer, group, serviceaccount, user) in the group are displayed; this option modifies that behavior:
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be displayed; others will not be displayed
* `memberemailskippattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will not be displayed; others will be displayed
* `memberemaildisplaypattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be displayed; others will not be displayed
* `memberemailskippattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will not be displayed; others will be displayed
By default, members of type GROUP are recursively expanded to show their constituent members. (Members of
type CUSTOMER are not expanded.) The `depth <Number>` argument controls the depth to which nested groups are displayed.
@@ -469,6 +480,11 @@ has in any constituent group, it is not necessarily its role in the top group.
The options `types user` and `includederivedmembership types user` return the same list of users.
The `includederivedmembership` option makes less API calls but doesn't show hierarchy.
@@ -272,11 +288,19 @@ By default, all direct members, managers and owners in the group are displayed;
* `membertree` - Display all roles; expand all groups
By default, when displaying members from a group, all types of members (customer, group, serviceaccount, user) in the group are displayed; this option modifies that behavior:
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal internaldomains <DomainNameList>` - Display members whose domain is in `<DomainNameList>`
* `external internaldomains <DomainNameList>` - Display members whose domain is not in `<DomainNameList>`
* `internal external internaldomains <DomainNameList>` - Display all members, indicate their category: internal or external
* `internaldomains <DomainNameList>` - Defaults to value of `domain` in `gam.cfg`
Members without an email address, e.g. `customer`, `chrome-os-device` and `cbcm-browser` are considered internal.
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be displayed; others will not be displayed
* `memberemailskippattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will not be displayed; others will be displayed
* `memberemaildisplaypattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be displayed; others will not be displayed
* `memberemailskippattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will not be displayed; others will be displayed
By default, all group aliases are displayed, these options modify that behavior:
* `noaliases` or `quick` - Do not display group aliases
@@ -296,13 +320,14 @@ This command displays information in CSV format.
@@ -313,12 +338,12 @@ By default, all groups in the account are displayed, these options allow selecti
* `query <String>` - Limit display to the groups that match the query
These options further limit the list of groups selected above:
* `emailmatchpattern <RegularExpression>` - Limit display to groups whose email address matches `<RegularExpression>`
* `emailmatchpattern not <RegularExpression>` - Limit display to groups whose email address does not match `<RegularExpression>`
* `namematchpattern <RegularExpression>` - Limit display to groups whose name matches `<RegularExpression>`
* `namematchpattern not <RegularExpression>` - Limit display to groups whose name does not match `<RegularExpression>`
* `descriptionmatchpattern <RegularExpression>` - Limit display to groups whose description matches `<RegularExpression>`
* `descriptionmatchpattern not <RegularExpression>` - Limit display to groups whose description does not match `<RegularExpression>`
* `emailmatchpattern <REMatchPattern>` - Limit display to groups whose email address matches `<REMatchPattern>`
* `emailmatchpattern not <REMatchPattern>` - Limit display to groups whose email address does not match `<REMatchPattern>`
* `namematchpattern <REMatchPattern>` - Limit display to groups whose name matches `<REMatchPattern>`
* `namematchpattern not <REMatchPattern>` - Limit display to groups whose name does not match `<REMatchPattern>`
* `descriptionmatchpattern <REMatchPattern>` - Limit display to groups whose description matches `<REMatchPattern>`
* `descriptionmatchpattern not <REMatchPattern>` - Limit display to groups whose description does not match `<REMatchPattern>`
By default, GAM does not make an additional API call todisplay the member restrictions from `SecuritySettings`.
* `memberrestrictions` - Make an additional API call and display the member restrictions from `SecuritySettings`
@@ -353,11 +378,19 @@ By default, no members, managers or owners in the group are displayed; these opt
* `totalcount` - Display sum of counts of members, managers, owners.
By default, when displaying members from a group, all types of members (customer, group, serviceaccount, user) in the group are displayed; this option modifies that behavior:
By default, when listing group members, GAM does not take the domain of the member into account.
* `internal internaldomains <DomainNameList>` - Display members whose domain is in `<DomainNameList>`
* `external internaldomains <DomainNameList>` - Display members whose domain is not in `<DomainNameList>`
* `internal external internaldomains <DomainNameList>` - Display all members, indicate their category: internal or external
* `internaldomains <DomainNameList>` - Defaults to value of `domain` in `gam.cfg`
Members without an email address, e.g. `customer`, `chrome-os-device` and `cbcm-browser` are considered internal.
Members that have met the above qualifications to be displayed can be further qualifed by their email address.
* `memberemaildisplaypattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will be displayed; others will not be displayed
* `memberemailskippattern <RegularExpression>` - Members with email addresses that match `<RegularExpression>` will not be displayed; others will be displayed
* `memberemaildisplaypattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be displayed; others will not be displayed
* `memberemailskippattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will not be displayed; others will be displayed
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
@@ -368,6 +401,37 @@ 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.
`quotechar` defaults to `gam.cfg/csv_output_quote_char`. When uploading CSV files to Google, double quote `"` should be used.
* `filter <String>` - Display filtered policies, See https://cloud.google.com/identity/docs/reference/rest/v1beta1/policies/list
* `group <REMatchPattern>` - Only display policies whose group email address matches the `<REMatchPattern>`
* `ou|org|orgunit <REMatchPattern>` - Only display policies whose OU path matches the `<REMatchPattern>`
By default, policy warnings are displayed, use the `nowarnings` option to suppress their display.
By default, additional API calls are made for `settings/workspace_marketplace.apps_allowlist`
to get the application name for the application ID. Use option `noappnames` to suppress these calls.
By default, Gam displays the information as columns of fields; the following option causes the output to be in JSON format,
* `formatjson` - Display the fields in JSON format.
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.
* `<FileName>(:<FieldName>)+` - A CSV file and the one or more columns that contain ChromeOS deviceIds
@@ -280,7 +277,7 @@ croscsvfile
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `(matchfield|skipfield <FieldName> <RESearchPattern>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `delimiter <Character>` - There are multiple deviceIds per column separated by `<Character>`; if not specified, there is single deviceId per column
## Selected ChromeOS serial numbers in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object
* `<FileName>(:<FieldName>)+` - A CSV file and the one or more columns that contain ChromeOS serial numbers
@@ -308,7 +305,7 @@ croscsvfile_sn
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `(matchfield|skipfield <FieldName> <RESearchPattern>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `delimiter <Character>` - There are multiple serial numbers per column separated by `<Character>`; if not specified, there is single deviceId per column
## ChromeOS devices from OUs in a flat file/Google Doc/Google Cloud Storage Object
* `cros|cros_ous|cros_ous_and_children` - The type of item in the file
@@ -354,7 +351,7 @@ csvdatafile
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `(matchfield|skipfield <FieldName> <RESearchPattern>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `delimiter <Character>` - There are multiple deviceIds per column separated by `<Character>`; if not specified, there is single deviceId per column
## ChromeOS devices directly in or from OUs in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object
* `cros|cros_sn|cros_ous|cros_ous_and_children` - The type of item in the file
@@ -383,15 +380,15 @@ csvkmd
* `quotechar <Character>` - The column quote characer is `<Character>`; if not specified, the value of `csv_input_quote_char` from `gam.cfg` will be used
* `endcsv` - Use this option to signal the end of the csvfile parameters in the case that the next argument on the command line is `fields` but is specifying the output field list for the command not column headings
* `fields <FieldNameList>` - The column headings of a CSV file that does not contain column headings
* `keyfield <FieldName>` - The column containing key values
* `[keypattern <RegularExpression>] [keyvalue <String>]` - Allows transforming the value(s) in the `keyfield` column. If only `keyvalue <String>` is specified, all instances of `<FieldName>` in `keyvalue <String>` will be replaced by the item value. If `keypattern <RegularExpression>` is specified, the item value is matched against `<RegularExpression>` and the matched segments are substituted into `keyvalue <String>`
* `[keypattern <RESearchPattern>] [keyvalue <RESubstitution>]` - Allows transforming the value(s) in the `keyfield` column. If only `keyvalue <RESubstitution>` is specified, all instances of `<FieldName>` in `keyvalue <RESubstitution>` will be replaced by the item value. If `keypattern <RESearchPattern>` is specified, the item value is matched against `<RESearchPattern>` and the matched segments are substituted into `keyvalue <RESubstitution>`
* `delimiter <Character>` - There are multiple values per keyfield column separated by `<Character>`; if not specified, there is single value per keyfield column
* `subkeyfield <FieldName>` - The column containing subkey values
* `[keypattern <RegularExpression>] [keyvalue <String>]` - Allows transforming the value(s) in the `subkeyfield` column. If only `keyvalue <String>` is specified, all instances of `<FieldName>` in `keyvalue <String>` will be replaced by the item value. If `keypattern <RegularExpression>` is specified, the item value is matched against `<RegularExpression>` and the matched segments are substituted into `keyvalue <String>`
* `[keypattern <RESearchPattern>] [keyvalue <RESubstitution>]` - Allows transforming the value(s) in the `subkeyfield` column. If only `keyvalue <RESubstitution>` is specified, all instances of `<FieldName>` in `keyvalue <RESubstitution>` will be replaced by the item value. If `keypattern <RESearchPattern>` is specified, the item value is matched against `<RESearchPattern>` and the matched segments are substituted into `keyvalue <RESubstitution>`
* `delimiter <Character>` - There are multiple values per subkeyfield column separated by `<Character>`; if not specified, there is single value per subkeyfield column
* `(matchfield|skipfield <FieldName> <RegularExpression>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `(matchfield|skipfield <FieldName> <RESearchPattern>)*` - The criteria to select rows from the CSV file; can be used multiple times; if not specified, all rows are selected
* `datafield <FieldName>(:<FieldName)*` - The column(s) containing data values
* `delimiter <Character>` - There are multiple values per datafield column separated by `<Character>`; if not specified, there is single value per datafield column
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.