Membuat kueri keanggotaan grup

Panduan ini menunjukkan cara membuat kueri keanggotaan grup secara transitif dan mengambil grafik keanggotaan anggota.

Selain mencantumkan anggota langsung grup, Anda dapat secara transitif menelusuri keanggotaan langsung dan tidak langsung serta melihat grafik keanggotaan anggota tertentu. Kemampuan ini mengatasi kasus penggunaan berikut:

  • Pemilik resource dapat membuat keputusan yang lebih tepat tentang perubahan ACL resource dengan memahami grup dan anggota mana yang terpengaruh oleh perubahan tersebut.
  • Pemilik grup dapat menilai dampak penambahan atau penghapusan grup dari grup yang terkait dengan kontrol ACL, dan menyelesaikan masalah keanggotaan dengan lebih mudah.
  • Auditor keamanan dapat mengaudit kebijakan akses secara lebih efektif karena struktur keanggotaan yang diperluas di seluruh organisasi mereka terlihat.
  • Auditor keamanan dapat menilai risiko keamanan anggota dengan melihat semua keanggotaan grup langsung dan tidak langsung mereka, atau memeriksa apakah anggota termasuk dalam grup tertentu.

Keanggotaan grup dapat dimiliki oleh individu, akun layanan, atau grup lain.

Pengguna atau akun layanan yang membuat kueri harus memiliki izin untuk melihat keanggotaan semua grup yang merupakan bagian dari kueri. Jika tidak, permintaan akan gagal. Jika kueri menampilkan error "PERMISSION_DENIED", mungkin Anda tidak memiliki izin yang benar untuk salah satu grup bertingkat, terutama jika salah satunya adalah grup yang dimiliki oleh organisasi lain.

Sebelum memulai

Aktifkan API Cloud Identity.

Mengaktifkan API

Menelusuri semua keanggotaan dalam grup

Kode ini menampilkan semua keanggotaan grup. Responsnya mencakup jenis keanggotaan (langsung, tidak langsung, atau keduanya) untuk setiap keanggotaan.

REST

Untuk mendapatkan daftar semua keanggotaan dalam grup, panggil groups.memberships.searchTransitiveMemberships() dengan ID grup induk.

Python

Untuk mengautentikasi ke Cloud Identity, siapkan Kredensial Default Aplikasi. Untuk mengetahui informasi selengkapnya, baca Menyiapkan autentikasi untuk lingkungan pengembangan lokal.

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

Menelusuri semua keanggotaan grup milik anggota

REST

Untuk menemukan semua grup tempat anggota berada, panggil groups.memberships.searchTransitiveGroups() dengan kunci anggota (misalnya, alamat email anggota).

Python

Untuk mengautentikasi ke Cloud Identity, siapkan Kredensial Default Aplikasi. Untuk mengetahui informasi selengkapnya, baca Menyiapkan autentikasi untuk lingkungan pengembangan lokal.

Kode ini menampilkan semua grup tempat seorang anggota berada (kecuali grup yang dipetakan identitasnya), baik secara langsung maupun tidak langsung.

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

Memeriksa keanggotaan dalam grup

REST

Untuk memeriksa apakah anggota termasuk dalam grup tertentu (baik secara langsung maupun tidak langsung), panggil checkTransitiveMembership() dengan ID grup induk dan kunci anggota (misalnya, alamat email anggota).

Python

Untuk mengautentikasi ke Cloud Identity, siapkan Kredensial Default Aplikasi. Untuk mengetahui informasi selengkapnya, baca Menyiapkan autentikasi untuk lingkungan pengembangan lokal.

Kode berikut menentukan apakah anggota termasuk dalam grup tertentu:

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

Mengambil grafik langganan untuk pelanggan

REST

Untuk mendapatkan grafik keanggotaan anggota (semua grup tempat anggota berada, beserta informasi jalur), panggil groups.memberships.getMembershipGraph() dengan ID grup induk dan kunci anggota (misalnya, alamat email anggota). Grafik ditampilkan sebagai daftar adjacency.

Python

Untuk mengautentikasi ke Cloud Identity, siapkan Kredensial Default Aplikasi. Untuk mengetahui informasi selengkapnya, baca Menyiapkan autentikasi untuk lingkungan pengembangan lokal.

Kode berikut menampilkan grafik keanggotaan tertentu dari anggota tertentu dalam Google Grup (kueri ini difilter menurut jenis grup menggunakan label):

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

Membuat representasi visual dari grafik keanggotaan

Berikut adalah contoh respons dari kode Python di atas. Dalam contoh ini, grup 000, 111, dan 222 terhubung sebagai berikut (panah berasal dari induk ke turunan): 000 -> 111 -> 222. Panggilan ke kode contoh untuk mengambil grafik lengkap untuk grup 222:

get_membership_graph(service, 'groups/-', '[email protected]')

menghasilkan respons berikut:

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

Setiap item dalam daftar yang ada di dekatnya mewakili grup dan anggota langsungnya (tepi) dan responsnya juga menyertakan detail semua grup dalam grafik keanggotaan. Elemen ini dapat diurai untuk menghasilkan representasi alternatif (misalnya, grafik DOT) yang dapat digunakan untuk memvisualisasikan grafik keanggotaan.

Contoh skrip ini dapat digunakan untuk mengonversi respons menjadi grafik 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='[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)

Berikut adalah hierarki visual yang dihasilkan untuk contoh respons:

Contoh grafik keanggotaan dari konversi DOT