Consultar membros do grupo
Este guia demonstra como consultar transitivamente as associações a grupos e obter o gráfico de associações de um membro.
Além de listar os membros diretos de um grupo, pode pesquisar transitivamente membros diretos e indiretos, e ver o gráfico de membros de um membro específico. Estas capacidades abordam os seguintes exemplos de utilização:
- Os proprietários de recursos podem tomar decisões mais informadas sobre as alterações às ACLs de recursos, compreendendo que grupos e membros são afetados pelas alterações.
- Os proprietários do grupo podem avaliar o impacto da adição ou remoção de um grupo de um grupo relacionado com o controlo da LCA e resolver mais facilmente problemas de inscrição.
- Os auditores de segurança podem auditar a política de acesso de forma mais eficaz porque a estrutura de associação expandida de toda a organização é visível.
- Os auditores de segurança podem avaliar o risco de segurança de um membro através da visualização de todas as respetivas associações a grupos diretas e indiretas ou verificando se um membro pertence a um grupo específico.
Uma associação a um grupo pode pertencer a um indivíduo, a uma conta de serviço ou a outro grupo.
O utilizador ou a conta de serviço que está a fazer a consulta tem de ter permissão para ver as associações de todos os grupos que fazem parte da consulta. Caso contrário, o pedido falha. Se a consulta devolver um erro "PERMISSION_DENIED", é provável que não tenha as autorizações corretas para um dos grupos aninhados, especialmente se um deles for um grupo pertencente a outra organização.
Antes de começar
Enable the Cloud Identity API.
Roles required to enable APIs
To enable APIs, you need the Service Usage Admin IAM
role (roles/serviceusage.serviceUsageAdmin
), which
contains the serviceusage.services.enable
permission. Learn how to grant
roles.
Pesquisar todas as associações num grupo
Este código devolve todas as associações de um grupo. A resposta inclui o tipo de subscrição (direta, indireta ou ambas) para cada subscrição.
REST
Para receber uma lista de todas as associações num grupo, chame
groups.memberships.searchTransitiveMemberships()
com o ID do grupo principal.
Python
Para se autenticar no Cloud ID, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento 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()
Pesquisar todos os registos de membro de um membro
REST
Para encontrar todos os grupos aos quais um membro pertence, chame
groups.memberships.searchTransitiveGroups()
com a chave do membro (por exemplo, o endereço de email do membro).
Python
Para se autenticar no Cloud ID, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
Este código devolve todos os grupos aos quais um membro pertence (exceto grupos mapeados por identidade), tanto direta como indiretamente.
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()
Verificar a subscrição de um grupo
REST
Para verificar se um membro pertence a um grupo específico (direta ou
indiretamente), chame
checkTransitiveMembership()
com o ID do grupo principal e a chave do membro (por exemplo, o endereço de email
do membro).
Python
Para se autenticar no Cloud ID, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
O código seguinte determina se o membro pertence a um grupo específico:
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()
Obter o gráfico de associação de um membro
REST
Para obter o gráfico de associação de um membro (todos os grupos aos quais um membro pertence, juntamente com as informações do caminho), chame groups.memberships.getMembershipGraph()
com o ID do grupo principal e a chave do membro (por exemplo, o endereço de email do membro). O gráfico é devolvido como uma lista de adjacências.
Python
Para se autenticar no Cloud ID, configure as Credenciais padrão da aplicação. Para mais informações, consulte o artigo Configure a autenticação para um ambiente de desenvolvimento local.
O código seguinte devolve o gráfico de associação de um membro especificado num grupo Google (esta consulta é filtrada por tipo de grupo através da etiqueta):
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()
Criar uma representação visual do gráfico de associação
Segue-se um exemplo de resposta do código Python acima. Neste exemplo, os grupos 000, 111 e 222 estão ligados da seguinte forma (as setas indicam a ligação do grupo principal ao grupo secundário): 000 -> 111 -> 222. Uma chamada ao código de exemplo para obter o gráfico completo do grupo 222:
get_membership_graph(service, 'groups/-', 'group-2@example.com')
resulta na seguinte resposta:
{
"@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": ""
}
}
]
}
Cada item na lista de adjacências representa um grupo e os respetivos membros diretos (arestas), e a resposta também inclui detalhes de todos os grupos no gráfico de associação. Pode ser analisado para gerar representações alternativas (por exemplo, um gráfico DOT) que podem ser usadas para visualizar o gráfico de associação.
Este script de exemplo pode ser usado para converter a resposta num gráfico 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)
Segue-se a hierarquia visual resultante para a resposta de exemplo: