mirror of
https://github.com/admindroid-community/powershell-scripts.git
synced 2025-12-17 08:25:20 +00:00
Connect MS Graph with Certificate: Automate Azure App Registration
This commit is contained in:
parent
55e81a45b1
commit
b7fed42391
@ -0,0 +1,444 @@
|
||||
<#
|
||||
=============================================================================================
|
||||
Name: Connect to MS Graph PowerShell using Certificate
|
||||
Description: This script automates Azure app registration
|
||||
For detailed Script execution: https://blog.admindroid.com/connect-to-microsoft-graph-powershell-using-certificate/
|
||||
============================================================================================
|
||||
#>
|
||||
param (
|
||||
$TenantID =$null,
|
||||
$ClientID = $null,
|
||||
$CertificateThumbprint = $null
|
||||
)
|
||||
Function ConnectMgGraphModule
|
||||
{
|
||||
$MsGraphModule = Get-Module Microsoft.Graph -ListAvailable
|
||||
if($MsGraphModule -eq $null)
|
||||
{
|
||||
Write-host "Important: Microsoft graph module is unavailable. It is mandatory to have this module installed in the system to run the script successfully."
|
||||
$confirm = Read-Host Are you sure you want to install Microsoft graph module? [Y] Yes [N] No
|
||||
if($confirm -match "[yY]")
|
||||
{
|
||||
Write-host "Installing Microsoft graph module..."
|
||||
Install-Module Microsoft.Graph -Scope CurrentUser
|
||||
Write-host "Microsoft graph module is installed in this machine successfully" -ForegroundColor Magenta
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-host "Exiting. `nNote: Microsoft graph module must be available in your system to run the script" -ForegroundColor Red
|
||||
Exit
|
||||
}
|
||||
}
|
||||
Connect-MgGraph -Scopes "Application.ReadWrite.All,Directory.ReadWrite.All" -ErrorAction SilentlyContinue -Errorvariable ConnectionError |Out-Null
|
||||
if($ConnectionError -ne $null)
|
||||
{
|
||||
Write-Host "$ConnectionError" -Foregroundcolor Red
|
||||
Exit
|
||||
}
|
||||
Write-Host "Microsoft Graph Powershell module is connected successfully" -ForegroundColor Green
|
||||
$Script:TenantID = (Get-MgOrganization).Id
|
||||
}
|
||||
function RegisterApplication
|
||||
{
|
||||
Write-Progress -Activity "Registering an application"
|
||||
while(1)
|
||||
{
|
||||
$Script:AppName = Read-Host "`nEnter a name for the new App"
|
||||
if($AppName -eq "")
|
||||
{
|
||||
Write-Host "You didn't enter any name. Please provide an app name to continue." -ForegroundColor Red
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
$Script:RedirectURI = "https://login.microsoftonline.com/common/oauth2/nativeclient"
|
||||
$params = @{
|
||||
DisplayName = $AppName
|
||||
SignInAudience="AzureADMyOrg"
|
||||
PublicClient=@{
|
||||
RedirectUris = "$RedirectURI"
|
||||
}
|
||||
RequiredResourceAccess = @(
|
||||
@{
|
||||
ResourceAppId = "00000003-0000-0000-c000-000000000000" # Microsoft Graph Resource ID
|
||||
ResourceAccess = @(
|
||||
@{
|
||||
Id = "7ab1d382-f21e-4acd-a863-ba3e13f7da61" #Directory.Read.All -> Id
|
||||
Type = "Role" #Role -> Application permission
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
try{
|
||||
$Script:App = New-MgApplication -BodyParameter $params
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Host $_.Exception.Message -ForegroundColor Red
|
||||
CloseConnection
|
||||
}
|
||||
Write-Host "`nApp created successfully" -ForegroundColor Green
|
||||
$Script:APPObjectID = $App.Id
|
||||
$Script:APPID = $App.AppId
|
||||
}
|
||||
function CertificateCreation
|
||||
{
|
||||
Write-Progress -Activity "Creating certificate"
|
||||
$Script:CertificateName = "$AppName-Keycertifcate"
|
||||
$Script:path = "Cert:\CurrentUser\My\"
|
||||
$Script:CertificatePath = Get-ChildItem -Path $path
|
||||
$Script:Subject = "CN=$CertificateName"
|
||||
try
|
||||
{
|
||||
$Script:Certificate = New-SelfSignedCertificate -Subject $Subject -CertStoreLocation "$path" -KeyExportPolicy Exportable -KeySpec Signature -KeyLength 2048 -HashAlgorithm SHA256
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Host $_.Exception.Message -ForegroundColor Red
|
||||
CloseConnection
|
||||
}
|
||||
Write-Host "`nCertificate created successfully" -ForegroundColor Green
|
||||
}
|
||||
Function ImportCertificate
|
||||
{
|
||||
Write-Progress -Activity "Importing certificate"
|
||||
$UploadCertificate = Read-Host "Enter the certificate path(For example: C:\Users\Admin\user.cer)"
|
||||
try
|
||||
{
|
||||
$Script:Certificate = Import-Certificate -FilePath "$UploadCertificate" -CertStoreLocation "Cert:\CurrentUser\My"
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Host $_.Exception.Message -ForegroundColor Red
|
||||
$ImportCertificateError = $True
|
||||
ShowAppDetails
|
||||
CloseConnection
|
||||
}
|
||||
Write-Host "`nCertificate imported successfully" -ForegroundColor Green
|
||||
}
|
||||
Function UpdateCertficateDetails
|
||||
{
|
||||
$GetAppInfo= Get-MgApplication -ApplicationId $APPObjectID -Property KeyCredentials
|
||||
$Thumbprint=$Certificate.Thumbprint
|
||||
$CertificateName=$Certificate.Subject
|
||||
if($GetAppInfo -ne $null)
|
||||
{
|
||||
$NewKeys+=$GetAppInfo.KeyCredentials
|
||||
UploadCertificate
|
||||
# Get new certificate key credentials after updating new certificate
|
||||
Start-Sleep -Milliseconds 10000 # Takes time to update certificate to an application
|
||||
while(1)
|
||||
{
|
||||
$GetAppInfo= Get-MgApplication -ApplicationId $APPObjectID -Property KeyCredentials
|
||||
if($GetAppInfo.KeyCredentials -eq $null)
|
||||
{
|
||||
Write-Host "The certificate is not yet uploaded to an application. Waiting for 3 seconds..." -ForegroundColor Yellow
|
||||
Start-Sleep -Seconds 3
|
||||
Continue
|
||||
}
|
||||
break
|
||||
}
|
||||
$NewKeys+=$GetAppInfo.KeyCredentials #new keycredential
|
||||
Update-MgApplication -ApplicationId $APPObjectID -KeyCredentials $NewKeys
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "The application does not exist. Please try again with a different name." -ForegroundColor Green
|
||||
}
|
||||
}
|
||||
function UploadCertificate
|
||||
{
|
||||
Write-Progress -Activity "Uploading certificate"
|
||||
$KeyCredential = @{
|
||||
Type = "AsymmetricX509Cert";
|
||||
Usage = "Verify";
|
||||
key = $Certificate.RawData
|
||||
}
|
||||
Update-MgApplication -ApplicationId $APPObjectID -KeyCredentials $KeyCredential -ErrorAction SilentlyContinue -ErrorVariable ApplicationError
|
||||
if($ApplicationError -ne $null)
|
||||
{
|
||||
Write-Host "$ApplicationError" -ForegroundColor Red
|
||||
CloseConnection
|
||||
}
|
||||
Write-Host "`nCertificate uploaded successfully" -ForegroundColor Green
|
||||
$Script:Thumbprint = $Certificate.Thumbprint
|
||||
}
|
||||
function SecureCertificate
|
||||
{
|
||||
Write-Progress -Activity "Exporting pfx certificate"
|
||||
$Script:CertificateLocation = Get-Location
|
||||
$Script:CertificateLocation = "$CertificateLocation\$CertificateName.pfx"
|
||||
$GetPassword = Read-Host "`nPlease enter password to secure your certificate"
|
||||
try
|
||||
{
|
||||
$script:ExportError="False"
|
||||
$MyPwd = ConvertTo-SecureString -String "$GetPassword" -Force -AsPlainText
|
||||
Export-PfxCertificate -Cert "Cert:\CurrentUser\My\$Thumbprint" -FilePath "$CertificateLocation" -Password $MyPwd |Out-Null
|
||||
}
|
||||
catch
|
||||
{
|
||||
$script:ExportError="True"
|
||||
Write-Host $_.Exception.Message -ForegroundColor Red
|
||||
return
|
||||
}
|
||||
Write-Host "`nPfx file exported successfully" -ForegroundColor Green
|
||||
}
|
||||
function GrantPermission
|
||||
{
|
||||
Write-Progress -Activity "Granting admin consent..."
|
||||
Start-Sleep -Seconds 20
|
||||
$Script:ClientID = $App.AppId
|
||||
$URL = "https://login.microsoftonline.com/$TenantID/adminconsent"
|
||||
$Url="$URL`?client_id=$ClientID"
|
||||
Write-Host "`nMS Graph requires admin consent to access data. Please grant access to the application" -ForegroundColor Cyan
|
||||
While(1)
|
||||
{
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
$script:mainForm = New-Object System.Windows.Forms.Form -Property @{
|
||||
Width = 680
|
||||
Height = 640
|
||||
}
|
||||
$script:webBrowser = New-Object System.Windows.Forms.WebBrowser -Property @{
|
||||
Width = 680
|
||||
Height = 640
|
||||
URL = $URL
|
||||
}
|
||||
$document={
|
||||
if($webBrowser.Url -eq "$RedirectURI`?admin_consent=True&tenant=$TenantID" -or $webBrowser.Url -match "error")
|
||||
{
|
||||
$mainForm.Close()
|
||||
}
|
||||
if($webBrowser.DocumentText.Contains("We received a bad request"))
|
||||
{
|
||||
$mainForm.Close()
|
||||
}
|
||||
}
|
||||
$webBrowser.ScriptErrorsSuppressed = $true
|
||||
$webBrowser.Add_DocumentCompleted($document)
|
||||
$mainForm.Controls.Add($webBrowser)
|
||||
$mainForm.Add_Shown({ $mainForm.Activate() ;$mainForm.Refresh()})
|
||||
[void] $mainForm.ShowDialog()
|
||||
if($webBrowser.Url.AbsoluteUri -eq "$RedirectURI`?admin_consent=True&tenant=$TenantID")
|
||||
{
|
||||
Write-Host "`nAdmin consent granted successfully" -ForegroundColor Green
|
||||
break
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "`nAdmin consent failed." -ForegroundColor Red
|
||||
$Confirm = Read-Host "Do you want to retry admin consent? [Y] Yes [N] No"
|
||||
if($confirm -match "[yY]")
|
||||
{
|
||||
Continue
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "You can grant admin consent manually in azure portal." -ForegroundColor Yellow
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Function ShowAppDetails
|
||||
{
|
||||
Write-Host "`nApp info:" -ForegroundColor Magenta
|
||||
$GetAppInfo = Get-MgApplication|?{$_.AppId -eq "$APPID"}
|
||||
$Owner = Get-MgApplicationOwner -ApplicationId $GetAppInfo.Id|Select-Object -ExpandProperty AdditionalProperties
|
||||
$Script:CertificateList = $GetAppInfo.KeyCredentials
|
||||
$AppInfo=[pscustomobject]@{'App Name' = $GetAppInfo.DisplayName
|
||||
'Application(Client) Id' = $GetAppInfo.AppId
|
||||
'Object Id' = $GetAppInfo.Id
|
||||
'Tenant Id' = $TenantID
|
||||
'CertificateThumbprint' = $Thumbprint
|
||||
'App Created Date Time' = $GetAppInfo.CreatedDateTime
|
||||
'App Owner' = (@($Owner.displayName)| Out-String).Trim()
|
||||
}
|
||||
if($ImportCertificateError -eq $True)
|
||||
{
|
||||
$AppInfo | select 'App Name','Application(Client) Id','Object Id','Tenant Id','App Created Date Time','App Owner'|fl
|
||||
Write-Host "You can copy & save" -NoNewline
|
||||
Write-Host " Client Id" -ForegroundColor Cyan -NoNewline
|
||||
Write-Host " and try again to add certificate to your application."
|
||||
Return
|
||||
}
|
||||
if($Action -ne 5)
|
||||
{
|
||||
$AppInfo | select 'App Name','Application(Client) Id','Object Id','Tenant Id','CertificateThumbprint','App Created Date Time','App Owner'|fl
|
||||
Write-Host "You can copy and save" -NoNewline
|
||||
Write-Host " Client Id, Tenant Id, Certificate ThumbPrint" -ForegroundColor Cyan -NoNewline
|
||||
Write-Host " as they will be required to connect to MS Graph PowerShell using certificate-based authentication."
|
||||
}
|
||||
else
|
||||
{
|
||||
$AppInfo | select 'App Name','Application(Client) Id','Object Id','Tenant Id','App Created Date Time','App Owner'|fl
|
||||
Write-Host "App certificates :"
|
||||
$CertificateList | Format-Table -Property DisplayName, KeyId, StartdateTime, EndDateTime
|
||||
|
||||
}
|
||||
}
|
||||
Function RevokeCertificate
|
||||
{
|
||||
Write-Progress -Activity "Revoking certificate"
|
||||
$NewKeys = @()
|
||||
$APPID = Read-Host "Enter an application ID(Client ID) you want to revoke the certificate for that app"
|
||||
$GetAppInfo = Get-MgApplication |?{$_.AppId -eq "$APPID"}
|
||||
if($GetAppInfo -ne $null)
|
||||
{
|
||||
ShowAppDetails
|
||||
$KeyId=Read-Host "`nEnter the certificate key ID to revoke that certificate"
|
||||
if($GetAppInfo.KeyCredentials.KeyId -notcontains($KeyId))
|
||||
{
|
||||
Write-Host "Certificate not found" -ForegroundColor Red
|
||||
CloseConnection
|
||||
}
|
||||
foreach($List in $CertificateList)
|
||||
{
|
||||
if($List.KeyId -eq "$KeyId")
|
||||
{
|
||||
continue
|
||||
}
|
||||
$NewKeys+=$List
|
||||
}
|
||||
Update-MgApplication -ApplicationId $GetAppInfo.Id -KeyCredentials $NewKeys
|
||||
Write-Host "`nCertificate revoked successfully" -ForegroundColor Green
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "The application does not exist." -ForegroundColor Red
|
||||
CloseConnection
|
||||
}
|
||||
}
|
||||
Function ConnectApplication
|
||||
{
|
||||
Write-Progress -Activity "Connecting MS Graph"
|
||||
try
|
||||
{
|
||||
if($ParameterPassed -eq "False")
|
||||
{
|
||||
$TenantID = Read-Host "`nPlease provide the tenant ID of the application"
|
||||
$ClientID = Read-Host "Please provide the client ID of the application"
|
||||
While($true){
|
||||
$CertificatePath = Read-Host "Please provide certificate path(.cer or .pfx)"
|
||||
$TestPath = Test-Path -Path $CertificatePath -PathType Leaf
|
||||
if($TestPath -eq $false)
|
||||
{
|
||||
Write-Host "The certificate file could not be found." -ForegroundColor Red
|
||||
Continue
|
||||
}
|
||||
}
|
||||
$CheckExtension = (Get-ChildItem "$CertificatePath").Extension
|
||||
if($CheckExtension -eq ".pfx")
|
||||
{
|
||||
$Password = Read-Host "Please enter password to import certificate"
|
||||
$MyPwd = ConvertTo-SecureString -String "$Password" -Force -AsPlainText
|
||||
$LoadCertificate = Import-PfxCertificate -FilePath $CertificatePath -CertStoreLocation "Cert:\CurrentUser\My" -Password $MyPwd
|
||||
}
|
||||
else
|
||||
{
|
||||
$LoadCertificate = Import-Certificate -FilePath "$CertificatePath" -CertStoreLocation "Cert:\CurrentUser\My"
|
||||
}
|
||||
$CertificateThumbprint = $LoadCertificate.Thumbprint
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Host $_.Exception.Message -ForegroundColor Red
|
||||
Exit
|
||||
}
|
||||
Connect-MgGraph -TenantId $TenantID -ClientId $ClientID -CertificateThumbprint $CertificateThumbprint -ErrorAction SilentlyContinue -ErrorVariable ApplicationConnectionError
|
||||
if($ApplicationConnectionError -ne $null)
|
||||
{
|
||||
Write-Host $ApplicationConnectionError -ForegroundColor Red
|
||||
Exit
|
||||
}
|
||||
|
||||
Get-MgContext
|
||||
}
|
||||
function CloseConnection
|
||||
{
|
||||
Disconnect-MgGraph|Out-Null
|
||||
Exit
|
||||
}
|
||||
$ParameterPassed="False"
|
||||
if($TenantID -ne $null -and $ClientID -ne $null -and $CertificateThumbprint -ne $null)
|
||||
{
|
||||
$ParameterPassed="True"
|
||||
ConnectApplication
|
||||
Exit
|
||||
}
|
||||
Write-Host "`nWe can perform below operations." -ForegroundColor Cyan
|
||||
Write-Host " 1. Register an app with new certificate" -ForegroundColor Yellow -NoNewline
|
||||
Write-Host " (Creates application - >Adds new certificate -> Grants admin consent -> Exports certificate)" -ForegroundColor White
|
||||
Write-Host " 2. Register an app with existing certificate" -ForegroundColor Yellow -NoNewline
|
||||
Write-Host " (Creates application -> Adds existing certificate -> Grants admin consent)" -ForegroundColor White
|
||||
Write-Host " 3. Add certificate to an existing application" -ForegroundColor Yellow
|
||||
Write-Host " 4. Connect MgGraph" -ForegroundColor Yellow
|
||||
Write-Host " 5. Revoke certificate" -ForegroundColor Yellow
|
||||
$Action=Read-Host "`nPlease choose the action to continue"
|
||||
switch($Action){
|
||||
1 {
|
||||
Write-Host "`nConnecting to MS Graph to create a application..."
|
||||
ConnectMgGraphModule
|
||||
RegisterApplication
|
||||
CertificateCreation
|
||||
UploadCertificate
|
||||
SecureCertificate
|
||||
GrantPermission
|
||||
ShowAppDetails
|
||||
if($ExportError -ne "True")
|
||||
{
|
||||
Write-Host "`nYour Pfx certificate is available in $CertificateLocation" -ForegroundColor Green
|
||||
}
|
||||
break
|
||||
|
||||
}
|
||||
2 {
|
||||
Write-Host "`nConnecting to MS Graph to create a application.."
|
||||
ConnectMgGraphModule
|
||||
RegisterApplication
|
||||
ImportCertificate
|
||||
UploadCertificate
|
||||
GrantPermission
|
||||
ShowAppDetails
|
||||
break
|
||||
}
|
||||
3 {
|
||||
ConnectMgGraphModule
|
||||
$APPID = Read-Host "Enter the application id(Client id) of the app:"
|
||||
$AppInfo = Get-MgApplication |?{$_.AppId -eq "$APPID"}
|
||||
if($AppInfo -eq $null)
|
||||
{
|
||||
Write-Host "Application not found." -ForegroundColor Red
|
||||
CloseConnection
|
||||
}
|
||||
$AppName = $AppInfo.DisplayName
|
||||
$APPObjectID =$AppInfo.Id
|
||||
$confirm= Read-Host Are you sure you want to create new certificate? [Y] Yes [N] No. Select '"No"' to import existing certificate.
|
||||
if($confirm -match "[yY]")
|
||||
{
|
||||
CertificateCreation
|
||||
}
|
||||
else
|
||||
{
|
||||
ImportCertificate
|
||||
}
|
||||
UpdateCertficateDetails
|
||||
ShowAppDetails
|
||||
break
|
||||
}
|
||||
4 {
|
||||
ConnectApplication
|
||||
Exit
|
||||
}
|
||||
5 {
|
||||
ConnectMgGraphModule
|
||||
RevokeCertificate
|
||||
break
|
||||
}
|
||||
Default {
|
||||
Write-Host "No Action Found" -ForegroundColor Red
|
||||
Exit
|
||||
}
|
||||
}
|
||||
CloseConnection
|
||||
Loading…
x
Reference in New Issue
Block a user