Я использую предоставленный Microsoft отчет об активных пользователях 365 через Graph API, однако в нем отсутствует только одна вещь, которая мне нужна, - номер сотрудника. Недавно мы расширили нашу схему, и я могу запросить номер сотрудника следующим образом:
Https://graph.microsoft.com/v1.0/users?$select=extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber
Вывод из приведенного ниже кода дает мне всех лицензированных активных пользователей 365, а также их типы лицензий, но я хотел бы каким-то образом также включить столбец employeeNumber. Я не уверен, что это вообще возможно, учитывая, что это готовый отчет Microsoft.
Могу ли я просто создать объект отчета с результатами $reports, а затем запустить отдельный запрос, чтобы получить все номера сотрудников и каким-то образом вставить этот столбец? Думаю, я мог бы сопоставить их, используя userPrincipalName.
# CHANGE THESE VALUES
$TenantID = 'tenantid' #The Directory ID from Azure AD
$ClientID = 'ClientID ' #The Application ID of the registered app
$ClientSecret = 'ClientSecret ' #The secret key of the registered app
# ------------------------------------------------------
# DO NOT CHANGE THESE
$body = @{grant_type = "client_credentials";scope = "https://graph.microsoft.com/.default";client_id=$ClientID;client_secret=$ClientSecret}
$oauth = Invoke-RestMethod -Method Post -Uri https://login.microsoftonline.com/$tenantID/oauth2/v2.0/token -Body $body
$token = @{'Authorization' = "$($oauth.token_type) $($oauth.access_token)"}
# ------------------------------------------------------
$graphApiUri = "https://graph.microsoft.com/v1.0/reports/getOffice365ActiveUserDetail(period='D90')"
$Reports = Invoke-RestMethod -Method Get -Uri $graphApiUri -Headers $token | ConvertFrom-Csv
$Reports | Export-Csv "c:\temp\GraphAPI365UsersReport.csv" -NoTypeInformation
Обновил скрипт, работает отлично.
# Application (client) ID, Directory (tenant) ID, and secret
$clientID = "clientID"
$tenantID = "tenantID"
$ClientSecret = "ClientSecret"
$resource = "https://graph.microsoft.com/"
#Get token
Write-Output "Acquire Graph Token."
try {
$body = @{grant_type = "client_credentials";scope = "https://graph.microsoft.com/.default";client_id=$ClientID;client_secret=$ClientSecret}
$oauth = Invoke-RestMethod -Method Post -Uri https://login.microsoftonline.com/$tenantID/oauth2/v2.0/token -Body $body
$token = @{'Authorization' = "$($oauth.token_type) $($oauth.access_token)"}
}
catch {
Write-Output "Error getting Graph Token."
Write-Output $_.Exception.Message
EXIT
}
# ------------------------------------------------------
$graphApiUri = "https://graph.microsoft.com/v1.0/reports/getOffice365ActiveUserDetail(period='D90')"
$Uri = "https://graph.microsoft.com/v1.0/users?`$select=userPrincipalName,extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber"
$O365Report = Invoke-RestMethod -Method Get -Uri $graphApiUri -Headers $token | ConvertFrom-Csv
# If the result is more than 999, we need to read the @odata.nextLink to show more than one side of users
$UserDetails = while (-not [string]::IsNullOrEmpty($uri)) {
# API Call
$apiCall = try {
Invoke-RestMethod -Headers $token -Uri $uri -Method Get
}
catch {
$errorMessage = $_.ErrorDetails.Message | ConvertFrom-Json
}
$uri = $null
if ($apiCall) {
# Check if any data is left
$uri = $apiCall.'@odata.nextLink'
$apiCall
}
}
$O365Report | ForEach-Object {
$CurrentEmpNumber = $UserDetails.value |
Where-Object userPrincipalName -eq $_.'User Principal Name' |
Select-Object -ExpandProperty extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber
$_ | Add-Member -MemberType NoteProperty -Name extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber -Value $CurrentEmpNumber
}
$O365Report | Export-Csv "c:\temp\GraphAPI365UsersReport.csv" -NoTypeInformation
К сожалению, эти отчеты действительно довольно статичны, однако получить нужную информацию не должно быть сложно. У меня нет вашего расширения, но что-то вроде этого должно работать:
$Reports = Invoke-RestMethod -Method Get -Uri $graphApiUri -Headers $token | ConvertFrom-Csv
$Uri = 'https://graph.microsoft.com/v1.0/users?$select=userPrincipalName,extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber'
$UserDetails = Invoke-RestMethod -Method Get -Uri $Uri -Headers $token
$Reports | ForEach-Object {
$CurrentEmpNumber = $UserDetails.value |
Where-Object userPrincipalName -eq $_.'User Principal Name' |
Select-Object -ExpandProperty extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber
$_ | Add-Member -MemberType NoteProperty -Name EmployeeNumber -Value $CurrentEmpNumber
}
$Reports | Export-Csv "c:\temp\GraphAPI365UsersReport.csv" -NoTypeInformation
В связи с этим, почему вы расширили схему для этого? В Azure AD уже есть атрибут EmployeeId, поэтому extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber в приведенном выше коде мог быть просто employeeId.
Пробелы должны быть там, вы получаете нулевые результаты без них. Ошибка предполагает, что имя атрибута, которое вы дали, неверно, я бы начал с двойной проверки.
Да, сэр, это правильное имя атрибута. На самом деле я вижу некоторые значения, хотя получаю сообщение об ошибке в консоли, но возвращаю только 11 значений для extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber — их должно быть намного больше, учитывая, что у нас более 7500 пользователей в нашем арендаторе. Я думаю, это потому, что мне нужно перейти к следующей '@odata.nextLink
Ага, это могло бы объяснить! Я тестировал только на небольшом личном арендаторе. Сегодня у меня, вероятно, не будет возможности сделать больше, но это должно быть легко исправить.
Спасибо! Я могу взять это отсюда, я полагаю. Я ценю вашу помощь.
Я только что опубликовал обновленный код, но все еще получаю только 11 результатов.
Вы переписываете $UserDetails каждый цикл, попробуйте вместо этого $UserDetails = while($uri){
Хм.... кажется, не хочет заканчивать. Я только что создал бесконечный цикл? Обновлен код выше. Я могу подтвердить, что userdetails.value | select userprincipalname,extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber показывает все значения.
Странный. Я обычно использую для этого цикл do ... until, но while должен работать нормально. Итак, ваш код в комментарии выше показывает все имена участников-пользователей с их номерами сотрудников? В этом случае цикл не нужен в любом случае. Странно, однако, что мой вывод /users имеет свойство User Principal Name с пробелами... Но даже если это отличается, если вы видите все номера сотрудников в $UserDetails, код должен работать.
Да, сэр, это так, если я устанавливаю точку останова после блока @odata.nextlink и подтверждаю значения в userdetails.value, однако, когда он переходит к вашему коду для расширения свойства, я получаю сообщение об ошибке: Select-Object : Property "extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber" cannot be found.
Что показывает $UserDetails.value | Get-Member -Name *Number | Select-Object -ExpandProperty Name? Соответствует ли он точно тому, что мы пытаемся выбрать?
Нет, я получаю результаты только в том случае, если делаю $userdetails.value | select extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber, а $uri = $UserDetails.'@odata.nextLink', похоже, тоже не хочет заканчивать. Я дал ему поработать некоторое время, и выбор всех пользователей в нашем арендаторе не занял много времени.
$UserDetails.value | get-member -name *
показывает только userPrincipalName, к сожалению, нет упоминания о employeenumber.
Хм, я не понимаю, как $userdetails.value | select extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber может работать, если есть только атрибут UPN. Как насчет того, чтобы просто Get-Member? Должно быть так же, но что-то тут странное.
Вот где я вижу Equals,GetHashCode,GetType,ToString,userPrincipalName, но UPN единственный NoteProperty
И вы говорите, что если вы запустите $userdetails.value | select extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber без каких-либо новых запросов или чего-то еще, сразу после этого вы действительно увидите номера сотрудников? Кажется, ну, невозможно. Что показывает $UserDetails.value.psobject.Properties.Name?
Count Length LongLength Rank SyncRoot IsReadOnly IsFixedSize IsSynchronized
Получил это, чтобы работать! Следующим шагом будет подавление предупреждений, когда не удается найти номер сотрудника — у некоторых пользователей в нашем арендаторе нет номеров сотрудников, если они являются учетными записями службы и т. д. Еще раз спасибо за вашу помощь @PMental
У нас есть как employeeId, так и employeeNumber в нашем локальном AD. Я получил эту ошибку: Select-Object : Property "extension_335d4df9847945fbaa472c8b8fbb5d75_employeeNumber" cannot be found. Итак, я удалил пробелы, чтобы изменить $_.'User Principal Name' на $_.'UserPrincipalName' , и он вставляет столбец в вывод, однако столбец не содержит записей.