Interroger les adhésions aux groupes
Ce guide explique comment interroger les adhésions aux groupes de manière transitoire et récupérer le graphique d'appartenance d'un membre.
En plus de répertorier les membres directs d'un groupe, vous pouvez rechercher les adhésions directes et indirectes de manière transitoire et consulter le graphique d'adhésion d'un membre spécifique. Ces fonctionnalités répondent aux cas d'utilisation suivants :
- Les propriétaires de ressources peuvent prendre des décisions plus éclairées sur les modifications de la LCA des ressources en analysant les groupes et les membres concernés par les modifications.
- Les propriétaires de groupe peuvent évaluer l'impact de l'ajout ou de la suppression d'un groupe dans un groupe lié au contrôle de la LCA, et résoudre plus facilement les problèmes d'adhésion.
- Les auditeurs de sécurité peuvent auditer plus efficacement la stratégie d'accès, car la structure d'adhésion étendue de l'ensemble de l'organisation est visible.
- Les auditeurs de sécurité peuvent évaluer le risque de sécurité d'un membre en affichant toutes leurs adhésions directes et indirectes à des groupes, ou en vérifiant si un membre appartient à un groupe spécifique.
Une adhésion à un groupe peut concerner une personne, un compte de service ou un autre groupe.
L'utilisateur ou le compte de service qui effectue la requête doit être autorisé à afficher les adhésions de tous les groupes inclus dans la requête, sinon la requête échoue. Si la requête renvoie une erreur "PERMISSION_DENIED" (autorisation refusée), il est probable que vous ne disposiez pas des autorisations appropriées pour l'un des groupes imbriqués, en particulier si l'un d'eux est un groupe appartenant à une autre organisation.
Avant de commencer
Enable the Cloud Identity API.
Rechercher toutes les adhésions à un groupe
Ce code renvoie toutes les adhésions d'un groupe. La réponse inclut le type d'adhésion (directe, indirecte ou les deux) pour chacune d'elle.
REST
Pour obtenir la liste de toutes les adhésions à un groupe, appelez groups.memberships.searchTransitiveMemberships()
avec l'ID du groupe parent.
Python
Pour vous authentifier auprès de Cloud Identity, configurez le service Identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.
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()
Rechercher toutes les adhésions d'un membre à des groupes
REST
Pour rechercher tous les groupes auxquels un membre appartient, appelez groups.memberships.searchTransitiveGroups()
avec la clé de membre (par exemple, son adresse e-mail).
Python
Pour vous authentifier auprès de Cloud Identity, configurez le service Identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.
Ce code renvoie tous les groupes auxquels un membre appartient (à l'exception des groupe de mappage d'identité), à la fois directement et indirectement.
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()
Vérifier l'adhésion à un groupe
REST
Pour vérifier si un membre appartient à un groupe spécifique (soit directement,
indirectement), appeler
checkTransitiveMembership()
par l'ID du groupe parent et la clé du membre (par exemple, l'adresse e-mail
l'adresse du membre).
Python
Pour vous authentifier auprès de Cloud Identity, configurez le service Identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.
Le code suivant détermine si le membre appartient à un groupe spécifique :
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()
Récupérer le graphique d'adhésion d'un membre
REST
Pour obtenir le graphique d'adhésion d'un membre (tous les groupes auxquels un membre appartient, ainsi que les informations de chemin d'accès), appelez groups.memberships.getMembershipGraph()
avec l'ID du groupe parent et la clé de membre (par exemple, l'adresse e-mail du membre). Le graphique est renvoyé sous la forme d'une liste de contiguïté.
Python
Pour vous authentifier auprès de Cloud Identity, configurez les identifiants par défaut de l'application. Pour en savoir plus, consultez Configurer l'authentification pour un environnement de développement local.
Le code suivant renvoie le graphique d'adhésion d'un membre spécifié dans un groupe Google (cette requête est filtrée par type de groupe à l'aide de l'étiquette) :
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()
Créer une représentation visuelle du graphique d'adhésion
Voici un exemple de réponse généré à partir du code Python ci-dessus. Dans cet exemple, les groupes 000, 111 et 222 sont connectés comme suit (les flèches vont du parent vers l'enfant) : 000 -> 111 -> 222. Un appel à l'exemple de code pour récupérer le graphique complet pour le groupe 222 :
get_membership_graph(service, 'groups/-', '[email protected]')
génère la réponse suivante :
{
"@type": "type.googleapis.com/google.apps.cloudidentity.groups.v1.GetMembershipGraphResponse",
"adjacencyList": [
{
"edges": [
{
"name": "groups/000/memberships/111",
"preferredMemberKey": {
"id": "[email protected]"
},
"roles": [
{
"name": "MEMBER"
}
]
}
],
"group": "groups/000"
},
{
"edges": [
{
"name": "groups/111/memberships/222",
"preferredMemberKey": {
"id": "[email protected]"
},
"roles": [
{
"name": "MEMBER"
}
]
}
],
"group": "groups/111"
}
],
"groups": [
{
"name": "groups/000",
"groupKey": {
"id": "[email protected]"
},
"displayName": "Group - 0",
"description": "Group - 0",
"labels": {
"cloudidentity.googleapis.com/groups.discussion_forum": ""
}
},
{
"name": "groups/111",
"groupKey": {
"id": "[email protected]"
},
"displayName": "Group - 1",
"description": "Group - 1",
"labels": {
"cloudidentity.googleapis.com/groups.discussion_forum": ""
}
},
{
"name": "groups/222",
"groupKey": {
"id": "[email protected]"
},
"displayName": "Group - 2",
"description": "Group - 2",
"labels": {
"cloudidentity.googleapis.com/groups.discussion_forum": ""
}
}
]
}
Chaque élément de la liste de contiguïté représente un groupe et ses membres directs (Edges), et la réponse inclut également des détails sur tous les groupes du graphique d'adhésion. Vous pouvez l'analyser pour générer d'autres représentations (par exemple, un nuage de points) qui peuvent être utilisées pour visualiser le graphique d'adhésion.
Cet exemple de script peut être utilisé pour convertir la réponse en nuage de points :
#
# 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='[email protected] (MEMBER)'];
# 'group0' -> 'group2' [label='[email protected] (MEMBER)'];
# 'group1' -> 'group3' [label='[email protected] (MEMBER)'];
# 'group3' -> 'group4' [label='[email protected] (MEMBER)'];
# 'group2' -> 'group3' [label='[email protected] (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)
Voici la hiérarchie visuelle obtenue pour l'exemple de réponse :