Ejemplo n.º 1
0
 def apply(self, graph: Graph):
     """Creates the user with extension data and assigns the license."""
     # Create user
     user_id = graph.create_user(self.user)
     # Add extension data (Tutti database ID)
     graph.add_user_extension(user_id, self.user.extension)
     # Assign Office 365 license (without Exchange)
     graph.assign_license(user_id=user_id,
                          sku_id="6634e0ce-1a9f-428c-a498-f84ec7b8aa2e",
                          disabled_plans=["9aaf7827-d63c-4b61-89c3-182f06f82e5c"])
Ejemplo n.º 2
0
    def handle(self, *args, **options):
        try:
            graph = Graph.from_settings()

            self.stdout.write('Comparing user and group objects...')
            operations = aad_sync_objects(graph)

            # Split out delete operations
            delete_ops = []
            non_delete_ops = []
            for o in operations:
                if isinstance(o, DeleteUserOperation) or isinstance(
                        o, DeleteGroupOperation):
                    delete_ops.append(o)
                else:
                    non_delete_ops.append(o)

            self.stdout.write('Create and update operations:')
            handle_operations(non_delete_ops, graph, self.stdout)
            self.stdout.write('Delete operations:')
            handle_operations(delete_ops, graph, self.stdout)

            self.stdout.write("Comparing group memberships...")
            operations = aad_sync_members(graph)
            self.stdout.write("Group membership operations:")
            handle_operations(operations, graph, self.stdout)

            # Do a sanity check for possible licensing issues
            self.stdout.write("Checking licenses...")
            users = graph.get_paged(
                "users",
                params={"$select": "userPrincipalName,assignedLicenses"})
            without_license = [
                u for u in users if not u.get("assignedLicenses")
            ]
            for u in without_license:
                self.stdout.write("User {} has no assigned licenses!".format(
                    u["userPrincipalName"]))

            # Print orphans
            self.stdout.write("Checking extensions...")
            users = graph.get_paged("users",
                                    params={
                                        "$select": "userPrincipalName",
                                        "$expand": "extensions"
                                    })
            groups = graph.get_paged("groups",
                                     params={
                                         "$select": "displayName",
                                         "$expand": "extensions"
                                     })
            for o in users + groups:
                ext = o.get("extensions")
                if not ext or len(
                        ext) != 1 or ext[0]["id"] != "nl.esmgquadrivium.tutti":
                    self.stdout.write(
                        "Unexpected extension for object: {}".format(o))
        except HTTPError as e:
            self.stderr.write(str(e))
            self.stderr.write(str(e.response.json()))
Ejemplo n.º 3
0
def aad_sync_objects(graph: Graph) -> List[SyncOperation]:
    """Gets the sync operations for syncing users and groups with AAD.

    Group memberships are synced separately and needs to be done after the
    operations returned here have been applied.
    """
    operations = []
    # Sync users
    local_users = [
        convert_local_person(p) for p in Person.objects.filter_members()
    ]
    aad_users = graph.get_users()
    operations.extend(sync_users(local_users, aad_users))
    # Sync groups
    local_groups = [convert_local_group(g) for g in QGroup.objects.all()]
    aad_groups = graph.get_groups()
    operations.extend(sync_groups(local_groups, aad_groups))
    return operations
Ejemplo n.º 4
0
 def get_user(graph: Graph, user_id: str):
     # Get user
     fields = [
         'id', 'displayName', 'userPrincipalName', 'identities',
         'lastPasswordChangeDateTime', 'licenseAssignmentStates',
         'passwordPolicies', 'passwordProfile', 'usageLocation',
         'onPremisesImmutableId'
     ]
     params = {'$select': ','.join(fields), '$expand': 'extensions'}
     return graph.call_resource('users/{}'.format(user_id),
                                params=params).json()
Ejemplo n.º 5
0
def aad_sync_members(graph: Graph) -> List[SyncOperation]:
    """Gets the sync operation for group membership adds/deletes.

    This uses the remote groups as the groups that will be synced, so this must
    be run after the aad_sync_objects operations have been applied on AAD. This
    is because the remote groups need to have been created already in order to
    be able to sync group memberships.
    """
    operations = []
    aad_users = graph.get_users()
    local_id_map = {u.extension["tuttiId"]: u for u in aad_users}
    remote_id_map = {u.directory_id: u for u in aad_users}
    for group in graph.get_groups():
        # Get local and remote group members
        qs = Person.objects.filter(groups=group.extension["tuttiId"])
        # Here we silently ignore local people that don't have a remote account
        local = [local_id_map[p.id] for p in qs if p.id in local_id_map]
        remote = [
            remote_id_map[i]
            for i in graph.get_group_members(group.directory_id)
        ]
        # Sync
        operations.extend(sync_members(group, local, remote))
    return operations
Ejemplo n.º 6
0
 def setUp(self):
     if not settings.GRAPH_CLIENT_ID:
         self.skipTest("Microsoft Graph is not set up")
         return
     self.graph = Graph.from_settings()
     self.graph.extension_id = "nl.esmgquadrivium.tutti-test"
Ejemplo n.º 7
0
 def apply(self, graph: Graph):
     graph.update_group(self.group.directory_id, self.changes)
Ejemplo n.º 8
0
 def apply(self, graph: Graph):
     graph.delete_group(self.group.directory_id)
Ejemplo n.º 9
0
 def apply(self, graph: Graph):
     group_id = graph.create_group(self.group)
     graph.add_group_extension(group_id, self.group.extension)
Ejemplo n.º 10
0
 def apply(self, graph: Graph):
     graph.update_user(self.user.directory_id, self.changes)
Ejemplo n.º 11
0
 def apply(self, graph: Graph):
     graph.delete_user(self.user.directory_id)
Ejemplo n.º 12
0
 def apply(self, graph: Graph):
     graph.remove_group_member(self.group.directory_id, self.user.directory_id)