Sharepoint online List and item level permission using pnpPowershel - sharepoint

I am trying to pull Site/List/Library/Item/subsite level permissions/unique permission on our SharePoint online site using the script below from reference :
https://social.technet.microsoft.com/Forums/forefront/en-US/77a8e9ef-56a5-47e4-9b54-209f37687013/sharepoint-online-subsite-permissions-list-credenstials-promt?forum=onlineservicessharepoint - Marked as answer by MichaelIT02
However, I am getting site/subsites level permission only in PNP Powershell using above code. I tried to work on scripts in PNP to get list and library permission/unique permission but unable to find an idea. If anyone could help me to extend same code, it would be greatly appreciated.
Thanks in Advance!!
Please check below code:
Here in I am unable to get Item level permission.
$siteUrl="https://TestSite.sharepoint.com/sites/TeamsiteSample"
$outputFile= "C:\Users\123\Desktop\SiteAndSubsitePermission.csv"
$username="xyz#xyz.onmicrosoft.com"
$password="xyz#12345"
$encpassword = convertto-securestring -String $password -AsPlainText -Force
$credential = new-object -typename System.Management.Automation.PSCredential -
argumentlist $username, $encpassword
Connect-PnPOnline -Url $siteUrl -Credentials $credential
# output file name and location
"List Title `t Title `t PrincipalType `t Permission `t GivenThrough" | Out-File
$outputFile -Append
#`t LoginName
# get document library
$library = Get-PnpList -Includes RoleAssignments
#-Identity $libraryName -Includes RoleAssignments
foreach($libraryList in $library)
{
# get all the users and groups who has access
$roleAssignment = $libraryList.RoleAssignments
foreach ($roleAssignment in $roleAssignment)
{
Get-PnPProperty -ClientObject $roleAssignment -Property RoleDefinitionBindings,
Member
$ListTitle = $libraryList.title
$loginName = $roleAssignment.Member.LoginName
$title = $roleAssignment.Member.Title
$principalType = $roleAssignment.Member.PrincipalType
$givenThrough = ""
$permissionLevel = ""
# loop through permission levels assigned to specific user/group
foreach ($roleDefinition in $roleAssignment.RoleDefinitionBindings){
$PermissionLevel += $RoleDefinition.Name + ";"
}
$givenThrough = "Given directly"
"$($ListTitle) `t $($title) `t $($principalType) `t $($permissionLevel) `t
$($givenThrough)" | Out-File $outputFile -Append
#`t $($loginName)
# if principal is SharePoint group -> get SharePoint group members
#if ($roleAssignment.Member.PrincipalType.ToString() -eq "SharePointGroup")
# {
# $givenThrough = $roleAssignment.Member.Title.ToString()
# $groupMembers = Get-PnpGroupMembers -Identity $roleAssignment.Member.LoginName
# foreach ($member in $groupMembers)
# {
# "$($member.Title) `t $($member.LoginName) `t $($member.PrincipalType) `t
$($permissionLevel) `t $($title) `t $($ListTitle)" | Out-File $outputFile -Append
# }
# }
}
}
$subwebs=Get-PNPSubWebs
foreach($subweb in $subwebs)
{
#Connect-PNPonline -Url $siteUrl -Credentials $credential
#Write-Host $subweb.Url
$groups=Get-PNPGroup
foreach($group in $groups)
{
#$DLGP = "" | Select "SiteUrl","GroupName","Permission"
$sPerm=Get-PNPGroupPermissions -Identity $group.loginname -ErrorAction
SilentlyContinue |Where-Object {$_.Hidden -like "False"}
if ($sPerm -ne $null)
{
$SiteUrl=$subwebs.title
$GroupName=$group.loginname
$Permission=$sPerm.Name
#Test columns
"$($SiteUrl) `t $($GroupName) `t $($Permission)" | Out-File $outputFile -Append
}
}
Write-Host $subweb.Url "permission fetched!" }

Related

Powershell does not create CSV if there is no data to export in Azure

I am trying to export VM data from Azure and below script is working perfect if subscription has VMs however it does create a .csv if there is no data (VMs) and I need that even if there is no data powershell should create a blank csv. Below is my script which is working fine if subscription has VMs created in it.
function create($path) {
$exists = Test-Path -path $path
Write-Host "tried the following path: $path, it" $(If ($exists) {"Exists"} Else {"Does not Exist!"})
if (!($exists)) { New-Item $path -itemType Directory }
}
# reading file contents
$subs_file = "C:\Scrpting\Subscriptions\Subscriptions.xlsx"
$azSubs = Import-Excel $subs_file
$azSubs
$output_folder = "C:\audit-automation"
# creating folder for outputing data
create("$output_folder")
# New-Item $output_folder -itemType Directory
# iterating over subscriptions
ForEach ( $sub in $azSubs ) {
# sub
$azsub = $sub.Subscription
# app
$app = $sub.Application
$azsub
$app
# creating folder to save data for apps
# New-Item $output_folder\$app -itemType Directory
# setting config for azure
Set-AzContext -SubscriptionName $azsub
# GET VM INFO
$vms = Get-AzVM
$vmrg = Get-AzVM | Select-Object "ResourceGroupName"
$nics = get-AzNetworkInterface | Where-Object { $_.VirtualMachine -NE $null }
# creating folder to save
# New-Item $output_folder\$app\vm_info -itemType Directory
create("$output_folder\$app")
ForEach ($nic in $nics) {
$info = "" | Select VMName, ResourceGroupName, OS, PrivateIPAddress, PublicIPAddress, SubscriptionID, Status, NICName
$vm = $vms | ? -Property Id -eq $nic.VirtualMachine.id
$info.NICName = $nic.Name
$info.VMName = $vm.Name
$info.SubscriptionID = $azsub
$info.ResourceGroupName = $vm.ResourceGroupName
$info.PrivateIPAddress = $nic.IpConfigurations.PrivateIpAddress
$PublicIPAddress =
(Az vm list-ip-addresses --name $vm.Name --resource-group $vm.ResourceGroupName | ConvertFrom-Json).virtualMachine.network.publicIpAddresses.ipaddress
$info.PublicIPAddress = if ($null -eq $PublicIPAddress ) { "Not Assigned" } else { $PublicIPAddress }
$info.OS = $vm.StorageProfile.osDisk.osType
$info.Status = ((Get-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Status).Statuses[1]).code
$info | Export-Csv -Path $output_folder\$app\$app-vm_data$((Get-Date).ToString("yyyy-MM-dd")).csv -Append
}}
You can remove the function create and replace that with just the one line $null = New-Item $output_folder -ItemType Directory -Force.
On file system, the -Force makes the cmdlet return either the DirectoryInfo object of an existing folder or create a new folder and return that.
(don't use this on registry keys!)
Next, if you capture the output you want in the CSV file first, it is easy enough to check if there is output or not and if not, write an empty csv file (only the headers will be in there)
Something like this:
# reading file contents
$subs_file = "C:\Scrpting\Subscriptions\Subscriptions.xlsx"
$azSubs = Import-Excel $subs_file
#$azSubs
$output_folder = "C:\audit-automation"
# creating folder for outputing data
$null = New-Item $output_folder -ItemType Directory -Force
# iterating over subscriptions
foreach($sub in $azSubs) {
# sub
$azsub = $sub.Subscription
# app
$app = $sub.Application
$azsub
$app
# setting config for azure
Set-AzContext -SubscriptionName $azsub
# GET VM INFO
$vms = Get-AzVM
$vmrg = Get-AzVM | Select-Object "ResourceGroupName"
$nics = Get-AzNetworkInterface | Where-Object { $null -ne $_.VirtualMachine }
# creating folder to save
$null = New-Item (Join-Path -Path $output_folder -ChildPath $app) -ItemType Directory -Force
# capture the output of the foreach loop
$result = foreach ($nic in $nics) {
$info = "" | Select VMName, ResourceGroupName, OS, PrivateIPAddress, PublicIPAddress, SubscriptionID, Status, NICName
$vm = $vms | ? -Property Id -eq $nic.VirtualMachine.id
$info.NICName = $nic.Name
$info.VMName = $vm.Name
$info.SubscriptionID = $azsub
$info.ResourceGroupName = $vm.ResourceGroupName
$info.PrivateIPAddress = $nic.IpConfigurations.PrivateIpAddress
$PublicIPAddress = (Az vm list-ip-addresses --name $vm.Name --resource-group $vm.ResourceGroupName |
ConvertFrom-Json).virtualMachine.network.publicIpAddresses.ipaddress
$info.PublicIPAddress = if ($null -eq $PublicIPAddress ) { "Not Assigned" } else { $PublicIPAddress }
$info.OS = $vm.StorageProfile.osDisk.osType
$info.Status = ((Get-AzVM -ResourceGroupName $vm.ResourceGroupName -Name $vm.Name -Status).Statuses[1]).code
# output the object to be collected in variable $result
$info
}
# test if you actually have data now in the $result variable
if (!#($result.Count)) {
# no data; create an empty csv with just the headers
$result = "" | Select VMName, ResourceGroupName, OS, PrivateIPAddress, PublicIPAddress, SubscriptionID, Status, NICName
}
$outFile = Join-Path -Path $output_folder -ChildPath ('{0}\{0}-vm_data{1:yyyy-MM-dd}.csv' -f $app, (Get-Date))
$result | Export-Csv -Path $outFile -NoTypeInformation
}
add outside the loop, since $vms may be empty
if (!($vms)){
$info = "" | Select VMName, ResourceGroupName, OS, PrivateIPAddress, PublicIPAddress, SubscriptionID, Status, NICName
$info | Export-Csv -Path $output_folder\$app\$app-vm_data$((Get-Date).ToString("yyyy-MM-dd")).csv -Append
}

My Powershell script is not explicitly calling for any specific resources but I am getting "ErrorCode: TargetResourceNotFound" error

My Powershell script is not explicitly calling for any specific resources but I am getting "ErrorCode: TargetResourceNotFound" error. I have attached the error in the image. What am I missing?
$subs = Get-AzSubscription | Where-Object {$_.Name -like "*-NonProd"}
foreach ($sub in $subs)
{
Select-AzSubscription -SubscriptionId $sub.Id
$RGs = Get-AzResourceGroup | Where-Object {$_.ResourceGroupName -like "*Infra"}
foreach ($RG in $RGs)
{
$NetworkWatchers = Get-AzNetworkWatcher
$NSGs = (Get-AzNetworkSecurityGroup).Id
foreach ($NSG in $NSGs)
{
foreach ($NetworkWatcher in $NetworkWatchers)
{
$Status = Get-AzNetworkWatcherFlowLogStatus -NetworkWatcherName $NetworkWatcher.Name
ResourceGroupName $RG.ResourceGroupName -TargetResourceId $NSG -Verbose
}
if (($Status).Enabled -eq $true)
{
Write-Output "$NSG in $(($sub).Name) has FlowLogs Enabled" | Tee-Object -FilePath 'C:\Users\user1\downloads\Output.txt' -Verbose -Append
}
if (($Status).Enabled -ne $true)
{
Write-Output "$NSG in $(($sub).Name) does not have FlowLogs Enabled" | Tee-Object -FilePath 'C:\Users\user1\downloads\Output.txt' -Verbose -Append
}
}
}
}
enter code here
Error Attached
Network Watchers are usually in a hidden resource group, and perhaps you are trying to find one in one of the available RGs. Try omitting the RG factor and use
$subs = Get-AzSubscription | Where-Object { $_.Name -like "*-NonProd" }
foreach ($sub in $subs) {
Select-AzSubscription -SubscriptionId $sub.Id
$NetworkWatchers = Get-AzNetworkWatcher
$NSGs = (Get-AzNetworkSecurityGroup).Id
foreach ($NSG in $NSGs) {
foreach ($NetworkWatcher in $NetworkWatchers) {
$Status = Get-AzNetworkWatcherFlowLogStatus -NetworkWatcher $NetworkWatcher -TargetResourceId $NSG -Verbose
}
if (($Status).Enabled -eq $true) {
Write-Output "$NSG in $(($sub).Name) has FlowLogs Enabled" | Tee-Object -FilePath 'C:\Users\user1\downloads\Output.txt' -Verbose -Append
}
if (($Status).Enabled -ne $true) {
Write-Output "$NSG in $(($sub).Name) does not have FlowLogs Enabled" | Tee-Object -FilePath 'C:\Users\user1\downloads\Output.txt' -Verbose -Append
}
}
}
I am able to get all flow logs configuration status.
Here is another approach:
I tried to reproduce the same in my environment and got the same error as below:
The error TargetResourceNotFound usually occurs if you are passing invalid resource group name or subscription name.
To confirm whether the resource group or subscription exists, execute the below code lines separately like below:
$subs = Get-AzSubscription | Where-Object {$_.Name -like "*-name"}
$subs
$RGs = Get-AzResourceGroup | Where-Object {$_.ResourceGroupName -like "*name"}
$RGs
The error states that Target resource identifier /subscriptions/subid/resourceGroups/RG/providers/Microsoft.Network/networkWatchers/*** not found in the region westeurope. Cross-verify whether the Network Watcher exists.
I am able to get the status of the Network Watcher successfully when I passed valid subscription and Resource group like below:
If the error still persists, try excluding the $RGs = Get-AzResourceGroup | Where-Object {$_.ResourceGroupName -like "*name"} and execute.
I appreciate your assistance.
I got it working by changing -NetworkWatcherName $NetworkWatcher.Name to -NetworkWatcherName $NetworkWatcher.ResourceGroupName
foreach ($NSG in $NSGs)
{
# $NSG.Id
# $NSGid = $NSG.Id
foreach ($NetworkWatcher in $NetworkWatchers)
{
$Status = Get-AzNetworkWatcherFlowLogStatus -NetworkWatcherName $NetworkWatcher.ResourceGroupName -ResourceGroupName $RG.ResourceGroupName -TargetResourceId $NSG -Verbose -ErrorAction SilentlyContinue
if (($Status).Enabled -eq $true)
{
Write-Output "$NSG in $(($sub).Name) has FlowLogs Enabled" | Tee-Object -FilePath 'C:\Users\A240379\downloads\OutEnabled.csv' -Verbose -Append
}
if (($Status).Enabled -ne $true)
{
Write-Output "$NSG in $(($sub).Name) does not have FlowLogs Enabled" | Tee-Object -FilePath 'C:\Users\A240379\downloads\OutNotEnabled.csv' -Verbose -Append
}
}
}

Trying to list Azure Virtual Network and export to CSV using Powershell

I am trying to create a script that can list all the Azure virtual networks and export it into Csv using Powershell.
$day = Get-Date -Format " MMM-yyyy"
$path = "C:\Users\admin-vishal.singh\Desktop\Test\Report\"+ "$day-Vnet-Report.csv"
foreach ($Sub in $Subs) {
Select-AzSubscription -SubscriptionName $Sub.Name | Out-Null
$resource_grps = Get-AzResourceGroup
foreach ($resource_grp in $resource_grps) {
$networks = Get-AzVirtualNetwork
foreach ($vnet in $networks)
{
$null = Get-AzVirtualNetwork |Select-Object SubscriptionName,ResourceGroupName,Name,AddressSpace,Subnets,SubnetAddressSpace,RouteTable | Export-CSV -Path $path -NoTypeInformation -Encoding ASCII -Append
}
}
}
I am not able to retrieve data in the right format & getting errors when retrieving data.
Below is snippet of data
Lots of values I am not able to retrieve like Subnet AddressSpace, Route Tables and Routes.
Building on what Jim Xu provided, you don't need to have a separate loop for each ResourceGroup. Get-AzVirtualNetwork will return all virtual networks for the entire subscription. Also, you'll need an expression for the SubscriptionName in the Select-Object, so the code would look like this:
foreach ($Sub in $Subs) {
Select-AzSubscription -SubscriptionName $Sub.Name | Out-Null
Get-AzVirtualNetwork |
Select-Object `
#{label='SubscriptionName'; expression={$Sub.Name}}, `
ResourceGroupName, `
Name, `
#{label='AddressSpace'; expression={$_.AddressSpace.AddressPrefixes}}, `
#{label='SubnetName'; expression={$_.Subnets.Name}}, `
#{label='SubnetAddressSpace'; expression={$_.Subnets.AddressPrefix}} |
Export-CSV -Path $path -NoTypeInformation -Encoding ASCII -Append
}
When we call export-csv command, the property values are converted to strings using the ToString() method. But the result of Get-AzVirtualNetwork are object, we cannot directly convert the value to string. For more details, please refer to here and here
So regarding the issue, I suggest you create a custom object with the information you need then save it into csv.
For exmaple
$vents =Get-AzVirtualNetwork|
Select-Object SubscriptionName,ResourceGroupName,Name, #{
label='AddressSpace'
expression={$_.AddressSpace.AddressPrefix}}, #{
label='SubnetName'
expression={$_.Subnets.Name}
}, #{
label='SubnetAddressSpace'
expression={$_.Subnets.AddressPrefix}
}
$vents | convertto-csv

Exporting Group Types from Azure AD Powershell

I am trying to export all Azure AD groups, their owners, description, email and its group type. Such as Office 365, Security or Distrubution. I have managed to export everything correctly into a .csv except the group type. Get-AzureADGroup will return only "Group" and I can't get any results from get-msolgroup -grouptype.
Script I have been using:
$array = #()
$Properties=#{}
$Properties.add("GroupDisplayName","1")
$Properties.add("OwnerObjectId","2")
$Properties.add("OwnerObjectType","3")
$Properties.add("OwnerUserType","4")
$Properties.add("OwnerUserPrincipalName","5")
$Properties.add("GroupDescription","6")
$Properties.add("Email","7")
$Properties.add("GroupTypes","8")
$groups = Get-AzureADGroup -All $true
$GroupType = Get-MsolGroup -Grouptype
Foreach($group in $groups){
$Owners = Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true
$Properties.GroupDisplayName=$group.DisplayName
$Properties.GroupDescription=$group.description
$Properties.Email=$group.mail
$Properties.GroupTypes=$group.GroupType
if($Owners -ne $null){
# group has owner
Foreach($Owner in $Owners){
$Properties.OwnerObjectId=$Owner.ObjectId
$Properties.OwnerObjectType=$Owner.ObjectType
$Properties.OwnerUserType=$Owner.UserType
$Properties.OwnerUserPrincipalName=$Owner.UserPrincipalName
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
else{
#group has no owner
$Properties.OwnerObjectId=$null
$Properties.OwnerObjectType=$null
$Properties.OwnerUserType=$null
$Properties.OwnerUserPrincipalName=$null
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
$array | export-csv -Path C:\scripts\Owners13.csv -NoTypeInformation -Encoding UTF8
According to my research, the command Get-MsolGroup is a command of Azure AD V1 module : MSOnline. But the other commands you use are the command of Azure AD V2 module: AzureAD. They are in different modules. So if you want to use the command Get-MsolGroup, you need to run the command Connect-MsolService at frist.
For example:
Connect-MsolService
Get-MsolGroup -all | Select-Object DisplayName, GroupType
Besides, if you just want to use AzureAD module to get group type, we can use the command Get-AzureADMSGroup to get it. But if we use the command, we need to make some judgments by the response's properties. For more details, please refer to the document
For example
Connect-AzureAD
Get-AzureADMSGroup -All $true | Select-Object DisplayName, GroupTypes,MailEnabled, SecurityEnabled
Update
You can use the following script to implement your need.
connect-AzureAD
$array = #()
$Properties=#{}
$Properties.add("GroupDisplayName","1")
$Properties.add("OwnerObjectId","2")
$Properties.add("OwnerObjectType","3")
$Properties.add("OwnerUserType","4")
$Properties.add("OwnerUserPrincipalName","5")
$Properties.add("GroupDescription","6")
$Properties.add("Email","7")
$Properties.add("GroupTypes","8")
$groups = Get-AzureADGroup -All $true
Foreach($group in $groups){
$Owners = Get-AzureADGroupOwner -ObjectId $group.ObjectId -All $true
$Properties.GroupDisplayName=$group.DisplayName
$Properties.GroupDescription=$group.description
$Properties.Email=$group.mail
$result=Get-AzureADMSGroup -Id $group.ObjectId | Select-Object GroupTypes,MailEnabled, SecurityEnabled, DisplayName
If($result.GroupTypes -contains "Unified"){
$Properties.GroupTypes="O365"
}
elseif($result.SecurityEnabled ){
$Properties.GroupTypes="Security"
}
else{
$Properties.GroupTypes="Distrubution"
}
if($Owners -ne $null){
# group has owner
Foreach($Owner in $Owners){
$Properties.OwnerObjectId=$Owner.ObjectId
$Properties.OwnerObjectType=$Owner.ObjectType
$Properties.OwnerUserType=$Owner.UserType
$Properties.OwnerUserPrincipalName=$Owner.UserPrincipalName
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
else{
#group has no owner
$Properties.OwnerObjectId=$null
$Properties.OwnerObjectType=$null
$Properties.OwnerUserType=$null
$Properties.OwnerUserPrincipalName=$null
$obj=New-Object PSObject -Property $Properties
$array +=$obj
}
}
$array | export-csv -Path E:\test.csv -Encoding UTF8 -NoTypeInformation

How To fix "add-member : Cannot add a member with the name "" because a member with that name already exists"

I need to list multiple FTP connexion on LogicApp service and export this list on csv file. This export is use for see if the SSL protocol connexion is activate or not. My script generate this error.
add-member : Cannot add a member with the name "FTP" because a member with that name already exists. To overwrite the member anyway, add the Force parameter to your command.
LogicApp FTP connexion :
https://learn.microsoft.com/en-us/azure/connectors/connectors-create-api-ftp
I need to add these FTP connections in this format on excel :
format need
$LogicApp_temp = $null
$LogicApp_obj = #()
$LogicApp_temp = new-object PSObject
$FTPAll = Get-AzResource -ResourceGroupName $RG -ResourceType Microsoft.Web/connections
foreach ( $FTPAlls in $FTPAll ) {
$FTPName = $FTPAlls.name
$FTPName1 = Get-AzResource -ResourceGroupName $RG -ResourceType Microsoft.Web/connections -Name $FTPName
foreach ($FTPName2 in $FTPName1) {
$FTPcheckType = $FTPName2.Properties.api.name
if ( $FTPcheckType -eq "ftp") {
$FTPSSL1 = $FTPName1.Properties.parameterValues.isSSL
}
else {
}
$LogicApp_temp | add-member -MemberType NoteProperty -Name "FTP" -Value "$FTPName2.Properties.displayName $FTPSSL1"
}
}
$LogicApp_obj += $LogicApp_temp
Write-Output "LogicApp Name : $Name Ressource Group : $RG OK"
# CSV Exports :
$LogicApp_obj | Export-Csv $csvPath -Append -NoTypeInformation
thank you in advance for your help
Because the PSObject property just could be set one value at one time, if you use the -Force, it will overwrite the value before.
If you want to get the .csv file like the format you provided, we could just append every string like joyftp True first.
My working sample:
$RG = "<resource group name>"
$LogicApp_obj = #()
$value = ""
$FTPAll = Get-AzResource -ResourceGroupName $RG -ResourceType Microsoft.Web/connections
foreach ( $FTPAlls in $FTPAll ) {
$FTPName = $FTPAlls.name
$FTPName1 = Get-AzResource -ResourceGroupName $RG -ResourceType Microsoft.Web/connections -Name $FTPName
foreach ($FTPName2 in $FTPName1) {
$FTPcheckType = $FTPName2.Properties.api.name
$displayname = $FTPName2.Properties.displayName
$LogicApp_temp = New-Object -TypeName PSObject
if ( $FTPcheckType -eq "ftp") {
$FTPSSL1 = $FTPName1.Properties.parameterValues.isSSL
$value += "$displayname $FTPSSL1 | "
$LogicApp_temp | add-member -MemberType NoteProperty -Name "FTP" -Value "$value" -Force
}
}
}
Write-Output "LogicApp Name : $Name Ressource Group : $RG OK"
# CSV Exports :
$LogicApp_temp | Export-Csv -Path "C:\Users\joyw\Desktop\ftp.csv" -NoTypeInformation
The .csv file:

Resources