Remove IAM API from DWD

This commit is contained in:
Ross Scroggs
2025-06-03 18:13:11 -07:00
parent 2f1a7eb347
commit f06944a1fa
4 changed files with 42 additions and 20 deletions

View File

@@ -1,11 +1,10 @@
7.08.03 7.08.03
Fixed bug in `gam <UserTypeEntity> check|update serviceaccount` where the first use of Removed the overly broad service account `IAM and Access Management API` scope `https://www.googleapis.com/auth/cloud-platform`
the command after project creation enabled the following scopes that should be off by default. from DWD. The `gam <UserTypeEntity> check|Update serviceaccount` commands issue an error message if this scope
``` is enabled promptig you to update your service account authorization so that the scope can be removed.
Identity and Access Management API
Youtube API - read only GAM commands that need IAM access now use the more limited scope `https://www.googleapis.com/auth/iam` in a non-DWD manner.
```
7.08.02 7.08.02

View File

@@ -10632,6 +10632,7 @@ def getOAuthClientIDAndSecret():
invalidClientSecretsJsonExit(str(e)) invalidClientSecretsJsonExit(str(e))
def getScopesFromUser(scopesList, clientAccess, currentScopes=None): def getScopesFromUser(scopesList, clientAccess, currentScopes=None):
forceOffScopes = []
OAUTH2_CMDS = ['s', 'u', 'e', 'c'] OAUTH2_CMDS = ['s', 'u', 'e', 'c']
oauth2_menu = '' oauth2_menu = ''
numScopes = len(scopesList) numScopes = len(scopesList)
@@ -10682,6 +10683,9 @@ Continue to authorization by entering a 'c'
break break
i += 1 i += 1
else: else:
for api in currentScopes:
if api in API.FORCE_OFF_SA_SCOPES:
forceOffScopes.extend(currentScopes[api])
i = 0 i = 0
for a_scope in scopesList: for a_scope in scopesList:
selectedScopes[i] = ' ' selectedScopes[i] = ' '
@@ -10750,12 +10754,12 @@ Continue to authorization by entering a 'c'
for i in range(numScopes): for i in range(numScopes):
selectedScopes[i] = ' ' selectedScopes[i] = ' '
elif selection == 'e': elif selection == 'e':
return None return (None, None)
break break
sys.stdout.write(f'{ERROR_PREFIX}Invalid input "{choice}"\n') sys.stdout.write(f'{ERROR_PREFIX}Invalid input "{choice}"\n')
if selection == 'c': if selection == 'c':
break break
return selectedScopes return (selectedScopes, forceOffScopes)
def _localhost_to_ip(): def _localhost_to_ip():
'''returns IPv4 or IPv6 loopback address which localhost resolves to. '''returns IPv4 or IPv6 loopback address which localhost resolves to.
@@ -11102,7 +11106,7 @@ def doOAuthRequest(currentScopes, login_hint, verifyScopes=False):
client_id, client_secret = getOAuthClientIDAndSecret() client_id, client_secret = getOAuthClientIDAndSecret()
scopesList = API.getClientScopesList(GC.Values[GC.TODRIVE_CLIENTACCESS]) scopesList = API.getClientScopesList(GC.Values[GC.TODRIVE_CLIENTACCESS])
if not currentScopes or verifyScopes: if not currentScopes or verifyScopes:
selectedScopes = getScopesFromUser(scopesList, True, currentScopes) selectedScopes, _ = getScopesFromUser(scopesList, True, currentScopes)
if selectedScopes is None: if selectedScopes is None:
return False return False
scopes = set(API.REQUIRED_SCOPES) scopes = set(API.REQUIRED_SCOPES)
@@ -12246,6 +12250,7 @@ def checkServiceAccount(users):
checkScopesSet = set() checkScopesSet = set()
saScopes = {} saScopes = {}
useColor = False useColor = False
forceOffScopes = []
while Cmd.ArgumentsRemaining(): while Cmd.ArgumentsRemaining():
myarg = getArgument() myarg = getArgument()
if myarg in {'scope', 'scopes'}: if myarg in {'scope', 'scopes'}:
@@ -12271,12 +12276,16 @@ def checkServiceAccount(users):
testWarn = 'WARN' testWarn = 'WARN'
if Act.Get() == Act.CHECK: if Act.Get() == Act.CHECK:
if not checkScopesSet: if not checkScopesSet:
for scope in iter(GM.Globals[GM.SVCACCT_SCOPES].values()): currentScopes = GM.Globals[GM.SVCACCT_SCOPES]
checkScopesSet.update(scope) for api in currentScopes:
if api in API.FORCE_OFF_SA_SCOPES:
forceOffScopes.extend(currentScopes[api])
else:
checkScopesSet.update(currentScopes[api])
else: else:
if not checkScopesSet: if not checkScopesSet:
scopesList = API.getSvcAcctScopesList(GC.Values[GC.USER_SERVICE_ACCOUNT_ACCESS_ONLY], True) scopesList = API.getSvcAcctScopesList(GC.Values[GC.USER_SERVICE_ACCOUNT_ACCESS_ONLY], True)
selectedScopes = getScopesFromUser(scopesList, False, GM.Globals[GM.SVCACCT_SCOPES] if GM.Globals[GM.SVCACCT_SCOPES_DEFINED] else None) selectedScopes, forceOffScopes = getScopesFromUser(scopesList, False, GM.Globals[GM.SVCACCT_SCOPES] if GM.Globals[GM.SVCACCT_SCOPES_DEFINED] else None)
if selectedScopes is None: if selectedScopes is None:
return False return False
i = 0 i = 0
@@ -12399,6 +12408,17 @@ def checkServiceAccount(users):
scopeStatus = testFail scopeStatus = testFail
allScopesPass = False allScopesPass = False
printPassFail(scope, f'{scopeStatus}{currentCount(j, jcount)}') printPassFail(scope, f'{scopeStatus}{currentCount(j, jcount)}')
if forceOffScopes:
allScopesPass = False
if useColor:
scopeStatus = createRedText('DISABLE')
else:
scopeStatus = 'DISABLE'
jcount = len(forceOffScopes)
j = 0
for scope in forceOffScopes:
j +=1
printPassFail(scope, f'{scopeStatus}{currentCount(j, jcount)}')
Ind.Decrement() Ind.Decrement()
service_account = GM.Globals[GM.OAUTH2SERVICE_JSON_DATA]['client_id'] service_account = GM.Globals[GM.OAUTH2SERVICE_JSON_DATA]['client_id']
if allScopesPass: if allScopesPass:

View File

@@ -118,6 +118,7 @@ JWT_APIS = {
ACCESSCONTEXTMANAGER: [CLOUD_PLATFORM_SCOPE], ACCESSCONTEXTMANAGER: [CLOUD_PLATFORM_SCOPE],
CHAT: ['https://www.googleapis.com/auth/chat.bot'], CHAT: ['https://www.googleapis.com/auth/chat.bot'],
CLOUDRESOURCEMANAGER: [CLOUD_PLATFORM_SCOPE], CLOUDRESOURCEMANAGER: [CLOUD_PLATFORM_SCOPE],
IAM: [IAM_SCOPE],
ORGPOLICY: [CLOUD_PLATFORM_SCOPE], ORGPOLICY: [CLOUD_PLATFORM_SCOPE],
} }
# #
@@ -131,6 +132,8 @@ APIS_NEEDING_ACCESS_TOKEN = {
CBCM: ['https://www.googleapis.com/auth/admin.directory.device.chromebrowsers'] CBCM: ['https://www.googleapis.com/auth/admin.directory.device.chromebrowsers']
} }
# #
FORCE_OFF_SA_SCOPES = {IAM}
#
REFRESH_PERM_ERRORS = [ REFRESH_PERM_ERRORS = [
'invalid_grant: reauth related error (rapt_required)', # no way to reauth today 'invalid_grant: reauth related error (rapt_required)', # no way to reauth today
'invalid_grant: Token has been expired or revoked', 'invalid_grant: Token has been expired or revoked',
@@ -645,11 +648,11 @@ _SVCACCT_SCOPES = [
'api': GMAIL, 'api': GMAIL,
'subscopes': [], 'subscopes': [],
'scope': 'https://www.googleapis.com/auth/gmail.settings.sharing'}, 'scope': 'https://www.googleapis.com/auth/gmail.settings.sharing'},
{'name': 'Identity and Access Management API', # {'name': 'Identity and Access Management API',
'api': IAM, # 'api': IAM,
'offByDefault': True, # 'offByDefault': True,
'subscopes': [], # 'subscopes': [],
'scope': IAM_SCOPE}, # 'scope': IAM_SCOPE},
{'name': 'Keep API', {'name': 'Keep API',
'api': KEEP, 'api': KEEP,
'subscopes': READONLY, 'subscopes': READONLY,

View File

@@ -145,7 +145,7 @@ SCOPE_AUTHORIZATION_PASSED = '''All scopes PASSED!
Service Account Client name: {0} is fully authorized. Service Account Client name: {0} is fully authorized.
''' '''
SCOPE_AUTHORIZATION_UPDATE_PASSED = '''All scopes PASSED! SCOPE_AUTHORIZATION_UPDATE_PASSED = '''All scopes PASSED!
To authorize them (in case some scopes were unselected), please go to the following link in your browser: To update authorization (in case some scopes were unselected), please go to the following link in your browser:
{0} {0}
{1} {1}
@@ -156,8 +156,8 @@ Click AUTHORIZE
When the box closes you're done When the box closes you're done
After authorizing it may take some time for this test to pass so wait a few moments and then try this command again. After authorizing it may take some time for this test to pass so wait a few moments and then try this command again.
''' '''
SCOPE_AUTHORIZATION_FAILED = '''Some scopes FAILED! SCOPE_AUTHORIZATION_FAILED = '''Some scopes FAILED or should be DISABLED!
To authorize them, please go to the following link in your browser: To update authorization, please go to the following link in your browser:
{0} {0}
{1} {1}