azure ad group name and member count - azure

i have a lots of azure ad group with this format "AA - BB - xxx" where xxx can be anything.
i am trying to do a report on how many members in this azure ad group by display the azure ad group name and the number of its members.
i know to do 1 group is using this:
(Get-AzureADGroupMember -all 1 -ObjectId "xxxxx").count
how do i do lots of group with same group naming format to display its name and number of members?
thanks.

You need to first get all groups with such a name and then loop over the resulting list like:
$result = Get-AzureADGroup -Filter "startswith(DisplayName, 'AA - BB -')" -All $true | ForEach-Object {
[PsCustomObject]#{
Group = $_.DisplayName
MemberCount = #(Get-AzureADGroupMember -ObjectId $_.ObjectId -All $true).Count
}
}
# output on screen
$result | Format-Table -AutoSize
# save as Csv file
$result | Export-Csv -Path 'X:\PathTo\GroupMemberCount.csv' -NoTypeInformation
Apparently, the startswith() Filter on Get-AzureADGroup does not always return the wanted results (depending on the version of the OData language??).
In that case do
$result = Get-AzureADGroup | Where-Object {$_.DisplayName -like 'AA - BB -*'} | ForEach-Object {...}

Related

Powershell odd behaviour when outputting to csv

I'm having a problem when outputting my foreach loop to a csv file.
My Groups are set like this:
$Groups = "Group1", "Group2", "Group3"
My code is:
$results = ForEach ($Group in $Groups) {
$memberof = get-adgroup $Group | select -expandproperty distinguishedname
Write-Output $Group
Get-ADObject -Filter 'memberof -eq $memberof -and (ObjectClass -eq "user" -or ObjectClass -eq "contact")' -properties * | select name, Objectclass, mail
Write-Output ""
Write-Output ""
}
$results | Export-csv Contacts.csv -NoTypeInformation
The problem seems to be coming from the Write-Output lines but I have no clue why. When I run my code without writing to a csv file, I get the expected result, something like:
NameOfGroup1
name Objectclass mail
---- ----------- ----
User1 user User1#mail.com
User2 user User2#mail.com
#Spaces caused by write-output ""
NameOfGroup2
User1 user User1#mail.com
Contact1 contact Contact1#externalmail.com
Then again when I run my code to write to csv file and have the write-output $Group commented out I get a similar result.
But if I run my full code from the top of this page including the write-output $Group, it comes out like this:
I've figured out what these results represent but I haven't got clue why they do print out like this.
Eseentially the numbers refer to the length of the group name, so the first 17 would be a 17 character group name, and then the number of lines below is equal to the number of contacts and users that are inside that group. The 2 zeros at the end of each group are the length of the write-output "" lines.
What is causing this behavior?
The following code will closely output what you are attempting.
$results = ForEach ($Group in $Groups) {
$memberof = get-adgroup $Group | select -expandproperty distinguishedname
Get-ADUser -Filter "memberof -eq '$memberof' -and (ObjectClass -eq 'user' -or ObjectClass -eq 'contact')" -properties name,ObjectClass,Mail | Select-Object #{n='Group';e={$Group}},name, Objectclass, mail
[pscustomobject]"" | Select-Object Group,Name,ObjectClass,Mail
[pscustomobject]"" | Select-Object Group,Name,ObjectClass,Mail
}
$results | Export-csv Contacts.csv -NoTypeInformation
Explanation:
Export-Csv converts an object or array of objects with properties into a CSV file. You can see the same result in the console with ConvertTo-Csv. Properties are converted into columns and property values are placed under their associated columns. When you output a string as in Write-Output $Group, it has a property of Length. To fix this, you need to add $Group as a calculated property in your Select-Object. If you want to do blank lines in your CSV, then you should output another object with all of the property values as ''.
When you mix objects in your PowerShell outputs, you can see unexpected results. Your Get-ADObject outputs a custom object. Your Write-Output lines output a string. Those two object types do not share properties. So you only see the properties for the first object in your array, which is a string. If you put all of the Write-Output statements at the end of your loop, you will see more properties in your CSV. See below for an example that just by reversing the order of processed objects, you get a different result.
$str = "string"
$obj = [pscustomobject]#{property1 = "value1"; property2 = "value2"}
$str,$obj | convertto-csv -notype
"Length"
"6"
$obj,$str | convertto-csv -notype
"property1","property2"
"value1","value2"
,
Notice the properties available to the custom object $obj and the string $str.
$obj | get-member -Type Properties
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
property1 NoteProperty string property1=value1
property2 NoteProperty string property2=value2
$str | get-member -Type Properties
TypeName: System.String
Name MemberType Definition
---- ---------- ----------
Length Property int Length {get;}

How to extract all PowerBI users and workspace access using the PowerBI API or Azure Portal?

New to Power BI. Trying to get a report of the Users who have access for each Dashboards. Any pointers would be helpful.
Thanks in advance!
Below is the script I created. First change the username and password for your PowerBI credentials. The script collects the results and then opens two Out Grid windows (Workspaces and Workspace Users). You can then copy/paste the grid results into excel. This doesn't export shared reports and dashboards.
I have two PBI powershell modules installed. I think this script uses only the MicrosoftPowerBIMgmt.
Check if you have the PBI modules.
get-module -ListAvailable | where {$_.Name -like '*BI*'}
And to check for the cmdlets available.
get-command -module MicrosoftPowerBIMgmt.Admin | sort CommandType, name
get-command -module MicrosoftPowerBIMgmt.Capacities | sort CommandType, name
get-command -module MicrosoftPowerBIMgmt.Data | sort CommandType, name
get-command -module MicrosoftPowerBIMgmt.Profile | sort CommandType, name
get-command -module MicrosoftPowerBIMgmt.Reports | sort CommandType, name
get-command -module MicrosoftPowerBIMgmt.Workspaces | sort CommandType, name
get-command -module PowerBIPS | sort CommandType, name
PBI WORKSPACES & PERMISSIONS
#****************
#------------------------------------------------------
# --> PBI WORKSPACES & PERMISSIONS
#
# Export PBI results to grid for copy/paste to Excel table
# * All groups (Active/Deleted)
# * All workspaces (Active)
# * All workspace permissions
#
# RestAPI call for each workspace (Group Users)
# * https://learn.microsoft.com/en-us/rest/api/power-bi/groups/getgroupusers
#
#------------------------------------------------------
#****************
#------------------------------------------------------
# --> PBI Connection
#------------------------------------------------------
Write-Host " PBI credentials ..." -ForegroundColor Yellow -BackgroundColor DarkGreen
## PBI credentials
$password = "myPassword" | ConvertTo-SecureString -asPlainText -Force
$username = "myemail#domain.com"
$credential = New-Object System.Management.Automation.PSCredential($username, $password)
## PBI connect
Connect-PowerBIServiceAccount -Credential $credential
# Login-PowerBI
#****************
#------------------------------------------------------
# --> Workspace info
#
# * Get-PowerBIWorkspace > "WARNING: Defaulted to show top 100 workspaces. Use -First & -Skip or -All to retrieve more results."
# * Grid exported for workspaces
#------------------------------------------------------
Write-Host " Workspace info ..." -ForegroundColor Yellow -BackgroundColor DarkGreen
## List all groups, Select ID desired for Variables section
## PBIWorkspace properties values are NULL if Scope is not set to Organization
# Get-PowerBIWorkspace -Scope Organization -Filter "tolower(name) eq 'BI Team POC - DEV'"
# SET
$Groups = Get-PowerBIWorkspace -Scope Organization -All | SORT #{Expression="Type"; Descending=$True}, Name
$Groups_deleted = $Groups | SELECT Id, Name, Type, State | WHERE State -EQ 'Deleted'
$Groups = $Groups | SELECT Id, Name, Type, State | WHERE State -NE 'Deleted'
$GroupWorkspaces = $Groups | WHERE Type -eq 'Workspace'
# PRINT
$Groups_deleted | Select Id, Name, Type, State | ft –auto
$Groups | Select Id, Name, Type, State | ft –auto
$GroupWorkspaces | Select Id, Name, Type | ft –auto
Get-PowerBIWorkspace -Scope Organization -Name "BI Team Sandbox" | Select Id, Name, Type | ft –auto
# OUT GRID
$GroupsWorkspaces | Select Id, Name, Type | Out-GridView
$Groups | Select Id, Name, Type | Out-GridView
$Groups_deleted | Select Id, Name, Type, State | Out-GridView
#------------------------------------------------------
## LOOP FOLDERS ##################
# * RestAPI call for each workspace (Group Users)
# * Grid exported for workspace user access
#------------------------------------------------------
# Clear variable before loop to reseat array data collector
clear-variable -name WorkspaceUsers
Write-Host " Looping ..." -ForegroundColor Yellow -BackgroundColor DarkGreen
foreach ($GroupWorkspaceId in $GroupWorkspaces.Id) {
$WorkspaceObject = Get-PowerBIWorkspace -Scope Organization -Id $GroupWorkspaceId
$pbiURL = "https://api.powerbi.com/v1.0/myorg/groups/$GroupWorkspaceId/users"
$WorkspaceObject | Select Id, Name, Type | ft –auto
Write-Host ($WorkspaceObject.Name +" | "+ $WorkspaceObject.Type) -ForegroundColor White -BackgroundColor Blue
Write-Host $GroupWorkspaceId -ForegroundColor White -BackgroundColor Blue
Write-Host $pbiURL -ForegroundColor White -BackgroundColor Blue
#****************
#------------------------------------------------------
# --> 1. API Call for WORKSPACE USERS
#------------------------------------------------------
Write-Host " API Call ..." -ForegroundColor Yellow -BackgroundColor DarkGreen
## API call
$resultJson = Invoke-PowerBIRestMethod –Url $pbiURL –Method GET
$resultObject = ConvertFrom-Json -InputObject $resultJson
## Collect data fields for each loop
$WorkspaceUsers += $resultObject.Value |
SELECT #{n='WorkspaceId';e={$GroupWorkspaceId}},
#{n='Workspace';e={$WorkspaceObject.Name}},
displayName,
emailAddress,
#{n='UserRole';e={$_.groupUserAccessRight}},
#{n='Principle';e={$_.principalType}} |
SELECT Workspace, displayName, UserRole, Principle, emailAddress |
SORT UserRole, displayName
## Print loop results
$WorkspaceUsers | ft -auto | Where{$_.WorkspaceId -eq $GroupWorkspaceId}
clear-variable -name resultJson
clear-variable -name resultObject
}
## END LOOP ##################
#------------------------------------------------------
## Export user access for all workspaces
$WorkspaceUsers | SORT Workspace, UserRole, displayName | Out-GridView
You can use Get-PowerBIWorkspace from Microsoft Power BI Cmdlets to get list of workspaces and then list the members of the underlying Office 365 group (unless you are using the new preview workspaces, which has no underlying Office 365 group) using Get-UnifiedGroup cmdlet. To be able to use it, you need to Connect to Exchange Online PowerShell. Then enumerate the groups, enumerate current group members, and export them to a CSV (or process the result the way you want). If you have rights, provide -Scope Organization parameter, or omit it to get a list of your workspaces.
Import-Module MicrosoftPowerBIMgmt
$password = "xxxxxxxx" | ConvertTo-SecureString -asPlainText -Force
$username = "xxxxxxxx#example.com"
$credential = New-Object System.Management.Automation.PSCredential($username, $password)
Connect-PowerBIServiceAccount -Credential $credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange `
-ConnectionUri https://outlook.office365.com/powershell-liveid/ `
-Credential $credential `
-Authentication Basic `
-AllowRedirection
Import-PSSession $Session
$Groups = Get-PowerBIWorkspace #-Scope Organization
$Groups | ForEach-Object {
$group = $_
Get-UnifiedGroupLinks -Identity $group.Name -LinkType Members -ResultSize Unlimited | ForEach-Object {
$member = $_
New-Object -TypeName PSObject -Property #{
Member = $member.Name
Group = $group.Name
}
}
} | Export-CSV "D:\\PowerBIGroupMembers.csv" -NoTypeInformation -Encoding UTF8
Remove-PSSession $Session
Disconnect-PowerBIServiceAccount

Azure Powershell - Script to obtain VM info across subscriptions

Trying to run a script that will connect to each subscription, and pull the
$azureSubs = Get-AzureRMSubscription
$azureSubs | ForEach-Object {Select-AzureRMSubscription $_ | Out-Null; Get-AzureRMVM | select resourcegroupname, name, licensetype -WarningAction SilentlyContinue}
This works, BUT I'd like to add two more pieces of information: the "OSType" and "VMSize"
If I do a GET-AZURERMVM, in the table for that subscription that the command is run in, the two pieces of information I need are there: VmSize and OsType
However, when I try to add them to the query, the columns are blank.
I believe the VmSize is in the HardwareProfile, and OsType is in the OsProfile, as if I run a "Get-AzureRMVM -name (name) -resourcegroupname (RGname)", then it shows "Hardware Profile: VMSize" and "OSProfile: ComputerName, AdminUsername windowsConfiguration, Secrets"
Ultimate goal is to get the script that will, for each subscription, print results like:
ResourceGroupName | Name | License Type | VMSize | OS Type
TEST_RG | Test_VM | Windows_Server | DS3_v2 | Windows
Test_RG | Test_VM2 | | DS3_v2 | Linux
etc.
Thankful for any help; sorry for such a noob question. Have spent so much time trying to figure this out...
Something like the following would work.
What you were missing mainly was calculated properties.
This is what allow you to perform a select of custom property.
Some notes:
In your code, you used -WarningAction SilentlyContinue on the Select statement. You need to put it on the Get-AzureRMVM CmdLet instead.
This is my opinion but unless you are writing one-liners on purposes, try aerating your code more. It will make it way easier to read, debug and maintain.
This is the code you wrote, modified to include the calculated properties and with the WarningAction parameter set to Get-AzureRMVM instead of the Select statement.
$azureSubs = Get-AzureRMSubscription
$Vms = $azureSubs | ForEach-Object {Select-AzureRMSubscription $_ | Out-Null; Get-AzureRMVM -WarningAction SilentlyContinue | select resourcegroupname, name, licensetype, #{Name="VMSize";Expression={$_.HardwareProfile.VmSize}},#{Name="OsType";Expression={$_.StorageProfile.OsDisk.OsType}}}
$Vms | ft
The same thing, with some progress indication without forcing everything on one line.
$azureSubs = Get-AzureRMSubscription
$Vms = New-Object 'System.Collections.Generic.List[PSObject]'
ForEach ($sub in $azureSubs) {
Select-AzureRMSubscription $sub | Out-Null
Write-Host "Processing Subscription $($sub.Name)".PadRight(50,' ') -ForegroundColor Cyan -NoNewline
[PsObject[]]$items = Get-AzureRMVM -WarningAction SilentlyContinue |
select resourcegroupname,
name,
licensetype,
#{Name="VMSize";Expression={$_.HardwareProfile.VmSize}},
#{Name="OsType";Expression={$_.StorageProfile.OsDisk.OsType}}
Write-Host "($($items.count) retrieved)"
if ($items -ne $null) {
$vms.AddRange($items)
}
}
$vms | Format-Table
You are looking for something like this on the select side
select resourcegroupname, name, licensetype, #{Name="VMSize";Expression={$_.HardwareProfile.VmSize}}, #{Name="OsType";Expression={$_.StorageProfile.OsDisk.OsType}}

Fill in column into excel with powershell

I'm trying to create a report which will get two sets of information, Group name and domain. The problem is that the information will be output into one column instead of two for example:
Group Member Domain
thisIsGroupMember,Domain
but I want it to be like this:
Group Member Domain
thisIsGroupMember, Domain
I also try export-csv but the created csv file only show
Length
32
Here's my code:
$appName = $findone.properties.name
$domain = (($findone.properties.adspath -split ',')[3].substring(3)
$inputstring = "$appName,$domain"
out-file -FilePath "C:\Test\Result.csv" -append -inputObject $inputstring
If your code iterates through a list of objects pulled from AD you can use something like this:
# your foreach code
{
...
$appName = $findone.properties.name
$domain = (($findone.properties.adspath -split ',')[3].substring(3)
$output += ,(New-Object -TypeName psobject -Property #{"Group Member"=$appName;"Domain"=$domain})
}
$output | Export-Csv "C:\Test\Result.csv"
$output is an array of objects being created on the fly with $appName and $domain values. It will then nicely export to a csv after all AD objects are processed.

How do I add another column to a System.Object using a list in Powershell?

I am making a script to query active directory via powershell and pull all computers that contain a username in the description field, then filter that list with only computers last logged in the past 14 days.
This is what I have so far:
$queryAD = Get-ADComputer -SearchBase 'OU=West Division,DC=cable,DC=comcast,DC=com' -Properties Name, Description -Filter {(Name -like "WA*") -and (Description -like $wildCard)} | Select-Object Name, Description
$lastLogon = $queryAD | Select-Object -ExpandProperty Description | %{$_.replace(("$NTname" + ";"),"").split(";")[0]} | %{get-date $_ -format d}
I'd like to add the list generated from $lastLogon to $queryAD, right now $queryAD is returning two columns with headers Name and Description. I need a third header added called Last Logon Date and contain the list in $lastLogon. Please advise.
You could assign the values to an array of objects to make your output cleaner (if this method is providing you the data you want) like so:
$queryAD = Get-ADComputer -SearchBase 'OU=West Division,DC=cable,DC=comcast,DC=com' -Properties Name, Description -Filter {(Name -like "WA*") -and (Description -like $wildCard)} | Select-Object Name, Description
$computer_list = #()
foreach($computer in $queryAD) {
$computer_info = New-Object PSObject -Property #{
Name = $computer.Name
Description = $computer.Description
LastLogonDate = $computer | Select-Object -ExpandProperty Description | %{$_.replace(("$NTname" + ";"),"").split(";")[0]} | %{get-date $_ -format d}
}
$computer_list += $computer_info
}
in which case $computer_list will contain all of the info you're gathering in tidy objects.
...but this method seems overcomplicated. Look into this blog entry by Matt Vogt for a better way to query for old machines in AD.

Resources