gam7 7.25.0__py3-none-any.whl → 7.26.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of gam7 might be problematic. Click here for more details.
- gam/__init__.py +41 -11
- gam/gamlib/glcfg.py +4 -0
- gam/gamlib/glglobals.py +3 -0
- {gam7-7.25.0.dist-info → gam7-7.26.0.dist-info}/METADATA +2 -2
- {gam7-7.25.0.dist-info → gam7-7.26.0.dist-info}/RECORD +8 -8
- {gam7-7.25.0.dist-info → gam7-7.26.0.dist-info}/WHEEL +0 -0
- {gam7-7.25.0.dist-info → gam7-7.26.0.dist-info}/entry_points.txt +0 -0
- {gam7-7.25.0.dist-info → gam7-7.26.0.dist-info}/licenses/LICENSE +0 -0
gam/__init__.py
CHANGED
|
@@ -25,7 +25,7 @@ https://github.com/GAM-team/GAM/wiki
|
|
|
25
25
|
"""
|
|
26
26
|
|
|
27
27
|
__author__ = 'GAM Team <google-apps-manager@googlegroups.com>'
|
|
28
|
-
__version__ = '7.
|
|
28
|
+
__version__ = '7.26.00'
|
|
29
29
|
__license__ = 'Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0)'
|
|
30
30
|
|
|
31
31
|
#pylint: disable=wrong-import-position
|
|
@@ -49,7 +49,7 @@ from email.policy import SMTP as policySMTP
|
|
|
49
49
|
import hashlib
|
|
50
50
|
from html.entities import name2codepoint
|
|
51
51
|
from html.parser import HTMLParser
|
|
52
|
-
import http.client
|
|
52
|
+
import http.client
|
|
53
53
|
import importlib
|
|
54
54
|
from importlib.metadata import version as lib_version
|
|
55
55
|
import io
|
|
@@ -375,6 +375,37 @@ YUBIKEY_VALUE_ERROR_RC = 85
|
|
|
375
375
|
YUBIKEY_MULTIPLE_CONNECTED_RC = 86
|
|
376
376
|
YUBIKEY_NOT_FOUND_RC = 87
|
|
377
377
|
|
|
378
|
+
DEBUG_REDACTION_PATTERNS = [
|
|
379
|
+
# Positional patterns that redact sensitive credentials based on their location
|
|
380
|
+
(r'(Bearer\s+)\S+', r'\1*****'), # access tokens and JWTs in auth header
|
|
381
|
+
(r'([?&]refresh_token=)[^&]*', r'\1*****'), # refresh token URL parameter
|
|
382
|
+
(r'([?&]client_secret=)[^&]*', r'\1*****'), # client secret URL parameter
|
|
383
|
+
(r'([?&]key=)[^&]*', r'\1*****'), # API key URL parameter
|
|
384
|
+
(r'([?&]code=)[^&]*', r'\1*****'), # auth code URL parameter
|
|
385
|
+
|
|
386
|
+
# Pattern match patterns that redact sensitive credentials based on known credential pattern
|
|
387
|
+
(r'ya29.[0-9A-Za-z-_]+', '*****'), # Access token
|
|
388
|
+
(r'1%2F%2F[0-9A-Za-z-_]{100}|1%2F%2F[0-9A-Za-z-_]{64}|1%2F%2F[0-9A-Za-z-_]{43}', '*****'), # Refresh token
|
|
389
|
+
(r'4/[0-9A-Za-z-_]+', '*****'), # Auth code
|
|
390
|
+
(r'GOCSPX-[0-9a-zA-Z-_]{28}', '*****'), # Client secret
|
|
391
|
+
(r'AIza[0-9A-Za-z-_]{35}', '*****'), # API key
|
|
392
|
+
(r'eyJ[a-zA-Z0-9\-_]+\.eyJ[a-zA-Z0-9\-_]+\.[a-zA-Z0-9\-_]*', '*****'), # JWT
|
|
393
|
+
]
|
|
394
|
+
|
|
395
|
+
def redactable_debug_print(*args):
|
|
396
|
+
processed_args = []
|
|
397
|
+
for arg in args:
|
|
398
|
+
if arg.startswith('b\''):
|
|
399
|
+
sbytes = arg[2:-1]
|
|
400
|
+
sbytes = bytes(sbytes, 'utf-8')
|
|
401
|
+
arg = sbytes.decode()
|
|
402
|
+
arg = arg.replace('\\r\\n', "\n ")
|
|
403
|
+
if GC.Values[GC.DEBUG_REDACTION]:
|
|
404
|
+
for pattern, replace in DEBUG_REDACTION_PATTERNS:
|
|
405
|
+
arg = re.sub(pattern, replace, arg)
|
|
406
|
+
processed_args.append(arg)
|
|
407
|
+
print(*processed_args)
|
|
408
|
+
|
|
378
409
|
# Multiprocessing lock
|
|
379
410
|
mplock = None
|
|
380
411
|
|
|
@@ -3716,12 +3747,12 @@ def SetGlobalVariables():
|
|
|
3716
3747
|
return stringlist
|
|
3717
3748
|
|
|
3718
3749
|
def _getCfgTimezone(sectionName, itemName):
|
|
3719
|
-
value = _stripStringQuotes(GM.Globals[GM.PARSER].get(sectionName, itemName)
|
|
3720
|
-
if value in {'utc', 'z'}:
|
|
3750
|
+
value = _stripStringQuotes(GM.Globals[GM.PARSER].get(sectionName, itemName))
|
|
3751
|
+
if value.lower() in {'utc', 'z'}:
|
|
3721
3752
|
GM.Globals[GM.CONVERT_TO_LOCAL_TIME] = False
|
|
3722
3753
|
return arrow.now('utc').tzinfo
|
|
3723
3754
|
GM.Globals[GM.CONVERT_TO_LOCAL_TIME] = True
|
|
3724
|
-
if value == 'local':
|
|
3755
|
+
if value.lower() == 'local':
|
|
3725
3756
|
return arrow.now(value).tzinfo
|
|
3726
3757
|
try:
|
|
3727
3758
|
return arrow.now(value).tzinfo
|
|
@@ -4124,6 +4155,8 @@ def SetGlobalVariables():
|
|
|
4124
4155
|
GM.Globals[GM.OAUTH2_TXT_LOCK] = f'{GC.Values[GC.OAUTH2_TXT]}.lock'
|
|
4125
4156
|
# Override httplib2 settings
|
|
4126
4157
|
httplib2.debuglevel = GC.Values[GC.DEBUG_LEVEL]
|
|
4158
|
+
# Use our own print function for http.client so we can redact and cleanup
|
|
4159
|
+
http.client.print = redactable_debug_print
|
|
4127
4160
|
# Reset global variables if required
|
|
4128
4161
|
if prevExtraArgsTxt != GC.Values[GC.EXTRA_ARGS]:
|
|
4129
4162
|
GM.Globals[GM.EXTRA_ARGS_LIST] = [('prettyPrint', GC.Values[GC.DEBUG_LEVEL] > 0)]
|
|
@@ -4775,7 +4808,7 @@ def getService(api, httpObj):
|
|
|
4775
4808
|
waitOnFailure(n, triesLimit, INVALID_JSON_RC, str(e))
|
|
4776
4809
|
continue
|
|
4777
4810
|
systemErrorExit(INVALID_JSON_RC, str(e))
|
|
4778
|
-
except (
|
|
4811
|
+
except (http.client.ResponseNotReady, OSError, googleapiclient.errors.HttpError) as e:
|
|
4779
4812
|
errMsg = f'Connection error: {str(e) or repr(e)}'
|
|
4780
4813
|
if n != triesLimit:
|
|
4781
4814
|
waitOnFailure(n, triesLimit, SOCKET_ERROR_RC, errMsg)
|
|
@@ -4810,7 +4843,6 @@ def defaultSvcAcctScopes():
|
|
|
4810
4843
|
saScopes[scope['api']].append(scope['scope'])
|
|
4811
4844
|
else:
|
|
4812
4845
|
saScopes[scope['api']].extend(scope['scope'])
|
|
4813
|
-
saScopes[API.DRIVEACTIVITY].append(API.DRIVE_SCOPE)
|
|
4814
4846
|
saScopes[API.DRIVE2] = saScopes[API.DRIVE3]
|
|
4815
4847
|
return saScopes
|
|
4816
4848
|
|
|
@@ -5089,7 +5121,7 @@ def callGData(service, function,
|
|
|
5089
5121
|
e = e.args[0]
|
|
5090
5122
|
handleOAuthTokenError(e, GDATA.SERVICE_NOT_APPLICABLE in throwErrors)
|
|
5091
5123
|
raise GDATA.ERROR_CODE_EXCEPTION_MAP[GDATA.SERVICE_NOT_APPLICABLE](str(e))
|
|
5092
|
-
except (
|
|
5124
|
+
except (http.client.ResponseNotReady, OSError) as e:
|
|
5093
5125
|
errMsg = f'Connection error: {str(e) or repr(e)}'
|
|
5094
5126
|
if n != triesLimit:
|
|
5095
5127
|
waitOnFailure(n, triesLimit, SOCKET_ERROR_RC, errMsg)
|
|
@@ -5399,7 +5431,7 @@ def callGAPI(service, function,
|
|
|
5399
5431
|
e = e.args[0]
|
|
5400
5432
|
handleOAuthTokenError(e, GAPI.SERVICE_NOT_AVAILABLE in throwReasons)
|
|
5401
5433
|
raise GAPI.REASON_EXCEPTION_MAP[GAPI.SERVICE_NOT_AVAILABLE](str(e))
|
|
5402
|
-
except (
|
|
5434
|
+
except (http.client.ResponseNotReady, OSError) as e:
|
|
5403
5435
|
errMsg = f'Connection error: {str(e) or repr(e)}'
|
|
5404
5436
|
if n != triesLimit:
|
|
5405
5437
|
waitOnFailure(n, triesLimit, SOCKET_ERROR_RC, errMsg)
|
|
@@ -12351,8 +12383,6 @@ def checkServiceAccount(users):
|
|
|
12351
12383
|
saScopes[scope['api']].append(scope['roscope'])
|
|
12352
12384
|
checkScopesSet.add(scope['roscope'])
|
|
12353
12385
|
i += 1
|
|
12354
|
-
if API.DRIVEACTIVITY in saScopes and API.DRIVE3 in saScopes:
|
|
12355
|
-
saScopes[API.DRIVEACTIVITY].append(API.DRIVE_SCOPE)
|
|
12356
12386
|
if API.DRIVE3 in saScopes:
|
|
12357
12387
|
saScopes[API.DRIVE2] = saScopes[API.DRIVE3]
|
|
12358
12388
|
GM.Globals[GM.OAUTH2SERVICE_JSON_DATA][API.OAUTH2SA_SCOPES] = saScopes
|
gam/gamlib/glcfg.py
CHANGED
|
@@ -149,6 +149,8 @@ CSV_OUTPUT_USERS_AUDIT = 'csv_output_users_audit'
|
|
|
149
149
|
CUSTOMER_ID = 'customer_id'
|
|
150
150
|
# If debug_level > 0: extra_args['prettyPrint'] = True, httplib2.debuglevel = gam_debug_level, appsObj.debug = True
|
|
151
151
|
DEBUG_LEVEL = 'debug_level'
|
|
152
|
+
# redact sensitive credentials from debug output
|
|
153
|
+
DEBUG_REDACTION = 'debug_redaction'
|
|
152
154
|
# Developer Preview API Key
|
|
153
155
|
DEVELOPER_PREVIEW_API_KEY = 'developer_preview_api_key'
|
|
154
156
|
# When retrieving lists of ChromeOS devices from API, how many should be retrieved in each chunk
|
|
@@ -378,6 +380,7 @@ Defaults = {
|
|
|
378
380
|
CSV_OUTPUT_USERS_AUDIT: FALSE,
|
|
379
381
|
CUSTOMER_ID: MY_CUSTOMER,
|
|
380
382
|
DEBUG_LEVEL: '0',
|
|
383
|
+
DEBUG_REDACTION: TRUE,
|
|
381
384
|
DEVELOPER_PREVIEW_API_KEY: '',
|
|
382
385
|
DEVICE_MAX_RESULTS: '200',
|
|
383
386
|
DOMAIN: '',
|
|
@@ -547,6 +550,7 @@ VAR_INFO = {
|
|
|
547
550
|
CSV_OUTPUT_USERS_AUDIT: {VAR_TYPE: TYPE_BOOLEAN},
|
|
548
551
|
CUSTOMER_ID: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'CUSTOMER_ID', VAR_LIMITS: (0, None)},
|
|
549
552
|
DEBUG_LEVEL: {VAR_TYPE: TYPE_INTEGER, VAR_SIGFILE: 'debug.gam', VAR_LIMITS: (0, None), VAR_SFFT: ('0', '4')},
|
|
553
|
+
DEBUG_REDACTION: {VAR_TYPE: TYPE_BOOLEAN},
|
|
550
554
|
DEVELOPER_PREVIEW_API_KEY: {VAR_TYPE: TYPE_STRING, VAR_LIMITS: (0, None)},
|
|
551
555
|
DEVICE_MAX_RESULTS: {VAR_TYPE: TYPE_INTEGER, VAR_LIMITS: (1, 200)},
|
|
552
556
|
DOMAIN: {VAR_TYPE: TYPE_STRING, VAR_ENVVAR: 'GA_DOMAIN', VAR_LIMITS: (0, None)},
|
gam/gamlib/glglobals.py
CHANGED
|
@@ -107,6 +107,8 @@ CURRENT_SVCACCT_USER = 'csa'
|
|
|
107
107
|
DATETIME_NOW = 'dtno'
|
|
108
108
|
# If debug_level > 0: extra_args['prettyPrint'] = True, httplib2.debuglevel = gam_debug_level, appsObj.debug = True
|
|
109
109
|
DEBUG_LEVEL = 'dbgl'
|
|
110
|
+
# Whether debug output should redact sensitive credentials
|
|
111
|
+
DEBUG_REDACTION = 'dbrd'
|
|
110
112
|
# Decoded ID token
|
|
111
113
|
DECODED_ID_TOKEN = 'didt'
|
|
112
114
|
# Index of start of <UserTypeEntity> in command line
|
|
@@ -263,6 +265,7 @@ Globals = {
|
|
|
263
265
|
CURRENT_SVCACCT_USER: None,
|
|
264
266
|
DATETIME_NOW: None,
|
|
265
267
|
DEBUG_LEVEL: 0,
|
|
268
|
+
DEBUG_REDACTION: True,
|
|
266
269
|
DECODED_ID_TOKEN: None,
|
|
267
270
|
ENTITY_CL_DELAY_START: 1,
|
|
268
271
|
ENTITY_CL_START: 1,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gam7
|
|
3
|
-
Version: 7.
|
|
3
|
+
Version: 7.26.0
|
|
4
4
|
Summary: CLI tool to manage Google Workspace
|
|
5
5
|
Project-URL: Homepage, https://github.com/GAM-team/GAM
|
|
6
6
|
Project-URL: Issues, https://github.com/GAM-team/GAM/issues
|
|
@@ -17,7 +17,7 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
17
17
|
Classifier: Programming Language :: Python :: 3.11
|
|
18
18
|
Classifier: Programming Language :: Python :: 3.12
|
|
19
19
|
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
-
Requires-Python: >=3.
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
21
|
Requires-Dist: arrow>=1.3.0
|
|
22
22
|
Requires-Dist: chardet>=5.2.0
|
|
23
23
|
Requires-Dist: cryptography>=44.0.2
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
gam/__init__.py,sha256=
|
|
1
|
+
gam/__init__.py,sha256=g2mdigRmCIiRlX0-UKoDG3_xVSPZ9jTWCBvX2MXtXYA,3625606
|
|
2
2
|
gam/__main__.py,sha256=VwEYS7a9vYQPbT6iLduMOoVUJ6p4R-HZgerZQmM1NpE,1307
|
|
3
3
|
gam/cacerts.pem,sha256=DUsVo2XlFYwfkhe3gnxa-Km4Z4noz74hSApXwTT-nQE,44344
|
|
4
4
|
gam/cbcm-v1.1beta1.json,sha256=xO5XloCQQULmPbFBx5bckdqmbLFQ7sJ2TImhE1ysDIY,19439
|
|
@@ -23,12 +23,12 @@ gam/atom/url.py,sha256=pxO1TlORxyKQTQ1bkBE1unFzjnv9c8LjJkm-UEORShY,4276
|
|
|
23
23
|
gam/gamlib/__init__.py,sha256=z5mF-y0j8pm-YNFBaiuxB4M_GAUPG-cXWwrhYwrVReM,679
|
|
24
24
|
gam/gamlib/glaction.py,sha256=1Il_HrChVnPkzZwiZs5au4mFQVtq4K1Z42uIuR6qdnI,9419
|
|
25
25
|
gam/gamlib/glapi.py,sha256=g49VStWE64nCdrpNIMl60U06m98d3AGO8-vUDxgcBog,37048
|
|
26
|
-
gam/gamlib/glcfg.py,sha256=
|
|
26
|
+
gam/gamlib/glcfg.py,sha256=do_FR9m9m7Bmh2SgjLPk2pysU-wPHt7PlqPPjX90tpw,28684
|
|
27
27
|
gam/gamlib/glclargs.py,sha256=LlTtwJJHqU48l7SQT4bcZCWlw3Y46g42Bn1ACGW8gIk,53307
|
|
28
28
|
gam/gamlib/glentity.py,sha256=KWFomkoNE6lLE83zVqVIlJ2rkzfLkhEasW1M0TWGieA,35373
|
|
29
29
|
gam/gamlib/glgapi.py,sha256=pdBbwNtnCwFWxJGaP-_3hdTjSNoOCJF2yo76WdQOi1k,40426
|
|
30
30
|
gam/gamlib/glgdata.py,sha256=weRppttWm6uRyqtBoGPKoHiNZ2h28nhfUV4J_mbCszY,2707
|
|
31
|
-
gam/gamlib/glglobals.py,sha256=
|
|
31
|
+
gam/gamlib/glglobals.py,sha256=U1eCXHOkWAtwVXG8-0HL4ZzQP0YcbeFlhJxbOa_x1QI,9804
|
|
32
32
|
gam/gamlib/glindent.py,sha256=RfBa2LDfLIqPLL5vMfC689TCVmqn8xf-qulSzkiatrc,1228
|
|
33
33
|
gam/gamlib/glmsgs.py,sha256=ODq-KS3jhXH5DB5DEo6eCX1DHhy4OGv_jeQjiLVPOHM,34049
|
|
34
34
|
gam/gamlib/glskus.py,sha256=29vlBLBJCL4u9GawCt3eNeZq9HQG3hGFZk9-EainNng,15384
|
|
@@ -47,8 +47,8 @@ gam/gdata/apps/audit/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrK
|
|
|
47
47
|
gam/gdata/apps/audit/service.py,sha256=Z1eueThcNeVUMWP1DRWc_DGHrJCiJI8W_xj6L-cqu-Q,9658
|
|
48
48
|
gam/gdata/apps/contacts/__init__.py,sha256=Um6zgIkiahZns7yAEuC3pxHSMD8iciZ_EoynSLoYPfU,30463
|
|
49
49
|
gam/gdata/apps/contacts/service.py,sha256=5lNb-Ii1Gyek6ePFji3kyoYtCBc8CuJTwagx2BL2o14,15684
|
|
50
|
-
gam7-7.
|
|
51
|
-
gam7-7.
|
|
52
|
-
gam7-7.
|
|
53
|
-
gam7-7.
|
|
54
|
-
gam7-7.
|
|
50
|
+
gam7-7.26.0.dist-info/METADATA,sha256=3oXqEu4CCb57Wjr8dvY1DHHG7-9ly_bvO80W5Zo6k8s,3093
|
|
51
|
+
gam7-7.26.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
52
|
+
gam7-7.26.0.dist-info/entry_points.txt,sha256=HVUM5J7dA8YwvJfG30jiLefR19ExMs387TWugWd9sf4,42
|
|
53
|
+
gam7-7.26.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
54
|
+
gam7-7.26.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|