mirror of
https://github.com/GAM-team/GAM.git
synced 2026-06-04 06:11:39 +00:00
Compare commits
44 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b0c8b75cb | ||
|
|
6eb7e59d56 | ||
|
|
5b4cf97702 | ||
|
|
997bd56bd6 | ||
|
|
e66db1a117 | ||
|
|
e3a5f33981 | ||
|
|
877465a82f | ||
|
|
7e9477c6ea | ||
|
|
1b2fc06f6f | ||
|
|
3d3b3eac85 | ||
|
|
882b930928 | ||
|
|
4d804177c4 | ||
|
|
de71baff60 | ||
|
|
79de854440 | ||
|
|
f0406af938 | ||
|
|
d51ca45626 | ||
|
|
00953b2984 | ||
|
|
735b131b44 | ||
|
|
cb6069bcb5 | ||
|
|
3a18143ba7 | ||
|
|
5021f685c1 | ||
|
|
2dd88a7d9e | ||
|
|
3496c2c96a | ||
|
|
98404e91b6 | ||
|
|
ddc36b42ba | ||
|
|
1cae3daa4a | ||
|
|
cc7b5c1a14 | ||
|
|
cd266ebec9 | ||
|
|
c1010d412b | ||
|
|
b41c49ea69 | ||
|
|
8617e9f57f | ||
|
|
b47f2fc4ea | ||
|
|
77f0d3abb3 | ||
|
|
71721d06f2 | ||
|
|
d51428f3dc | ||
|
|
b92239fb6f | ||
|
|
b50376656e | ||
|
|
7796baf685 | ||
|
|
6639e1be33 | ||
|
|
a8b666b32d | ||
|
|
97ce3e9b8d | ||
|
|
f9402cb21a | ||
|
|
1dc7868078 | ||
|
|
c0dc8ae790 |
29
.github/workflows/build.yml
vendored
29
.github/workflows/build.yml
vendored
@@ -77,33 +77,37 @@ jobs:
|
||||
jid: 9
|
||||
goal: build
|
||||
name: Build Arm MacOS 15
|
||||
- os: macos-26
|
||||
- os: macos-15-intel
|
||||
jid: 10
|
||||
goal: build
|
||||
name: Build x86_64 macOS 15
|
||||
- os: macos-26
|
||||
jid: 11
|
||||
goal: build
|
||||
name: Build Arm MacOS 26
|
||||
- os: windows-2025
|
||||
jid: 11
|
||||
jid: 12
|
||||
goal: build
|
||||
name: Build Intel Windows
|
||||
- os: windows-11-arm
|
||||
jid: 12
|
||||
jid: 13
|
||||
goal: build
|
||||
name: Build Arm Windows
|
||||
- os: ubuntu-24.04
|
||||
goal: test
|
||||
python: "3.10"
|
||||
jid: 13
|
||||
jid: 14
|
||||
name: Test Python 3.10
|
||||
- os: ubuntu-24.04
|
||||
goal: test
|
||||
python: "3.11"
|
||||
jid: 14
|
||||
name: Test Python 3.11
|
||||
- os: ubuntu-24.04
|
||||
goal: test
|
||||
python: "3.12"
|
||||
jid: 15
|
||||
name: Test Python 3.12
|
||||
name: Test Python 3.11
|
||||
#- os: ubuntu-24.04
|
||||
# goal: test
|
||||
# python: "3.12"
|
||||
# jid: 16
|
||||
# name: Test Python 3.12
|
||||
#- os: ubuntu-24.04
|
||||
# goal: test
|
||||
# python: "3.14-dev"
|
||||
@@ -131,7 +135,7 @@ jobs:
|
||||
with:
|
||||
path: |
|
||||
cache.tar.xz
|
||||
key: gam-${{ matrix.jid }}-20250916
|
||||
key: gam-${{ matrix.jid }}-20250922
|
||||
|
||||
- name: Untar Cache archive
|
||||
if: matrix.goal == 'build' && steps.cache-python-ssl.outputs.cache-hit == 'true'
|
||||
@@ -463,9 +467,6 @@ jobs:
|
||||
echo "before anything..."
|
||||
"$PYTHON" -m pip list
|
||||
"$PYTHON" -m pip install --upgrade ..[yubikey]
|
||||
# forcefully update all installed packages
|
||||
"$PYTHON" -m pip --disable-pip-version-check list --outdated --format=json | "$PYTHON" -c "import json, sys; print('\n'.join([x['name'] for x in json.load(sys.stdin)]))" | xargs -n1 "$PYTHON" -m pip install -U
|
||||
"$PYTHON" -m pip list
|
||||
echo "after everything..."
|
||||
"$PYTHON" -m pip list
|
||||
|
||||
|
||||
2
.github/workflows/pushwiki.yml
vendored
2
.github/workflows/pushwiki.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
cd GAM.wiki
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "GitHub Action"
|
||||
git add *.md
|
||||
git add -A
|
||||
git commit -m "[no ci] Push Wiki changes"
|
||||
git status
|
||||
git push
|
||||
|
||||
@@ -18,6 +18,11 @@ this will download GAM, install it and start setup.
|
||||
|
||||
Download the MSI Installer from the [GitHub Releases] page. Install the MSI and you'll be prompted to setup GAM.
|
||||
|
||||
## Use your own Python
|
||||
If you'd prefer to install GAM as a Python package you can install with pip:
|
||||
```
|
||||
pip install gam7
|
||||
```
|
||||
# Documentation
|
||||
|
||||
The GAM documentation is hosted in the [GitHub Wiki]
|
||||
|
||||
@@ -19,10 +19,11 @@ dependencies = [
|
||||
"google-auth-httplib2>=0.2.0",
|
||||
"google-auth-oauthlib>=1.2.2",
|
||||
"google-auth>=2.39.0",
|
||||
"httplib2>=0.22.0",
|
||||
"httplib2>=0.31.0",
|
||||
"lxml>=5.4.0",
|
||||
"passlib>=1.7.4",
|
||||
"pathvalidate>=3.2.3"
|
||||
"pathvalidate>=3.2.3",
|
||||
"pysocks>=1.7.1",
|
||||
]
|
||||
description = "CLI tool to manage Google Workspace"
|
||||
readme = "README.md"
|
||||
|
||||
@@ -428,6 +428,8 @@ If an item contains spaces, it should be surrounded by ".
|
||||
<CourseWorkState> ::= draft|published|deleted
|
||||
<CrOSID> ::= <String>
|
||||
<CustomerID> ::= <String>
|
||||
<DateTimeFormat> ::= <String>
|
||||
See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
|
||||
<DeliverySetting> ::=
|
||||
allmail|
|
||||
abridged|daily|
|
||||
@@ -563,6 +565,7 @@ If an item contains spaces, it should be surrounded by ".
|
||||
See: https://support.google.com/mail/answer/7190
|
||||
<QueryGroup> ::= <String>
|
||||
See: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
|
||||
<QueryItem> ::= <UniqueID>|<String>
|
||||
<QueryMemberRestrictions> ::= <String>
|
||||
See: https://cloud.google.com/identity/docs/reference/rest/v1beta1/SecuritySettings#MemberRestriction
|
||||
<QueryMobile> ::= <String>
|
||||
@@ -663,11 +666,11 @@ If an item contains spaces, it should be surrounded by ".
|
||||
(tdreturnidonly [<Boolean>])|
|
||||
(tdshare <EmailAddress> commenter|reader|writer)*|
|
||||
(tdsheet (id:<Number>)|<String>)|
|
||||
(tdsheettimestamp [<Boolean>] [tdsheettimeformat <String>])
|
||||
(tdsheettimestamp [<Boolean>] [tdsheettimeformat <DateTimeFormat>])
|
||||
(tdsheettitle <String>)|
|
||||
(tdsubject <String>)|
|
||||
([tdsheetdaysoffset <Number>] [tdsheethoursoffset <Number>])|
|
||||
(tdtimestamp [<Boolean>] [tdtimeformat <String>]
|
||||
(tdtimestamp [<Boolean>] [tdtimeformat <DateTimeFormat>]
|
||||
[tddaysoffset <Number>] [tdhoursoffset <Number>])|
|
||||
(tdtimezone <TimeZone>)|
|
||||
(tdtitle <String>)|
|
||||
@@ -902,25 +905,25 @@ Specify a collection of ChromeOS devices by directly specifying them or by speci
|
||||
Specify a collection of Users by directly specifying them or by specifying items that will yield a list of users.
|
||||
|
||||
<UserTypeEntity> ::=
|
||||
(all users|users_ns|users_susp|users_ns_susp)|
|
||||
(all users|users_na|users_arch|users_ns|users_susp|users_arch_or_susp|users_na_ns|users_ns_susp)|
|
||||
(user <UserItem>)|
|
||||
(users <UserList>)|
|
||||
(oauthuser)
|
||||
(domains|domains_ns|domains_susp <DomainNameListList>)|
|
||||
(group|group_ns|group_susp|group_inde <GroupItem>)|
|
||||
(groups|groups_ns|groups_susp|groups_inde <GroupList>)|
|
||||
(domains|domains_na|domains_arch|domains_ns|domains_susp|domains_na_ns <DomainNameListList>)|
|
||||
(group|group_na|group_arch|group_ns|group_susp|group_na_ns|group_inde <GroupItem>)|
|
||||
(groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde <GroupList>)|
|
||||
(group_inde <GroupItem>)|(groups_inde <GroupList>)|
|
||||
(group_users|group_users_ns|group_users_susp <GroupList>
|
||||
(group_users|group_users_na|group_users_arch|group_users_ns|group_users_susp|group_users_na_ns <GroupList>
|
||||
[members] [managers] [owners]
|
||||
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
|
||||
(group_users_select <GroupList>
|
||||
[members] [managers] [owners]
|
||||
[notsuspended|suspended] [notarchived|archived]
|
||||
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
|
||||
(ou|ou_ns|ou_susp <OrgUnitItem>)|
|
||||
(ou_and_children|ou_and_children_ns|ou_and_children_susp <OrgUnitItem>)|
|
||||
(ous|ous_ns|ous_susp <OrgUnitList>)|
|
||||
(ous_and_children|ous_and_children_ns|ous_and_children_susp <OrgUnitList>)|
|
||||
(ou|ou_na|ou_arch|ou_ns|ou_susp|ou_na_ns <OrgUnitItem>)|
|
||||
(ou_and_children|ou_and_children_na|ou_and_children_arch|ou_and_children_ns|ou_and_children_susp|ou_and_children_na_ns <OrgUnitItem>)|
|
||||
(ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns <OrgUnitList>)|
|
||||
(ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns <OrgUnitList>)|
|
||||
(courseparticipants <CourseIDList>)|
|
||||
(students <CourseIDList>)|
|
||||
(teachers <CourseIDList>)|
|
||||
@@ -940,20 +943,24 @@ Specify a collection of Users by directly specifying them or by specifying items
|
||||
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
|
||||
[warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
|
||||
[endcsv|(fields <FieldNameList>)]
|
||||
(matchfield|skipfield <FieldName> <REMatchPattern>)*
|
||||
(matchfield|skipfield <FieldName> <RESearchPattern>)*
|
||||
[delimiter <Character>])|
|
||||
(datafile
|
||||
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
|
||||
ous_and_children|ous_and_children_ns|ous_and_children_susp|
|
||||
courseparticipants|students|teachers
|
||||
users|
|
||||
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
|
||||
ous|ous_na|ous_arch|ous_ns|ous_susps|ous_na_ns|
|
||||
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
|
||||
courseparticipants|students|teachers
|
||||
((<FileName> [charset <Charset>])|
|
||||
(gdoc <UserGoogleDoc>)|
|
||||
(gcsdoc <StorageBucketObjectName>))
|
||||
[delimiter <Character>])|
|
||||
(csvdatafile
|
||||
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
|
||||
ous_and_children|ous_and_children_ns|ous_and_children_susp|
|
||||
courseparticipants|students|teachers
|
||||
users|
|
||||
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
|
||||
ous|ous_na|ous_arch|ous_ns|ous_susps|ous_na_ns|
|
||||
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
|
||||
courseparticipants|students|teachers
|
||||
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
|
||||
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
|
||||
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
|
||||
@@ -961,21 +968,23 @@ Specify a collection of Users by directly specifying them or by specifying items
|
||||
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
|
||||
[warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
|
||||
[endcsv|(fields <FieldNameList>)]
|
||||
(matchfield|skipfield <FieldName> <REMatchPattern>)*
|
||||
(matchfield|skipfield <FieldName> <RESearchPattern>)*
|
||||
[delimiter <Character>])|
|
||||
(csvkmd
|
||||
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
|
||||
ous_and_children|ous_and_children_ns|ous_and_children_susp|
|
||||
courseparticipants|students|teachers
|
||||
users|
|
||||
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
|
||||
ous|ous_na|ous_arch|ous_ns|ous_susps|ous_na_ns|
|
||||
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
|
||||
courseparticipants|students|teachers
|
||||
((<FileName>|
|
||||
(gsheet <UserGoogleSheet>)|
|
||||
(gdoc <UserGoogleDoc>)|
|
||||
(gcscsv <StorageBucketObjectName>)|
|
||||
(gcsdoc <StorageBucketObjectName>))
|
||||
[charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>])
|
||||
keyfield <FieldName> [keypattern <REMatchPattern>] [keyvalue <String>] [delimiter <Character>]
|
||||
subkeyfield <FieldName> [keypattern <REMatchPattern>] [keyvalue <String>] [delimiter <Character>]
|
||||
(matchfield|skipfield <FieldName> <REMatchPattern>)*
|
||||
keyfield <FieldName> [keypattern <RESearchPattern>] [keyvalue <RESubstitution>] [delimiter <Character>]
|
||||
subkeyfield <FieldName> [keypattern <RESearchPattern>] [keyvalue <RESubstitution>] [delimiter <Character>]
|
||||
(matchfield|skipfield <FieldName> <RESearchPattern>)*
|
||||
[datafield <FieldName>(:<FieldName>)* [delimiter <Character>]])
|
||||
(csvdata <FieldName>(:<FieldName>*))
|
||||
|
||||
@@ -1007,23 +1016,25 @@ Specify a collection of items by directly specifying them; the item type is dete
|
||||
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
|
||||
[warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
|
||||
[endcsv|(fields <FieldNameList>)]
|
||||
(matchfield|skipfield <FieldName> <REMatchPattern>)*
|
||||
(matchfield|skipfield <FieldName> <RESearchPattern>)*
|
||||
[delimiter <Character>]
|
||||
|
||||
<CSVkmdSelector> ::=
|
||||
csvkmd
|
||||
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
|
||||
ous_and_children|ous_and_children_ns|ous_and_children_susp|
|
||||
courseparticipants|students|teachers
|
||||
users|
|
||||
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_inde|
|
||||
ous|ous_na|ous_arch|ous_ns|ous_susp|
|
||||
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|
|
||||
courseparticipants|students|teachers
|
||||
((<FileName>|
|
||||
(gsheet <UserGoogleSheet>)|
|
||||
(gdoc <UserGoogleDoc>)|
|
||||
(gcscsv <StorageBucketObjectName>)|
|
||||
(gcsdoc <StorageBucketObjectName>))
|
||||
[charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>])
|
||||
keyfield <FieldName> [keypattern <REMatchPattern>] [keyvalue <String>] [delimiter <Character>]
|
||||
subkeyfield <FieldName> [keypattern <REMatchPattern>] [keyvalue <String>] [delimiter <Character>]
|
||||
(matchfield|skipfield <FieldName> <REMatchPattern>)*
|
||||
keyfield <FieldName> [keypattern <RESearchPattern>] [keyvalue <String>] [delimiter <Character>]
|
||||
subkeyfield <FieldName> [keypattern <RESearchPattern>] [keyvalue <String>] [delimiter <Character>]
|
||||
(matchfield|skipfield <FieldName> <RESearchPattern>)*
|
||||
[datafield <FieldName>(:<FieldName>)* [delimiter <Character>]]
|
||||
<CSVSubkeySelector> ::= csvsubkey <FieldName>
|
||||
<CSVDataSelector> ::= csvdata <FieldName>(:<FieldName>)*
|
||||
@@ -1379,13 +1390,13 @@ gam tbatch <BatchContent> [showcmds [<Boolean>]]
|
||||
|
||||
gam csv <CSVLoopContent> [warnifnodata]
|
||||
[columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>]
|
||||
(matchfield|skipfield <FieldName> <REMatchPattern>)* [showcmds [<Boolean>]]
|
||||
(matchfield|skipfield <FieldName> <RESearchPattern>)* [showcmds [<Boolean>]]
|
||||
[skiprows <Integer>] [maxrows <Integer>]
|
||||
gam <GAMArgumentList>
|
||||
|
||||
gam loop <CSVLoopContent> [warnifnodata]
|
||||
[columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>]
|
||||
(matchfield|skipfield <FieldName> <REMatchPattern>)* [showcmds [<Boolean>]]
|
||||
(matchfield|skipfield <FieldName> <RESearchPattern>)* [showcmds [<Boolean>]]
|
||||
[skiprows <Integer>] [maxrows <Integer>]
|
||||
gam <GAMArgumentList>
|
||||
|
||||
@@ -1532,8 +1543,8 @@ gam print adminroles|roles [todrive <ToDriveAttribute>*]
|
||||
[formatjson [quotechar <Character>]]
|
||||
gam show adminroles|roles
|
||||
[role <RoleItem>] [privileges]
|
||||
[nosystemroles]
|
||||
[formatjson]
|
||||
[nosystemroles]
|
||||
[formatjson]
|
||||
|
||||
gam create|add admin <EmailAddress>|<UniqueID> <RoleItem> customer|(org_unit <OrgUnitItem>)
|
||||
[condition securitygroup|nonsecuritygroup]
|
||||
@@ -1582,7 +1593,7 @@ gam print alias|aliases [todrive <ToDriveAttribute>*]
|
||||
[limittoou <OrgUnitItem>])
|
||||
[user|users <EmailAddressList>] [group|groups <EmailAddressList>]
|
||||
[select <UserTypeEntity>]
|
||||
[aliasmatchpattern <REMatchPattern>]
|
||||
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
||||
[shownoneditable] [nogroups] [nousers]
|
||||
[onerowpertarget] [delimiter <Character>]
|
||||
[suppressnoaliasrows]
|
||||
@@ -1743,7 +1754,7 @@ gam calendar <CalendarEntity> printacl [todrive <ToDriveAttribute>*]
|
||||
(range <Date> <Date>)|
|
||||
(recurrence <RRULE, EXRULE, RDATE and EXDATE line>)|
|
||||
(reminder <Number> email|popup))|
|
||||
(resource <ResourceID>)|
|
||||
(resource <ResourceID>)|
|
||||
(selectattendees [<AttendeeAttendance>] [<AttendeeStatus>] <UserTypeEntity>)|
|
||||
(sequence <Integer>)|
|
||||
(sharedproperty <PropertyKey> <PropertyValue>)|
|
||||
@@ -4470,8 +4481,10 @@ gam update orgs|ous <OrgUnitEntity> sync <CrOSTypeEntity> [removetoou <OrgUnitIt
|
||||
gam update orgs|ous <OrgUnitEntity> sync <UserTypeEntity> [removetoou <OrgUnitItem>]
|
||||
gam delete orgs|ous <OrgUnitEntity>
|
||||
|
||||
gam info org|ou <OrgUnitItem> [nousers|notsuspended|suspended] [children|child]
|
||||
gam info orgs|ous <OrgUnitEntity> [nousers|notsuspended|suspended] [children|child]
|
||||
gam info org|ou <OrgUnitItem>
|
||||
[nousers | ([notarchived|archived] [notsuspended|suspended])] [children|child]
|
||||
gam info orgs|ous <OrgUnitEntity>
|
||||
[nousers | ([notarchived|archived] [notsuspended|suspended])] [children|child]
|
||||
|
||||
<OrgUnitSelector> ::=
|
||||
cros_ou | cros_ou_and_children|
|
||||
@@ -5410,6 +5423,15 @@ gam print vaultcounts [todrive <ToDriveAttributes>*]
|
||||
gam print vaultcounts [todrive <ToDriveAttributes>*]
|
||||
matter <MatterItem> operation <String> [wait <Integer>]
|
||||
|
||||
gam create vaultexport|export matter <MatterItem> [name <String>]
|
||||
vaultquery <QueryItem>
|
||||
[driveclientsideencryption any|encrypted|unencrypted]
|
||||
[includeaccessinfo <Boolean>]
|
||||
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
|
||||
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
|
||||
[format ics|mbox|pst|xml]
|
||||
[region any|europe|us] [showdetails|returnidonly]
|
||||
|
||||
gam create vaultexport|export matter <MatterItem> [name <String>] corpus calendar|drive|gemini|groups|hangouts_chat|mail|voice
|
||||
(accounts <EmailAddressEntity>) | (orgunit|org|ou <OrgUnitPath>) | everyone
|
||||
(shareddrives|teamdrives (<SharedDriveIDList>|(select <FileSelector>|<CSVFileSelector>))) |
|
||||
@@ -5420,12 +5442,13 @@ gam create vaultexport|export matter <MatterItem> [name <String>] corpus calenda
|
||||
[locationquery <StringList>] [peoplequery <StringList>] [minuswords <StringList>]
|
||||
[responsestatuses <AttendeeStatus>(,<AttendeeStatus>)*] [calendarversiondate <Date>|<Time>]
|
||||
[(includeshareddrives <Boolean>)|(shareddrivesoption included|included_if_account_is_not_a_member|not_included)]
|
||||
[driveversiondate <Date>|<Time>] [includeaccessinfo <Boolean>]
|
||||
[driveclientsideencryption any|encrypted|unencrypted]
|
||||
[driveversiondate <Date>|<Time>]
|
||||
[includerooms <Boolean>]
|
||||
(covereddata calllogs|textmessages|voicemails)*
|
||||
[driveclientsideencryption any|encrypted|unencrypted]
|
||||
[includeaccessinfo <Boolean>]
|
||||
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
|
||||
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
|
||||
[covereddata calllogs|textmessages|voicemails]
|
||||
[format ics|mbox|pst|xml]
|
||||
[region any|europe|us] [showdetails|returnidonly]
|
||||
gam delete vaultexport|export <ExportItem> matter <MatterItem>
|
||||
@@ -5481,18 +5504,21 @@ gam show vaultexports|exports
|
||||
[fields <VaultExportFieldNameList>] [shownames]
|
||||
[formatjson]
|
||||
|
||||
gam create vaulthold|hold matter <MatterItem> [name <String>]
|
||||
vaultquery <QueryItem>
|
||||
[showdetails|returnidonly]
|
||||
gam create vaulthold|hold matter <MatterItem> [name <String>] corpus calendar|drive|mail|groups|hangouts_chat|voice
|
||||
[(accounts|groups|users <EmailItemList>) | (orgunit|org|ou <OrgUnit>)]
|
||||
[query <QueryVaultCorpus>]
|
||||
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
||||
[includerooms <Boolean>] [covereddata calllogs|textmessages|voicemails]
|
||||
[includerooms <Boolean>] (covereddata calllogs|textmessages|voicemails)*
|
||||
[includeshareddrives <Boolean>]
|
||||
[showdetails|returnidonly]
|
||||
gam update vaulthold|hold <HoldItem> matter <MatterItem>
|
||||
[([addaccounts|addgroups|addusers <EmailItemList>] [removeaccounts|removegroups|removeusers <EmailItemList>]) | (orgunit|org|ou <OrgUnit>)]
|
||||
[query <QueryVaultCorpus>]
|
||||
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
||||
[includerooms <Boolean>] [covereddata calllogs|textmessages|voicemails]
|
||||
[includerooms <Boolean>] (covereddata calllogs|textmessages|voicemails)*
|
||||
[includeshareddrives <Boolean>]
|
||||
[showdetails]
|
||||
gam delete vaulthold|hold <HoldItem> matter <MatterItem>
|
||||
@@ -5710,7 +5736,7 @@ gam create|add user <EmailAddress> [ignorenullpassword] <UserAttribute>*
|
||||
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
|
||||
[alias|aliases <EmailAddressList>]
|
||||
[license <SKUIDList> [product|productid <ProductID>]]
|
||||
[notify <EmailAddressList>
|
||||
[[notify <EmailAddressList>] [notifyrecoveryemail]
|
||||
[subject <String>]
|
||||
[notifypassword <String>]
|
||||
[from <EmailAaddress>]
|
||||
@@ -5736,7 +5762,7 @@ gam update user <UserItem> [ignorenullpassword] <UserAttribute>*
|
||||
[createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]
|
||||
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
|
||||
[alias|aliases <EmailAddressList>]
|
||||
[notify <EmailAddressList>
|
||||
[[notify <EmailAddressList>] [notifyrecoveryemail]
|
||||
[subject <String>]
|
||||
[notifypassword <String>]
|
||||
[from <EmailAaddress>]
|
||||
@@ -5774,7 +5800,7 @@ gam update users <UserTypeEntity> [ignorenullpassword] <UserAttribute>*
|
||||
[createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]
|
||||
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
|
||||
[alias|aliases <EmailAddressList>]
|
||||
[notify <EmailAddressList>
|
||||
[[notify <EmailAddressList>] [notifyrecoveryemail]
|
||||
[subject <String>]
|
||||
[notifypassword <String>]
|
||||
[from <EmailAddress>]
|
||||
@@ -5811,7 +5837,7 @@ gam <UserTypeEntity> update users [ignorenullpassword] <UserAttribute>*
|
||||
[createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]
|
||||
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
|
||||
[alias|aliases <EmailAddressList>]
|
||||
[notify <EmailAddressList>
|
||||
[[notify <EmailAddressList>] [notifyrecoveryemail]
|
||||
[subject <String>]
|
||||
[notifypassword <String>]
|
||||
[from <EmailAaddress>]
|
||||
@@ -5856,7 +5882,7 @@ gam print users [todrive <ToDriveAttribute>*]
|
||||
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
|
||||
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
|
||||
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
|
||||
[issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
||||
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
||||
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
|
||||
[showitemcountonly]
|
||||
|
||||
@@ -5873,7 +5899,7 @@ gam print users [todrive <ToDriveAttribute>*] select <UserTypeEntity>
|
||||
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
|
||||
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
|
||||
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
|
||||
[issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
||||
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
||||
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
|
||||
[showitemcountonly]
|
||||
|
||||
@@ -5888,7 +5914,7 @@ gam <UserTypeEntity> print users [todrive <ToDriveAttribute>*]
|
||||
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
|
||||
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
|
||||
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
|
||||
[issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
||||
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
||||
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
|
||||
[showitemcountonly]
|
||||
|
||||
@@ -5909,7 +5935,7 @@ gam print users [todrive <ToDriveAttribute>*]
|
||||
([domain|domains <DomainNameEntity>] [(query <QueryUser>)|(queries <QueryUserList>)]
|
||||
[limittoou <OrgUnitItem>] [deleted_only|only_deleted])
|
||||
[formatjson [quotechar <Character>]] [countsonly|countonly]
|
||||
[issuspended <Boolean>]
|
||||
[issuspended <Boolean>] [isarchived <Boolean>]
|
||||
|
||||
Print user domain counts for specified users.
|
||||
|
||||
@@ -6688,7 +6714,7 @@ gam <UserTypeEntity> create|add drivefile
|
||||
[(localfile <FileName>|-)|(url <URL>)]
|
||||
[(drivefilename|newfilename <DriveFileName>) | (replacefilename <REMatchPattern> <RESubstitution>)*]
|
||||
[stripnameprefix <String>] [noduplicate]
|
||||
[timestamp [<Boolean>]] [timeformat <String>]
|
||||
[timestamp [<Boolean>]] [timeformat <DateTimeFormat>]
|
||||
<DriveFileCreateAttribute>*
|
||||
[(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> currenttime|<String>)*) |
|
||||
(returnidonly|returnlinkonly|returneditlinkonly|showdetails)]
|
||||
@@ -6709,7 +6735,7 @@ gam <UserTypeEntity> update drivefile <DriveFileEntity> [copy] [returnidonly|ret
|
||||
[(localfile <FileName>|-)|(url <URL>)]
|
||||
[retainname | (newfilename <DriveFileName>) | (replacefilename <REMatchPattern> <RESubstitution>)*]
|
||||
[stripnameprefix <String>]
|
||||
[timestamp [<Boolean>]] [timeformat <String>]
|
||||
[timestamp [<Boolean>]] [timeformat <DateTimeFormat>]
|
||||
<DriveFileUpdateAttribute>*
|
||||
[(gsheet|csvsheet <SheetEntity> [clearfilter])|(addsheet <String>)]
|
||||
[charset <Charset>] [columndelimiter <Character>]
|
||||
@@ -8591,7 +8617,7 @@ gam <UserTypeEntity> print shareddriveorganizers [todrive <ToDriveAttribute>*]
|
||||
[shownorganizerdrives [false|true|only]]
|
||||
[includefileorganizers [<Boolean>]]
|
||||
[delimiter <Character>]
|
||||
|
||||
|
||||
# Users - Force Signout and Turn Off 2-Step Verification
|
||||
|
||||
gam <UserTypeEntity> signout
|
||||
|
||||
@@ -1,3 +1,59 @@
|
||||
7.22.05
|
||||
|
||||
Added a variant of `gam create vaultexport` that gets its query parameters from a saved Vault query.
|
||||
|
||||
```
|
||||
gam create vaultexport|export matter <MatterItem> [name <String>]
|
||||
vaultquery <QueryItem>
|
||||
[driveclientsideencryption any|encrypted|unencrypted]
|
||||
[includeaccessinfo <Boolean>]
|
||||
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
|
||||
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
|
||||
[format ics|mbox|pst|xml]
|
||||
[region any|europe|us] [showdetails|returnidonly]
|
||||
```
|
||||
|
||||
7.22.04
|
||||
|
||||
Added a variant of `gam create vaulthold` that gets its parameters from a saved Vault query.
|
||||
```
|
||||
gam create vaulthold matter <MatterItem> [name <String>]
|
||||
vaultquery <QueryItem>
|
||||
[showdetails|returnidonly]
|
||||
```
|
||||
|
||||
7.22.03
|
||||
|
||||
Fix backwards compatability bug introduced in 7.22.00 for `gam print users` that changed `suspended`
|
||||
from a field name to a query option; it is now correctly interpreted as a field name.
|
||||
|
||||
7.22.02
|
||||
|
||||
An update to the httplib2 library caused GAM proxy connections to fail; this has been fixed
|
||||
by including the pysocks library needed by the latest httplib2 library.
|
||||
|
||||
7.22.00
|
||||
|
||||
Expanded `<UserTypeEntity>` to allow specification of non-archived/archived users.
|
||||
* See [Collections of Users](Collections-of-Users)
|
||||
|
||||
These commands have been updated:
|
||||
* `gam print aliases`
|
||||
* `gam update groups`
|
||||
* `gam info orgs`
|
||||
* `gam print orgs`
|
||||
* `gam print users`
|
||||
|
||||
Added `datetime <DateTimeFormat>` command that can be embedded in Gam batch files. The current time is formatted with `<DateTimeFormat>`
|
||||
and subsequent lines in `<BatchContent>` will have `%datetime%` replaced with the formatted time value.
|
||||
|
||||
See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
|
||||
|
||||
7.21.03
|
||||
|
||||
Added option `notifyrecoveryemail` to `gam create user` and `gam <UserTypeEntity> update user password <String>`
|
||||
that sends the passsword notification email to the user's recovery email address (if defined).
|
||||
|
||||
7.21.02
|
||||
|
||||
GAM now builds on macOS 26 Tahoe and properly identifies the OS.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -49,43 +49,71 @@ class GamCLArgs():
|
||||
ENTITY_CROS_OUS_AND_CHILDREN_QUERIES = 'cros_ous_and_children_queries'
|
||||
ENTITY_CROS_SN = 'cros_sn'
|
||||
ENTITY_DOMAINS = 'domains'
|
||||
ENTITY_DOMAINS_NA = 'domains_na'
|
||||
ENTITY_DOMAINS_ARCH = 'domains_arch'
|
||||
ENTITY_DOMAINS_NS = 'domains_ns'
|
||||
ENTITY_DOMAINS_SUSP = 'domains_susp'
|
||||
ENTITY_DOMAINS_NA_NS = 'domains_na_ns'
|
||||
ENTITY_GROUP = 'group'
|
||||
ENTITY_GROUP_INDE = 'group_inde'
|
||||
ENTITY_GROUP_NA = 'group_na'
|
||||
ENTITY_GROUP_ARCH = 'group_arch'
|
||||
ENTITY_GROUP_NS = 'group_ns'
|
||||
ENTITY_GROUP_SUSP = 'group_susp'
|
||||
ENTITY_GROUP_NA_NS = 'group_na_ns'
|
||||
ENTITY_GROUPS = 'groups'
|
||||
ENTITY_GROUPS_INDE = 'groups_inde'
|
||||
ENTITY_GROUPS_NA = 'groups_na'
|
||||
ENTITY_GROUPS_ARCH = 'groups_arch'
|
||||
ENTITY_GROUPS_NS = 'groups_ns'
|
||||
ENTITY_GROUPS_SUSP = 'groups_susp'
|
||||
ENTITY_GROUPS_NA_NS = 'groups_na_ns'
|
||||
ENTITY_GROUP_USERS = 'group_users'
|
||||
ENTITY_GROUP_USERS_NA = 'group_users_na'
|
||||
ENTITY_GROUP_USERS_ARCH = 'group_users_arch'
|
||||
ENTITY_GROUP_USERS_NS = 'group_users_ns'
|
||||
ENTITY_GROUP_USERS_SUSP = 'group_users_susp'
|
||||
ENTITY_GROUP_USERS_NA_NS = 'group_users_na_ns'
|
||||
ENTITY_GROUP_USERS_SELECT = 'group_users_select'
|
||||
ENTITY_LICENSES = 'licenses'
|
||||
ENTITY_OAUTHUSER = 'oauthuser'
|
||||
ENTITY_OU = 'ou'
|
||||
ENTITY_OU_NA = 'ou_na'
|
||||
ENTITY_OU_ARCH = 'ou_arch'
|
||||
ENTITY_OU_NS = 'ou_ns'
|
||||
ENTITY_OU_SUSP = 'ou_susp'
|
||||
ENTITY_OU_NA_NS = 'ou_na_ns'
|
||||
ENTITY_OU_AND_CHILDREN = 'ou_and_children'
|
||||
ENTITY_OU_AND_CHILDREN_NA = 'ou_and_children_na'
|
||||
ENTITY_OU_AND_CHILDREN_ARCH = 'ou_and_children_arch'
|
||||
ENTITY_OU_AND_CHILDREN_NS = 'ou_and_children_ns'
|
||||
ENTITY_OU_AND_CHILDREN_SUSP = 'ou_and_children_susp'
|
||||
ENTITY_OU_AND_CHILDREN_NA_NS = 'ou_and_children_na_ns'
|
||||
ENTITY_OUS = 'ous'
|
||||
ENTITY_OUS_NA = 'ous_na'
|
||||
ENTITY_OUS_ARCH = 'ous_arch'
|
||||
ENTITY_OUS_NS = 'ous_ns'
|
||||
ENTITY_OUS_SUSP = 'ous_susp'
|
||||
ENTITY_OUS_NA_NS = 'ous_na_ns'
|
||||
ENTITY_OUS_AND_CHILDREN = 'ous_and_children'
|
||||
ENTITY_OUS_AND_CHILDREN_NA = 'ous_and_children_na'
|
||||
ENTITY_OUS_AND_CHILDREN_ARCH = 'ous_and_children_arch'
|
||||
ENTITY_OUS_AND_CHILDREN_NS = 'ous_and_children_ns'
|
||||
ENTITY_OUS_AND_CHILDREN_SUSP = 'ous_and_children_susp'
|
||||
ENTITY_OUS_AND_CHILDREN_NA_NS = 'ous_and_children_na_ns'
|
||||
ENTITY_QUERIES = 'queries'
|
||||
ENTITY_QUERY = 'query'
|
||||
ENTITY_STUDENTS = 'students'
|
||||
ENTITY_TEACHERS = 'teachers'
|
||||
ENTITY_USER = 'user'
|
||||
ENTITY_USERS = 'users'
|
||||
ENTITY_USERS_NA = 'users_na'
|
||||
ENTITY_USERS_ARCH = 'users_arch'
|
||||
ENTITY_USERS_NS = 'users_ns'
|
||||
ENTITY_USERS_NS_SUSP = 'users_ns_susp'
|
||||
ENTITY_USERS_SUSP = 'users_susp'
|
||||
ENTITY_USERS_NA_NS = 'users_na_ns'
|
||||
ENTITY_USERS_ARCH_OR_SUSP = 'users_arch_or_susp'
|
||||
ENTITY_USERS_NS_SUSP = 'users_ns_susp'
|
||||
#
|
||||
BROWSER_ENTITIES = [
|
||||
ENTITY_BROWSER,
|
||||
@@ -118,34 +146,58 @@ class GamCLArgs():
|
||||
ENTITY_CIGROUP_USERS,
|
||||
ENTITY_COURSEPARTICIPANTS,
|
||||
ENTITY_DOMAINS,
|
||||
ENTITY_DOMAINS_NA,
|
||||
ENTITY_DOMAINS_ARCH,
|
||||
ENTITY_DOMAINS_NS,
|
||||
ENTITY_DOMAINS_SUSP,
|
||||
ENTITY_DOMAINS_NA_NS,
|
||||
ENTITY_GROUP,
|
||||
ENTITY_GROUP_INDE,
|
||||
ENTITY_GROUP_NA,
|
||||
ENTITY_GROUP_ARCH,
|
||||
ENTITY_GROUP_NS,
|
||||
ENTITY_GROUP_SUSP,
|
||||
ENTITY_GROUP_NA_NS,
|
||||
ENTITY_GROUPS,
|
||||
ENTITY_GROUPS_INDE,
|
||||
ENTITY_GROUPS_NA,
|
||||
ENTITY_GROUPS_ARCH,
|
||||
ENTITY_GROUPS_NS,
|
||||
ENTITY_GROUPS_SUSP,
|
||||
ENTITY_GROUPS_NA_NS,
|
||||
ENTITY_GROUP_USERS,
|
||||
ENTITY_GROUP_USERS_NA,
|
||||
ENTITY_GROUP_USERS_ARCH,
|
||||
ENTITY_GROUP_USERS_NS,
|
||||
ENTITY_GROUP_USERS_SUSP,
|
||||
ENTITY_GROUP_USERS_NA_NS,
|
||||
ENTITY_GROUP_USERS_SELECT,
|
||||
ENTITY_LICENSES,
|
||||
ENTITY_OAUTHUSER,
|
||||
ENTITY_OU,
|
||||
ENTITY_OU_NA,
|
||||
ENTITY_OU_ARCH,
|
||||
ENTITY_OU_NS,
|
||||
ENTITY_OU_SUSP,
|
||||
ENTITY_OU_NA_NS,
|
||||
ENTITY_OU_AND_CHILDREN,
|
||||
ENTITY_OU_AND_CHILDREN_NA,
|
||||
ENTITY_OU_AND_CHILDREN_ARCH,
|
||||
ENTITY_OU_AND_CHILDREN_NS,
|
||||
ENTITY_OU_AND_CHILDREN_SUSP,
|
||||
ENTITY_OU_AND_CHILDREN_NA_NS,
|
||||
ENTITY_OUS,
|
||||
ENTITY_OUS_NA,
|
||||
ENTITY_OUS_ARCH,
|
||||
ENTITY_OUS_NS,
|
||||
ENTITY_OUS_SUSP,
|
||||
ENTITY_OUS_NA_NS,
|
||||
ENTITY_OUS_AND_CHILDREN,
|
||||
ENTITY_OUS_AND_CHILDREN_NA,
|
||||
ENTITY_OUS_AND_CHILDREN_ARCH,
|
||||
ENTITY_OUS_AND_CHILDREN_NS,
|
||||
ENTITY_OUS_AND_CHILDREN_SUSP,
|
||||
ENTITY_OUS_AND_CHILDREN_NA_NS,
|
||||
ENTITY_QUERIES,
|
||||
ENTITY_QUERY,
|
||||
ENTITY_STUDENTS,
|
||||
@@ -222,29 +274,53 @@ class GamCLArgs():
|
||||
'licence': ENTITY_LICENSES,
|
||||
'licences': ENTITY_LICENSES,
|
||||
'org': ENTITY_OU,
|
||||
'org_na': ENTITY_OU_NA,
|
||||
'org_arch': ENTITY_OU_ARCH,
|
||||
'org_ns': ENTITY_OU_NS,
|
||||
'org_susp': ENTITY_OU_SUSP,
|
||||
'org_na_ns': ENTITY_OU_NA_NS,
|
||||
'org_and_child': ENTITY_OU_AND_CHILDREN,
|
||||
'org_and_child_na': ENTITY_OU_AND_CHILDREN_NA,
|
||||
'org_and_child_arch': ENTITY_OU_AND_CHILDREN_ARCH,
|
||||
'org_and_child_ns': ENTITY_OU_AND_CHILDREN_NS,
|
||||
'org_and_child_susp': ENTITY_OU_AND_CHILDREN_SUSP,
|
||||
'org_and_child_na_ns': ENTITY_OU_AND_CHILDREN_NA_NS,
|
||||
'org_and_children': ENTITY_OU_AND_CHILDREN,
|
||||
'org_and_children_na': ENTITY_OU_AND_CHILDREN_NA,
|
||||
'org_and_children_arch': ENTITY_OU_AND_CHILDREN_ARCH,
|
||||
'org_and_children_ns': ENTITY_OU_AND_CHILDREN_NS,
|
||||
'org_and_children_susp': ENTITY_OU_AND_CHILDREN_SUSP,
|
||||
'org_and_children_na_ns': ENTITY_OU_AND_CHILDREN_NA_NS,
|
||||
'orgs': ENTITY_OUS,
|
||||
'orgs_na': ENTITY_OUS_NA,
|
||||
'orgs_arch': ENTITY_OUS_ARCH,
|
||||
'orgs_ns': ENTITY_OUS_NS,
|
||||
'orgs_susp': ENTITY_OUS_SUSP,
|
||||
'orgs_na_ns': ENTITY_OUS_NA_NS,
|
||||
'orgs_and_child': ENTITY_OUS_AND_CHILDREN,
|
||||
'orgs_and_child_na': ENTITY_OUS_AND_CHILDREN_NA,
|
||||
'orgs_and_child_arch': ENTITY_OUS_AND_CHILDREN_ARCH,
|
||||
'orgs_and_child_ns': ENTITY_OUS_AND_CHILDREN_NS,
|
||||
'orgs_and_child_susp': ENTITY_OUS_AND_CHILDREN_SUSP,
|
||||
'orgs_and_child_na_ns': ENTITY_OUS_AND_CHILDREN_NA_NS,
|
||||
'orgs_and_children': ENTITY_OUS_AND_CHILDREN,
|
||||
'orgs_and_children_na': ENTITY_OUS_AND_CHILDREN_NA,
|
||||
'orgs_and_children_arch': ENTITY_OUS_AND_CHILDREN_ARCH,
|
||||
'orgs_and_children_ns': ENTITY_OUS_AND_CHILDREN_NS,
|
||||
'orgs_and_children_susp': ENTITY_OUS_AND_CHILDREN_SUSP,
|
||||
'orgs_and_children_na_ns': ENTITY_OUS_AND_CHILDREN_NA_NS,
|
||||
'ou_and_child': ENTITY_OU_AND_CHILDREN,
|
||||
'ou_and_child_na': ENTITY_OU_AND_CHILDREN_NA,
|
||||
'ou_and_child_arch': ENTITY_OU_AND_CHILDREN_ARCH,
|
||||
'ou_and_child_ns': ENTITY_OU_AND_CHILDREN_NS,
|
||||
'ou_and_child_susp': ENTITY_OU_AND_CHILDREN_SUSP,
|
||||
'ou_and_child_na_ns': ENTITY_OU_AND_CHILDREN_NA_NS,
|
||||
'ous_and_child': ENTITY_OUS_AND_CHILDREN,
|
||||
'ous_and_child_na': ENTITY_OUS_AND_CHILDREN_NA,
|
||||
'ous_and_child_arch': ENTITY_OUS_AND_CHILDREN_ARCH,
|
||||
'ous_and_child_ns': ENTITY_OUS_AND_CHILDREN_NS,
|
||||
'ous_and_child_susp': ENTITY_OUS_AND_CHILDREN_SUSP,
|
||||
'ous_and_child_na_ns': ENTITY_OUS_AND_CHILDREN_NA_NS,
|
||||
}
|
||||
# CL entity source selectors
|
||||
ENTITY_SELECTOR_ALL = 'all'
|
||||
@@ -315,30 +391,217 @@ class GamCLArgs():
|
||||
]
|
||||
USER_ENTITY_SELECTOR_ALL_SUBTYPES = [
|
||||
ENTITY_USERS,
|
||||
ENTITY_USERS_NA,
|
||||
ENTITY_USERS_ARCH,
|
||||
ENTITY_USERS_NS,
|
||||
ENTITY_USERS_NS_SUSP,
|
||||
ENTITY_USERS_SUSP,
|
||||
ENTITY_USERS_ARCH_OR_SUSP,
|
||||
ENTITY_USERS_NA_NS,
|
||||
ENTITY_USERS_NS_SUSP,
|
||||
]
|
||||
#
|
||||
ENTITY_ALL_CROS = ENTITY_SELECTOR_ALL+' '+ENTITY_CROS
|
||||
ENTITY_ALL_USERS = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS
|
||||
ENTITY_ALL_USERS_NA = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NA
|
||||
ENTITY_ALL_USERS_ARCH = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_ARCH
|
||||
ENTITY_ALL_USERS_NS = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NS
|
||||
ENTITY_ALL_USERS_NS_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NS_SUSP
|
||||
ENTITY_ALL_USERS_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_SUSP
|
||||
ENTITY_ALL_USERS_NA_NS = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NA_NS
|
||||
ENTITY_ALL_USERS_ARCH_OR_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_ARCH_OR_SUSP
|
||||
ENTITY_ALL_USERS_NS_SUSP = ENTITY_SELECTOR_ALL+' '+ENTITY_USERS_NS_SUSP
|
||||
#
|
||||
ALL_USER_ENTITY_TYPES = {
|
||||
ENTITY_ALL_USERS,
|
||||
ENTITY_ALL_USERS_NA,
|
||||
ENTITY_ALL_USERS_ARCH,
|
||||
ENTITY_ALL_USERS_NS,
|
||||
ENTITY_ALL_USERS_SUSP,
|
||||
ENTITY_ALL_USERS_NA_NS,
|
||||
ENTITY_ALL_USERS_NS_SUSP,
|
||||
}
|
||||
DOMAIN_ENTITY_TYPES = {
|
||||
ENTITY_DOMAINS,
|
||||
ENTITY_DOMAINS_NA,
|
||||
ENTITY_DOMAINS_ARCH,
|
||||
ENTITY_DOMAINS_NS,
|
||||
ENTITY_DOMAINS_SUSP,
|
||||
ENTITY_DOMAINS_NA_NS,
|
||||
}
|
||||
GROUP_ENTITY_TYPES = {
|
||||
ENTITY_GROUP,
|
||||
ENTITY_GROUP_NA,
|
||||
ENTITY_GROUP_ARCH,
|
||||
ENTITY_GROUP_NS,
|
||||
ENTITY_GROUP_SUSP,
|
||||
ENTITY_GROUP_NA_NS,
|
||||
ENTITY_GROUP_INDE,
|
||||
}
|
||||
GROUPS_ENTITY_TYPES = {
|
||||
ENTITY_GROUPS,
|
||||
ENTITY_GROUPS_NA,
|
||||
ENTITY_GROUPS_ARCH,
|
||||
ENTITY_GROUPS_NS,
|
||||
ENTITY_GROUPS_SUSP,
|
||||
ENTITY_GROUPS_NA_NS,
|
||||
ENTITY_GROUPS_INDE,
|
||||
}
|
||||
GROUP_USERS_ENTITY_TYPES = {
|
||||
ENTITY_GROUP_USERS,
|
||||
ENTITY_GROUP_USERS_NA,
|
||||
ENTITY_GROUP_USERS_ARCH,
|
||||
ENTITY_GROUP_USERS_NS,
|
||||
ENTITY_GROUP_USERS_SUSP,
|
||||
ENTITY_GROUP_USERS_NA_NS,
|
||||
ENTITY_GROUP_USERS_SELECT,
|
||||
}
|
||||
OU_ENTITY_TYPES = {
|
||||
ENTITY_OU,
|
||||
ENTITY_OU_AND_CHILDREN,
|
||||
ENTITY_OU_NA,
|
||||
ENTITY_OU_AND_CHILDREN_NA,
|
||||
ENTITY_OU_ARCH,
|
||||
ENTITY_OU_AND_CHILDREN_ARCH,
|
||||
ENTITY_OU_NS,
|
||||
ENTITY_OU_AND_CHILDREN_NS,
|
||||
ENTITY_OU_SUSP,
|
||||
ENTITY_OU_AND_CHILDREN_SUSP,
|
||||
ENTITY_OU_NA_NS,
|
||||
ENTITY_OU_AND_CHILDREN_NA_NS,
|
||||
}
|
||||
OUS_ENTITY_TYPES = {
|
||||
ENTITY_OUS,
|
||||
ENTITY_OUS_AND_CHILDREN,
|
||||
ENTITY_OUS_NA,
|
||||
ENTITY_OUS_AND_CHILDREN_NA,
|
||||
ENTITY_OUS_ARCH,
|
||||
ENTITY_OUS_AND_CHILDREN_ARCH,
|
||||
ENTITY_OUS_NS,
|
||||
ENTITY_OUS_AND_CHILDREN_NS,
|
||||
ENTITY_OUS_SUSP,
|
||||
ENTITY_OUS_AND_CHILDREN_SUSP,
|
||||
ENTITY_OUS_NA_NS,
|
||||
ENTITY_OUS_AND_CHILDREN_NA_NS,
|
||||
}
|
||||
OU_DIRECT_ENTITY_TYPES = {
|
||||
ENTITY_OU,
|
||||
ENTITY_OUS,
|
||||
ENTITY_OU_NA,
|
||||
ENTITY_OUS_NA,
|
||||
ENTITY_OU_ARCH,
|
||||
ENTITY_OUS_ARCH,
|
||||
ENTITY_OU_NS,
|
||||
ENTITY_OUS_NS,
|
||||
ENTITY_OU_SUSP,
|
||||
ENTITY_OUS_SUSP,
|
||||
ENTITY_OU_NA_NS,
|
||||
ENTITY_OUS_NA_NS,
|
||||
}
|
||||
CROS_OU_ENTITY_TYPES = {
|
||||
ENTITY_CROS_OU,
|
||||
ENTITY_CROS_OU_AND_CHILDREN,
|
||||
ENTITY_CROS_OU_QUERY,
|
||||
ENTITY_CROS_OU_AND_CHILDREN_QUERY,
|
||||
ENTITY_CROS_OU_QUERIES,
|
||||
ENTITY_CROS_OU_AND_CHILDREN_QUERIES,
|
||||
}
|
||||
CROS_OUS_ENTITY_TYPES = {
|
||||
ENTITY_CROS_OUS,
|
||||
ENTITY_CROS_OUS_AND_CHILDREN,
|
||||
ENTITY_CROS_OUS_QUERY,
|
||||
ENTITY_CROS_OUS_AND_CHILDREN_QUERY,
|
||||
ENTITY_CROS_OUS_QUERIES,
|
||||
ENTITY_CROS_OUS_AND_CHILDREN_QUERIES,
|
||||
}
|
||||
CROS_OU_CHILDREN_ENTITY_TYPES = {
|
||||
ENTITY_CROS_OU_AND_CHILDREN,
|
||||
ENTITY_CROS_OU_AND_CHILDREN_QUERY,
|
||||
ENTITY_CROS_OU_AND_CHILDREN_QUERIES,
|
||||
ENTITY_CROS_OUS_AND_CHILDREN,
|
||||
ENTITY_CROS_OUS_AND_CHILDREN_QUERY,
|
||||
ENTITY_CROS_OUS_AND_CHILDREN_QUERIES,
|
||||
}
|
||||
CROS_OU_QUERY_ENTITY_TYPES = {
|
||||
ENTITY_CROS_OU_QUERY,
|
||||
ENTITY_CROS_OU_AND_CHILDREN_QUERY,
|
||||
ENTITY_CROS_OUS_QUERY,
|
||||
ENTITY_CROS_OUS_AND_CHILDREN_QUERY,
|
||||
}
|
||||
CROS_OU_QUERIES_ENTITY_TYPES = {
|
||||
ENTITY_CROS_OU_QUERIES,
|
||||
ENTITY_CROS_OU_AND_CHILDREN_QUERIES,
|
||||
ENTITY_CROS_OUS_QUERIES,
|
||||
ENTITY_CROS_OUS_AND_CHILDREN_QUERIES,
|
||||
}
|
||||
#
|
||||
ALL_USERS_QUERY_MAP = {
|
||||
ENTITY_ALL_USERS: 'isSuspended=False',
|
||||
ENTITY_ALL_USERS_NA: 'isArchived=False',
|
||||
ENTITY_ALL_USERS_ARCH: 'isArchived=True',
|
||||
ENTITY_ALL_USERS_NS: 'isSuspended=False',
|
||||
ENTITY_ALL_USERS_NS_SUSP: None,
|
||||
ENTITY_ALL_USERS_SUSP: 'isSuspended=True',
|
||||
ENTITY_ALL_USERS_NA_NS: 'isArchived=False isSuspended=False',
|
||||
ENTITY_ALL_USERS_NS_SUSP: None,
|
||||
}
|
||||
DOMAINS_QUERY_MAP = {
|
||||
ENTITY_DOMAINS: None,
|
||||
ENTITY_DOMAINS_NA: 'isArchived=False',
|
||||
ENTITY_DOMAINS_ARCH: 'isArchived=True',
|
||||
ENTITY_DOMAINS_NS: 'isSuspended=False',
|
||||
ENTITY_DOMAINS_SUSP: 'isSuspended=True',
|
||||
ENTITY_DOMAINS_NA_NS: 'isArchived=False isSuspended=False',
|
||||
}
|
||||
GROUPS_QUERY_MAP = { #(isArchived, isSuspended)
|
||||
ENTITY_GROUP_NA: (False, None),
|
||||
ENTITY_GROUPS_NA: (False, None),
|
||||
ENTITY_GROUP_ARCH: (True, None),
|
||||
ENTITY_GROUPS_ARCH: (True, None),
|
||||
ENTITY_GROUP_NS: (None, False),
|
||||
ENTITY_GROUPS_NS: (None, False),
|
||||
ENTITY_GROUP_SUSP: (None, True),
|
||||
ENTITY_GROUPS_SUSP: (None, True),
|
||||
ENTITY_GROUP_NA_NS: (False, False),
|
||||
ENTITY_GROUPS_NA_NS: (False, False),
|
||||
}
|
||||
GROUP_USERS_QUERY_MAP = { #(isArchived, isSuspended)
|
||||
ENTITY_GROUP_USERS_NA: (False, None),
|
||||
ENTITY_GROUP_USERS_ARCH: (True, None),
|
||||
ENTITY_GROUP_USERS_NS: (None, False),
|
||||
ENTITY_GROUP_USERS_SUSP: (None, True),
|
||||
ENTITY_GROUP_USERS_NA_NS: (False, False),
|
||||
}
|
||||
OU_QUERY_MAP = { #(isArchived, isSuspended)
|
||||
ENTITY_OU_NA: (False, None),
|
||||
ENTITY_OUS_NA: (False, None),
|
||||
ENTITY_OU_AND_CHILDREN_NA: (False, None),
|
||||
ENTITY_OUS_AND_CHILDREN_NA: (False, None),
|
||||
ENTITY_OU_ARCH: (True, None),
|
||||
ENTITY_OUS_ARCH: (True, None),
|
||||
ENTITY_OU_AND_CHILDREN_ARCH: (True, None),
|
||||
ENTITY_OUS_AND_CHILDREN_ARCH: (True, None),
|
||||
ENTITY_OU_NS: (None, False),
|
||||
ENTITY_OUS_NS: (None, False),
|
||||
ENTITY_OU_AND_CHILDREN_NS: (None, False),
|
||||
ENTITY_OUS_AND_CHILDREN_NS: (None, False),
|
||||
ENTITY_OU_SUSP: (None, True),
|
||||
ENTITY_OUS_SUSP: (None, True),
|
||||
ENTITY_OU_AND_CHILDREN_SUSP: (None, True),
|
||||
ENTITY_OUS_AND_CHILDREN_SUSP: (None, True),
|
||||
ENTITY_OU_NA_NS: (False, False),
|
||||
ENTITY_OUS_NA_NS: (False, False),
|
||||
ENTITY_OU_AND_CHILDREN_NA_NS: (False, False),
|
||||
ENTITY_OUS_AND_CHILDREN_NA_NS: (False, False),
|
||||
}
|
||||
#
|
||||
ENTITY_SELECTOR_ALL_SUBTYPES_MAP = {
|
||||
ENTITY_CROS: ENTITY_ALL_CROS,
|
||||
ENTITY_USERS: ENTITY_ALL_USERS,
|
||||
ENTITY_USERS_NA: ENTITY_ALL_USERS_NA,
|
||||
ENTITY_USERS_ARCH: ENTITY_ALL_USERS_ARCH,
|
||||
ENTITY_USERS_NS: ENTITY_ALL_USERS_NS,
|
||||
ENTITY_USERS_NS_SUSP: ENTITY_ALL_USERS_NS_SUSP,
|
||||
ENTITY_USERS_SUSP: ENTITY_ALL_USERS_SUSP,
|
||||
ENTITY_USERS_NA_NS: ENTITY_ALL_USERS_NA_NS,
|
||||
ENTITY_USERS_ARCH_OR_SUSP: ENTITY_ALL_USERS_ARCH_OR_SUSP,
|
||||
ENTITY_USERS_NS_SUSP: ENTITY_ALL_USERS_NS_SUSP,
|
||||
}
|
||||
# Allowed values for CL source selector datafile, csvkmd
|
||||
CROS_ENTITY_SELECTOR_DATAFILE_CSVKMD_SUBTYPES = [
|
||||
@@ -352,22 +615,37 @@ class GamCLArgs():
|
||||
ENTITY_CIGROUPS,
|
||||
ENTITY_CIGROUP_USERS,
|
||||
ENTITY_DOMAINS,
|
||||
ENTITY_DOMAINS_NA,
|
||||
ENTITY_DOMAINS_ARCH,
|
||||
ENTITY_DOMAINS_NS,
|
||||
ENTITY_DOMAINS_SUSP,
|
||||
ENTITY_DOMAINS_NA_NS,
|
||||
ENTITY_GROUPS,
|
||||
ENTITY_GROUPS_INDE,
|
||||
ENTITY_GROUPS_NA,
|
||||
ENTITY_GROUPS_ARCH,
|
||||
ENTITY_GROUPS_NS,
|
||||
ENTITY_GROUPS_SUSP,
|
||||
ENTITY_GROUPS_NA_NS,
|
||||
ENTITY_GROUP_USERS,
|
||||
ENTITY_GROUP_USERS_NA,
|
||||
ENTITY_GROUP_USERS_ARCH,
|
||||
ENTITY_GROUP_USERS_NS,
|
||||
ENTITY_GROUP_USERS_SUSP,
|
||||
ENTITY_GROUP_USERS_NA_NS,
|
||||
ENTITY_GROUP_USERS_SELECT,
|
||||
ENTITY_OUS,
|
||||
ENTITY_OUS_NA,
|
||||
ENTITY_OUS_ARCH,
|
||||
ENTITY_OUS_NS,
|
||||
ENTITY_OUS_SUSP,
|
||||
ENTITY_OUS_NA_NS,
|
||||
ENTITY_OUS_AND_CHILDREN,
|
||||
ENTITY_OUS_AND_CHILDREN_NA,
|
||||
ENTITY_OUS_AND_CHILDREN_ARCH,
|
||||
ENTITY_OUS_AND_CHILDREN_NS,
|
||||
ENTITY_OUS_AND_CHILDREN_SUSP,
|
||||
ENTITY_OUS_AND_CHILDREN_NA_NS,
|
||||
ENTITY_COURSEPARTICIPANTS,
|
||||
ENTITY_STUDENTS,
|
||||
ENTITY_TEACHERS,
|
||||
@@ -377,6 +655,7 @@ class GamCLArgs():
|
||||
GAM_CMD = 'gam'
|
||||
COMMIT_BATCH_CMD = 'commit-batch'
|
||||
PRINT_CMD = 'print'
|
||||
DATETIME_CMD = 'datetime'
|
||||
SET_CMD = 'set'
|
||||
CLEAR_CMD = 'clear'
|
||||
SLEEP_CMD = 'sleep'
|
||||
@@ -924,6 +1203,7 @@ class GamCLArgs():
|
||||
OB_CSE_KEYPAIR_ID = 'CSEKeyPairID'
|
||||
OB_CUSTOMER_ID = 'CustomerID'
|
||||
OB_CUSTOMER_AUTH_TOKEN = 'CustomerAuthToken'
|
||||
OB_DATETIME_FORMAT = 'DateTimeFormat'
|
||||
OB_DEVICE_FILE_ENTITY = 'DeviceFileEntity'
|
||||
OB_DEVICE_ENTITY = 'DeviceEntity'
|
||||
OB_DEVICE_ID = 'DeviceID'
|
||||
|
||||
@@ -384,11 +384,13 @@ class GamEntity():
|
||||
URL = 'url '
|
||||
USER = 'user'
|
||||
USER_ALIAS = 'uali'
|
||||
USER_NOT_ARCHIVED = 'usna'
|
||||
USER_ARCHIVED = 'usar'
|
||||
USER_EMAIL = 'uema'
|
||||
USER_INVITATION = 'uinv'
|
||||
USER_NOT_SUSPENDED = 'uns'
|
||||
USER_SCHEMA = 'usch'
|
||||
USER_NOT_SUSPENDED = 'usns'
|
||||
USER_SUSPENDED = 'usup'
|
||||
USER_SCHEMA = 'usch'
|
||||
VACATION = 'vaca'
|
||||
VACATION_ENABLED = 'vace'
|
||||
VALUE = 'val'
|
||||
@@ -748,11 +750,13 @@ class GamEntity():
|
||||
URL: ['URLs', 'URL'],
|
||||
USER: ['Users', 'User'],
|
||||
USER_ALIAS: ['User Aliases', 'User Alias'],
|
||||
USER_NOT_ARCHIVED: ['Users (Not archived)', 'User (Not archived)'],
|
||||
USER_ARCHIVED: ['Users (Archived)', 'User (Archived)'],
|
||||
USER_EMAIL: ['User Emails', 'User Email'],
|
||||
USER_INVITATION: ['User Invitations', 'User Invitation'],
|
||||
USER_NOT_SUSPENDED: ['Users (Not suspended)', 'User (Not suspended)'],
|
||||
USER_SCHEMA: ['Schemas', 'Schema'],
|
||||
USER_SUSPENDED: ['Users (Suspended)', 'User (Suspended)'],
|
||||
USER_SCHEMA: ['Schemas', 'Schema'],
|
||||
VACATION: ['Vacation', 'Vacation'],
|
||||
VACATION_ENABLED: ['Vacation Enabled', 'Vacation Enabled'],
|
||||
VALUE: ['Values', 'Value'],
|
||||
|
||||
@@ -103,7 +103,7 @@ gam print aliases [todrive <ToDriveAttribute>*]
|
||||
[limittoou <OrgUnitItem>])
|
||||
[user|users <EmailAddressList>] [group|groups <EmailAddressList>]
|
||||
[select <UserTypeEntity>]
|
||||
[aliasmatchpattern <REMatchPattern>]
|
||||
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
||||
[shownoneditable] [nogroups] [nousers]
|
||||
[onerowpertarget] [delimiter <Character>]
|
||||
[suppressnoaliasrows]
|
||||
@@ -117,6 +117,8 @@ By default, group and user aliases in all domains in the account are selected; t
|
||||
* `user|users <EmailAddressList>` - Print aliases for users in `<EmailAddressList`
|
||||
* `select <UserTypeEntity>` - Print aliases for users in `<UserTypeEntity>`
|
||||
* `group|groups <EmailAddressList>` - Print aliases for groups in `<EmailAddressList`
|
||||
* `issuspended <Boolean>` - Limit users based on their status
|
||||
* `isarchived <Boolean>` - Limit users based on their status
|
||||
* `aliasmatchpattern <REMatchPattern>` - Print aliases that match a pattern
|
||||
* `nogroups` - Print only user aliases
|
||||
* `nousers` - Print only group aliases
|
||||
|
||||
@@ -184,7 +184,7 @@ perform these steps and then retry the create project command.
|
||||
|
||||
## Authorize Service Account Key Uploads
|
||||
|
||||
*IMPORTANT:* Google best practice is to NOT use service account keys. Rather than overriding Google's default policy please consider [running GAM on Google Compute Engine Securely](https://github.com/GAM-team/GAM/wiki/l-Running-GAM-on-Google-Compute-Engine-(GCE)-Securely) so that service account keys are not necessary.
|
||||
*IMPORTANT:* Google best practice is to NOT use service account keys. Rather than overriding Google's default policy please consider [Running GAM7 securely on a Google Compute Engine](https://github.com/GAM-team/GAM/wiki/Running-GAM7-securely-on-a-Google-Compute-Engine) (if running in Google Cloud) or [Workload Identity Federation](https://github.com/GAM-team/GAM/wiki/Using-GAM7-with-keyless-authentication-Workload-Identity-Federation) (if running outside Google Cloud) so that service account keys are not necessary.
|
||||
|
||||
If you try to create a project and get an error saying that Constraint `constraints/iam.disableServiceAccountKeyUpload violated for service account projects/gam-project-xxxxx`,
|
||||
perform these steps and then you should be able to authorize and use your project.
|
||||
|
||||
@@ -325,6 +325,8 @@
|
||||
<CourseWorkState> ::= draft|published|deleted
|
||||
<CrOSID> ::= <String>
|
||||
<CustomerID> ::= <String>
|
||||
<DateTimeFormat> ::= <String>
|
||||
See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
|
||||
<DeliverySetting> ::=
|
||||
allmail|
|
||||
abridged|daily|
|
||||
@@ -460,6 +462,7 @@
|
||||
See: https://support.google.com/mail/answer/7190
|
||||
<QueryGroup> ::= <String>
|
||||
See: https://developers.google.com/admin-sdk/directory/v1/guides/search-groups
|
||||
<QueryItem> ::= <UniqueID>|<String>
|
||||
<QueryMemberRestrictions> ::= <String>
|
||||
See: https://cloud.google.com/identity/docs/reference/rest/v1beta1/SecuritySettings#MemberRestriction
|
||||
<QueryMobile> ::= <String>
|
||||
|
||||
@@ -18,6 +18,9 @@ The variables `num_threads`, `num_tbatch_threads` and `auto_batch_min` in `gam.c
|
||||
* [Command data from Google Docs/Sheets/Storage](Command-Data-From-Google-Docs-Sheets-Storage)
|
||||
`gdoc <UserGoogleDoc>` and `gsheet <UserGoogleSheet>`
|
||||
|
||||
<DateTimeFormat> ::= <String>
|
||||
See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
|
||||
|
||||
## Batch files
|
||||
There are two types of batch processing, one that uses processes and one that uses threads. Using processes is higher performance but `gam csv` commands are not supported.
|
||||
* `gam batch` - gam commands are run as processes, gam csv commands are not allowed in the batch file
|
||||
@@ -45,6 +48,9 @@ Batch files can contain the following types of lines:
|
||||
* sleep \<Integer\> - Batch processing will suspend for \<Integer\> seconds before the next command line is processed
|
||||
* To be effective, this should immediately follow commit-batch
|
||||
* print \<String\> - Print \<String\> on stderr
|
||||
* datetime \<DateTimeFormat\>
|
||||
* The current time is formatted with \<DateTimeFormat\> and subsequent lines will have `%datetime%` replaced with the formatted time value.
|
||||
* See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
|
||||
* set \<KeywordString\> \<ValueString\>
|
||||
* Subsequent lines will have %\<KeywordString\>% replaced with \<ValueString\>
|
||||
* clear \<KeywordString\>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# Collections of Users
|
||||
- [Python Regular Expressions](Python-Regular-Expressions) Search function
|
||||
- [Notes](#notes)
|
||||
- [Definitions](#definitions)
|
||||
- [User Type Entity](#user-type-entity)
|
||||
- [All non-suspended Users](#all-non-suspended-users)
|
||||
@@ -37,6 +38,37 @@
|
||||
- [Examples using CSV files to print users from groups](#examples-using-CSV-files-to-print-users-from-groups)
|
||||
- [Examples using multiple queries](#examples-using-multiple-queries)
|
||||
|
||||
## Notes
|
||||
|
||||
The followig items referencing non-archived/archived users were added to `<UserTypeEntity>` in version 7.22.00.
|
||||
```
|
||||
all users_na
|
||||
all users_arch
|
||||
all users_na_ns
|
||||
all users_arch_or_susp
|
||||
domains_na
|
||||
domains_arch
|
||||
domains_na_ns
|
||||
groups_na
|
||||
groups_arch
|
||||
groups_na_ns
|
||||
group_users_na
|
||||
group_users_arch
|
||||
group_users_na_ns
|
||||
ou_na
|
||||
ou_arch
|
||||
ou_na_ns
|
||||
ou_and_children_na
|
||||
ou_and_children_arch
|
||||
ou_and_children_na_ns
|
||||
ous_na
|
||||
ous_arch
|
||||
ous_na_ns
|
||||
ous_and_children_na
|
||||
ous_and_children_arch
|
||||
ous_and_children_na_ns
|
||||
```
|
||||
|
||||
## Definitions
|
||||
* [Basic Items](Basic-Items)
|
||||
|
||||
@@ -90,25 +122,25 @@
|
||||
<SharedDriveNameEntity>
|
||||
|
||||
<UserTypeEntity> ::=
|
||||
(all users|users_ns|users_susp|users_ns_susp)|
|
||||
(all users|users_na|users_arch|users_ns|users_susp|users_ns_susp|users_arch_or_susp|users_na_ns)|
|
||||
(user <UserItem>)|
|
||||
(users <UserList>)|
|
||||
(oauthuser)
|
||||
(domains|domains_ns|domains_susp <DomainNameList>)|
|
||||
(group|group_ns|group_susp|group_inde <GroupItem>)|
|
||||
(groups|groups_ns|groups_susp|groups_inde <GroupList>)|
|
||||
(domains|domains_na|domains_arch|domains_ns|domains_susp|domains_na_ns <DomainNameListList>)|
|
||||
(group|group_na|group_arch|group_ns|group_susp|group_na_ns|group_inde <GroupItem>)|
|
||||
(groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde <GroupList>)|
|
||||
(group_inde <GroupItem>)|(groups_inde <GroupList>)|
|
||||
(group_users|group_users_ns|group_users_susp <GroupList>
|
||||
(group_users|group_users_na|group_users_arch|group_users_ns|group_users_susp|group_users_na_ns <GroupList>
|
||||
[members] [managers] [owners]
|
||||
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
|
||||
(group_users_select <GroupList>
|
||||
[members] [managers] [owners]
|
||||
[notsuspended|suspended] [notarchived|archived]
|
||||
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
|
||||
(ou|ou_ns|ou_susp <OrgUnitItem>)|
|
||||
(ou_and_children|ou_and_children_ns|ou_and_children_susp <OrgUnitItem>)|
|
||||
(ous|ous_ns|ous_susp <OrgUnitList>)|
|
||||
(ous_and_children|ous_and_children_ns|ous_and_children_susp <OrgUnitList>)|
|
||||
(ou|ou_na|ou_arch|ou_ns|ou_susp|ou_na_ns <OrgUnitItem>)|
|
||||
(ou_and_children|ou_and_children_na|ou_and_children_arch|ou_and_children_ns|ou_and_children_susp|ou_and_children_na_ns <OrgUnitItem>)|
|
||||
(ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns <OrgUnitList>)|
|
||||
(ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns <OrgUnitList>)|
|
||||
(courseparticipants <CourseIDList>)|
|
||||
(students <CourseIDList>)|
|
||||
(teachers <CourseIDList>)|
|
||||
@@ -126,41 +158,47 @@
|
||||
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
|
||||
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
|
||||
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
|
||||
[warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>][quotechar <Character>]
|
||||
[warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
|
||||
[endcsv|(fields <FieldNameList>)]
|
||||
(matchfield|skipfield <FieldName> <RESearchPattern>)*
|
||||
[delimiter <Character>])|
|
||||
(datafile
|
||||
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
|
||||
ous_and_children|ous_and_children_ns|ous_and_children_susp|
|
||||
courseparticipants|students|teachers
|
||||
users|
|
||||
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
|
||||
ous|ous_na|ous_arch|ous_ns|ous_susps|ous_na_ns|
|
||||
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
|
||||
courseparticipants|students|teachers
|
||||
((<FileName> [charset <Charset>])|
|
||||
(gdoc <UserGoogleDoc>)|
|
||||
(gcsdoc <StorageBucketObjectName>))
|
||||
[delimiter <Character>])|
|
||||
(csvdatafile
|
||||
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
|
||||
ous_and_children|ous_and_children_ns|ous_and_children_susp|
|
||||
courseparticipants|students|teachers
|
||||
users|
|
||||
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
|
||||
ous|ous_na|ous_arch|ous_ns|ous_susps|ous_na_ns|
|
||||
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
|
||||
courseparticipants|students|teachers
|
||||
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
|
||||
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
|
||||
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
|
||||
(gcscsv(:<FieldName>)+ <StorageBucketObjectName>)|
|
||||
(gcsdoc(:<FieldName>)+ <StorageBucketObjectName>))
|
||||
[warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>][quotechar <Character>]
|
||||
[warnifnodata] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>]
|
||||
[endcsv|(fields <FieldNameList>)]
|
||||
(matchfield|skipfield <FieldName> <RESearchPattern>)*
|
||||
[delimiter <Character>])|
|
||||
(csvkmd
|
||||
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
|
||||
ous_and_children|ous_and_children_ns|ous_and_children_susp|
|
||||
courseparticipants|students|teachers
|
||||
users|
|
||||
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
|
||||
ous|ous_na|ous_arch|ous_ns|ous_susps|ous_na_ns|
|
||||
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
|
||||
courseparticipants|students|teachers
|
||||
((<FileName>|
|
||||
(gsheet <UserGoogleSheet>)|
|
||||
(gdoc <UserGoogleDoc>)|
|
||||
(gcscsv <StorageBucketObjectName>)|
|
||||
(gcsdoc <StorageBucketObjectName>))
|
||||
[charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>][quotechar <Character>] [fields <FieldNameList>])
|
||||
[charset <Charset>] [columndelimiter <Character>] [noescapechar <Boolean>] [quotechar <Character>] [fields <FieldNameList>])
|
||||
keyfield <FieldName> [keypattern <RESearchPattern>] [keyvalue <RESubstitution>] [delimiter <Character>]
|
||||
subkeyfield <FieldName> [keypattern <RESearchPattern>] [keyvalue <RESubstitution>] [delimiter <Character>]
|
||||
(matchfield|skipfield <FieldName> <RESearchPattern>)*
|
||||
@@ -172,6 +210,12 @@
|
||||
|
||||
Use these options to select users for GAM commands.
|
||||
|
||||
## All non-archived Users
|
||||
* `all users_na`
|
||||
|
||||
## All archived Users
|
||||
* `all users_arch`
|
||||
|
||||
## All non-suspended Users
|
||||
* `all users`
|
||||
* `all users_ns`
|
||||
@@ -179,6 +223,12 @@ Use these options to select users for GAM commands.
|
||||
## All suspended Users
|
||||
* `all users_susp`
|
||||
|
||||
## All archived or suspended Users
|
||||
* `all users_arch_or_susp`
|
||||
|
||||
## All non-archived and non-suspended Users
|
||||
* `all users_na_ns`
|
||||
|
||||
## All non-suspended and suspended Users
|
||||
* `all users_ns_susp`
|
||||
|
||||
@@ -192,22 +242,31 @@ Use these options to select users for GAM commands.
|
||||
* `oauthuser`
|
||||
|
||||
## Users in the domains `<DomainNameList>`
|
||||
* `domains|domains_ns|domains_susp <DomainNameList>`
|
||||
* `domains|domains_na|domains_arch|domains_ns|domains_susp|domains_na_ns <DomainNameList>`
|
||||
* `domains` - All users
|
||||
* `domains_na` - Non-archived users
|
||||
* `domains_arch` - Archived users
|
||||
* `domains_ns` - Non-suspended users
|
||||
* `domains_susp` - Suspended users
|
||||
* `domains_na_ns` - Non-archived and non-suspended users
|
||||
|
||||
## Users directly in the group `<GroupItem>`
|
||||
* `group|group_ns|group_susp <GroupItem>`
|
||||
* `group|group_na|group_arch|group_ns|group_susp|group_na_ns <GroupItem>`
|
||||
* `group` - All user members
|
||||
* `group_na` - Non-archived user members
|
||||
* `group_arch` - Archived user members
|
||||
* `group_ns` - Non-suspended user members
|
||||
* `group_susp` - Suspended user members
|
||||
* `group_na_ns` - Non-archived and non-suspended user members
|
||||
|
||||
## Users directly in the groups `<GroupList>`
|
||||
* `groups|groups_ns|groups_susp <GroupList>`
|
||||
* `groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns <GroupList>`
|
||||
* `groups` - All user members
|
||||
* `groups_na` - Non-archived user members
|
||||
* `groups_arch` - Archived user members
|
||||
* `groups_ns` - Non-suspended user members
|
||||
* `groups_susp` - Suspended user members
|
||||
* `groups_na_ns` - Non-archived and non-suspended user members
|
||||
|
||||
## Users directly and indirectly in the group `<GroupItem>`
|
||||
* `group_inde` - All user members including those from all subgroups
|
||||
@@ -216,10 +275,13 @@ Use these options to select users for GAM commands.
|
||||
* `groups_inde` - All user members including those from all subgroups
|
||||
|
||||
## Selected Users from groups
|
||||
* `group_users|group_users_ns|group_users_susp <GroupList> [members] [managers] [owners] [primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end`
|
||||
* `group_users|group_users_na|group_users_arch|group_users_ns|group_users_susp|group_users_na_ns <GroupList> [members] [managers] [owners] [primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end`
|
||||
* `group_users` - All user members
|
||||
* `group_users_na` - Non-archived user members
|
||||
* `group_users_arch` - Archived user members
|
||||
* `group_users_ns` - Non-suspended user members
|
||||
* `group_users_susp` - Suspended user members
|
||||
* `group_users_na_ns` - Non-archived and non-suspended user members
|
||||
* `[members] [managers] [owners]` - The desired roles; if roles are not specified, all roles are included
|
||||
* `primarydomain` - Select Users from the primary domain
|
||||
* `domains <DomainNameList>` - Select Users from the list of domains
|
||||
@@ -259,30 +321,41 @@ Use these options to select users for GAM commands.
|
||||
* `end` - Terminate the selection
|
||||
|
||||
## Users directly in the Organization Unit `<OrgUnitItem>`
|
||||
* `ou|ou_ns|ou_susp <OrgUnitItem>`
|
||||
* `ou|ou_na|ou_arch|ou_ns|ou_susp|ou_na_ns <OrgUnitItem>`
|
||||
* `ou` - All users
|
||||
* `ou_ns` - Non-Suspended users
|
||||
* `ou_na` - Non-archived users
|
||||
* `ou_arch` - Archived users
|
||||
* `ou_ns` - Non-suspended users
|
||||
* `ou_susp` - Suspended users
|
||||
* `ou_na_ns` - Non-archived and nn-suspended users
|
||||
|
||||
## Users in the Organization Unit `<OrgUnitItem>` and all of its sub Organization Units
|
||||
* `ou_and_children|ou_and_children_ns|ou_and_children_susp <OrgUnitItem>`
|
||||
* `ou_and_children|ou_and_children_na|ou_and_children_arch|ou_and_children_ns|ou_and_children_susp|ou_and_children_na_ns <OrgUnitItem>`
|
||||
* `ou_and_children` - All users
|
||||
* `ou_and_children_na` - Non-archived users
|
||||
* `ou_and_children_arch` - Archived users
|
||||
* `ou_and_children_ns` - Non-suspended users
|
||||
* `ou_and_children_susp` - Suspended users
|
||||
* `ou_and_children_na_ns` - Non-archived and nn-suspended users
|
||||
|
||||
## Users directly in the Organization Units `<OrgUnitList>`
|
||||
* `ous|ous_ns|ous_susp <OrgUnitList>` - Users directly in the Organization Units `<OrgUnitList>`
|
||||
* `ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns <OrgUnitList>` - Users directly in the Organization Units `<OrgUnitList>`
|
||||
* `ous` - All users
|
||||
* `ous_na` - Non-archived users
|
||||
* `ous_arch` - Archived users
|
||||
* `ous_ns` - Non-suspended users
|
||||
* `ous_susp` - Suspended users
|
||||
* `ous_na_ns` - Non-archived and nn-suspended users
|
||||
|
||||
`<OrgUnitList>` may require special quoting based on whether the OUs contain spaces, commas or single quotes.
|
||||
|
||||
For quoting rules, see: [List Quoting Rules](Command-Line-Parsing)
|
||||
|
||||
## Users in the Organization Units `<OrgUnitList>` and all of their sub Organization Units
|
||||
* `ous_and_children|ous_and_children_ns|ous_and_children_susp <OrgUnitList>` - Users in the Organization Units `<OrgUnitList>` and all of their sub Organization Units
|
||||
* `ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns <OrgUnitList>` - Users in the Organization Units `<OrgUnitList>` and all of their sub Organization Units
|
||||
* `ous_and_children` - All users
|
||||
* `ous_and_children_na` - Non-archived users
|
||||
* `ous_and_children_arch` - Archived users
|
||||
* `ous_and_children_ns` - Non-suspended users
|
||||
* `ous_and_children_susp` - Suspended users
|
||||
|
||||
@@ -363,15 +436,21 @@ csvfile
|
||||
## Users from groups/OUs/courses in a flat file/Google Doc/Google Cloud Storage Object
|
||||
```
|
||||
datafile
|
||||
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
|
||||
ous_and_children|ous_and_children_ns|ous_and_children_susp|
|
||||
courseparticipants|students|teachers
|
||||
users|
|
||||
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
|
||||
ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns|
|
||||
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
|
||||
courseparticipants|students|teachers
|
||||
((<FileName> [charset <Charset>])|
|
||||
(gdoc <UserGoogleDoc>)|
|
||||
(gcsdoc <StorageBucketObjectName>))
|
||||
[delimiter <Character>]
|
||||
```
|
||||
* `users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|ous_and_children|ous_and_children_ns|ous_and_children_susp|courseparticipants|students|teachers` - The type of item in the file
|
||||
* `users|`
|
||||
* `groups|groups_na|groups_arch|groups_ns_|groups_susp|groups_na_ns|groups_inde|`
|
||||
* `ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns|`
|
||||
* `ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|`
|
||||
* `courseparticipants|students|teachers` - The type of item in the file
|
||||
* `<FileName>` - A flat file containing rows of the type of item specified
|
||||
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
|
||||
* `gdoc <UserGoogleDoc>` - A Google Doc containing rows of the type of item specified
|
||||
@@ -381,9 +460,11 @@ datafile
|
||||
## Users from groups/OUs/courses in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object
|
||||
```
|
||||
csvdatafile
|
||||
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
|
||||
ous_and_children|ous_and_children_ns|ous_and_children_susp|
|
||||
courseparticipants|students|teachers
|
||||
users|
|
||||
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
|
||||
ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns|
|
||||
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
|
||||
courseparticipants|students|teachers
|
||||
((<FileName>(:<FieldName>)+ [charset <Charset>] )|
|
||||
(gsheet(:<FieldName>)+ <UserGoogleSheet>)|
|
||||
(gdoc(:<FieldName>)+ <UserGoogleDoc>)|
|
||||
@@ -394,9 +475,13 @@ csvdatafile
|
||||
(matchfield|skipfield <FieldName> <RESearchPattern>)*
|
||||
[delimiter <Character>]
|
||||
```
|
||||
* `users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|ous_and_children|ous_and_children_ns|ous_and_children_susp|courseparticipants|students|teachers` - The type of item in the file
|
||||
* `users|`
|
||||
* `groups|groups_na|groups_arch|groups_ns_|groups_susp|groups_na_ns|groups_inde|`
|
||||
* `ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns|`
|
||||
* `ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|`
|
||||
* `courseparticipants|students|teachers` - The type of item in the file
|
||||
* `<FileName>(:<FieldName>)+` - A CSV file and the one or more columns contain the type of item specified
|
||||
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
|
||||
* `charset <Charset>` - The character set of the file if it isn't UTF-8
|
||||
* `gsheet(:<FieldName>)+ <UserGoogleSheet>` - A Google Sheet and the one or more columns contain the type of item specified
|
||||
* `gdoc(:<FieldName>)+ <UserGoogleDoc>` - A Google Doc and the one or more columns contain the type of item specified
|
||||
* `gcscsv(:<FieldName>)+ <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object and the one or more columns contain the type of item specified
|
||||
@@ -413,9 +498,11 @@ csvdatafile
|
||||
## Users directly in or from groups/OUs/courses in a CSV file/Google Sheet/Google Doc/Google Cloud Storage Object
|
||||
```
|
||||
csvkmd
|
||||
users|groups|groups_ns|groups_susp|groups_inde|ous|ous_ns|ous_susp|
|
||||
ous_and_children|ous_and_children_ns|ous_and_children_susp|
|
||||
courseparticipants|students|teachers
|
||||
users|
|
||||
groups|groups_na|groups_arch|groups_ns|groups_susp|groups_na_ns|groups_inde|
|
||||
ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns|
|
||||
ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|
|
||||
courseparticipants|students|teachers
|
||||
((<FileName>|
|
||||
(gsheet <UserGoogleSheet>)|
|
||||
(gdoc <UserGoogleDoc>)|
|
||||
@@ -427,9 +514,13 @@ csvkmd
|
||||
(matchfield|skipfield <FieldName> <RESearchPattern>)*
|
||||
[datafield <FieldName>(:<FieldName>)* [delimiter <Character>]]
|
||||
```
|
||||
* `users|groups|groups_ns_|groups_susp|groups_inde|ous|ous_ns|ous_susp|ous_and_children|ous_and_children_ns|ous_and_children_susp|courseparticipants|students|teachers` - The type of item in the file
|
||||
* `users|`
|
||||
* `groups|groups_na|groups_arch|groups_ns_|groups_susp|groups_na_ns|groups_inde|`
|
||||
* `ous|ous_na|ous_arch|ous_ns|ous_susp|ous_na_ns|`
|
||||
* `ous_and_children|ous_and_children_na|ous_and_children_arch|ous_and_children_ns|ous_and_children_susp|ous_and_children_na_ns|`
|
||||
* `courseparticipants|students|teachers` - The type of item in the file
|
||||
* `<FileName>` - A CSV file containing rows with columns of the type of item specified
|
||||
* `charset <Charset>` - The character aset of the file if it isn't UTF-8
|
||||
* `charset <Charset>` - The character set of the file if it isn't UTF-8
|
||||
* `gsheet <UserGoogleSheet>` - A Google Sheet containing rows with columns of the type of item specified
|
||||
* `gdoc <UserGoogleDoc>` - A Google Doc containing rows with columns of the type of item specified
|
||||
* `gcscsv <StorageBucketObjectName>` - A Google Cloud Storage Bucket Object with columns of the type of item specified
|
||||
|
||||
21
wiki/GAM-Release-Process.md
Normal file
21
wiki/GAM-Release-Process.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Steps to release a new GAM version
|
||||
1. In a final commit before release:
|
||||
- [src/gam/__init.py](https://github.com/GAM-team/GAM/blob/main/src/gam/__init__.py) `__version___` value should be updated to the new version.
|
||||
- [src/GamUpdate.txt](https://github.com/GAM-team/GAM/blob/main/src/GamUpdate.txt) should be updated with a high-level changelog.
|
||||
- [wiki/GamUpdates.md](https://github.com/GAM-team/GAM/blob/main/wiki/GamUpdates.md) should be updated with same high-level changelog.
|
||||
- [wiki/Version-and-Help.md](https://github.com/GAM-team/GAM/blob/main/wiki/Version-and-Help.md) should be updated with current version N.NN.NN
|
||||
- [wiki/How-to-Upgrade-Legacy-GAM-to-GAM7.md](https://github.com/GAM-team/GAM/blob/main/wiki/How-to-Upgrade-Legacy-GAM-to-GAM7.md) should be updated with current version N.NN.NN
|
||||
2. The [build.yaml](https://github.com/GAM-team/GAM/blob/main/.github/workflows/build.yml) Github Action for final commit should complete successfully and creating a new dated Draft release.
|
||||
- We should *NEVER* upload release files manually. Only release files automatically created and [attested](https://github.com/GAM-team/GAM/wiki/Verifying-a-GAM7-Build-is-Legitimate-and-Official#github-attestation-linuxmacoswindows) as created by the Github Action should be used.
|
||||
3. Edit the Draft release:
|
||||
- Create a new tag with the format: `vN.NN.NN` where N.NN.NN is the GAM release version.
|
||||
- name the release "GAM N.NN.NN" where N.NN.NN is the GAM release version.
|
||||
- Include the changelog details for the new version in details.
|
||||
- leave "Set as pre-release" unchecked and "Set as the latest release" checked.
|
||||
- Publish the release.
|
||||
|
||||
# TODO: Release Process Improvements
|
||||
- copying changelog between GamUpdate.txt, GamUpdates.md and release description is manual and tedious. Automate it.
|
||||
- copying version string from gam/__init__.py, changelogs and release details and tag in manual and tedious. Automate it.
|
||||
- See if we can block releases with binaries not uploaded by GitHub Actions to further secure release pipelines.
|
||||
|
||||
@@ -15,7 +15,7 @@ The 27ft RV Jay drove his family to Niagara Falls this summer. They’re all sti
|
||||
some in full sentences 🙂
|
||||
|
||||
# Has something changed with Ross?
|
||||
He’s just older, 75 and counting.
|
||||
He’s just older, 76 and counting.
|
||||
|
||||
(Jay here, this is all I could get from Ross but he’s his usual awesome self helping admins in Chat and Groups forums as I write this and adding new features. Because some have asked, Ross is a real person. He is not an Advanced GenAI as rumours have claimed. 🙂)
|
||||
|
||||
@@ -49,8 +49,8 @@ Both GAM7 and GAM-ADV versions use the same configuration file (gam.cfg), and cr
|
||||
# Help!!! Something went wrong!
|
||||
Well that’s not really a question but as ever, please reach out to either the GAM email support group:
|
||||
|
||||
[git.io/gam-group](http://git.io/gam-group)
|
||||
[GAM Discussion Forum](https://groups.google.com/forum/#!forum/google-apps-manager)
|
||||
|
||||
Or the Google Chat Space:
|
||||
|
||||
[git.io/gam-chat](http://git.io/gam-chat)
|
||||
[GAM Public Chat Room](GAM-Public-Chat-Room)
|
||||
@@ -10,6 +10,48 @@ Add the `-s` option to the end of the above commands to suppress creating the `g
|
||||
|
||||
See [Downloads-Installs-GAM7](https://github.com/GAM-team/GAM/wiki/Downloads-Installs) for Windows or other options, including manual installation
|
||||
|
||||
### - 7.22.04
|
||||
|
||||
Added a variant of `gam create vaulthold` that gets its parameters from a saved Vault query.
|
||||
```
|
||||
gam create vaulthold matter <MatterItem> [name <String>]
|
||||
vaultquery <QueryItem>
|
||||
[showdetails|returnidonly]
|
||||
```
|
||||
|
||||
### 7.22.03
|
||||
|
||||
Fix backwards compatability bug introduced in 7.22.00 for `gam print users` that changed `suspended`
|
||||
from a field name to a query option; it is now correctly interpreted as a field name.
|
||||
|
||||
### 7.22.02
|
||||
|
||||
An update to the httplib2 library caused GAM proxy connections to fail; this has been fixed
|
||||
by including the pysocks library needed by the latest httplib2 library.
|
||||
|
||||
### 7.22.00
|
||||
|
||||
Expanded `<UserTypeEntity>` to allow specification of non-archived/archived users.
|
||||
* See [Collections of Users](Collections-of-Users)
|
||||
|
||||
These commands have also been updated to deal with archived users:
|
||||
* `gam print aliases`
|
||||
* `gam update groups`
|
||||
* `gam info orgs`
|
||||
* `gam print orgs`
|
||||
* `gam print users`
|
||||
|
||||
Added `datetime <DateTimeFormat>` command that can be embedded in Gam batch files.
|
||||
The current time is formatted with `<DateTimeFormat>` and subsequent lines in `<BatchContent>`
|
||||
will have `%datetime%` replaced with the formatted time value.
|
||||
|
||||
See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
|
||||
|
||||
### 7.21.03
|
||||
|
||||
Added option `notifyrecoveryemail` to `gam create user` and `gam <UserTypeEntity> update user password <String>`
|
||||
that sends the passsword notification email to the user's recovery email address (if defined).
|
||||
|
||||
### 7.21.02
|
||||
|
||||
GAM now builds on macOS 26 Tahoe and properly identifies the OS.
|
||||
@@ -1912,7 +1954,7 @@ number of domain aliasess on stdout; no CSV file is written.
|
||||
|
||||
Added option `showitemcountonly` to `gam print domains` that causes GAM to display the
|
||||
number of domains on stdout; no CSV file is written.
|
||||
|
||||
|
||||
### 6.77.16
|
||||
|
||||
Fixed bug in `gam <UserTypeEntity> print filelist` that caused a trap.
|
||||
@@ -2676,7 +2718,7 @@ Batch processing will suspend for `<Integer>` seconds before the next command li
|
||||
|
||||
Added the following options to `<PermissionMatch>` that allow more powerful matching.
|
||||
```
|
||||
nottype <DriveFileACLType>
|
||||
nottype <DriveFileACLType>
|
||||
typelist <DriveFileACLTypeList>
|
||||
nottypelist <DriveFileACLTypeList>
|
||||
rolelist <DriveFileACLRoleList>
|
||||
@@ -3328,7 +3370,7 @@ Added support for Google Workspace Labs license.
|
||||
|
||||
### 6.64.10
|
||||
|
||||
Fixed bug introduced in 6.64.09 that caused a trap when `gam redirect csv <FileName> multiprocess` was used.
|
||||
Fixed bug introduced in 6.64.09 that caused a trap when `gam redirect csv <FileName> multiprocess` was used.
|
||||
|
||||
### 6.64.09
|
||||
|
||||
|
||||
@@ -92,6 +92,38 @@ See [Collections of Items](Collections-of-Items)
|
||||
Group membership commands involve specifying collections of users;
|
||||
for `<UserTypeEntity>`, see: [Collections of Users](Collections-of-Users)
|
||||
|
||||
### Select users based on archived state
|
||||
When adding, deleting or synchronizing group members, to select only archived or non-archived users, use the following`<UserTypeEntity>`:
|
||||
```
|
||||
(all users_na|users_arch)|
|
||||
(domains_na|domains_arch <DomainNameList>)|
|
||||
(group_na|group_arch <GroupItem>)|
|
||||
(groups_na|groups_arch <GroupList>)|
|
||||
(group_users_na|group_users_arch <GroupList>
|
||||
[members] [managers] [owners]
|
||||
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
|
||||
(ou_na|ou_arch <OrgUnitItem>)|
|
||||
(ou_and_children_na|ou_and_children_arch <OrgUnitItem>)|
|
||||
(ous_na|ous_arch <OrgUnitList>)|
|
||||
(ous_and_children_na|ous_and_children_arch <OrgUnitList>)
|
||||
```
|
||||
|
||||
When adding, deleting or synchronizing group members, the `notarchived|archived` option can be used to select
|
||||
users in a particular archived state. This option can be used with the following `<UserTypeEntity>`:
|
||||
```
|
||||
(all users)|
|
||||
(domains <DomainNameList>)|
|
||||
(group <GroupItem>)|
|
||||
(groups <GroupList>)|
|
||||
(group_users <GroupList>
|
||||
[members] [managers] [owners]
|
||||
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
|
||||
(ou <OrgUnitItem>)|
|
||||
(ou_and_children <OrgUnitItem>)|
|
||||
(ous <OrgUnitList>)|
|
||||
(ous_and_children <OrgUnitList>)
|
||||
```
|
||||
|
||||
### Select users based on suspension state
|
||||
When adding, deleting or synchronizing group members, to select only suspended or non-suspended users, use the following`<UserTypeEntity>`:
|
||||
```
|
||||
@@ -124,25 +156,6 @@ users in a particular suspension state. This option can be used with the followi
|
||||
(ous_and_children <OrgUnitList>)
|
||||
```
|
||||
|
||||
### Select users based on archived state
|
||||
When adding, deleting or synchronizing group members, the `notarchived|archived` option can be used to select
|
||||
users in a particular archived state. This option can be used with the following `<UserTypeEntity>`:
|
||||
```
|
||||
(all users|users_ns|users_susp|users_ns_susp)|
|
||||
(domains|domains_ns|domains_susp <DomainNameList>)|
|
||||
(group|group_ns|group_susp <GroupItem>)|
|
||||
(groups|groups_ns|groups_susp <GroupList>)|
|
||||
(group_users|group_users_ns|group_users_susp <GroupList>
|
||||
[members] [managers] [owners]
|
||||
[primarydomain] [domains <DomainNameList>] [recursive|includederivedmembership] end)|
|
||||
(ou|ou_ns|ou_susp <OrgUnitItem>)|
|
||||
(ou_and_children|ou_and_children_ns|ou_and_children_susp <OrgUnitItem>)|
|
||||
(ous|ous_ns|ous_susp <OrgUnitList>)|
|
||||
(ous_and_children|ous_and_children_ns|ous_and_children_susp <OrgUnitList>)|
|
||||
(query <QueryUser>)|
|
||||
(queries <QueryUserList>)
|
||||
```
|
||||
|
||||
## Add members to a group
|
||||
```
|
||||
gam update group|groups <GroupEntity> create|add [<GroupRole>]
|
||||
@@ -275,6 +288,11 @@ For `notarchived|archived`, see: [Select users based on archived state](#select-
|
||||
|
||||
The `notsuspended|suspended` and `notarchived|archived` not only control what users are selected from `<UserTypeEntity>`
|
||||
but they also control what users are selected from `<GroupEntity>`.
|
||||
* `notsuspended` - Select only non-suspended members
|
||||
* `suspended` - Select only suspended members
|
||||
* `notarchived` - Select only non-archived members
|
||||
* `archived` - Select only archived users
|
||||
* `notsuspended notarchived` - Select non-suspended and non-archived members
|
||||
|
||||
The `remove_domain_nostatus_members` option is used to remove members from the group that are in your domain but have no status.
|
||||
These members were added to the group before the user or group that they represent was created.
|
||||
@@ -373,10 +391,7 @@ By default, when clearing members from a group, all members, whether suspended/a
|
||||
* `suspended` - Clear only suspended members
|
||||
* `notarchived` - Clear only non-archived members
|
||||
* `archived` - Clear only archived users
|
||||
* `notsuspended notarchived` - Do not clear suspended and archived members
|
||||
* `suspended archived` - Clear suspended and archived members
|
||||
* `notsuspended archived` - Do not clear archived members
|
||||
* `suspended notarchived` - Do not clear suspended members
|
||||
* `notsuspended notarchived` - Clear non-suspended and non-archived members
|
||||
|
||||
Members that have met the above qualifications to be cleared can be further qualifed by their email address.
|
||||
* `emailclearpattern <REMatchPattern>` - Members with email addresses that match `<REMatchPattern>` will be cleared; others will be retained
|
||||
@@ -417,19 +432,12 @@ When `<UserTypeEntity>` specifies a group or groups:
|
||||
* `usersonly` - Only the user members from the specified groups are added
|
||||
* `groupsonly` - Only the group members from the specified groups are added
|
||||
|
||||
By default, when updating members from organization units, all users, whether suspended or not, are included.
|
||||
* `notsuspended` - Do not include suspended users
|
||||
* `suspended` - Only include suspended users
|
||||
|
||||
By default, when updating members from groups, all users, whether suspended/archived or not, are included.
|
||||
* `notsuspended` - Do not include suspended users
|
||||
* `suspended` - Only include suspended users
|
||||
* `notarchived` - Do not include archived users
|
||||
* `archived` - Only include archived users
|
||||
* `notsuspended notarchived` - Do not include suspended and archived users
|
||||
* `suspended archived` - Include only suspended or archived users
|
||||
* `notsuspended archived` - Only include archived users
|
||||
* `suspended notarchived` - Only include suspended users
|
||||
By default, when updating members from groups/organization units, all users, whether suspended/archived or not, are included.
|
||||
* `notsuspended` - Update only non-suspended members
|
||||
* `suspended` - Update only suspended members
|
||||
* `notarchived` - Update only non-archived members
|
||||
* `archived` - Update only archived users
|
||||
* `notsuspended notarchived` - Update non-suspended and non-archived members
|
||||
|
||||
You can set the `delivery` option for the updated members:
|
||||
* `allmail` - All messages, delivered as soon as they arrive
|
||||
|
||||
@@ -252,7 +252,7 @@ writes the credentials into the file oauth2.txt.
|
||||
admin@server:/Users/admin$ rm -f /Users/admin/GAMConfig/oauth2.txt
|
||||
admin@server:/Users/admin$ gam version
|
||||
WARNING: Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: /Users/admin/GAMConfig/oauth2.txt, Not Found
|
||||
GAM 7.21.01 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM 7.22.04 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM Team <google-apps-manager@googlegroups.com>
|
||||
Python 3.13.7 64-bit final
|
||||
MacOS Sequoia 15.6.1 x86_64
|
||||
@@ -990,7 +990,7 @@ writes the credentials into the file oauth2.txt.
|
||||
C:\>del C:\GAMConfig\oauth2.txt
|
||||
C:\>gam version
|
||||
WARNING: Config File: C:\GAMConfig\gam.cfg, Section: DEFAULT, Item: oauth2_txt, Value: C:\GAMConfig\oauth2.txt, Not Found
|
||||
GAM 7.21.01 - https://github.com/GAM-team/GAM - pythonsource
|
||||
GAM 7.22.00 - https://github.com/GAM-team/GAM - pythonsource
|
||||
GAM Team <google-apps-manager@googlegroups.com>
|
||||
Python 3.13.7 64-bit final
|
||||
Windows-10-10.0.17134 AMD64
|
||||
|
||||
@@ -187,11 +187,15 @@ given if invalid CrOS deviceIds are specified.
|
||||
## Display organizational units
|
||||
These commands display information as an indented list of keys and values.
|
||||
```
|
||||
gam info org|ou <OrgUnitPath> [nousers|notsuspended|suspended] [children|child]
|
||||
gam info orgs|ous <OrgUnitEntity> [nousers|notsuspended|suspended] [children|child]
|
||||
gam info org|ou <OrgUnitPath> [nousers|notarchived|archived|notsuspended|suspended] [children|child]
|
||||
[nousers | ([notarchived|archived] [notsuspended|suspended])] [children|child]
|
||||
gam info orgs|ous <OrgUnitEntity> [nousers|notarchived|archived|notsuspended|suspended] [children|child]
|
||||
[nousers | ([notarchived|archived] [notsuspended|suspended])] [children|child]
|
||||
```
|
||||
By default, all users of the org units are displayed:
|
||||
* `nousers` - Don't display users of the org units
|
||||
* `notarchived` - Display non-archived users of the org units
|
||||
* `archived` - Display archived users of the org units
|
||||
* `notsuspended` - Display non-suspended users of the org units
|
||||
* `suspended` - Display suspended users of the org units
|
||||
* `children|child` - Display users in any child org unit
|
||||
@@ -214,7 +218,7 @@ By default, Gam prints all child org units of /.
|
||||
* `convertcrnl` - In the description field, convert carriage return to \r and new line to \n.
|
||||
|
||||
Options `parentselector <OrgUnitSelector>` and `childselector <OrgUnitSelector>` add an additional column `orgUnitSelector` to the output.
|
||||
This column value can be used in subsequent `gam csv` commands to appropriateley select members without duplication.
|
||||
This column value can be used in subsequent `gam csv` commands to appropriately select members without duplication.
|
||||
|
||||
By default, all OUs are displayed. You can limit the display of OUs to those where the number
|
||||
of ChromeOS devices/users falls within a range. Gathering this data requires additional API calls
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
## Introduction
|
||||
GAM7 can run on a Linux or Windows [Google Compute Engine (GCE)](https://cloud.google.com/products/compute) virtual machine and use the attached service account to access Google Workspace APIs. The advantage of this configuration is that no service account private key is accessible to GAM7 directly and [there is no risk of the key being stolen/lost](https://cloud.google.com/iam/docs/best-practices-for-managing-service-account-keys#alternatives).
|
||||
|
||||
**Note**: This method is recommended when running GAM **inside** Google Cloud. If you're running GAM **outside** Google Cloud (on-premises, other cloud providers, CI/CD systems), consider [Workload Identity Federation](https://github.com/GAM-team/GAM/wiki/Using-GAM7-with-keyless-authentication-Workload-Identity-Federation) instead - Google's officially recommended keyless authentication method for external environments.
|
||||
|
||||
## Setup Steps
|
||||
1. Create a [GCP project](https://cloud.google.com/resource-manager/docs/creating-managing-projects).
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ You can modify the default todrive behavior with options in `gam.cfg` or on the
|
||||
|
||||
## Definitions
|
||||
```
|
||||
<DateTimeFormat> ::= <String>
|
||||
See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
|
||||
<DriveFileID> ::= <String>
|
||||
<DriveFolderID> ::= <String>
|
||||
<TimeZone> ::= <String>
|
||||
@@ -194,11 +196,11 @@ direct the uploaded file to a particular user and location and add a timestamp t
|
||||
(tdreturnidonly [<Boolean>])|
|
||||
(tdshare <EmailAddress> commenter|reader|writer)*|
|
||||
(tdsheet (id:<Number>)|<String>)|
|
||||
(tdsheettimestamp [<Boolean>] [tdsheettimeformat <String>])
|
||||
(tdsheettimestamp [<Boolean>] [tdsheettimeformat <DateTimeFormat>])
|
||||
(tdsheettitle <String>)|
|
||||
(tdsubject <String>)|
|
||||
([tdsheetdaysoffset <Number>] [tdsheethoursoffset <Number>])|
|
||||
(tdtimestamp [<Boolean>] [tdtimeformat <String>]
|
||||
(tdtimestamp [<Boolean>] [tdtimeformat <DateTimeFormat>]
|
||||
([tddaysoffset <Number>] [tdhoursoffset <Number>])|
|
||||
(tdtimezone <TimeZone>)|
|
||||
(tdtitle <String>)|
|
||||
|
||||
@@ -570,17 +570,12 @@ gam config auto_batch_min 1 csv_output_row_filter "owners.0.emailAddress:notrege
|
||||
### Multiple parents
|
||||
No existing parents are copied for source top/sub files/folders.
|
||||
|
||||
### Removed options
|
||||
The following options will generate an error; they were removed in 6.23.00:
|
||||
* `copysubfileparents` and `copysubfolderparents`.
|
||||
|
||||
### Move Folder Permissions
|
||||
When a folder is moved by recreating it, its permissions are not copied; these options control copying permissions for folders.
|
||||
When a folder is moved by recreating it, its permissions are not copied by the Drive API; these options control copying permissions for folders.
|
||||
|
||||
For options of the form `option [<Boolean>]`; if `<Boolean>` is omitted, `true` is assumed.
|
||||
|
||||
When recreated, a target folder inherits the permissions of its parent folder; these options control whether/how GAM copies the existing source folder permissions;
|
||||
The default values of options introduced in version 6.14.00 are set to match the behavior of earlier versions.
|
||||
|
||||
When `mergewithparent` is `true`:
|
||||
* `copymergewithparentfolderpermissions false` - The permissions of the source top folder are not not copied to the target folder; this is the default action.
|
||||
@@ -594,7 +589,7 @@ When `duplicatefolders` is `merge` and a sub folder is a duplicate:
|
||||
* `copymergedsubfolderpermissions false` - The permissions of the source sub folder are not not copied to the target folder.
|
||||
* `copymergedsubfolderpermissions true` - The permissions of the source sub folder are copied to the target folder; this is the default action.
|
||||
|
||||
When `duplicatefolders` is `duplicatename` or `uniquename` and a top/sub folder is not a duplicate:
|
||||
When `duplicatefolders` is `merge` or `duplicatename` or `uniquename` and a top/sub folder is not a duplicate:
|
||||
* `copytopfolderpermissions true` - The permissions of the source top folder are copied to the target folder; this is the default action.
|
||||
* `copytopfolderpermissions false` - The permissions of the source top folder are not not copied to the target folder.
|
||||
* `copysubfolderpermissions true` - The permissions of the source sub folders are copied to the target folder; this is the default action.
|
||||
|
||||
@@ -68,6 +68,8 @@
|
||||
<ColorValue> ::= <ColorName>|<ColorHex>
|
||||
```
|
||||
```
|
||||
<DateTimeFormat> ::= <String>
|
||||
See: https://docs.python.org/3/library/datetime.html#strftime-and-strptime-format-codes
|
||||
<DomainName> ::= <String>(.<String>)+
|
||||
<EmailAddress> ::= <String>@<DomainName>
|
||||
<DriveFileRevisionID> ::= <String>
|
||||
@@ -178,7 +180,7 @@ gam <UserTypeEntity> create|add drivefile
|
||||
[(localfile <FileName>|-)|(url <URL>)]
|
||||
[(drivefilename|newfilename <DriveFileName>) | (replacefilename <REMatchPattern> <RESubstitution>)*]
|
||||
[stripnameprefix <String>] [noduplicate]
|
||||
[timestamp [<Boolean>]] [timeformat <String>]
|
||||
[timestamp [<Boolean>]] [timeformat <DateTimeFormat>]
|
||||
<DriveFileCreateAttribute>*
|
||||
[(csv [todrive <ToDriveAttribute>*] (addcsvdata <FieldName> <String>)*) |
|
||||
(returnidonly|returnlinkonly|returneditlinkonly|showdetails)]
|
||||
@@ -478,7 +480,7 @@ gam <UserTypeEntity> update drivefile <DriveFileEntity> [copy] [returnidonly|ret
|
||||
[(localfile <FileName>|-)|(url <URL>)]
|
||||
[retainname | (newfilename <DriveFileName>) | (replacefilename <REMatchPattern> <RESubstitution>)*]
|
||||
[stripnameprefix <String>]
|
||||
[timestamp [<Boolean>]] [timeformat <String>]
|
||||
[timestamp [<Boolean>]] [timeformat <DateTimeFormat>]
|
||||
<DriveFileUpdateAttribute>*
|
||||
[(gsheet|csvsheet <SheetEntity> [clearfilter])|(addsheet <String>)]
|
||||
[charset <Charset>] [columndelimiter <Character>]
|
||||
|
||||
@@ -10,12 +10,16 @@
|
||||
- [Delete all ACLs except owner from a user's My Drive](#delete-all-acls-except-owner-from-a-users-my-drive)
|
||||
- [Change shares to User1 to shares to User2](#change-shares-to-user1-to-shares-to-user2)
|
||||
- [Map All ACLs from an old domain to a new domain](#map-all-acls-from-an-old-domain-to-a-new-domain)
|
||||
- [Remove all ACLs for a specific user or group email address](#remove-all-ACLs-for-a-specific-user-or-group-email-address)
|
||||
- [Remove anyone-anyoneWithLink ACLs](#remove-anyone-anyonewithlink-acls)
|
||||
- [Remove ACLs for a specific user or group email address](#remove-ACLs-for-a-specific-user-or-group-email-address)
|
||||
- [Remove ACLs for all users-groups in external domains](#remove-acls-for-all-users-groups-in-external-domains)
|
||||
- [Remove domainCanFind-domainWithLink ACLs for internal domain](#remove-domaincanfind-domainwithlink-acls-for-internal-domain)
|
||||
- [Remove My Drive ACLs for external domains](#remove-my-drive-acls-for-external-domains)
|
||||
- [Remove anyoneCanFind-anyoneWithLink ACLs](#remove-anyonecanfind-anyonewithlink-acls)
|
||||
|
||||
## API documentation
|
||||
* [Drive API - Permissions](https://developers.google.com/drive/api/v3/reference/permissions)
|
||||
* [Shortcuts](https://developers.google.com/drive/api/guides/shortcuts)
|
||||
* [Roles and permissions](https://developers.google.com/workspace/drive/api/guides/ref-roles)
|
||||
* [Limited and Expansive Access](https://developers.google.com/workspace/drive/api/guides/limited-expansive-access)
|
||||
|
||||
## Definitions
|
||||
@@ -407,7 +411,7 @@ gam config csv_input_row_filter "permission.type:regex:user|group" redirect stdo
|
||||
gam config csv_input_row_filter "permission.type:regex:domain" redirect stdout ./AddNewDomainACLsDomainShares.txt multiprocess redirect stderr stdout csv ./allUsersFiles.csv gam user "~Owner" create drivefileacl "~id" "~permission.type" "~permission.domain" role "~permission.role" allowfilediscovery "~permission.allowFileDiscovery" mappermissionsdomain olddomain.com newdomain.com
|
||||
```
|
||||
|
||||
## Remove all ACLs for a specific user or group email address
|
||||
## Remove ACLs for a specific user or group email address
|
||||
|
||||
### My Drives
|
||||
|
||||
@@ -420,12 +424,12 @@ gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv mult
|
||||
|
||||
Delete those My Drive ACLs.
|
||||
```
|
||||
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
|
||||
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
|
||||
```
|
||||
|
||||
Add My Drive ACLs with a different email address and the same role.
|
||||
```
|
||||
gam config num_threads 20 redirect stdout ./AddMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" add drivefleacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
|
||||
gam config num_threads 20 redirect stdout ./AddMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" add drivefileacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
|
||||
```
|
||||
|
||||
### Shared Drives
|
||||
@@ -443,31 +447,44 @@ gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect
|
||||
|
||||
Delete those Shared Drive ACLs.
|
||||
```
|
||||
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
|
||||
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
|
||||
```
|
||||
|
||||
Add Shared Drive ACLs with a different email address and the same role.
|
||||
```
|
||||
gam config num_threads 20 redirect stdout ./ReplaceSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" add drivefleacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
|
||||
gam config num_threads 20 redirect stdout ./ReplaceSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" add drivefileacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
|
||||
```
|
||||
|
||||
## Remove anyone-anyoneWithLink ACLs
|
||||
|
||||
Here are the queries that will be used in these commands:
|
||||
* anyone - query "visibility='anyoneCanFind'"
|
||||
* anyoneWithLink - query "visibility='anyoneWithLink'"
|
||||
* both - query "(visibility='anyoneCanFind' or visibility='anyoneWithLink')"
|
||||
## Remove ACLs for all users-groups in external domains
|
||||
|
||||
### My Drives
|
||||
|
||||
Get My Drive anyone/anyoneWithLink ACLs
|
||||
Get My Drive ACLs sharing to external domain users/groups.
|
||||
|
||||
Replace `<Types>` as required:
|
||||
* `type user` - External domain users
|
||||
* `type group` - External domain groups
|
||||
* `typelist user,group` - External domain users and groups
|
||||
|
||||
Replace `<Domains>` with specification of external domain(s)
|
||||
* `domain domain.com` - A single external domain
|
||||
* `domainlist domain1.com,domain2.com,domain3.com...` - A list of external domains
|
||||
|
||||
If you want domains other than your internal domain(s)
|
||||
* `notdomain domain.com` - A single internal domain
|
||||
* `notdomainlist domain1.com,domain2.com,domain3.com...` - A list of internal domains
|
||||
```
|
||||
gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv multiprocess redirect stderr - multiprocess all users print filelist fields id,name,mimetype,basicpermissions <Query> pm type anyone em pmfilter oneitemperrow
|
||||
gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv multiprocess redirect stderr - multiprocess all users print filelist fields id,name,mimetype,basicpermissions pm notrole owner <Types> <Domains> em pmfilter oneitemperrow
|
||||
```
|
||||
|
||||
Delete those My Drive ACLs.
|
||||
```
|
||||
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
|
||||
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
|
||||
```
|
||||
|
||||
Add My Drive ACLs with a different email address and the same role.
|
||||
```
|
||||
gam config num_threads 20 redirect stdout ./AddMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" add drivefileacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
|
||||
```
|
||||
|
||||
### Shared Drives
|
||||
@@ -476,14 +493,123 @@ Get an organizer for each Shared Drive
|
||||
gam redirect csv ./SharedDriveOrganizers.csv print shareddriveorganizers
|
||||
```
|
||||
|
||||
Get Shared Drive anyone/anyoneWithLink ACLs
|
||||
Get Shared Drive ACLs sharing to external domain users/groups.
|
||||
|
||||
Replace `<Types>` as required:
|
||||
* `type user` - External domain users
|
||||
* `type group` - External domain groups
|
||||
* `typelist user,group` - External domain users and groups
|
||||
|
||||
Replace `<Domains>` with specification of external domain(s)
|
||||
* `domain domain.com` - A single external domain
|
||||
* `domainlist domain1.com,domain2.com,domain3.com...` - A list of external domains
|
||||
|
||||
If you want domains other than your internal domain(s)
|
||||
* `notdomain domain.com` - A single internal domain
|
||||
* `notdomainlist domain1.com,domain2.com,domain3.com...` - A list of internal domains
|
||||
```
|
||||
gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect csv ./SharedDriveShares.csv multiprocess redirect stderr - multiprocess csv SharedDriveOrganizers.csv gam user "~organizers" print filelist select shareddriveid "~id" fields id,name,mimetype,basicpermissions,driveid showdrivename pm <Types> <Domains> inherited false em pmfilter oneitemperrow
|
||||
```
|
||||
|
||||
Delete those Shared Drive ACLs.
|
||||
```
|
||||
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
|
||||
```
|
||||
|
||||
Add Shared Drive ACLs with a different email address and the same role.
|
||||
```
|
||||
gam config num_threads 20 redirect stdout ./ReplaceSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" add drivefileacl "~id" "~permission.type" newemail@domain.rom role "~permission.role"
|
||||
```
|
||||
|
||||
## Remove domainCanFind-domainWithLink ACLs for internal domain
|
||||
|
||||
Replace `<Query>` below with one of these; they only apply to your internal domain:
|
||||
* domainCanFind - query "visibility='domainCanFind'"
|
||||
* domainWithLink - query "visibility='domainWithLink'"
|
||||
* both - query "(visibility='domainCanFind' or visibility='domainWithLink')"
|
||||
|
||||
### My Drives
|
||||
|
||||
Get My Drive domainCanFind/domainWithLink ACLs for internal domain
|
||||
```
|
||||
gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv multiprocess redirect stderr - multiprocess all users print filelist fields id,name,mimetype,basicpermissions <Query> pm type domain em pmfilter oneitemperrow
|
||||
```
|
||||
|
||||
Delete those My Drive ACLs.
|
||||
```
|
||||
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
|
||||
```
|
||||
|
||||
### Shared Drives
|
||||
Get an organizer for each Shared Drive
|
||||
```
|
||||
gam redirect csv ./SharedDriveOrganizers.csv print shareddriveorganizers
|
||||
```
|
||||
|
||||
Get Shared Drive ACLs domainCanFind/domainWithLink ACLs for internal domain
|
||||
* Replace `<Domain>` with actual domain name
|
||||
```
|
||||
gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect csv ./SharedDriveShares.csv multiprocess redirect stderr - multiprocess csv SharedDriveOrganizers.csv gam user "~organizers" print filelist select shareddriveid "~id" fields id,name,mimetype,basicpermissions,driveid showdrivename <Query> pm type domain inherited false em pmfilter oneitemperrow
|
||||
```
|
||||
|
||||
Delete those Shared Drive ACLs.
|
||||
```
|
||||
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
|
||||
```
|
||||
|
||||
## Remove My Drive ACLs for external domains
|
||||
|
||||
### My Drives
|
||||
|
||||
Get My Drive ACLs sharing to external domain(s)
|
||||
|
||||
Replace `<Domains>` with specification of external domain(s)
|
||||
* `domain domain.com` - A single external domain
|
||||
* `domainlist domain1.com,domain2.com,domain3.com...` - A list of external domains
|
||||
|
||||
If you want domains other than your internal domain(s)
|
||||
* `notdomain domain.com` - A single internal domain
|
||||
* `notdomainlist domain1.com,domain2.com,domain3.com...` - A list of internal domains
|
||||
```
|
||||
gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv multiprocess redirect stderr - multiprocess all users print filelist fields id,name,mimetype,basicpermissions pm type domain <Domains> em pmfilter oneitemperrow
|
||||
```
|
||||
|
||||
Delete those My Drive ACLs.
|
||||
```
|
||||
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
|
||||
```
|
||||
|
||||
## Remove anyoneCanFind-anyoneWithLink ACLs
|
||||
|
||||
Replace `<Query>` below with one of these:
|
||||
* anyoneCanFind - query "visibility='anyoneCanFind'"
|
||||
* anyoneWithLink - query "visibility='anyoneWithLink'"
|
||||
* both - query "(visibility='anyoneCanFind' or visibility='anyoneWithLink')"
|
||||
|
||||
### My Drives
|
||||
|
||||
Get My Drive anyoneCanFind/anyoneWithLink ACLs
|
||||
```
|
||||
gam config auto_batch_min 1 num_threads 20 redirect csv ./MyDriveShares.csv multiprocess redirect stderr - multiprocess all users print filelist fields id,name,mimetype,basicpermissions <Query> pm type anyone em pmfilter oneitemperrow
|
||||
```
|
||||
|
||||
Delete those My Drive ACLs.
|
||||
```
|
||||
gam config num_threads 20 redirect stdout ./DeleteMyDriveShares.txt multiprocess redirect stderr stdout csv MyDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
|
||||
```
|
||||
|
||||
### Shared Drives
|
||||
Get an organizer for each Shared Drive
|
||||
```
|
||||
gam redirect csv ./SharedDriveOrganizers.csv print shareddriveorganizers
|
||||
```
|
||||
|
||||
Get Shared Drive anyoneCanFind/anyoneWithLink ACLs
|
||||
```
|
||||
gam config num_threads 20 csv_input_row_filter "organizers:regex:^.+$" redirect csv ./SharedDriveShares.csv multiprocess redirect stderr - multiprocess csv SharedDriveOrganizers.csv gam user "~organizers" print filelist select shareddriveid "~id" fields id,name,mimetype,basicpermissions,driveid showdrivename <Query> pm type anyone inherited false em pmfilter oneitemperrow
|
||||
```
|
||||
|
||||
Delete those Shared Drive ACLs.
|
||||
```
|
||||
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefleacl "~id" "id:~~permission.id~~"
|
||||
gam config num_threads 20 redirect stdout ./DeleteSharedDriveShares.txt multiprocess redirect stderr stdout csv SharedDriveShares.csv gam user "~Owner" delete drivefileacl "~id" "id:~~permission.id~~"
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
## API documentation
|
||||
* [Gmail API - Labels](https://developers.google.com/gmail/api/v1/reference/users.labels)
|
||||
* [Gmail Labels](https://developers.google.com/workspace/gmail/api/guides/labels)
|
||||
|
||||
## Definitions
|
||||
* [`<UserTypeEntity>`](Collections-of-Users)
|
||||
|
||||
@@ -401,9 +401,10 @@ password "helloworld" nohash
|
||||
```
|
||||
|
||||
## Password Notification
|
||||
When creating a user or updating a user's password, you can send a message with details to an email address; this might be the user's secondary email address.
|
||||
When creating a user or updating a user's password, you can send a message with details to an email address;'
|
||||
this might be the user's secondary email address or their recovery email address.
|
||||
```
|
||||
[notify <EmailAddressList>
|
||||
[[notify <EmailAddressList>] [notifyrecoveryemail]
|
||||
[subject <String>]
|
||||
[notifypassword <String>]
|
||||
[from <EmailAaddress>]
|
||||
@@ -416,6 +417,7 @@ When creating a user or updating a user's password, you can send a message with
|
||||
[notifyonupdate [<Boolean>]]
|
||||
```
|
||||
* `notify <EmailAddressList>` - Specify recipients
|
||||
* `notifyrecoveryemail` - Use the user's recovery email address (if defined) as a recipient
|
||||
|
||||
If subject is not specified, the following value will be used:
|
||||
* create - `Welcome to #domain#`
|
||||
@@ -653,7 +655,7 @@ gam update user <UserItem> [ignorenullpassword] <UserAttribute>*
|
||||
[createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]
|
||||
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
|
||||
[alias|aliases <EmailAddressList>]
|
||||
[notify <EmailAddressList>
|
||||
[[notify <EmailAddressList>] [notifyrecoveryemail]
|
||||
[subject <String>]
|
||||
[notifypassword <String>]
|
||||
[from <EmailAaddress>]
|
||||
@@ -675,7 +677,7 @@ gam update users <UserTypeEntity> [ignorenullpassword] <UserAttribute>*
|
||||
[createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]
|
||||
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
|
||||
[alias|aliases <EmailAddressList>]
|
||||
[notify <EmailAddressList>
|
||||
[[notify <EmailAddressList>] [notifyrecoveryemail]
|
||||
[subject <String>]
|
||||
[notifypassword <String>]
|
||||
[from <EmailAddress>]
|
||||
@@ -697,7 +699,7 @@ gam <UserTypeEntity> update users [ignorenullpassword] <UserAttribute>*
|
||||
[createifnotfound] [notfoundpassword (random [<Integer>])|blocklogin|<Password>]
|
||||
(groups [<GroupRole>] [[delivery] <DeliverySetting>] <GroupEntity>)*
|
||||
[alias|aliases <EmailAddressList>]
|
||||
[notify <EmailAddressList>
|
||||
[[notify <EmailAddressList>] [notifyrecoveryemail]
|
||||
[subject <String>]
|
||||
[notifypassword <String>]
|
||||
[from <EmailAaddress>]
|
||||
@@ -1057,7 +1059,7 @@ gam print users [todrive <ToDriveAttribute>*]
|
||||
[userview] [allfields|basic|full|(<UserFieldName>*|fields <UserFieldNameList>)]
|
||||
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
|
||||
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
|
||||
[issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
||||
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
||||
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
|
||||
```
|
||||
|
||||
@@ -1068,6 +1070,7 @@ By default, users in all domains in the account are selected; these options allo
|
||||
* `limittoou <OrgUnitPath>|<OrgUnitID>` - Limit users to those in the specified `<OrgUnitItem>>`
|
||||
* `deleted_only|only_deleted` - Only display deleted users
|
||||
* `issuspended <Boolean>` - Limit users based on their status
|
||||
* `isarchived <Boolean>` - Limit users based on their status
|
||||
|
||||
### Print a header row and fields for users specified by `<UserTypeEntity>`
|
||||
```
|
||||
@@ -1082,7 +1085,7 @@ gam print users [todrive <ToDriveAttribute>*] select <UserTypeEntity>
|
||||
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
|
||||
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
|
||||
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
|
||||
[issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
||||
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
||||
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
|
||||
|
||||
gam <UserTypeEntity> print users [todrive <ToDriveAttribute>*]
|
||||
@@ -1096,7 +1099,7 @@ gam <UserTypeEntity> print users [todrive <ToDriveAttribute>*]
|
||||
[userview] [basic|full|allfields|(<UserFieldName>*|fields <UserFieldNameList>)]
|
||||
[delimiter <Character>] [sortheaders [<Boolean>]] [scalarsfirst [<Boolean>]]
|
||||
[formatjson [quotechar <Character>]] [quoteplusphonenumbers]
|
||||
[issuspended <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
||||
[issuspended <Boolean>] [isarchived <Boolean>] [aliasmatchpattern <REMatchPattern>]
|
||||
[showvalidcolumn] (addcsvdata <FieldName> <String>)*
|
||||
```
|
||||
|
||||
@@ -1187,7 +1190,7 @@ gam print users countonly [todrive <ToDriveAttribute>*]
|
||||
([domain|domains <DomainNameEntity>] [(query <QueryUser>)|(queries <QueryUserList>)]
|
||||
[limittoou <OrgUnitItem>] [deleted_only|only_deleted])
|
||||
[formatjson [quotechar <Character>]]
|
||||
[issuspended <Boolean>]
|
||||
[issuspended <Boolean>] [isarchived <Boolean>]
|
||||
```
|
||||
By default, users in all domains in the account are selected; these options allow selection of subsets of users:
|
||||
* `domain|domains <DomainNameEntity>` - Limit users to those in the domains specified by `<DomainNameEntity>`
|
||||
@@ -1196,6 +1199,7 @@ By default, users in all domains in the account are selected; these options allo
|
||||
* `limittoou <OrgUnitPath>|<OrgUnitID>` - Limit users to those in the specified `<OrgUnitItem>>`
|
||||
* `deleted_only|only_deleted` - Only display deleted users
|
||||
* `issuspended <Boolean>` - Limit users based on their status
|
||||
* `isarchived <Boolean>` - Limit users based on their status
|
||||
|
||||
### Print domain counts for users specified by `<UserTypeEntity>`
|
||||
```
|
||||
@@ -1323,7 +1327,7 @@ gam print users select <UserTypeEntity> showitemcountonly
|
||||
gam print users
|
||||
([domain|domains <DomainNameEntity>] [(query <QueryUser>)|(queries <QueryUserList>)]
|
||||
[limittoou <OrgUnitItem>] [deleted_only|only_deleted])|[select <UserTypeEntity>]
|
||||
[issuspended <Boolean>]
|
||||
[issuspended <Boolean>] [isarchived <Boolean>]
|
||||
showitemcountonly
|
||||
```
|
||||
Example
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
- [FAQs](#faqs)
|
||||
- [Setup Steps](#setup-steps)
|
||||
|
||||
**Alternative Approach**: For enhanced security and simplified operations when running GAM outside Google Cloud, consider [Workload Identity Federation](https://github.com/GAM-team/GAM/wiki/Using-GAM7-with-keyless-authentication-Workload-Identity-Federation) - Google's recommended keyless authentication method that eliminates the need for managing any long-lived credentials. If running GAM in Google Cloud, use [attached service accounts on GCE](https://github.com/GAM-team/GAM/wiki/Running-GAM7-securely-on-a-Google-Compute-Engine) instead.
|
||||
|
||||
## Thanks
|
||||
|
||||
Thanks to Jay Lee for the original version of this document.
|
||||
@@ -69,4 +71,4 @@ gam user admin@example.com check serviceaccount
|
||||
```
|
||||
and see the YubiKey lights flash as the YubiKey interacts with GAM7 to sign the GAM7 authentication requests. If you look at the oauth2service.json file, you'll see it contains some new fields like yubikey_serial and yubikey_pin but no longer contains the private_key field where GAM7 would normally store the private key data.
|
||||
|
||||
7. As a last step, since YubiKey-stored private keys do not need to be and should not be rotated, you can remove the service account's permissions to change it's own key. Navigate to the [Cloud Console](https://console.cloud.google.com/iam-admin/serviceaccounts) select the correct project and service account and on the Permissions tab, edit and remove the "Service Account Key Admin" permission that the service account has to itself.
|
||||
7. As a last step, since YubiKey-stored private keys do not need to be and should not be rotated, you can remove the service account's permissions to change it's own key. Navigate to the [Cloud Console](https://console.cloud.google.com/iam-admin/serviceaccounts) select the correct project and service account and on the Permissions tab, edit and remove the "Service Account Key Admin" permission that the service account has to itself.
|
||||
|
||||
@@ -0,0 +1,290 @@
|
||||
# Using GAM7 with Keyless Authentication - Workload Identity Federation
|
||||
|
||||
**Important**: This method is designed for running GAM7 **outside** of Google Cloud (on-premises, other cloud providers, CI/CD systems). If you're running GAM7 **inside** Google Cloud, use [attached service accounts on Google Compute Engine](Running-GAM7-securely-on-a-Google-Compute-Engine) instead, which provides the same keyless benefits with simpler configuration.
|
||||
|
||||
This guide explains how to configure GAM7 to use Google Cloud's Workload Identity Federation for keyless authentication. **This is Google's officially recommended authentication method** for enhanced security and simplified credential management.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Prerequisites](#prerequisites)
|
||||
- [Setup Steps](#setup-steps)
|
||||
- [1. Enable Required APIs](#1-enable-required-apis)
|
||||
- [2. Create Workload Identity Pool](#2-create-workload-identity-pool)
|
||||
- [3. Create or Use Existing Service Account](#3-create-or-use-existing-service-account)
|
||||
- [4. Grant Required Permissions](#4-grant-required-permissions)
|
||||
- [AWS Configuration](#aws-configuration)
|
||||
- [1. Create Workload Identity Provider for AWS](#1-create-workload-identity-provider-for-aws)
|
||||
- [2. Allow AWS Identity to Impersonate Service Account](#2-allow-aws-identity-to-impersonate-service-account)
|
||||
- [3. Create Credential Configuration File](#3-create-credential-configuration-file)
|
||||
- [4. Configure GAM7 Environment for AWS](#4-configure-gam7-environment-for-aws)
|
||||
- [5. Initialize GAM7](#5-initialize-gam7)
|
||||
- [GitHub Actions Configuration](#github-actions-configuration)
|
||||
- [1. Create Workload Identity Provider for GitHub Actions](#1-create-workload-identity-provider-for-github-actions)
|
||||
- [2. Allow GitHub Actions to Impersonate Service Account](#2-allow-github-actions-to-impersonate-service-account)
|
||||
- [3. GitHub Actions Workflow Configuration](#3-github-actions-workflow-configuration)
|
||||
- [Clean Up](#clean-up)
|
||||
- [Security Best Practices](#security-best-practices)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [Benefits](#benefits)
|
||||
- [References](#references)
|
||||
|
||||
## Overview
|
||||
|
||||
Workload Identity Federation allows GAM7 to authenticate to Google Cloud services without storing long-lived service account keys. Instead, it uses short-lived tokens from external identity providers like AWS, Azure, or GitHub Actions, eliminating the security risks associated with managing static credentials.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- GAM7 [installed and configured](https://github.com/GAM-team/GAM/wiki/How-to-Install-GAM7)
|
||||
- Run `gam config` to generate the `gam.cfg` file
|
||||
- Run `gam create/use project` to generate the `oauth2service.json` file
|
||||
- Optionally enable [DASA](https://github.com/GAM-team/GAM/wiki/Using-GAM7-with-a-delegated-admin-service-account) `gam config enable_dasa true admin_email admin@domain.com customer_id domain domain.com save`
|
||||
- Google Cloud CLI (gcloud) installed and configured
|
||||
- [Install gcloud CLI](https://cloud.google.com/sdk/docs/install)
|
||||
- Run `gcloud auth login` to authenticate
|
||||
- Run `gcloud config set project PROJECT_ID` to set your project
|
||||
- **Alternative**: Use the [Google Cloud Console](https://console.cloud.google.com) web interface to perform the same operations
|
||||
- Google Cloud project with appropriate APIs enabled
|
||||
- External identity provider (AWS, Azure, GitHub Actions, etc.)
|
||||
- Appropriate permissions to create Workload Identity Pools and manage IAM
|
||||
|
||||
## Setup Steps
|
||||
|
||||
### 1. Enable Required APIs
|
||||
|
||||
```bash
|
||||
gcloud services enable iamcredentials.googleapis.com
|
||||
gcloud services enable sts.googleapis.com
|
||||
```
|
||||
|
||||
### 2. Create Workload Identity Pool
|
||||
|
||||
```bash
|
||||
gcloud iam workload-identity-pools create POOL_ID \
|
||||
--location="global" \
|
||||
--description="Pool for GAM authentication"
|
||||
```
|
||||
|
||||
### 3. Create or Use Existing Service Account
|
||||
|
||||
You can either create a new service account or reuse an existing one that has the necessary permissions.
|
||||
|
||||
#### Option A: Create New Service Account
|
||||
```bash
|
||||
gcloud iam service-accounts create SERVICE_ACCOUNT_ID \
|
||||
--description="Service account for GAM operations" \
|
||||
--display-name="GAM Service Account"
|
||||
```
|
||||
|
||||
#### Option B: Use Existing Service Account
|
||||
If you already have a service account with appropriate Google Workspace permissions (typically the one created during GAM7 initial setup), you can reuse it. Just note the service account email for the next steps.
|
||||
|
||||
```bash
|
||||
# List existing service accounts to find the one you want to use
|
||||
gcloud iam service-accounts list
|
||||
```
|
||||
|
||||
### 4. Grant Required Permissions
|
||||
|
||||
```bash
|
||||
# Grant necessary Google Workspace permissions
|
||||
gcloud projects add-iam-policy-binding PROJECT_ID \
|
||||
--member="serviceAccount:SERVICE_ACCOUNT_EMAIL" \
|
||||
--role="roles/iam.serviceAccountTokenCreator"
|
||||
```
|
||||
|
||||
## AWS Configuration
|
||||
|
||||
### 1. Create Workload Identity Provider for AWS
|
||||
```bash
|
||||
gcloud iam workload-identity-pools providers create-aws PROVIDER_ID \
|
||||
--workload-identity-pool="POOL_ID" \
|
||||
--account-id="YOUR_AWS_ACCOUNT_ID" \
|
||||
--location="global"
|
||||
```
|
||||
|
||||
### 2. Allow AWS Identity to Impersonate Service Account
|
||||
```bash
|
||||
gcloud iam service-accounts add-iam-policy-binding \
|
||||
SERVICE_ACCOUNT_EMAIL \
|
||||
--role="roles/iam.workloadIdentityUser" \
|
||||
--member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.aws_role/arn:aws:sts::YOUR_AWS_ACCOUNT:assumed-role/YOUR_ROLE_NAME"
|
||||
```
|
||||
|
||||
### 3. Create Credential Configuration File
|
||||
|
||||
Create a JSON file with your Workload Identity Federation configuration:
|
||||
|
||||
#### For AWS [IMDSv1](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html#instance-metadata-retrieval-examples-imdsv1)
|
||||
```bash
|
||||
gcloud iam workload-identity-pools create-cred-config \
|
||||
projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
|
||||
--service-account=SERVICE_ACCOUNT_EMAIL \
|
||||
--service-account-token-lifetime-seconds=SERVICE_ACCOUNT_TOKEN_LIFETIME \
|
||||
--aws \
|
||||
--output-file=FILEPATH.json
|
||||
```
|
||||
|
||||
#### For AWS [IMDSv2](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html#instance-metadata-retrieval-examples)
|
||||
```bash
|
||||
gcloud iam workload-identity-pools create-cred-config \
|
||||
projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID \
|
||||
--service-account=SERVICE_ACCOUNT_EMAIL \
|
||||
--aws \
|
||||
--enable-imdsv2 \
|
||||
--output-file=FILEPATH.json
|
||||
```
|
||||
|
||||
### 4. Configure GAM7 Environment for AWS
|
||||
|
||||
Set the environment variable to use the credential file:
|
||||
|
||||
```bash
|
||||
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/credential-configurations.json"
|
||||
```
|
||||
|
||||
Open the `oauth2service.json` file, and set the `key_type` to `signjwt`.
|
||||
|
||||
```
|
||||
...
|
||||
"key_type": "signjwt",
|
||||
...
|
||||
```
|
||||
|
||||
### 5. Initialize GAM7
|
||||
|
||||
```bash
|
||||
gam version
|
||||
gam info user
|
||||
```
|
||||
|
||||
## GitHub Actions Configuration
|
||||
|
||||
### 1. Create Workload Identity Provider for GitHub Actions
|
||||
```bash
|
||||
gcloud iam workload-identity-pools providers create-oidc PROVIDER_ID \
|
||||
--workload-identity-pool="POOL_ID" \
|
||||
--issuer-uri="https://token.actions.githubusercontent.com" \
|
||||
--attribute-mapping="google.subject=assertion.sub,attribute.repository=assertion.repository" \
|
||||
--attribute-condition="assertion.repository_owner=='YOUR_GITHUB_ORGANIZATION'"
|
||||
--location="global"
|
||||
```
|
||||
|
||||
### 2. Allow GitHub Actions to Impersonate Service Account
|
||||
```bash
|
||||
gcloud iam service-accounts add-iam-policy-binding \
|
||||
SERVICE_ACCOUNT_EMAIL \
|
||||
--role="roles/iam.workloadIdentityUser" \
|
||||
--member="principalSet://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/attribute.repository/YOUR_GITHUB_ORG/YOUR_REPO"
|
||||
```
|
||||
|
||||
### 3. GitHub Actions Workflow Configuration
|
||||
.github/workflows/example.yml
|
||||
```yaml
|
||||
name: GAM Operations
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
gam-job:
|
||||
runs-on: ubuntu-24.04
|
||||
permissions:
|
||||
id-token: write
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Download and install GAM
|
||||
run: |
|
||||
bash <(curl -s -S -L https://git.io/gam-install) -l
|
||||
|
||||
- name: Copy GAM configs into target dir
|
||||
# Make sure to remove the private key from oauth2service.json and set `key_type` to `signjwt`
|
||||
run: |
|
||||
cp ./gam.cfg ~/.gam/gam.cfg
|
||||
cp ./oauth2service.json ~/.gam/oauth2service.json
|
||||
|
||||
# # For debugging GitHub identity tokens
|
||||
# - name: Print out GitHub OIDC token
|
||||
# uses: github/actions-oidc-debugger@2e9ba5d3f4bebaad1f91a2cede055115738b7ae8
|
||||
# with:
|
||||
# audience: https://iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID
|
||||
|
||||
- id: 'auth'
|
||||
name: 'Authenticate to Google Cloud'
|
||||
uses: 'google-github-actions/auth@v1'
|
||||
with:
|
||||
create_credentials_file: true
|
||||
workload_identity_provider: 'projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL_ID/providers/PROVIDER_ID'
|
||||
service_account: 'SERVICE_ACCOUNT_EMAIL'
|
||||
|
||||
- name: Run GAM commands
|
||||
run: |
|
||||
~/bin/gam7/gam info user
|
||||
```
|
||||
|
||||
## Clean Up
|
||||
|
||||
After verifying that gam is working as expected, delete the old key if it's no longer in use.
|
||||
```bash
|
||||
gcloud iam service-accounts keys delete KEY_ID --iam-account=SERVICE_ACCOUNT_EMAIL
|
||||
```
|
||||
Also remove it from the `oauth2service.json` file.
|
||||
```
|
||||
...
|
||||
"private_key": "",
|
||||
"private_key_id": "",
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
## Security Best Practices
|
||||
|
||||
1. **Principle of Least Privilege**: Grant only necessary permissions to the service account
|
||||
2. **Attribute Conditions**: Use attribute conditions to restrict access based on specific criteria
|
||||
3. **Regular Auditing**: Regularly review and audit Workload Identity Federation configurations
|
||||
4. **Token Lifetime**: Configure appropriate token lifetimes for your use case
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **Authentication Errors**
|
||||
- Verify the audience URL matches your Workload Identity Pool
|
||||
- Check that the external identity has permission to impersonate the service account
|
||||
|
||||
2. **Permission Denied**
|
||||
- Ensure the service account has necessary Google Workspace permissions
|
||||
- Verify domain-wide delegation is configured if required
|
||||
|
||||
3. **Token Expiration**
|
||||
- Tokens are automatically refreshed by the Google Auth libraries
|
||||
- Check network connectivity to Google STS endpoints
|
||||
|
||||
### Debug Commands
|
||||
|
||||
```bash
|
||||
# Test authentication
|
||||
gcloud auth print-access-token
|
||||
|
||||
# Verify service account impersonation
|
||||
gcloud auth print-access-token --impersonate-service-account=SERVICE_ACCOUNT_EMAIL
|
||||
|
||||
# Check GAM authentication
|
||||
gam info user
|
||||
```
|
||||
|
||||
## Benefits
|
||||
|
||||
- **Reduced Attack Surface**: Short-lived tokens minimize exposure window if compromised
|
||||
- **Reduced Operational Cost**: Eliminates the overhead of managing and rotating service account keys
|
||||
- **Improved Scalability**: Easily scale across multiple environments without distributing keys
|
||||
- **Better Integration**: Native integration with cloud provider identity systems (AWS IAM, GitHub OIDC)
|
||||
- **Compliance**: Meets security requirements for keyless authentication
|
||||
|
||||
## References
|
||||
|
||||
- [Google Cloud Workload Identity Federation](https://cloud.google.com/iam/docs/workload-identity-federation)
|
||||
- [Workload Identity Federation With Other Clouds](https://cloud.google.com/iam/docs/workload-identity-federation-with-other-clouds)
|
||||
- [Authenticate to Google Cloud from GitHub Actions](https://github.com/google-github-actions/auth/blob/main/README.md)
|
||||
- [Service Account Impersonation](https://cloud.google.com/iam/docs/impersonating-service-accounts)
|
||||
@@ -73,6 +73,7 @@
|
||||
<MatterItem> ::= <UniqueID>|<String>
|
||||
<MatterState> ::= open|closed|deleted
|
||||
<MatterStateList> ::= "<MatterState>(,<MatterState>)*"
|
||||
<QueryItem> ::= <UniqueID>|<String>
|
||||
<SharedDriveID> ::= <String>
|
||||
<SharedDriveIDList> ::= "<SharedDriveID>(,<SharedDriveID>)*"
|
||||
<URL> ::= <String>
|
||||
@@ -259,7 +260,7 @@ gam create vaultexport|export matter <MatterItem> [name <String>] corpus calenda
|
||||
[includerooms <Boolean>]
|
||||
[excludedrafts <Boolean>] [mailclientsideencryption any|encrypted|unencrypted]
|
||||
[showconfidentialmodecontent <Boolean>] [usenewexport <Boolean>] [exportlinkeddrivefiles <Boolean>]
|
||||
[covereddata calllogs|textmessages|voicemails]
|
||||
(covereddata calllogs|textmessages|voicemails)*
|
||||
[format ics|mbox|pst|xml]
|
||||
[region any|europe|us] [showdetails|returnidonly]
|
||||
```
|
||||
@@ -376,7 +377,8 @@ For `corpus groups`, `corpus hangouts_chat`, `corpus mail` and `corpus voice`, y
|
||||
* `format mbox` - Export in MBOX format, this is the default
|
||||
* `format pst` - Export in PST format
|
||||
|
||||
For `corpus voice` you can specify thet data covered by the export:
|
||||
For `corpus voice` you can specify thet data covered by the export,
|
||||
multiple values are allowed.:
|
||||
* `covereddata calllogs` - Call logs
|
||||
* `covereddata textmessages` - Voice text messages
|
||||
* `covereddata voicemail` - Voicemail
|
||||
@@ -606,13 +608,28 @@ The `shownames` argument controls whether account and org unit names are display
|
||||
|
||||
## Vault Holds
|
||||
## Create Vault Holds
|
||||
### Create a hold from a saved Vault query.
|
||||
```
|
||||
gam create vaulthold|hold matter <MatterItem> [name <String>]
|
||||
vaultquery <QueryItem>
|
||||
[showdetails|returnidonly]
|
||||
```
|
||||
Specify the name of the hold:
|
||||
* `name <String>` - The hold will be named `<String>`
|
||||
* `default` - The hold will be named `GAM <corpus> Hold - <Time>`
|
||||
|
||||
Use the `showdetails` option to have the full details of the hold displayed.
|
||||
|
||||
Use the `returnidonly` option to have only the hold ID displayed.
|
||||
|
||||
### Create a hold from parameters.
|
||||
```
|
||||
gam create vaulthold|hold matter <MatterItem> [name <String>] corpus calendar|drive|mail|groups|hangouts_chat|voice
|
||||
[(accounts|groups|users <EmailItemList>) | (orgunit|org|ou <OrgUnit>)]
|
||||
[query <QueryVaultCorpus>]
|
||||
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
||||
[includerooms <Boolean>]
|
||||
[covereddata calllogs|textmessages|voicemails]
|
||||
(covereddata calllogs|textmessages|voicemails)*
|
||||
[includeshareddrives <Boolean>]
|
||||
[showdetails|returnidonly]
|
||||
```
|
||||
@@ -649,7 +666,8 @@ For `corpus hangouts_chat` you can specify advanced search options:
|
||||
* `includerooms False` - Do not include rooms, this is the default
|
||||
* `includerooms True` - Include rooms
|
||||
|
||||
For `corpus voice` you can specify the data covered by the hold:
|
||||
For `corpus voice` you can specify the data covered by the hold,
|
||||
multiple values are allowed.:
|
||||
* `covereddata calllogs` - Call logs
|
||||
* `covereddata textmessages` - Voice text messages
|
||||
* `covereddata voicemail` - Voicemail
|
||||
@@ -665,7 +683,7 @@ gam update vaulthold|hold <HoldItem> matter <MatterItem>
|
||||
[query <QueryVaultCorpus>]
|
||||
[terms <String>] [start|starttime <Date>|<Time>] [end|endtime <Date>|<Time>]
|
||||
[includerooms <Boolean>]
|
||||
[covereddata calllogs|textmessages|voicemails]
|
||||
(covereddata calllogs|textmessages|voicemails)*
|
||||
[includeshareddrives <Boolean>]
|
||||
[showdetails]
|
||||
```
|
||||
@@ -684,7 +702,8 @@ For a hold with `corpus hangouts_chat` you can specify advanced search options:
|
||||
* `includerooms False` - Do not include rooms, this is the default
|
||||
* `includerooms True` - Include rooms
|
||||
|
||||
For a hold with `corpus voice` you can specify the data covered by the hold:
|
||||
For a hold with `corpus voice` you can specify the data covered by the hold,
|
||||
multiple values are allowed.:
|
||||
* `covereddata calllogs` - Call logs
|
||||
* `covereddata textmessages` - Voice text messages
|
||||
* `covereddata voicemail` - Voicemail
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
Print the current version of Gam with details
|
||||
```
|
||||
gam version
|
||||
GAM 7.21.01 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM 7.22.04 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM Team <google-apps-manager@googlegroups.com>
|
||||
Python 3.13.7 64-bit final
|
||||
MacOS Sequoia 15.6.1 x86_64
|
||||
macOS Sequoia 15.7 x86_64
|
||||
Path: /Users/Admin/bin/gam7
|
||||
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||
Time: 2023-06-02T21:10:00-07:00
|
||||
@@ -15,10 +15,10 @@ Time: 2023-06-02T21:10:00-07:00
|
||||
Print the current version of Gam with details and time offset information
|
||||
```
|
||||
gam version timeoffset
|
||||
GAM 7.21.01 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM 7.22.04 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM Team <google-apps-manager@googlegroups.com>
|
||||
Python 3.13.7 64-bit final
|
||||
MacOS Sequoia 15.6.1 x86_64
|
||||
macOS Sequoia 15.7 x86_64
|
||||
Path: /Users/Admin/bin/gam7
|
||||
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||
Your system time differs from www.googleapis.com by less than 1 second
|
||||
@@ -27,25 +27,29 @@ Your system time differs from www.googleapis.com by less than 1 second
|
||||
Print the current version of Gam with extended details and SSL information
|
||||
```
|
||||
gam version extended
|
||||
GAM 7.21.01 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM 7.22.04 - https://github.com/GAM-team/GAM - pyinstaller
|
||||
GAM Team <google-apps-manager@googlegroups.com>
|
||||
Python 3.13.7 64-bit final
|
||||
MacOS Sequoia 15.6.1 x86_64
|
||||
macOS Sequoia 15.7 x86_64
|
||||
Path: /Users/Admin/bin/gam7
|
||||
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||
Time: 2023-06-02T21:10:00-07:00
|
||||
Your system time differs from admin.googleapis.com by less than 1 second
|
||||
OpenSSL 3.5.2 5 ASug 2025
|
||||
cryptography 43.0.3
|
||||
filelock 3.16.1
|
||||
google-api-python-client 2.149.0
|
||||
OpenSSL 3.5.3 16 Sep 2025
|
||||
arrow 1.3.0
|
||||
chardet 5.2.0
|
||||
cryptography 46.0.1
|
||||
filelock 3.19.1
|
||||
google-api-python-client 2.182.0
|
||||
google-auth-httplib2 0.2.0
|
||||
google-auth-oauthlib 1.2.1
|
||||
google-auth 2.35.0
|
||||
httplib2 0.22.0
|
||||
google-auth-oauthlib 1.2.2
|
||||
google-auth 2.40.3
|
||||
lxml 6.0.1
|
||||
httplib2 0.31.0
|
||||
passlib 1.7.4
|
||||
python-dateutil 2.9.0.post0
|
||||
yubikey-manager 5.5.1
|
||||
pathvalidate 3.3.1
|
||||
pyscard 2.3.0
|
||||
yubikey-manager 5.8.0
|
||||
admin.googleapis.com connects using TLSv1.3 TLS_AES_256_GCM_SHA384
|
||||
```
|
||||
|
||||
@@ -64,7 +68,7 @@ MacOS High Sierra 10.13.6 x86_64
|
||||
Path: /Users/Admin/bin/gam7
|
||||
Version Check:
|
||||
Current: 5.35.08
|
||||
Latest: 7.21.01
|
||||
Latest: 7.22.00
|
||||
echo $?
|
||||
1
|
||||
```
|
||||
@@ -72,7 +76,7 @@ echo $?
|
||||
Print the current version number without details
|
||||
```
|
||||
gam version simple
|
||||
7.21.01
|
||||
7.22.00
|
||||
```
|
||||
In Linux/MacOS you can do:
|
||||
```
|
||||
@@ -82,10 +86,10 @@ echo $VER
|
||||
Print the current version of Gam and address of this Wiki
|
||||
```
|
||||
gam help
|
||||
GAM 7.21.01 - https://github.com/GAM-team/GAM
|
||||
GAM 7.22.00 - https://github.com/GAM-team/GAM
|
||||
GAM Team <google-apps-manager@googlegroups.com>
|
||||
Python 3.13.7 64-bit final
|
||||
MacOS Sequoia 15.6.1 x86_64
|
||||
macOS Sequoia 15.7 x86_64
|
||||
Path: /Users/Admin/bin/gam7
|
||||
Config File: /Users/admin/GAMConfig/gam.cfg, Section: DEFAULT, customer_id: my_customer, domain: domain.com
|
||||
Time: 2023-06-02T21:10:00-07:00
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
[FAQ](GAM7-FAQ)
|
||||
|
||||
Update History
|
||||
* [GAM Updates](GamUpdates)
|
||||
|
||||
@@ -22,6 +24,7 @@ Configuration
|
||||
* [Multiple Users-Projects on One Computer](https://github.com/GAM-team/GAM/wiki/gam.cfg#multiple-users-projects-on-one-computer)
|
||||
* [Running GAM7 securely on a Google Compute Engine](Running-GAM7-securely-on-a-Google-Compute-Engine)
|
||||
* [Using GAM7 with a delegated admin service account](Using-GAM7-with-a-delegated-admin-service-account)
|
||||
* [Using GAM7 with keyless authentication - Workload Identity Federation](Using-GAM7-with-keyless-authentication-Workload-Identity-Federation)
|
||||
* [Using GAM7 with a YubiKey](Using-GAM7-with-a-YubiKey)
|
||||
* [GAM with minimal GCP rights](GAM-with-minimal-GCP-rights)
|
||||
|
||||
@@ -177,30 +180,3 @@ Service Account Access
|
||||
* [Users - Tasks](Users-Tasks)
|
||||
* [Users - YouTube](Users-YouTube)
|
||||
* [Users - Web Resources and Sites](Users-Web-Resources-and-Sites)
|
||||
|
||||
GAM Tutorials
|
||||
* [Account Auditing](l-ExamplesAccountAuditing)
|
||||
* [Calendar Settings](l-CalendarExamples)
|
||||
* [Chat Bot commands](Chat-Bot)
|
||||
* [Chrome Browser Management](l-Chrome-Browser-Management)
|
||||
* [Chrome Policy Settings](l-Chrome-Policy-Settings)
|
||||
* [Context Aware Access levels](Context-Aware-Access-Levels)
|
||||
* [Data Transfers](l-Data-Transfers)
|
||||
* [Domain Verification](l-DomainVerification)
|
||||
* [Google Drive Management](l-GoogleDriveManagement)
|
||||
* [Group Settings](l-GAM3GroupSettings)
|
||||
* [Inbound SSO Settings](l-Inbound-SSO-Settings)
|
||||
* [Managing Admins](l-Managing-Admins)
|
||||
* [Managing Classroom](l-Managing-Google-Classroom)
|
||||
* [Managing Custom User Schemas](l-Custom-Schemas)
|
||||
* [Managing Devices](l-Managing-Devices)
|
||||
* [Managing Organizations](l-ExamplesOrganizations)
|
||||
* [Managing Product Licenses](l-LicenseExamples)
|
||||
* [Managing Users, Groups, Aliases, Domains, Mobile and Chrome Devices, and Resource Calendars](l-GAM3DirectoryCommands)
|
||||
* [OAuth Authentication Related Commands](l-OAuthKeyManagement)
|
||||
* [Print Users, Groups, Aliases, Mobile and Chrome OS devices, OUs, Licenses and Reports](l-GAM3CSVListings)
|
||||
* [Printers](l-Printers)
|
||||
* [Unmanaged Users and Invitations](l-UnmanagedUsersExamples)
|
||||
* [User Email Settings](l-ExamplesEmailSettings)
|
||||
* [User Security Settings](l-SecurityExamples)
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
# Intro
|
||||
GAM can run on a Linux or Windows Google Compute Engine (GCE) VM and use the attached service account to access Google Workspace APIs. The advantage of this configuration is that no service account private key is accessible to GAM directly and there is no risk of the key being stolen/lost. To use GAM on GCE with a service account:
|
||||
|
||||
1. Create a [GCP project](https://cloud.google.com/resource-manager/docs/creating-managing-projects).
|
||||
|
||||
2. Create [a service account](https://cloud.google.com/iam/docs/creating-managing-service-accounts) which will be used by GAM. Continue steps 2 and 3 without granting the new service account any special access to the project and without granting users access to the service account.
|
||||
|
||||
3. Grant the service account rights to generate authentication tokens.
|
||||
* go to [console.cloud.google.com](https://console.cloud.google.com).
|
||||
* go to "IAM & Admin" > Service accounts
|
||||
* click on the service account you created (not the default service account).
|
||||
* copy the email address of your service account to the clipboard.
|
||||
* click on the Permissions tab.
|
||||
* click "Grant Access".
|
||||
* In the "New principals text box, paste the service account email you copied.
|
||||
* Give your service account the "Service Account Token Creator" and "View Service Accounts" roles.
|
||||
|
||||
4. [Create a Windows or Linux virtual machine](https://cloud.google.com/compute/docs/instances/create-start-instance).
|
||||
* You can choose a region physically close to you though you may be limited in your choices if you want to use the free tier.
|
||||
* GAM can run on the minimal `e2-micro` [free tier VM](https://cloud.google.com/free/docs/free-cloud-features#compute) though performance may suffer. If you are performing batch operations, raising the CPU count will help performance. If you have a very large and busy Workspace instance downloading reports or Drive file lists may require more RAM.
|
||||
* [DO NOT use the default service account](https://cloud.google.com/iam/docs/best-practices-service-accounts#single-purpose). Choose the service account you created above instead.
|
||||
* GAM does not use a significant amount of storage, unless you have specific storage needs the default disk size should suffice.
|
||||
* leave other VM instance settings at their defaults unless you know what you are doing.
|
||||
|
||||
5. Install GAM on the VM with the command:
|
||||
```
|
||||
bash <(curl -s -S -L https://git.io/gam-install) -l
|
||||
```
|
||||
the `-l` argument causes GAM to be installed and SKIP the normal setup wizard.
|
||||
|
||||
6. Logout and log back in to the VM, you should now be able to run GAM commands like:
|
||||
```
|
||||
gam version
|
||||
```
|
||||
|
||||
7. Create the special `oauth2service.json` file GAM will use:
|
||||
```
|
||||
gam create signjwtserviceaccount
|
||||
```
|
||||
If you'd like, take a look at the generated ```oauth2service.json``` file with:
|
||||
```
|
||||
cat ~/bin/gam/oauth2service.json
|
||||
```
|
||||
you'll notice that while the file has some fields similar to a normal service account file, there is no `private_key` attribute containing an RSA private key.
|
||||
|
||||
8. Enable the Google APIs GAM will use:
|
||||
```
|
||||
gam enable apis
|
||||
```
|
||||
you are given the option to enable them automatically or manually. Automatic enablement will ask you to authenticate to GAM. You should authenticate as a user with rights to manage project APIs, probably a project owner. If you are not the project owner you can choose manual enablement and GAM will provide two or more URLs which you can send to the project owner. When the owner opens these URLs, they'll be prompted to enable all the APIs GAM needs.
|
||||
|
||||
9. GAM is now installed, the last steps are to grant GAM permissions to your Google Workspace domain.
|
||||
* If you want to manage user data, run ```gam user you@example.com check serviceaccount``` and follow the instructions to perform domain-wide delegation.
|
||||
* If you want to perform admin actions (manage users, groups, etc) [you can configure delegated admin service account (DASA)](https://github.com/GAM-team/GAM/wiki/Using-GAM-with-a-delegated-admin-service-account-(DASA)).
|
||||
@@ -1,49 +0,0 @@
|
||||
## Description
|
||||
GAM supports using a [YubiKey](https://www.yubico.com/products/yubikey-5-overview/) to generate and store the service account's private RSA key. Private keys generated by the YubiKey cannot be exported even to the computer running GAM. When compared to the plain text oauth2service.json file with the private key stored in text, the YubiKey offers a more secure option that prevents digital theft and copying of the private key. Instead of reading the private key from the oauth2service.json file and signing requests itself, GAM will simply send signing requests to the YubiKey and get back the signature.
|
||||
|
||||
## FAQs
|
||||
### Can I use a Google Titan or other brand security key?
|
||||
No, while Titan keys are great as security keys / U2F / 2SV, that is not the protocol being used by GAM here. GAM uses the PIV app of YubiKeys to work with service accounts. You need to use [a genuine Yubikey.](https://yubico.com/genuine/).
|
||||
|
||||
### Does this protect the admin credentials GAM stores in oauth2.txt?
|
||||
No, the admin credentials GAM stores in oauth2.txt are not protected by the YubiKey as they are not using RSA private keys. Only the service account credentials normally stored in oauth2service.json are protected. The service account credentials are used for domain-wide delegation operations like managing Workspace user data in Drive, Gmail and Calendar. Note that GAM also has the ability to perform admin actions as a delegated admin service account (DASA). See [instructions for setting up DASA](https://github.com/GAM-team/GAM/wiki/Using-GAM-with-a-delegated-admin-service-account-(DASA)) when DASA is setup, GAM will use the service account to authenticate which can be protected by the YubiKey.
|
||||
|
||||
### What if someone physically steals the YubiKey?
|
||||
The YubiKey can be configured with a PIN that must be entered in order for it to sign data with the private key. GAM stores this PIN string in the oauth2service.json file so it can use it as needed. What this means is that an attacker would need to steal *both* the physical YubiKey and the PIN stored in oauth2service.json. The recommendation is to store oauth2service.json and the rest of the GAM directory on an encrypted partition. The YubiKey itself should also be kept in a secure location.
|
||||
|
||||
### Can I require a physical touch of the YubiKey before the private key can be used?
|
||||
Yes but in practice this does not work very well with GAM. The YubiKey will need to be touched every time there is a GAM command running which for batch or cron jobs may be constant. GAM can use a PIN configured on the YubiKey in order to offer an additional layer of protection.
|
||||
|
||||
### If I use a YubiKey, do I need to rotate the private key regularly?
|
||||
No, because the YubiKey generated the private key it cannot be digitally exported from the YubiKey so there is not chance for it to be copied and stolen. Instead you should physically secure the YubiKey from theft.
|
||||
|
||||
### What data does the service account private key have access to?
|
||||
When using domain-wide delegation with GAM, the service account and anyone possessing the service account private key oauth2service.json file has access to the Gmail, Drive and Calendar data of ALL Workspace users in your domain. For this reason, whether using a YubiKey or not, you should take strong measures to protect the service account private key.
|
||||
|
||||
## Setup Steps
|
||||
1. Upgrade to at least GAM 6.07. Best practice is to always use the [latest version of GAM](https://github.com/GAM-team/GAM).
|
||||
2. Setup GAM according to the [Quick Start Guide](https://github.com/GAM-team/GAM#quick-start). Once setup you will have a service account created and it's private key credentials in the oauth2service.json file.
|
||||
3. **If you are using a new YubiKey or don't care about the PIV app data on the YubiKey**
|
||||
1. Tell GAM to reset and configure the PIV app data on the YubiKey. This wipes all existing keys and config and then configures a private key and PIN for GAM. Run:
|
||||
```gam yubikey reset_piv```
|
||||
2. During the PIV reset, GAM will print out a PIN for the private key, record this key.
|
||||
4. **OR If you are already using the YubiKey and wish to preserve the PIV app data and keys**
|
||||
1. You need to configure one of the PIV slots for a private key and certificate GAM can use. The full steps here are beyond this guide's scope but might include:
|
||||
```
|
||||
ykman piv keys generate -P some_pin --pin-policy ALWAYS --touch-policy NEVER --algorithm RSA2048 9c new_pubkey.txt
|
||||
ykman piv certificates generate -P some_pin --subject "GAM Service Account" -d 36500 9c new_pubkey.txt
|
||||
```
|
||||
|
||||
5. Now that you have a private key on your YubiKey, tell GAM to use that instead of the private_key stored in oauth2service.json. We can do that by rotating the key:
|
||||
```
|
||||
gam rotate sakey yubikey yubikey_pin yubikey_slot AUTHENTICATION
|
||||
```
|
||||
The yubikey argument tells GAM to use a private key on a plugged in YubiKey. The yubikey_pin argument tells GAM to prompt you to input the PIN that was set in the previous step. The yubikey_slot argument tells GAM which PIV slot to use on the YubiKey.
|
||||
|
||||
6. Now you should be able to run GAM commands like:
|
||||
```
|
||||
gam user admin@example.com check serviceaccount
|
||||
```
|
||||
and see the YubiKey lights flash as the YubiKey interacts with GAM to sign the GAM authentication requests. If you look at the oauth2service.json file, you'll see it contains some new fields like yubikey_serial and yubikey_pin but no longer contains the private_key field where GAM would normally store the private key data.
|
||||
|
||||
7. As a last step, since YubiKey-stored private keys do not need to be and should not be rotated, you can remove the service account's permissions to change it's own key. Navigate to the [Cloud Console](https://console.cloud.google.com/iam-admin/serviceaccounts) select the correct project and service account and on the Permissions tab, edit and remove the "Service Account Key Admin" permission that the service account has to itself.
|
||||
Reference in New Issue
Block a user