Esecuzione di query sulle appartenenze ai gruppi
Questa guida illustra come eseguire query transitive sulle iscrizioni ai gruppi e recuperare il grafico delle iscrizioni di un membro.
Oltre a elencare i membri diretti di un gruppo, puoi cercare in modo transitivo le iscrizioni dirette e indirette e visualizzare il grafico delle iscrizioni di un membro specifico. Queste funzionalità sono utili per i seguenti casi d'uso:
- I proprietari delle risorse possono prendere decisioni più consapevoli sulle modifiche all'ACL delle risorse comprendendo quali gruppi e membri sono interessati dalle modifiche.
- I proprietari di gruppi possono valutare l'impatto dell'aggiunta o della rimozione di un gruppo da un gruppo relativo al controllo ACL e risolvere più facilmente i problemi relativi all'appartenenza.
- I revisori della sicurezza possono controllare in modo più efficace i criteri di accesso perché è visibile la struttura dei membri ampliata dell'intera organizzazione.
- I revisori della sicurezza possono valutare il rischio per la sicurezza di un membro visualizzando tutte le loro iscrizioni dirette e indirette ai gruppi o verificando se un membro appartiene a un gruppo specifico.
L'appartenenza a un gruppo può appartenere a un individuo, a un account di servizio o a un altro gruppo.
L'account utente o di servizio che esegue la query deve disporre dell'autorizzazione per visualizzare le iscrizioni di tutti i gruppi che fanno parte della query, altrimenti la richiesta avrà esito negativo. Se la query restituisce un errore "PERMISSION_DENIED", è probabile che tu non disponga delle autorizzazioni corrette per uno dei gruppi nidificati, soprattutto se uno di questi è un gruppo di proprietà di un'altra organizzazione.
Prima di iniziare
Attiva l'API Cloud Identity.
Ricerca di tutte le iscrizioni a un gruppo
Questo codice restituisce tutte le iscrizioni a un gruppo. La risposta include il tipo di appartenenza (diretta, indiretta o entrambi) per ogni appartenenza.
REST
Per visualizzare un elenco di tutte le iscrizioni in un gruppo, chiama il numero
groups.memberships.searchTransitiveMemberships()
con l'ID del gruppo principale.
Python
Per eseguire l'autenticazione su Cloud Identity, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.
import googleapiclient.discovery
from urllib.parse import urlencode
def search_transitive_memberships(service, parent, page_size):
try:
memberships = []
next_page_token = ''
while True:
query_params = urlencode(
{
"page_size": page_size,
"page_token": next_page_token
}
)
request = service.groups().memberships().searchTransitiveMemberships(parent=parent)
request.uri += "&" + query_params
response = request.execute()
if 'memberships' in response:
memberships += response['memberships']
if 'nextPageToken' in response:
next_page_token = response['nextPageToken']
else:
next_page_token = ''
if len(next_page_token) == 0:
break;
print(memberships)
except Exception as e:
print(e)
def main():
service = googleapiclient.discovery.build('cloudidentity', 'v1')
# Return results with a page size of 50
search_transitive_memberships(service, 'groups/GROUP_ID', 50)
if __name__ == '__main__':
main()
Ricerca di tutte le iscrizioni al gruppo di un membro
REST
Per trovare tutti i gruppi a cui appartiene un membro, chiama groups.memberships.searchTransitiveGroups()
utilizzando la chiave del membro (ad esempio l'indirizzo email del membro).
Python
Per eseguire l'autenticazione su Cloud Identity, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.
Questo codice restituisce tutti i gruppi a cui appartiene un membro (tranne quelli con mappatura delle identità), sia direttamente che indirettamente.
import googleapiclient.discovery
from urllib.parse import urlencode
def search_transitive_groups(service, member, page_size):
try:
groups = []
next_page_token = ''
while True:
query_params = urlencode(
{
"query": "member_key_id == '{}' && 'cloudidentity.googleapis.com/groups.discussion_forum' in labels".format(member),
"page_size": page_size,
"page_token": next_page_token
}
)
request = service.groups().memberships().searchTransitiveGroups(parent='groups/-')
request.uri += "&" + query_params
response = request.execute()
if 'memberships' in response:
groups += response['memberships']
if 'nextPageToken' in response:
next_page_token = response['nextPageToken']
else:
next_page_token = ''
if len(next_page_token) == 0:
break;
print(groups)
except Exception as e:
print(e)
def main():
service = googleapiclient.discovery.build('cloudidentity', 'v1')
# Return results with a page size of 50
search_transitive_groups(service, 'MEMBER_EMAIL_ADDRESS', 50)
if __name__ == '__main__':
main()
Verifica dell'appartenenza a un gruppo
REST
Per verificare se un membro appartiene a un gruppo specifico (direttamente o indirettamente), chiama
checkTransitiveMembership()
con l'ID del gruppo principale e la chiave del membro (ad esempio l'indirizzo
email del membro).
Python
Per eseguire l'autenticazione su Cloud Identity, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.
Il seguente codice determina se il membro appartiene a un gruppo specifico:
import googleapiclient.discovery
from urllib.parse import urlencode
def check_transitive_membership(service, parent, member):
try:
query_params = urlencode(
{
"query": "member_key_id == '{}'".format(member)
}
)
request = service.groups().memberships().checkTransitiveMembership(parent=parent)
request.uri += "&" + query_params
response = request.execute()
print(response['hasMembership'])
except Exception as e:
print(e)
def main():
service = googleapiclient.discovery.build('cloudidentity', 'v1')
check_transitive_membership(service, 'groups/GROUP_ID', 'MEMBER_EMAIL_ADDRESS')
if __name__ == '__main__':
main()
Recupero del grafico delle iscrizioni per un membro
REST
Per ottenere il grafico delle iscrizioni di un membro (tutti i gruppi a cui appartiene
un membro, insieme alle informazioni sul percorso), chiama
groups.memberships.getMembershipGraph()
con l'ID del gruppo principale e la chiave del membro (ad esempio, l'indirizzo
email del membro). Il grafico viene restituito come elenco adiacente.
Python
Per eseguire l'autenticazione su Cloud Identity, configura Credenziali predefinite dell'applicazione. Per maggiori informazioni, consulta Configurare l'autenticazione per un ambiente di sviluppo locale.
Il seguente codice restituisce il grafico delle iscrizioni di un membro specificato in un gruppo Google (questa query viene filtrata in base al tipo di gruppo utilizzando l'etichetta):
import googleapiclient.discovery
from urllib.parse import urlencode
def get_membership_graph(service, parent, member):
try:
query_params = urlencode(
{
"query": "member_key_id == '{}' && 'cloudidentity.googleapis.com/groups.discussion_forum' in labels".format(member)
}
)
request = service.groups().memberships().getMembershipGraph(parent=parent)
request.uri += "&" + query_params
response = request.execute()
print(response['response'])
except Exception as e:
print(e)
def main()
service = googleapiclient.discovery.build('cloudidentity', 'v1')
# Specify parent group as 'groups/-' to get ALL the groups of a member
# along with path information
get_membership_graph(service, 'groups/GROUP_ID', 'MEMBER_KEY')
if __name__ == '__main__':
main()
Creazione di una rappresentazione visiva del grafico delle iscrizioni
Di seguito è riportato un esempio di risposta dal codice Python riportato sopra. In questo esempio, i gruppi 000, 111 e 222 sono collegati come segue (le frecce vanno dall'elemento padre all'elemento figlio): 000 -> 111 -> 222. Una chiamata al codice campione per recuperare il grafico completo per il gruppo 222:
get_membership_graph(service, 'groups/-', 'group-2@example.com')
genera la seguente risposta:
{
"@type": "type.googleapis.com/google.apps.cloudidentity.groups.v1.GetMembershipGraphResponse",
"adjacencyList": [
{
"edges": [
{
"name": "groups/000/memberships/111",
"preferredMemberKey": {
"id": "group-1@example.com"
},
"roles": [
{
"name": "MEMBER"
}
]
}
],
"group": "groups/000"
},
{
"edges": [
{
"name": "groups/111/memberships/222",
"preferredMemberKey": {
"id": "group-2@example.com"
},
"roles": [
{
"name": "MEMBER"
}
]
}
],
"group": "groups/111"
}
],
"groups": [
{
"name": "groups/000",
"groupKey": {
"id": "group-0@example.com"
},
"displayName": "Group - 0",
"description": "Group - 0",
"labels": {
"cloudidentity.googleapis.com/groups.discussion_forum": ""
}
},
{
"name": "groups/111",
"groupKey": {
"id": "group-1@example.com"
},
"displayName": "Group - 1",
"description": "Group - 1",
"labels": {
"cloudidentity.googleapis.com/groups.discussion_forum": ""
}
},
{
"name": "groups/222",
"groupKey": {
"id": "group-2@example.com"
},
"displayName": "Group - 2",
"description": "Group - 2",
"labels": {
"cloudidentity.googleapis.com/groups.discussion_forum": ""
}
}
]
}
Ogni elemento nell'elenco adiacente rappresenta un gruppo e i suoi membri diretti (edge) e la risposta include anche i dettagli di tutti i gruppi nel grafico di appartenenza. Può essere analizzato per generare rappresentazioni alternative (ad esempio, un grafico DOT) che possono essere utilizzate per visualizzare il grafico delle iscrizioni.
Questo script di esempio può essere utilizzato per convertire la risposta in un grafico DOT:
#
# Generates output in a dot format. Invoke this method using
# response['response'] from get_membership_graph()
#
# Save the output to a .dot file (say graph.dot)
# Use the dot tool to generate a visualization of the graph
# Example:
# dot -Tpng -o graph.png graph.dot
#
# Generates output like below:
#
# digraph {
# 'group0' [label='groups/000 (GROUP 0)'];
# 'group1' [label='groups/111 (GROUP 1)'];
# 'group2' [label='groups/222 (GROUP 2)'];
# 'group3' [label='groups/333 (GROUP 3)'];
# 'group4' [label='groups/444 (GROUP 4)'];
#
# 'group0' -> 'group1' [label='group-1@example.com (MEMBER)'];
# 'group0' -> 'group2' [label='group-2@example.com (MEMBER)'];
# 'group1' -> 'group3' [label='group-3@example.com (MEMBER)'];
# 'group3' -> 'group4' [label='group-4@example.com (MEMBER)'];
# 'group2' -> 'group3' [label='group-3@example.com (MEMBER)'];
# }
#
def convert_to_dot_format(graph):
output = "digraph {\n"
try:
# Generate labels for the group nodes
for group in graph['groups']:
if 'displayName' in group:
label = '{} ({})'.format(group['name'], group['displayName'])
else:
label = group['name']
output += ' "{}" [label="{}"];\n'.format(group['name'].split('/')[1], label)
output += '\n'
# Generate edges
for item in graph['adjacencyList']:
group_id = item['group'].split('/')[1]
for edge in item['edges']:
edge_to = edge['name'].split('/')[3]
edge_key = edge['preferredMemberKey']['id']
# Collect the roles
roles = []
for role in edge['roles']:
roles.append(role['name'])
output += ' "{}" -> "{}" [label="{} ({})"];\n'.format(group_id,
edge_to,
edge_key,
','.join(roles))
output += "}\n"
print(output)
except Exception as e:
print(e)
Di seguito è riportata la gerarchia visiva risultante per la risposta di esempio: