Is it possible to add Microsoft Graph delegated permissions to Azure AD app via Powershell? - azure-active-directory

I registered an application in Azure AD from PowerShell using the below script.
//To create new application
$myapp = New-AzureADApplication -DisplayName MyApp
$myappId=$myapp.AppId
//To set ApplicationID URI
Set-AzureADApplication -ApplicationId $myappId -IdentifierUris "api://$myappId"
//To retrieve details of new application
Get-AzureADApplication -Filter "DisplayName eq $myapp"
Now I want to set delegated API permissions(Calendars.Read, Application.Read.All, Directory.Read.All) for this app.
From Azure Portal, I know how to assign these. But is it possible to add these permissions via PowerShell? If yes, can anyone help me with the script or cmdlets?
Any help will be appreciated. Thank you.

Yes, it's possible to set delegated API permissions via PowerShell
Initially, please note AppID of new application that can be retrieved by below cmdlet:
Get-AzureADApplication -Filter "DisplayName eq $myapp"
Check whether you have Service Principal named "Microsoft Graph" using below cmdlet:
Get-AzureADServicePrincipal -All $true | ? { $_.DisplayName -eq "Microsoft Graph" }
In order to assign API permissions via PowerShell, you should know the GUIDs of those delegated permissions that can be displayed using below cmdlet:
$MSGraph.Oauth2Permissions | FT ID, Value
Note the IDs of required permissions like Calendars.Read, Application.Read.All and Directory.Read.All
Please find the complete script below:
$myapp = New-AzureADApplication -DisplayName MyApp
$myappId=$myapp.ObjectId
Get-AzureADApplication -Filter "DisplayName eq 'MyApp'"
$MSGraph = Get-AzureADServicePrincipal -All $true | ? { $_.DisplayName -eq "Microsoft Graph" }
$MSGraph.Oauth2Permissions | FT ID, Value
# Create a Resource Access resource object and assign the service principal’s App ID to it.
$Graph = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess"
$Graph.ResourceAppId = $MSGraph.AppId
# Create a set of delegated permissions using noted IDs
$Per1 = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "c79f8feb-a9db-4090-85f9-90d820caa0eb","Scope"
$Per2 = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "465a38f9-76ea-45b9-9f34-9e8b0d4b0b42","Scope"
$Per3 = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "06da0dbc-49e2-44d2-8312-53f166ab848a","Scope"
$Graph.ResourceAccess = $Per1, $Per2, $Per3
# Set the above resource access object to your application ObjectId so permissions can be assigned.
Set-AzureADApplication -ObjectId $myappId -RequiredResourceAccess $Graph
Reference:
How to assign Permissions to Azure AD App by using PowerShell?

Related

powershell core 7.0.3 Az.Account PSADServicePrincipal appRoles and oauth2permissions

I have windows powershell 5.1 script block like the following that successfully retrieves appRoles and oauth2permissions.
import-module -name AzureAD
if ($null -eq $mycredentials) { $mycredentials = Get-Credential }
$azConnectionContext = Connect-AzureAD -Credential $mycredentials
# $svp = Get-AzureADServicePrincipal -Filter "DisplayName -eq 'Microsoft Graph' } # not working, why ???
$svp = Get-AzureADServicePrincipal -All $true | ? { $_.DisplayName -eq 'Microsoft Graph }
$appRoles = $svp.AppRoles; $oauth2permissions = $svp.Oauth2Permissions
I'm trying to convert to powershell core 7 script block like the following and i'm unable to retrive appRoles and oauth2permissions because the PSADServicePrincipal type doesn't expose those properties.
import-module -name Az.Accounts
$azConnectionContext = Connect-AzAccount
$svp = Get-AzADServicePrincipal -DisplayName 'Microsoft Graph' }
$appRoles = $svp.AppRoles; $oauth2permissions = $svp.Oauth2Permissions # both of these fail
Question - anyone know how i get at azure ad service principal appRoles and oauth2permissions using powershell core 7.0.3 apis and types?
Instead of:
$svp.AppRoles;
Use:
$svp.AppRole;
$svp.Oauth2Permissions should work. Type should be Microsoft.Azure.PowerShell.Cmdlets.Resources.Models.Api16.OAuth2Permission.
To your last question, remove-module only removes a module for the current session. You need to run Uninstall-Module instead.
There is an Uninstall-AzModule function here that might help you: https://learn.microsoft.com/en-us/powershell/azure/uninstall-az-ps?view=azps-4.6.1

How to create Azure SQL Managed Instance using AzureRm.Sql PowerShell library?

I need to automate creation of Azure SQL Database Managed Instance using PowerShell scripts (AzureRm.Sql). What command should be used to create it?
If you have installed AzureRm.Sql and properly configured network environment (VNet and subnet), you can use the following script that deploys 8-core "General Purpose" instance with 1024 max storage:
Select-AzureRmSubscription -Subscription "60d9f1df-......"
$resourceGroup = "<resource group>"
$vNetName = "<VNet name"
$subnetName = "<subnet name>"
$instanceName = "<subnet name>"
$region = "South India"
$vNet = Get-AzureRmVirtualNetwork -Name $vNetName -ResourceGroupName $resourceGroup
$subnet = Get-AzureRmVirtualNetworkSubnetConfig -Name $SubnetName -VirtualNetwork $vNet
$subnetId = $subnet.Id
New-AzureRmSqlManagedInstance -Name $instanceName `
-ResourceGroupName $resourceGroup -Location $region -SubnetId $subnetId `
-AdministratorCredential (Get-Credential) `
-StorageSizeInGB 1024 -VCore 8 -Edition "GeneralPurpose" `
-ComputeGeneration Gen5 -LicenseType BasePrice

Download all SSRS reports

I want to get a copy of all .rdl files in one server.
I can do the download manually one report at the time, but this is time consuming especially that this server has around 1500 reports.
Is there any way or any tool that allows me to download all the .rdl files and take a copy of them?
There is a complete & simpler way to do this using PowerShell.
This code will export ALL report content in the exact same structure as the Report server. Take a look at the Github wiki for other options & commands
#------------------------------------------------------
#Prerequisites
#Install-Module -Name ReportingServicesTools
#------------------------------------------------------
#Lets get security on all folders in a single instance
#------------------------------------------------------
#Declare SSRS URI
$sourceRsUri = 'http://ReportServerURL/ReportServer/ReportService2010.asmx?wsdl'
#Declare Proxy so we dont need to connect with every command
$proxy = New-RsWebServiceProxy -ReportServerUri $sourceRsUri
#Output ALL Catalog items to file system
Out-RsFolderContent -Proxy $proxy -RsFolder / -Destination 'C:\SSRS_Out' -Recurse
I've created this powershell script to copy them into a ZIP. You have to provide the SQL server database details.
Add-Type -AssemblyName "System.IO.Compression.Filesystem"
$dataSource = "SQLSERVER"
$user = "sa"
$pass = "sqlpassword"
$database = "ReportServer"
$connectionString = "Server=$dataSource;uid=$user; pwd=$pass;Database=$database;Integrated Security=False;"
$tempfolder = "$env:TEMP\Reports"
$zipfile = $PSScriptRoot + '\reports.zip'
$connection = New-Object System.Data.SqlClient.SqlConnection
$connection.ConnectionString = $connectionString
$connection.Open()
$allreports = $connection.CreateCommand()
$allreports.CommandText = "SELECT ItemID, Path, CASE WHEN Type = 2 THEN '.rdl' ELSE '.rds' END AS Ext FROM Catalog WHERE Type IN(2,5)"
$result = $allreports.ExecuteReader()
$reportable = new-object "System.Data.DataTable"
$reportable.Load($result)
[int]$objects = $reportable.Rows.Count
foreach ($report in $reportable) {
$cmd = $connection.CreateCommand()
$cmd.CommandText = "SELECT CAST(CAST(Content AS VARBINARY(MAX)) AS XML) FROM Catalog WHERE ItemID = '" + $report[0] + "'"
$xmldata = [string]$cmd.ExecuteScalar()
$filename = $tempfolder + $report["Path"].Replace('/', '\') + $report["Ext"]
New-Item $filename -Force | Out-Null
Set-Content -Path ($filename) -Value $xmldata -Force
Write-Host "$($objects.ToString()).$($report["Path"])"
$objects -= 1
}
Write-Host "Compressing to zip file..."
if (Test-Path $zipfile) {
Remove-Item $zipfile
}
[IO.Compression.Zipfile]::CreateFromDirectory($tempfolder, $zipfile)
Write-Host "Removing temporarly data"
Remove-Item -LiteralPath $tempfolder -Force -Recurse
Invoke-Item $zipfile
If you just need this for backup purposes or something similar, this might be useful: Where does a published RDL file sit?
The relevant query from that thread is:
select convert(varchar(max), convert(varbinary(max), content))
from catalog
where content is not null
The original answer was using 2005, and I've used it on 2016, so I imagine it should work for 2008 and 2012.
When I had to use this, I added in the Path to the query as well, so that I knew which report was which.
CAVEAT: prior to SSMS v18, Results to Grid is limited to 64KB per tuple and Results to Text are limited to 8,192 characters per tuple. If your report definition is larger than these limits you will not be able to get the entire definition.
In SSMS v18, those limits have been increased to 2MB per tuple for both Reports to Grid as well as Results to Text.
This is based on SQL2016/SSRS2016 but I think it should work for 2012.
SELECT 'http://mySQLServerName/reports/api/v1.0/catalogitems(' + cast(itemid as varchar(256))+ ')/Content/$value' AS url
FROM ReportServer.dbo.Catalog
This will give you a list of URL's, one for each report.
If the above did not work in SSRS 2012 then go to the report manager and do as if you were going to download the file from there. Check the URL on the download button and you'll probably see a URL with and item id embedded int it. Just adjust the above code to match that url structure.
What you do with then after this is up to you.
Personally I would use the Chrome extension called 'Tab Save' available in the Chrome store here. You can simply copy and paste all the URL's created above into it and hit the download button...
Found and used this without any issues. Nothing to install, just added my url, and pasted into Powershell.
https://microsoft-bitools.blogspot.com/2018/09/ssrs-snack-download-all-ssrs-reports.html
In case the link breaks, here's the code from the link:
###################################################################################
# Download Reports and DataSources from a SSRS server and create the same folder
# structure in the local download folder.
###################################################################################
# Parameters
###################################################################################
$downloadFolder = "c:\temp\ssrs\"
$ssrsServer = "http://myssrs.westeurope.cloudapp.azure.com"
###################################################################################
# If you can't use integrated security
#$secpasswd = ConvertTo-SecureString "MyPassword!" -AsPlainText -Force
#$mycreds = New-Object System.Management.Automation.PSCredential ("MyUser", $secpasswd)
#$ssrsProxy = New-WebServiceProxy -Uri "$($ssrsServer)/ReportServer/ReportService2010.asmx?WSDL" -Credential $mycreds
# SSRS Webserver call
$ssrsProxy = New-WebServiceProxy -Uri "$($ssrsServer)/ReportServer/ReportService2010.asmx?WSDL" -UseDefaultCredential
# List everything on the Report Server, recursively, but filter to keep Reports and DataSources
$ssrsItems = $ssrsProxy.ListChildren("/", $true) | Where-Object {$_.TypeName -eq "DataSource" -or $_.TypeName -eq "Report"}
# Loop through reports and data sources
Foreach($ssrsItem in $ssrsItems)
{
# Determine extension for Reports and DataSources
if ($ssrsItem.TypeName -eq "Report")
{
$extension = ".rdl"
}
else
{
$extension = ".rds"
}
# Write path to screen for debug purposes
Write-Host "Downloading $($ssrsItem.Path)$($extension)";
# Create download folder if it doesn't exist (concatenate: "c:\temp\ssrs\" and "/SSRSFolder/")
$downloadFolderSub = $downloadFolder.Trim('\') + $ssrsItem.Path.Replace($ssrsItem.Name,"").Replace("/","\").Trim()
New-Item -ItemType Directory -Path $downloadFolderSub -Force > $null
# Get SSRS file bytes in a variable
$ssrsFile = New-Object System.Xml.XmlDocument
[byte[]] $ssrsDefinition = $null
$ssrsDefinition = $ssrsProxy.GetItemDefinition($ssrsItem.Path)
# Download the actual bytes
[System.IO.MemoryStream] $memoryStream = New-Object System.IO.MemoryStream(#(,$ssrsDefinition))
$ssrsFile.Load($memoryStream)
$fullDataSourceFileName = $downloadFolderSub + "\" + $ssrsItem.Name + $extension;
$ssrsFile.Save($fullDataSourceFileName);
}
I'vr tried several permutations of this script and keep getting the "can't create proxy connection" error. Here's the one that "should" work:
#------------------------------------------------------
#Prerequisites
#Install-Module -Name ReportingServicesTools
#------------------------------------------------------
#Lets get security on all folders in a single instance
#------------------------------------------------------
#Declare SSRS URI
$sourceRsUri = "http://hqmnbi:80/ReportServer_SQL08/ReportService2010.asmx?wsdl"
#Declare Proxy so we dont need to connect with every command
$proxy = New-RsWebServiceProxy -ReportServerUri $sourceRsUri
#Output ALL Catalog items to file system
Out-RsFolderContent -Proxy $proxy -RsFolder / -Destination 'C:\Users\arobinson\source\Workspaces\EDW\MAIN\SSRS\HQMNBI' -Recurse
This is the error I'm getting:
Failed to establish proxy connection to http://hqmnbi/ReportServer_SQL08/ReportService2010.asmx : The HTML document does not contain
Web service discovery information.
At C:\Program Files\WindowsPowerShell\Modules\ReportingServicesTools\0.0.6.6\Functions\Utilities\New-RsWebServiceProxy.ps1:136 char:9
throw (New-Object System.Exception("Failed to establish proxy ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : OperationStopped: (:) [], Exception
FullyQualifiedErrorId : Failed to establish proxy connection to http://hqmnbi/ReportServer_SQL08/ReportService2010.asmx : The
HTML document does not contain Web service discovery information.
I've tried the URI with htttp:// and without, I've tried including the port number. etc. Still can't get this to actually work. We have two other SSRS instances that I was able to run this against no problem.
From this question: SQL Reporting Services - COPY reports to another folder
I found this tool can both download and upload reports. Plus it lists out folders and subfolders.
http://code.google.com/p/reportsync/

Powershell Script to Start Service if it is Stopped and wait for minute and send an email notification

I am very new to Powershell and in learning stage, I have tried to create an script to do automate below task. This script is not working as i am expected. Could you please review it and give me some help on it.
My task is,
I am trying to find out SQL Services (more than one SQL services in multiple servers) which are in stopped state and trying to start it, Waiting for an minute to complete the service start and verifying the service status again. If still it is stopped state i am trying to sending an email to setup of people for an action.
Could you please review the below code and correct the mistake, i tried to find it but unable to do
#Define servers & Services Variables
$Servers = GC "E:\Bhanu\SQLServer.txt"
$Services = GC "E:\Bhanu\SQLService.txt"
#Function Call
Function ServiceStatus ($Servers, $Services)
{
foreach ($Server in $Servers)
{
foreach ($Service in $Services)
{
$Servicestatus = get-service -ComputerName $Server -Name $Service
if ($Servicestatus.Status -eq "Stopped")
{
Start-service $Service
Start-Sleep -Seconds 60
$ServiceStatus1 = Get-Service -ComputerName $Server -Name $Service
if ($Servicestatus1.Status -eq "Stopped")
{
FuncMail -To “abc#gmail.com” -From “abc#gmail.com” -Subject $Server + $Service "fails to Start, Take immediate Action to avoid Impact” -Body $ServiceName "Service fails to Start, Take immediate Action to avoid Impact” -smtpServer “servername”
}
}
}
}
}
function FuncMail
{
#param($strTo, $strFrom, $strSubject, $strBody, $smtpServer)
param($To, $From, $Subject, $Body, $smtpServer)
$msg = new-object Net.Mail.MailMessage
$smtp = new-object Net.Mail.SmtpClient($smtpServer)
$msg.From = $From
$msg.To.Add($To)
$msg.Subject = $Subject
$msg.IsBodyHtml = 1
$msg.Body = $Body
$smtp.Send($msg)
}
servicestatus $Servers $Services
Please let me know if you need anything here from my end
Hi this isn't the best approach and i'm doing it in quick way.
note %=foreach-object; ?=Where-Object.
You have to save your password on one file if your smtp-server require authentication otherwise don't run it using read-host -assecurestring | convertfrom-securestring | out-file "C:\Secure\Password.txt"
I'm also assuming you have your servers saved on one file.
My solution is to start all sql server service if you want to start specific just save the service name on one file on separate line.
The code to execute bellow.
#Loading Server and service details
$Services=Get-content C:\PS\Service.txt
$servidores=get-content C:\PS\Servers\Servers.txt
#Loading Mail credential
$Mailpasswordpath="C:\PS\Securestring.txt"
$Mailusername="DOmain\User"
$password=cat $Mailpasswordpath |ConvertTo-Securestring
$Cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Mailusername,$password
$servidores|Foreach-Object{Get-Service -ComputerName $_ -Name $Services }| #Get the services running on all servers
Where-Object{$_.Status -eq "Stopped"}| #Which status is equal stopped
Foreach-Object{
$_.Start(); #try to start
Start-Sleep -Seconds 60; #wait one minute
$_.Refresh(); #refresh then service to update status
#validate is status still stopped
if($_.Status -eq "Stopped")
{
#LOADING Mail details
$To="user#domain.com"
$subject="$($_.MachineName) $($_.Name) fails to Start, Take immediate Action to avoid Impact"
$From="ServiceStatus#domain.com"
$smtp="Server.domain.com"
$body="$($_.Name) Service fails to Start, Take immediate Action to avoid Impact"
#Sending email to notify
Send-MailMessage -To $To -Subject $subject -From $From -SmtpServer $smtp -Body $body -Credential $Cred
}
}
P.S: It's not the best approach I only decide to solve this problem. if you want we can create a function together later just test it first.

How to find the client name who has logged in to machine?

We are trying to find from which machine a user has taken rdp .
Using "quser" utility we are able to get all the information about logged in user except client name.
Following is the command
function Get-LoggedOnUser
{
param([String[]]$ComputerName = $env:COMPUTERNAME)
$ComputerName | ForEach-Object {
(quser /SERVER:$_) -replace '\s{2,}', ',' |
ConvertFrom-CSV |
Add-Member -MemberType NoteProperty -Name ComputerName -Value $_ -PassThru
}
}
It displays all the information which can be provided in Windows task manager except client Name .
How to get client Name using powershell?
I doubt if WMI has a way to do this. You can check the PSTerminal Services module and it has a Get-TSSession cmdlet which does the same job you are looking for.
http://archive.msdn.microsoft.com/PSTerminalServices
This module uses binary Cassia namespace.
You can use this:
http://gallery.technet.microsoft.com/scriptcenter/0e43993a-895a-4afe-a2b2-045a5146048a
and look for the logged on user with a logon type of RemoteInteractive
You can read that information from the Security eventlog (look for logon type 10):
$username = '...'
$eventID = 4624 # 526 on Server 2003 and earlier
$date = (Get-Date).Date
$pattern = 'logon type:\s+10[\s\S]+source network address:\s+(\S+)'
Get-EventLog Security -InstanceId $eventID -EntryType SuccessAudit `
-After $date -Message '*$username*' `
| ? { $_.Message -match $pattern } `
| % { $matches[1] } `
| select -Unique
Note that on Server 2003 and earlier you need to check for event ID 528 instead of 4624.
References:
http://technet.microsoft.com/en-us/library/cc787567
http://support.microsoft.com/kb/977519

Resources