Como consultar associações a grupos
Neste guia, demonstramos como consultar temporariamente as associações a grupos e recuperar o gráfico de associação de um membro.
Importante: estes recursos estão disponíveis apenas para contas premium do Cloud Identity Premium, Google Workspace Enterprise Standard, Enterprise Plus e Enterprise for Education.Além de listar os membros diretos de um grupo, é possível pesquisar transitivamente por assinaturas diretas e indiretas e visualizar o gráfico de associação de um membro específico. Esses recursos abordam os seguintes casos de uso:
- Os proprietários de recursos podem tomar decisões mais fundamentadas sobre alterações na ACL do recurso. Para isso, é preciso entender quais grupos e membros são afetados pelas alterações.
- Os proprietários de grupos podem avaliar o impacto de adicionar ou remover um grupo de um grupo relacionado ao controle de ACL e resolver mais facilmente problemas de associação.
- Os auditores de segurança podem auditar a política de acesso com mais eficácia porque a estrutura de associação expandida da organização inteira fica visível.
- Os auditores de segurança podem avaliar o risco de segurança de um membro visualizando todas as suas associações a grupos diretas e indiretas ou verificando se um membro pertence a um grupo específico.
Observação: uma associação a um grupo pode pertencer a uma pessoa, uma conta de serviço ou a outro grupo.
A conta de usuário ou de serviço que está fazendo a consulta precisa ter permissão para visualizar as associações de todos os grupos que fazem parte da consulta. Caso contrário, a solicitação falhará. Se a consulta retorna um erro "PERMISSION_DENIED", é provável que você não tenha as permissões corretas para um dos grupos aninhados, especialmente se um deles for de um grupo de outra organização.
Antes de começar
Enable the Cloud Identity API.
Como pesquisar por todas as associações de um grupo
Esse código retorna todas as associações de um grupo. A resposta inclui o tipo de associação (direta, indireta ou ambas) para cada associação.
REST
Para ver uma lista de todas as associações de um grupo, chame
groups.memberships.searchTransitiveMemberships()
pelo ID do grupo pai.
Python
Para autenticar no Cloud Identity, configure o Application Default Credentials. Para mais informações, consulte Configurar 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 todas as associações a grupos de um membro
REST
Para encontrar todos os grupos a que um membro pertence, chame
groups.memberships.searchTransitiveGroups()
com a chave de membro (por exemplo, o endereço de e-mail do membro).
Python
Para autenticar no Cloud Identity, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
Esse código retorna todos os grupos a que um membro pertence (exceto grupos mapeados por identidade), direta e 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()
Como verificar a participação em um grupo
REST
Para verificar se um participante pertence a um grupo específico (diretamente ou
indiretamente), chame
checkTransitiveMembership()
pelo ID do grupo pai e a chave de membro (por exemplo, o e-mail
e o endereço do membro).
Python
Para autenticar no Cloud Identity, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
O código a seguir 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()
Como recuperar o gráfico de associação de um membro
REST
Para ver o gráfico de associação de um membro (todos os grupos a que um membro pertence
e as informações do caminho), chame
groups.memberships.getMembershipGraph()
com o código do grupo pai e a chave de membro (por exemplo, o endereço
de e-mail do membro). O gráfico é retornado como uma lista de adjacências.
Python
Para autenticar no Cloud Identity, configure o Application Default Credentials. Para mais informações, consulte Configurar a autenticação para um ambiente de desenvolvimento local.
O código a seguir retorna o gráfico de associação de um membro especificado em uma Grupo do Google (esta consulta é filtrada por tipo de grupo usando o rótulo):
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()
Como criar uma representação visual do gráfico de associação
Veja a seguir um exemplo de resposta do código Python acima. Neste exemplo, os grupos 000, 111 e 222 são conectados da seguinte forma (as setas são de pai para filho): 000 -> 111 -> 222. Uma chamada ao código de amostra para recuperar o gráfico completo do grupo 222:
get_membership_graph(service, 'groups/-', '[email protected]')
resulta na seguinte resposta:
{
"@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": ""
}
}
]
}
Cada item na lista de adjacência representa um grupo e seus membros diretos (bordas), e a resposta também inclui detalhes de todos os grupos no gráfico de associação. Ele pode ser analisado para gerar representações alternativas (por exemplo, um gráfico DOT) que pode ser usado para visualizar o gráfico de associação.
Este exemplo de script pode ser usado para converter a resposta em um 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='[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)
Veja a seguir a hierarquia visual resultante para a amostra de resposta: