コード例 #1
0
        public async Task <HashSet <string> > DirectoryRoles()
        {
            try
            {
                var directoryRoles = await GraphServiceHelper.GetDirectoryRolesAsync(_graphClient, _httpContext);

                var userIds = await GraphServiceHelper.GetUsersAsync(_graphClient, _httpContext);

                var administrators      = new HashSet <string>();
                var directoryRolesNames = new HashSet <string>();

                await directoryRoles.ForEachAsync(async _ =>
                {
                    var roleMembers = await GraphServiceHelper.GetDirectoryRoleMembers(_graphClient, _httpContext, _.Id);
                    var members     = Extensions.DirectoryRoleMembersResultsToList(roleMembers);
                    BloodHoundHelper.DirectoryRoleMembership(_, members);

                    if (Startup.IsCosmosDbGraphEnabled)
                    {
                        CosmosDbGraphHelper.DirectoryRoleMembership(_, members);
                        GetDeviceAdministratorsIds(_.DisplayName, members, administrators);
                        CosmosDbGraphHelper.DirectoryRolePermissions(_, userIds, administrators);
                    }

                    directoryRolesNames.Add(_.DisplayName);
                });

                return(directoryRolesNames);
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"{nameof(DirectoryRoles)} {ex.Message} {ex.InnerException}");
                return(null);
            }
        }
コード例 #2
0
        public async Task <int> Applications()
        {
            try
            {
                var applications = await GraphServiceHelper.GetApplications(_graphClient);

                applications.ForEach(async _ =>
                {
                    try
                    {
                        var owners = await GraphServiceHelper.GetApplicationsOwner(_graphClient, _.Id);
                        CosmosDbGraphHelper.AppOwnership(_, owners);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e);
                    }
                }
                                     );

                return(applications.Count);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                throw;
            }

            return(0);
        }
コード例 #3
0
        public async Task <HashSet <string> > Groups()
        {
            try
            {
                var groupsCollectionPage = await GraphServiceHelper.GetGroupsAsync(_graphClient, _httpContext);

                var groups = new HashSet <string>();
                await groupsCollectionPage.ForEachAsync(async _ =>
                {
                    var groupOwner     = await GraphServiceHelper.GetGroupOwnersAsync(_graphClient, _httpContext, _.Id);
                    var groupOwnership = BloodHoundHelper.BuildGroupOwnership(groupOwner);

                    var groupMembersList = await GraphServiceHelper.GetGroupMembers(_graphClient, _httpContext, _.Id);
                    var groupMembers     = BloodHoundHelper.BuildGroupMembersList(groupMembersList);
                    BloodHoundHelper.GroupMembership(_, groupMembers);
                    if (Startup.IsCosmosDbGraphEnabled)
                    {
                        CosmosDbGraphHelper.GroupMembership(_, groupMembers);
                        CosmosDbGraphHelper.GroupMembership(_, groupOwnership);
                    }
                    groups.Add(_.DisplayName);
                });

                return(groups);
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"{nameof(Groups)} {ex.Message} {ex.InnerException}");
                return(null);
            }
        }
コード例 #4
0
 public async Task <int> Users()
 {
     try
     {
         return((await GraphServiceHelper.GetUsersAsync(_graphClient, _httpContext)).Count);
     }
     catch (Exception ex)
     {
         _logger.Error(ex, $"{nameof(Users)} {ex.Message} {ex.InnerException}");
         return(-1);
     }
 }
コード例 #5
0
        /// <summary>
        /// Updates the content of the synchronized OneNote page to reflect the given list of ToDo
        /// objects.
        /// </summary>
        /// <param name="todos">The list of todos to synchronize with OneNote.</param>
        /// <returns></returns>
        public async Task UpdateToDoList(List <ToDo> todos)
        {
            // First get the page that we are syncing with from OneNote.
            var client = GraphServiceHelper.GetAuthenticatedClient();
            var pages  = await OneNoteService.GetMyPages(client);

            var todoPage = pages.Where(page => page.Title == todoPageTitle).SingleOrDefault();

            if (todoPage == null)
            {
                throw new Exception("Cannot update todo list. Failed to get OneNote page to update.");
            }

            // Load the HTML content of the page with OneNote IDs.
            Stream contentStream = await OneNoteService.GetPageContent(client, todoPage, includeIds : true);

            var pageContent = new HtmlDocument();

            using (StreamReader reader = new StreamReader(contentStream))
            {
                string stringContent = reader.ReadToEnd();
                pageContent.LoadHtml(stringContent);
            }

            // The container of our todos will be the first <div> tag on the page.
            var targetDiv = pageContent.DocumentNode.Descendants("div").FirstOrDefault();

            if (targetDiv == null)
            {
                throw new Exception("Cannot update todo list. Text content on a OneNote page must be contained within a div tag.");
            }

            // The div's ID will be used to identify the target on the page that we want to update.
            var targetDivId = targetDiv.ChildAttributes("id").FirstOrDefault();

            if (targetDivId == null)
            {
                throw new Exception("Cannot update todo list. Target div tag does not have an id.");
            }

            // Regenerate HTML content for current todos.
            targetDiv.RemoveAllChildren();
            foreach (ToDo todo in todos)
            {
                string dataTag = todo.Done ? "to-do:completed" : "to-do";
                targetDiv.AppendChild(HtmlNode.CreateNode($"<p data-tag=\"{dataTag}\">{todo.Task}</p>"));
            }

            // Update the OneNote page.
            await OneNoteService.UpdatePage(client, todoPage, targetDivId.Value, targetDiv.InnerHtml);
        }
コード例 #6
0
        public async Task <List <InteractiveLogon> > InteractiveLogins()
        {
            try
            {
                var signIns = await GraphServiceHelper.GetSignIns(_graphClient, _httpContext);

                var interactiveLogOns = new List <InteractiveLogon>();

                signIns
                .Where(_ => _.ClientAppUsed?.Equals("Mobile Apps and Desktop clients",
                                                    StringComparison.OrdinalIgnoreCase) == true)
                .Where(_ => _.ResourceDisplayName?.Equals("Windows Azure Active Directory",
                                                          StringComparison.OrdinalIgnoreCase) == true)
                .Where(_ => _.CreatedDateTime.HasValue &&
                       _.CreatedDateTime.Value.UtcDateTime.IsNotOlderThan(10.Days()))
                .ForEach(_ =>
                {
                    interactiveLogOns.Add(
                        new InteractiveLogon(
                            _.DeviceDetail,
                            _.Location,
                            _.UserId,
                            _.CreatedDateTime.GetValueOrDefault().UtcDateTime,
                            _.UserDisplayName));
                });

                interactiveLogOns.DistinctBy(_ => new { _.UserId, _.DeviceId });

                interactiveLogOns.
                Where(_ => _.UserId != null &&
                      _.UserDisplayName != null &&
                      _.DeviceDisplayName != null).
                ForEach(_ =>
                {
                    BloodHoundHelper.InteractiveLogOns(_);
                    if (Startup.IsCosmosDbGraphEnabled)
                    {
                        CosmosDbGraphHelper.InteractiveLogOns(_, _deviceObjectIdToDeviceId);
                    }
                });

                return(interactiveLogOns);
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"{nameof(InteractiveLogins)} {ex.Message} {ex.InnerException}");
                return(null);
            }
        }
コード例 #7
0
        /// <summary>
        /// Reads the synchronized page in OneNote and translates the content into a list of todo objects.
        /// </summary>
        /// <returns>The list of todos synchronized with OneNote.</returns>
        public async Task <List <ToDo> > GetToDoList()
        {
            // First get the synchronized page. If it doesn't exist, create it.
            var client = GraphServiceHelper.GetAuthenticatedClient();
            var pages  = await OneNoteService.GetMyPages(client);

            var todoPage = pages.Where(page => page.Title == todoPageTitle).SingleOrDefault();

            if (todoPage == null)
            {
                todoPage = await CreateToDoPage(client);
            }

            // Read the HTML content of the synchronized page and translate that into ToDo objects.
            List <ToDo> result        = new List <ToDo>();
            Stream      contentStream = await OneNoteService.GetPageContent(client, todoPage);

            using (StreamReader reader = new StreamReader(contentStream))
            {
                string pageContent = reader.ReadToEnd();
                var    document    = new HtmlDocument();
                document.LoadHtml(pageContent);

                // A OneNote todo list is a sequence of <p> tags with the data-tag attribute set
                // to "to-do" or "to-do:completed".
                foreach (var node in document.DocumentNode.Descendants("p").Where(
                             p => p.GetAttributeValue("data-tag", "not-to-do") != "not-to-do"))
                {
                    string dataTag = node.Attributes["data-tag"].Value;
                    if (dataTag != "to-do" && dataTag != "to-do:completed")
                    {
                        continue; // node is not a OneNote todo
                    }
                    result.Add(new ToDo
                    {
                        Task = node.InnerText,
                        Done = dataTag == "to-do:completed"
                    });
                }
            }

            return(result);
        }
コード例 #8
0
        public async Task <HashSet <string> > Domains()
        {
            try
            {
                var domainResults = await GraphServiceHelper.GetDomains(_graphClient, _httpContext);

                var domains = new HashSet <string>();
                domainResults.ForEach(_ => {
                    domains.Add(_.Id);
                    BloodHoundHelper.Domains(_);
                });

                return(domains);
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"{nameof(Domains)} {ex.Message} {ex.InnerException}");
                return(null);
            }
        }
コード例 #9
0
        public async Task <HashSet <DirectoryObject> > DeviceOwners()
        {
            try
            {
                var directoryRoles = await GraphServiceHelper.GetDirectoryRolesAsync(_graphClient, _httpContext);

                var devices = await GraphServiceHelper.GetDevicesAsync(_graphClient, _httpContext);

                HashSet <DirectoryObject> ownersList = new HashSet <DirectoryObject>();

                await devices.
                Where(_ => _.DisplayName != null).
                ForEachAsync(async _ =>
                {
                    _deviceObjectIdToDeviceId.Add(_.DeviceId, _.Id);
                    var ownerList =
                        (await GraphServiceHelper.GetDeviceOwners(_graphClient, _httpContext, _.Id))
                        .Where(__ => __ != null)
                        .ToList();

                    BloodHoundHelper.DeviceOwners(_, ownerList);
                    if (Startup.IsCosmosDbGraphEnabled)
                    {
                        CosmosDbGraphHelper.DeviceOwners(_, ownerList, directoryRoles);
                    }

                    ownersList.UnionWith(ownerList);
                });

                return(ownersList);
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"{nameof(DeviceOwners)} {ex.Message} {ex.InnerException}");
                return(null);
            }
        }
コード例 #10
0
 public GraphService()
 {
     _authProvider       = new AuthenticationProvider(appId, scopes);
     _graphServiceHelper = new GraphServiceHelper(_authProvider);
 }
コード例 #11
0
        public async Task <int> ServicePrincipals()
        {
            try
            {
                var appsPermissions = await GraphServiceHelper.GetAppsPermission(_graphClient, _httpContext);

                var principalsPermissions = await GraphServiceHelper.GetDirectoryAudits(_graphClient, _httpContext);

                var servicePrincipals = await GraphServiceHelper.GetServicePrincipals(_graphClient, _httpContext);

                var principalIdToPermissions = new Dictionary <string, HashSet <string> >();
                principalsPermissions.ForEach(_ =>
                {
                    principalIdToPermissions.TryAdd(
                        _.TargetResources.First().Id,
                        ToHashSetExtension.ToHashSet(_.TargetResources.First().ModifiedProperties.First(__ => __.DisplayName == "ConsentAction.Permissions").NewValue.Split("Scope:").Last().
                                                     Split("]").First().Split(" ").Where(__ => __ != ""))
                        );
                });

                var appIdToPermissionsSetDictionary = new Dictionary <string, HashSet <string> >();
                appsPermissions.ForEach(_ =>
                {
                    var permissionsSet =
                        ToHashSetExtension.ToHashSet(Newtonsoft.Json.Linq.Extensions.Value <string>(_["scope"])
                                                     .Split(' '));

                    var appId = Newtonsoft.Json.Linq.Extensions.Value <string>(_["clientId"]);
                    appIdToPermissionsSetDictionary.TryAdd(appId, permissionsSet);
                });

                var appIdToNameDictionary = new Dictionary <string, Tuple <string, string, string, string> >();
                servicePrincipals.ForEach(_ =>
                                          appIdToNameDictionary.Add(
                                              Newtonsoft.Json.Linq.Extensions.Value <string>(_["id"]),
                                              new Tuple <string, string, string, string>(
                                                  Newtonsoft.Json.Linq.Extensions.Value <string>(_["appId"]),
                                                  Newtonsoft.Json.Linq.Extensions.Value <string>(_["displayName"]),
                                                  Newtonsoft.Json.Linq.Extensions.Value <string>(_["homepage"]),
                                                  Newtonsoft.Json.Linq.Extensions.Value <string>(_["appOwnerOrganizationId"])
                                                  )));

                appIdToNameDictionary.ForEach(_ =>
                {
                    appIdToPermissionsSetDictionary.TryGetValue(_.Key, out var appPermissions);
                    principalIdToPermissions.TryGetValue(_.Key, out var principalPermissions);

                    if (Startup.IsCosmosDbGraphEnabled && (principalPermissions != null || appPermissions != null))
                    {
                        if (principalPermissions != null)
                        {
                            CosmosDbGraphHelper.Applications(_.Value.Item2, _.Value.Item1, principalPermissions, UserIds, _.Key, _.Value.Item3, _.Value.Item4);
                        }
                        else
                        {
                            CosmosDbGraphHelper.Applications(_.Value.Item2, _.Key, appPermissions, UserIds, _.Value.Item1, _.Value.Item3, _.Value.Item4);
                        }
                    }
                });

                return(appIdToNameDictionary.Count);
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"{nameof(ServicePrincipals)} {ex.Message} {ex.InnerException}");
            }

            return(0);
        }
コード例 #12
0
        /// <summary>
        /// Initiate restoration of data from OneDrive.
        /// <para>*Application restarts if finished successfully.</para>
        /// </summary>
        private async void RestoreFromOneDrive()
        {
            progressRing.IsActive = true;
            try
            {
                // Request a token to sign in the user
                var accessToken = await authProvider.GetAccessToken();

                // Initialize Graph Client
                GraphServiceHelper.InitializeClient(authProvider);

                // Set current user (temp)
                App.CurrentUser = await GraphServiceHelper.GetMeAsync();

                // Find the backupFolder in OneDrive, if it exists
                var backupFolder = await GraphServiceHelper.GetOneDriveFolderAsync("Kanban Tasker");

                if (backupFolder != null)
                {
                    // Restore local data file using the backup file, if it exists
                    await GraphServiceHelper.RestoreFileFromOneDriveAsync(backupFolder.Id, "ktdatabase.db");

                    await DisplayMessageAsync("Data restored successfully.");

                    var displayName = await GraphServiceHelper.GetMyDisplayNameAsync();

                    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
                                              () =>
                    {
                        txtResults.Text         = "Welcome " + App.CurrentUser.GivenName;
                        btnSignOutTip.IsEnabled = true;
                    });

                    Thread.Sleep(2000);

                    // Restart app to make changes
                    await Windows.ApplicationModel.Core.CoreApplication.RequestRestartAsync("");
                }
                else
                {
                    await DisplayMessageAsync("No backup folder found to restore from.");
                }
            }
            catch (ServiceException ex)
            {
                if (ex.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                {
                    // MS Graph Known Error
                    // Users need to sign into OneDrive at least once
                    // https://docs.microsoft.com/en-us/graph/known-issues#files-onedrive

                    // Empty all cached accounts / data to allow user to rety
                    await authProvider.SignOut();

                    await DisplayMessageAsync("Error 401. Access Denied. Please make sure you've logged\ninto OneDrive and your email at least once then try again.");
                }
                else if (ex.StatusCode == HttpStatusCode.NotFound)
                {
                    await DisplayMessageAsync("Error 404. Resource requested is not available.");
                }
                else if (ex.StatusCode == HttpStatusCode.Conflict)
                {
                    await DisplayMessageAsync("Error 409. Error backing up, issue retrieving backup folder. Please try again.");
                }
                else if (ex.StatusCode == HttpStatusCode.BadGateway)
                {
                    await DisplayMessageAsync("Error 502. Bad Gateway.\nPlease check your internet connection and try again in a few.");
                }
                else if (ex.StatusCode == HttpStatusCode.ServiceUnavailable)
                {
                    await DisplayMessageAsync("Error 503. Service unavailable due to high load or maintenance.\nPlease try again in a few.");
                }
                else if (ex.IsMatch(GraphErrorCode.GeneralException.ToString()))
                {
                    await DisplayMessageAsync("General Exception. Please check your internet connection and try again in a few.");
                }
            }
            catch (MsalException msalex)
            {
                if (msalex.ErrorCode == MsalError.AuthenticationCanceledError)
                {
                    await DisplayMessageAsync(msalex.Message);
                }
                else if (msalex.ErrorCode == MsalError.InvalidGrantError)
                {
                    // invalid_grant comes from no consent to needed scopes
                    await DisplayMessageAsync("Invalid access scopes, please contact the developer.");
                }
            }
            catch (Exception ex)
            {
                await DisplayMessageAsync("Unexpected Error: " + ex.Message);
            }
            finally
            {
                progressRing.IsActive = false;
            }
        }
コード例 #13
0
        /// <summary>
        /// Initiate backup of data to OneDrive.
        /// </summary>
        private async void BackupToOneDrive()
        {
            progressRing.IsActive = true;
            try
            {
                // Request a token to sign in the user
                var accessToken = await authProvider.GetAccessToken();

                // Initialize Graph Client
                GraphServiceHelper.InitializeClient(authProvider);

                // Set current user (temp)
                App.CurrentUser = await GraphServiceHelper.GetMeAsync();

                // Find backupFolder in user's OneDrive, if it exists
                var backupFolder = await GraphServiceHelper.GetOneDriveFolderAsync("Kanban Tasker");

                // Create backup folder in OneDrive if not exists
                if (backupFolder == null)
                {
                    backupFolder = await GraphServiceHelper.CreateNewOneDriveFolderAsync("Kanban Tasker") as DriveItem;
                }

                // Backup datafile (or overwrite)
                var uploadedFile = await GraphServiceHelper.UploadFileToOneDriveAsync(backupFolder.Id, DataFilename);

                await DisplayMessageAsync("Data backed up successfully.");

                var displayName = await GraphServiceHelper.GetMyDisplayNameAsync();

                await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal,
                                          () =>
                {
                    txtResults.Text         = "Welcome " + displayName;
                    btnSignOutTip.IsEnabled = true;
                });
            }
            catch (ServiceException ex)
            {
                if (ex.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                {
                    // MS Graph Known Error
                    // Users need to sign into OneDrive at least once
                    // https://docs.microsoft.com/en-us/graph/known-issues#files-onedrive

                    // Empty all cached accounts / data to allow user to rety
                    await authProvider.SignOut();

                    await DisplayMessageAsync("Error 401. Access Denied. Please make sure you've logged\ninto OneDrive and your email at least once then try again.");
                }
                else if (ex.StatusCode == HttpStatusCode.NotFound)
                {
                    await DisplayMessageAsync("Error 404. Resource requested is not available.");
                }
                else if (ex.StatusCode == HttpStatusCode.Conflict)
                {
                    await DisplayMessageAsync("Error 409. Error backing up, issue retrieving backup folder. Please try again.");
                }
                else if (ex.StatusCode == HttpStatusCode.BadGateway)
                {
                    await DisplayMessageAsync("Error 502. Bad Gateway.\nPlease check your internet connection and try again in a few.");
                }
                else if (ex.StatusCode == HttpStatusCode.ServiceUnavailable)
                {
                    await DisplayMessageAsync("Error 503. Service unavailable due to high load or maintenance.\nPlease try again in a few.");
                }
                else if (ex.IsMatch(GraphErrorCode.GeneralException.ToString()))
                {
                    await DisplayMessageAsync("General Exception. Please check your internet connection and try again in a few.");
                }
            }
            catch (MsalException msalex)
            {
                if (msalex.ErrorCode == MsalError.AuthenticationCanceledError)
                {
                    await DisplayMessageAsync(msalex.Message);
                }
                else if (msalex.ErrorCode == MsalError.InvalidGrantError)
                {
                    // invalid_grant ErrorCode comes from no consent
                    // for the correct scopes (todo: add interactive retry)
                    await DisplayMessageAsync("Invalid access scopes, please contact the developer.");
                }
            }
            catch (Exception ex)
            {
                await DisplayMessageAsync(ex.Message);
            }
            finally
            {
                progressRing.IsActive = false;
            }
        }