Office 365. Отчет по назначенным лицензиям
Отчет
Отчет формируется консольным приложением в формате Excel (.xlsx). Отчет содержит следующую информацию о пользователях:
- Имя
- Электронная почта
- Департамент
- Разрешен ли вход
- Тип учетной записи
Вы можете запустить приложение и найти все заблокированные учетные записи, на которые назначены лицензии и уменьшить стоимость владения Office 365 удалив ненужные лицензии.
Nuget Пакеты
Приложение использует Microsoft Graph для получения данных. Значит надо добавить пакет Microsoft.Graph в проект. Исполните эту команду в Package Manager Console:
PM> Install-Package Microsoft.Graph
Также понадобится пакет Microsoft.IdentityModel.Clients.ActiveDirectory для авторизации в Microsoft Graph:
PM> Install-Package Microsoft.IdentityModel.Clients.ActiveDirectory
Последний пакет, который будет задействован - это ClosedXML для генерации Excel файла.
PM> Install-Package ClosedXML
Регистрация приложения
Для того чтобы приложение могло работать с Microsoft Graph необходимо его зарегистрировать на портале Azure. Это можно сделать, следуя инструкции Регистрация приложения с помощью конечной точки Azure AD версии 2.0.
Всего три параметра, которые необходимо знать о зарегистрированном приложении:
1. ClientId. Идентификатор приложения (APPLICATION ID) можно найти в списке всех приложений:
2. ClientSecret. Секретный ключ можно сгенерировать на странице параметров приложения:
3.
Tenant Name - имя тенанта, в котором будет авторизовываться приложение {yourtenant}.microsoftonline.com.
Конфигурация приложения (app.config)
Откройте файл app.config и добавьте параметры из списка выше в секцию appSettings:
Приложение создано, его параметры сохранены в конфигурационном файле. Теперь можно приступить с генерации отчета.
Провайдер для Microsoft Graph
Создайте файл GraphProvider.cs со следующим содержимым:
using System.Configuration;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Graph;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
namespace Zhukov.Demo.GraphLicensesReport
{
public class GraphProvider : IAuthenticationProvider
{
public async Task AuthenticateRequestAsync(HttpRequestMessage request)
{
var token = await GetToken();
request.Headers.Add("Authorization", "Bearer " + token);
}
public static async Task GetToken(string resource = @"https://graph.microsoft.com/")
{
var clientId = ConfigurationManager.AppSettings["ida:ClientId"];
var clientKey = ConfigurationManager.AppSettings["ida:ClientSecret"];
var azureDomain = ConfigurationManager.AppSettings["ida:Domain"];
var authory = $@"https://login.microsoftonline.com/{azureDomain}";
var creds = new ClientCredential(clientId, clientKey);
var authContext = new AuthenticationContext(authory);
var authResult = await authContext.AcquireTokenAsync(resource, creds);
return authResult.AccessToken;
}
}
}
Этот провайдер будет использован для выполнения запросов к Microsoft Graph.
Код приложения
Приложение будет делать следующее:
- 1. Получать информацию обо всех пользователях;
- 2. Формировать таблицу, где строки - пользователь, а колонки - лицензии;
Код для получения списка пользователей:
// Провайдер Microsoft Graph
var provider = new GraphProvider();
// Клиент Microsoft Graph
var client = new GraphServiceClient(provider);
// Список пользователей
var users = new List();
// Постраничный запрос
IGraphServiceUsersCollectionPage items = null;
// Наполнение списка сотрудников
while (items == null || items.NextPageRequest != null)
{
// Запрос к Microsoft Graph
var itemsRequest = items?.NextPageRequest ?? client
.Users
.Request()
.OrderBy("displayName")
.Select("displayName, mail, department, assignedLicenses, accountEnabled, userType")
.Top(100);
// Получаем пользователей
items = itemsRequest
.GetAsync()
.GetAwaiter()
.GetResult();
// Добавляем пользователей в список
users.AddRange(items);
}
Свойство AssignedLicenses содержит информацию о назначенных лицензиях. Но так нет никакой информации, воспринимаемой человеком - только идентификаторы SKU (Stock Keeping Unit).
SKU
Таблица содержит информацию о кодах SKU в Office 365:
SKU | Продукт |
---|---|
2B9C8E7C-319C-43A2-A2A0-48C5C6161DE7 | Azure Active Directory Basic |
C7D15985-E746-4F01-B113-20B575898250 | Dynamics 365 for Field Service Enterprise Edition |
6A4A1628-9B9A-424D-BED5-4118F0EDE3FD | Dynamics 365 for Financials for IWs |
28B81EF4-B535-4E5C-AE14-BD40148C89C5 | Dynamics 365 for Project Service Automation Enterprise Edition |
8E7A3D30-D97D-43AB-837C-D7701CEF83DC | Dynamics 365 for Sales Enterprise Edition |
E561871F-74FA-4F02-ABEE-5B0EF54DD36D | Dynamics 365 for Talent: Attract |
1E1A282C-9C54-43A2-9310-98EF728FAACE | Dynamics 365 for Team Members Enterprise Edition |
EA126FC5-A19E-42E2-A731-DA9D437BFFCF | Dynamics 365 Plan 1 Enterprise Edition |
B05E124F-C7CC-45A0-A6AA-8CF78C946968 | Enterprise Mobility + Security E5 |
EFCCB6F7-5641-4E0E-BD10-B4976E1BF68E | Enterprise Mobility Suite |
9AAF7827-D63C-4B61-89C3-182F06F82E5C | Exchange Online (Plan 1) |
0F9B09CB-62D1-4FF4-9129-43F4996F83F4 | Flow for Office 365 in E1 |
76846AD7-7776-4C40-A281-A386362DD1B9 | Flow for Office 365 in E3 |
061F9ACE-7D42-4136-88AC-31DC755F143F | Intune |
FCECD1F9-A91E-488D-A918-A96CDB6CE2B0 | Microsoft Dynamics AX7 User Trial |
F30DB892-07E9-47E9-837C-80727F46FD3D | Microsoft Flow Free |
87BBBC60-4754-4998-8C88-227DCA264858 | Microsoft PowerApps and Logic flows |
DCB1A3AE-B33F-4487-846A-A640262FADF4 | Microsoft PowerApps Plan 2 Trial |
1F2F344A-700D-42C9-9427-5CEA1D5D7BA6 | Microsoft Stream Trial |
57FF2DA0-773E-42DF-B2AF-FFB7A2317929 | Microsoft Teams |
3B555118-DA6A-4418-894F-7DF1E2096870 | Office 365 Business Essentials |
F245ECC8-75AF-4F8E-B61F-27D8114DE5F3 | Office 365 Business Premium |
18181A46-0D4E-45CD-891E-60AABD171B4E | Office 365 Enterprise E1 |
6FD2C87F-B296-42F0-B197-1E91E994B900 | Office 365 Enterprise E3 |
C7DF2760-2C81-4EF7-B578-5B5392B571DF | Office 365 Enterprise E5 |
26D45BD9-ADF1-46CD-A9E1-51E9A5524128 | Office 365 Enterprise E5 without Audio Conferencing |
E95BEC33-7C88-4A70-8E19-B10BD9D0C014 | Office Online |
92F7A6F3-B89B-4BBD-8C30-809E6DA5AD1C | Power App for Office 365 in E1 |
A403EBCC-FAE0-4CA2-8C8C-7A907FD6C235 | Power BI (Free) |
F8A1DB68-BE16-40ED-86D5-CB42CE701560 | Power BI Pro |
C68F8D98-5534-41C8-BF36-22FA496FA792 | PowerApps for Office 365 in E3 |
53818B1B-4A27-454B-8896-0DBA576410E6 | Project Online Professional |
A10D5E58-74DA-4312-95C8-76BE4E5B75A0 | Project Pro for Office 365 |
8C4CE438-32A7-4AC5-91A6-E22AE08D9C8B | Rights Management Adhoc |
1FC08A02-8B3D-43B9-831E-F76859E04E1A | SharePoint Online (Plan 1) |
0FEAEB32-D00E-4D66-BD5A-43B5B83DB82C | Skype Enterprise Online (plan 2) |
E43B5B99-8DFB-405F-9987-DC307F34BCBD | Skype for Business Cloud PBX |
47794CD0-F0E5-45C5-9033-2EB6B5FC84E0 | Skype for Business PSTN Consumption |
D3B4FE1F-9992-4930-8ACB-CA6EC609365E | Skype for Business PSTN Domestic and International Calling |
C5928F49-12BA-48F7-ADA3-0D743A3601D5 | Visio Pro for Office 365 |
Отчет
Последняя часть приложения - генерация отчета:
// Новая книга Excel
using (var workbook = new XLWorkbook())
{
// Добавляем вкладку
using (var worksheet = workbook.Worksheets.Add("Назначенные лицензии"))
{
// номер строки
var r = 1;
// Заголовок таблицы -->
worksheet.Cell(r, 1).Value = "Имя";
worksheet.Cell(r, 2).Value = "Тип учетной записи";
worksheet.Cell(r, 3).Value = "Электронная почта";
worksheet.Cell(r, 4).Value = "Департамент";
worksheet.Cell(r, 5).Value = "Разрешен ли вход";
// номер колонки
var c = 6;
foreach (var sku in SKUs)
{
worksheet.Cell(r, c).Value = sku.Value;
c = c + 1;
}
// <-- Заголовок таблицы
// переходим к следующей строке
r = r + 1;
foreach (var user in users)
{
// Информация о пользователе
worksheet.Cell(r, 1).Value = user.DisplayName;
worksheet.Cell(r, 2).Value = user.UserType;
worksheet.Cell(r, 3).Value = user.Mail;
worksheet.Cell(r, 4).Value = user.Department;
worksheet.Cell(r, 5).Value = user.AccountEnabled == false ? "Заблокирован" : string.Empty;
// go to 6th column (колонки с 1 по 5 для информации о пользователе)
c = 6;
foreach (var sku in SKUs)
{
// назначена ли лицензия текущему пользователю
var assignedFlag = user
.AssignedLicenses
.Any(x => x.SkuId == sku.Key);
worksheet.Cell(r, c).Value = assignedFlag ? 1 : 0;
// переходим к следующей колонке
c = c + 1;
}
// переходим к следующей строке
r = r + 1;
}
// создаем таблицу -->
var table = worksheet.Range(1, 1, r - 1, 5 + SKUs.Count).CreateTable();
table.Theme = XLTableTheme.TableStyleMedium2;
// <-- создаем таблицу
// увеличиваем ширину колонок
worksheet.Columns().AdjustToContents(5, 40);
// фиксируем первые две колонки
worksheet.SheetView.FreezeColumns(2);
}
// сохраняем отчет
workbook.SaveAs("AssignedLicesesReport.xlsx");
}
Вот и всё!
Исходные коды
Исходные коды доступны тут: https://code.msdn.microsoft.com/Office-365-Assigned-8c2eb22e.