Gruppenmitgliedschaften abfragen

In diesem Leitfaden wird gezeigt, wie Sie eine Gruppenmitgliedschaft transitiv abfragen und das Mitgliedsdiagramm eines Mitglieds abrufen können.

Zusätzlich zur Auflistung der direkten Mitglieder einer Gruppe können Sie auch transitiv sowohl direkte als auch indirekte Mitgliedschaften suchen und sich das Mitgliedschaftsdiagramm eines bestimmten Mitglieds anzeigen lassen. Diese Funktionen sind für folgende Anwendungsfälle relevant:

  • Ressourceninhaber können fundierte Entscheidungen über Änderungen an Ressourcen-ACLs treffen, wenn sie verstehen, welche Gruppen und Mitglieder von Änderungen betroffen sind.
  • Gruppeninhaber können die Auswirkungen des Hinzufügens oder Entfernens einer Gruppe zu/von einer Gruppe mit ACL-Kontrolle besser bewerten und Mitgliedschaftsprobleme einfacher lösen.
  • Sicherheitsprüfer können Zugriffsrichtlinien effektiver prüfen, da die erweiterte Mitgliedschaftsstruktur ihrer gesamten Organisation sichtbar ist.
  • Sicherheitsprüfer können das Sicherheitsrisiko eines Mitglieds bewerten. Dazu müssen sie sich ihre direkten und indirekten Gruppenmitgliedschaften ansehen oder prüfen, ob ein Mitglied zu einer bestimmten Gruppe gehört.

Eine Gruppenmitgliedschaft kann zu einer Einzelperson, einem Dienstkonto oder einer anderen Gruppe gehören.

Das Nutzer- oder Dienstkonto, von dem die Abfrage stammt, muss die Berechtigung zum Anzeigen der Mitgliedschaften aller Gruppen haben, die Teil der Abfrage sind. Andernfalls schlägt die Anfrage fehl. Wenn die Abfrage den Fehler „PERMISSION_DENIED” zurückgibt, haben Sie wahrscheinlich nicht die richtigen Berechtigungen für eine der verschachtelten Gruppen, insbesondere wenn eine dieser Gruppen zu einer anderen Organisation gehört.

Hinweise

Cloud Identity API aktivieren.

Aktivieren Sie die API

Nach allen Mitgliedschaften in einer Gruppe suchen

Dieser Code gibt alle Mitgliedschaften einer Gruppe zurück. Die Antwort enthält für jede Mitgliedschaft den Typ der Mitgliedschaft (direkt, indirekt oder beides).

REST

Rufen Sie groups.memberships.searchTransitiveMemberships() mit der ID der übergeordneten Gruppe auf, um eine Liste aller Mitgliedschaften in einer Gruppe abzurufen.

Python

Richten Sie für die Authentifizierung bei Cloud Identity Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.

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()

Nach allen Gruppenmitgliedschaften eines Mitglieds suchen

REST

Wenn Sie alle Gruppen ermitteln möchten, zu denen ein Mitglied gehört, rufen Sie groups.memberships.searchTransitiveGroups() mit dem Mitgliedsschlüssel (z. B. der E-Mail-Adresse des Mitglieds) auf.

Python

Richten Sie für die Authentifizierung bei Cloud Identity Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.

Dieser Code gibt alle Gruppen zurück, zu denen ein Mitglied gehört (mit Ausnahme von Gruppen mit Identitätszuweisung), sowohl direkt als auch indirekt.

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()

Mitgliedschaft in einer Gruppe prüfen

REST

Wenn Sie prüfen möchten, ob ein Mitglied zu einer bestimmten Gruppe gehört (entweder direkt oder indirekt), rufen Sie checkTransitiveMembership() mit der ID der übergeordneten Gruppe und dem Mitgliedsschlüssel (z. B. die E-Mail-Adresse des Mitglieds) auf.

Python

Richten Sie für die Authentifizierung bei Cloud Identity Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.

Folgender Code bestimmt, ob das Mitglied zu einer bestimmten Gruppe gehört:

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()

Mitgliedschaftsdiagramm für ein Mitglied abrufen

REST

Rufen Sie groups.memberships.getMembershipGraph() mit der ID die übergeordnete Gruppe und den Mitgliedsschlüssel (z. B. die E-Mail-Adresse des Mitglieds) auf, um das Mitgliedschaftsdiagramm (alle Gruppen, zu denen ein Mitglied gehört, zusammen mit den Pfadinformationen) eines Mitglieds zu erhalten. Das Diagramm wird als Adjazenzliste zurückgegeben.

Python

Richten Sie für die Authentifizierung bei Cloud Identity Standardanmeldedaten für Anwendungen ein. Weitere Informationen finden Sie unter Authentifizierung für eine lokale Entwicklungsumgebung einrichten.

Mit dem folgenden Code wird die Mitgliedschaftsgrafik eines bestimmten Mitglieds in einer Google-Gruppe zurückgegeben (diese Abfrage wird anhand des Labels nach Gruppentyp gefiltert):

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()

Eine visuelle Darstellung des Mitgliedsdiagramms erstellen

Das folgende Beispiel zeigt eine Antwort vom Python-Code oben. In diesem Beispiel sind die Gruppen 000, 111 und 222 so verbunden (Pfeile sind vom übergeordneten zum untergeordneten Element): 000 -> 111 -> 222. Ein Aufruf des Beispielcodes zum Abrufen der vollständigen Grafik für Gruppe 222:

get_membership_graph(service, 'groups/-', 'group-2@example.com')

führt zur folgenden Antwort:

{
  "@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": ""
      }
    }
  ]
}

Jedes Element in der Adjazenz-Liste stellt eine Gruppe und deren direkte Mitglieder (Edges) dar. Die Antwort enthält auch Details zu allen Gruppen im Mitgliedschaftsdiagramm. Sie kann geparst werden, um alternative Darstellungen (z. B. ein DOT-Diagramm) zu generieren, die zur Visualisierung des Mitgliedsdiagramms dienen können.

Dieses Beispielskript kann verwendet werden, um die Antwort in eine DOT-Grafik zu konvertieren:

#
# 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)

Im Folgenden ist die resultierende visuelle Hierarchie der Beispielantwort dargestellt:

Beispiel eines Mitgliedschaftsdiagramms per DOT-Konvertierung