Last active
February 6, 2024 08:32
-
-
Save Zerg00s/848e5a7bde46c20254dff377b6a5b6d2 to your computer and use it in GitHub Desktop.
Register Azure AD App and Upload a certificate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@ECHO OFF | |
PowerShell.exe -Command "& '%~dpn0.ps1' -path '%~dp0'" | |
REM PAUSE |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.SYNOPSIS | |
Creates a Self Signed Certificate for use in server to server authentication | |
.DESCRIPTION | |
.EXAMPLE | |
PS C:\> .\Create-SelfSignedCertificate.ps1 -CommonName "MyCert" -StartDate 2015-11-21 -EndDate 2017-11-21 | |
This will create a new self signed certificate with the common name "CN=MyCert". During creation you will be asked to provide a password to protect the private key. | |
.EXAMPLE | |
PS C:\> .\Create-SelfSignedCertificate.ps1 -CommonName "MyCert" -StartDate 2015-11-21 -EndDate 2017-11-21 -Password (ConvertTo-SecureString -String "MyPassword" -AsPlainText -Force) | |
This will create a new self signed certificate with the common name "CN=MyCert". The password as specified in the Password parameter will be used to protect the private key | |
.EXAMPLE | |
PS C:\> .\Create-SelfSignedCertificate.ps1 -CommonName "MyCert" -StartDate 2015-11-21 -EndDate 2017-11-21 -Force | |
This will create a new self signed certificate with the common name "CN=MyCert". During creation you will be asked to provide a password to protect the private key. If there is already a certificate with the common name you specified, it will be removed first. | |
#> | |
Param( | |
[Parameter(Mandatory=$true)] | |
[string]$CommonName, | |
[Parameter(Mandatory=$true)] | |
[DateTime]$StartDate, | |
[Parameter(Mandatory=$true)] | |
[DateTime]$EndDate, | |
[Parameter(Mandatory=$false, HelpMessage="Will overwrite existing certificates")] | |
[Switch]$Force, | |
[Parameter(Mandatory=$false)] | |
[SecureString]$Password | |
) | |
# DO NOT MODIFY BELOW | |
function CreateSelfSignedCertificate(){ | |
#Remove and existing certificates with the same common name from personal and root stores | |
#Need to be very wary of this as could break something | |
if($CommonName.ToLower().StartsWith("cn=")) | |
{ | |
# Remove CN from common name | |
$CommonName = $CommonName.Substring(3) | |
} | |
$certs = Get-ChildItem -Path Cert:\LocalMachine\my | Where-Object{$_.Subject -eq "CN=$CommonName"} | |
if($certs -ne $null -and $certs.Length -gt 0) | |
{ | |
if($Force) | |
{ | |
foreach($c in $certs) | |
{ | |
remove-item $c.PSPath | |
} | |
} else { | |
Write-Host -ForegroundColor Red "One or more certificates with the same common name (CN=$CommonName) are already located in the local certificate store. Use -Force to remove them"; | |
return $false | |
} | |
} | |
$name = new-object -com "X509Enrollment.CX500DistinguishedName.1" | |
$name.Encode("CN=$CommonName", 0) | |
$key = new-object -com "X509Enrollment.CX509PrivateKey.1" | |
$key.ProviderName = "Microsoft RSA SChannel Cryptographic Provider" | |
$key.KeySpec = 1 | |
$key.Length = 2048 | |
$key.SecurityDescriptor = "D:PAI(A;;0xd01f01ff;;;SY)(A;;0xd01f01ff;;;BA)(A;;0x80120089;;;NS)" | |
$key.MachineContext = 1 | |
$key.ExportPolicy = 1 # This is required to allow the private key to be exported | |
$key.Create() | |
$serverauthoid = new-object -com "X509Enrollment.CObjectId.1" | |
$serverauthoid.InitializeFromValue("1.3.6.1.5.5.7.3.1") # Server Authentication | |
$ekuoids = new-object -com "X509Enrollment.CObjectIds.1" | |
$ekuoids.add($serverauthoid) | |
$ekuext = new-object -com "X509Enrollment.CX509ExtensionEnhancedKeyUsage.1" | |
$ekuext.InitializeEncode($ekuoids) | |
$cert = new-object -com "X509Enrollment.CX509CertificateRequestCertificate.1" | |
$cert.InitializeFromPrivateKey(2, $key, "") | |
$cert.Subject = $name | |
$cert.Issuer = $cert.Subject | |
$cert.NotBefore = $StartDate | |
$cert.NotAfter = $EndDate | |
$cert.X509Extensions.Add($ekuext) | |
$cert.Encode() | |
$enrollment = new-object -com "X509Enrollment.CX509Enrollment.1" | |
$enrollment.InitializeFromRequest($cert) | |
$certdata = $enrollment.CreateRequest(0) | |
$enrollment.InstallResponse(2, $certdata, 0, "") | |
return $true | |
} | |
function ExportPFXFile() | |
{ | |
if($CommonName.ToLower().StartsWith("cn=")) | |
{ | |
# Remove CN from common name | |
$CommonName = $CommonName.Substring(3) | |
} | |
if($Password -eq $null) | |
{ | |
$Password = Read-Host -Prompt "Enter Password to protect private key" -AsSecureString | |
} | |
$cert = Get-ChildItem -Path Cert:\LocalMachine\my | where-object{$_.Subject -eq "CN=$CommonName"} | |
Export-PfxCertificate -Cert $cert -Password $Password -FilePath "$($CommonName).pfx" | |
Export-Certificate -Cert $cert -Type CERT -FilePath "$CommonName.cer" | |
} | |
function RemoveCertsFromStore() | |
{ | |
# Once the certificates have been been exported we can safely remove them from the store | |
if($CommonName.ToLower().StartsWith("cn=")) | |
{ | |
# Remove CN from common name | |
$CommonName = $CommonName.Substring(3) | |
} | |
$certs = Get-ChildItem -Path Cert:\LocalMachine\my | Where-Object{$_.Subject -eq "CN=$CommonName"} | |
foreach($c in $certs) | |
{ | |
remove-item $c.PSPath | |
} | |
} | |
if(CreateSelfSignedCertificate) | |
{ | |
ExportPFXFile | |
RemoveCertsFromStore | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ------------------------------------------------------------------------------- | |
# This script is meant to deploy self-signed certificate to Azure AD | |
# When running it, you will be asked to login to Office 365 then to Azure. | |
# This script generates X509 certificates and automatically applies them. | |
# Refer to comments below to see the entire list of things that the script is doing. | |
# | |
# ------------------------------------------------------------------------------- | |
$ErrorActionPreference = "Stop" | |
# ------------------------------------------------------------------------------- | |
# CHECK IF WE ARE RUNNING THE SCRIPT AS AN ADMIN: | |
# ------------------------------------------------------------------------------- | |
$IsRunningAsAdmin = [bool](([System.Security.Principal.WindowsIdentity]::GetCurrent()).groups -match "S-1-5-32-544") | |
if ($IsRunningAsAdmin -eq $false) { | |
Write-Host "[ERROR] MAKE SURE YOU RUN THIS SCRIPT AS AN ADMINISTRATOR" -ForegroundColor Red | |
Read-Host "Press Enter to exit" | |
return | |
} | |
# ------------------------------------------------------------------------------- | |
# Depending on how we run the script, we must find location of the script in different ways. | |
# We need to set execution location to the current folder before we can use relative paths. | |
# This gives as an ability to just double-click a .bat file without having to CD to a certain folder on disk. | |
# ------------------------------------------------------------------------------- | |
if ($psISE) { $scriptLocation = Split-Path -Path $psISE.CurrentFile.FullPath } | |
else { $scriptLocation = $PSScriptRoot } | |
Set-Location $scriptLocation | |
Write-Host $PSScriptRoot | |
try { | |
$appName = "DeploymentApp" | |
# ------------------------------------------------------------------------------- | |
# We name certificate the same name as the AAD Application | |
# ------------------------------------------------------------------------------- | |
$certificateName = $appName | |
# ------------------------------------------------------------------------------- | |
# Generate strong passwords for the certificate | |
# ------------------------------------------------------------------------------- | |
Add-Type -AssemblyName System.Web | |
# "&" is converted to "\u0026" when using ConvertTo-Json, so we strip this off. | |
$certificatePassword = [System.Web.Security.Membership]::GeneratePassword(12, 3) -replace "&","!" | |
$encryptedCertPassword = ConvertTo-SecureString -String $certificatePassword -AsPlainText -Force | |
# ------------------------------------------------------------------------------- | |
# Generate self-signed .cer and .pfx files | |
# ------------------------------------------------------------------------------- | |
.\Create-SelfSignedCertificate.ps1 ` | |
-CommonName $certificateName ` | |
-StartDate (Get-Date).AddDays(-1) ` | |
-EndDate "2299-01-01" ` | |
-Password $encryptedCertPassword | |
Write-Host "[Success] Generated a self-signed certificate: $certificateName" -ForegroundColor Green | |
# ------------------------------------------------------------------------------- | |
# Logging to Azure Cli using Office 365 Global Tenant Admin | |
# ------------------------------------------------------------------------------- | |
Write-Host "[Pending user action] Enter Global Office 365 Admin credentials..." -ForegroundColor Yellow | |
az login --allow-no-subscriptions | |
Write-Host "[Success] Connected Office 365's Azure tenant" -ForegroundColor Green | |
# ------------------------------------------------------------------------------- | |
# Select Azure Subscription Associated with Office 365 tenant | |
# ------------------------------------------------------------------------------- | |
$subscription = az account show | ConvertFrom-Json | |
$account = az account show | ConvertFrom-Json | |
# ------------------------------------------------------------------------------- | |
# Delete the app if it already exists | |
# ------------------------------------------------------------------------------- | |
$apps = az ad app list | ConvertFrom-Json | |
$app = $apps | Where-Object { $_.displayName -eq $appName } | |
if ($null -ne $app) { | |
az ad app delete --id $app.appId | |
Write-Host "[Success] Deleted existing AAD Application with the name $appName" -ForegroundColor Green | |
} | |
# ------------------------------------------------------------------------------- | |
# Find existing application by name | |
# ------------------------------------------------------------------------------- | |
$apps = az ad app list | ConvertFrom-Json | |
$app = $apps | Where-Object { $_.displayName -eq $appName } | |
# ------------------------------------------------------------------------------- | |
# Assign Permissions the app. Permissions are described in the json file. | |
# We are only asking for one permission: SharePoint Online: Read all site collections | |
# ------------------------------------------------------------------------------- | |
if ($null -eq $app) { | |
$app = az ad app create ` | |
--display-name $appName ` | |
--identifier-uris https://$appName.websites.net ` | |
--required-resource-accesses "requiredResourceManifest.json" ` | |
| ConvertFrom-Json | |
Write-Host "[Success] Registered a new AAD Application with the name $appName" -ForegroundColor Green | |
} | |
# ------------------------------------------------------------------------------- | |
# Grant permissions (Admin-consent) programmatically. This commandlet became first available April 04 2019 | |
# ------------------------------------------------------------------------------- | |
az ad app permission admin-consent --id $app.appId | |
Write-Host "[Success] $appName was granted permissions to access SharePoint Online Site collections for read-only" -ForegroundColor Green | |
# ------------------------------------------------------------------------------- | |
# Upload a .cer file to the AAD application | |
# ------------------------------------------------------------------------------- | |
$cerName = $certificateName + ".cer" | |
az ad app credential reset --id $app.appId --cert `@$cerName | |
Write-Host "[Success] Uploaded self-signed certificate to the $appName application" -ForegroundColor Green | |
$fileContentBytes = Get-Content "$certificateName.pfx" -Encoding Byte | |
$pfxBlob = [System.Convert]::ToBase64String($fileContentBytes) | |
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 | |
$cert.Import((Get-Location).Path + "\" + $cerName) | |
$thumbprint = $cert.Thumbprint | |
# ------------------------------------------------------------------------------- | |
# Preparing an object that will contain all useful information about our Azure AD App | |
# ------------------------------------------------------------------------------- | |
$o365AppDetails = @{ | |
thumbprint = $thumbprint | |
pfxBlob = $pfxBlob | |
appId = $app.appId | |
tenantId = $account.tenantId | |
certificatePassword = $certificatePassword | |
certificateName = $certificateName | |
appName = $appName | |
} | |
# ------------------------------------------------------------------------------- | |
# Save information about the O365 Application in a file | |
# ------------------------------------------------------------------------------- | |
$o365AppDetails | ConvertTo-Json | Out-File "o365AppDetails.json" | |
Write-Host "[Success] Saved o365AppDetails.json file about the '$appName' application on disk" -ForegroundColor Green | |
# ------------------------------------------------------------------------------- | |
# We no longer need to work with Azure associated with Office 365 | |
# ------------------------------------------------------------------------------- | |
az logout | |
Write-Host "[Success] Logged out from Office 365's Azure tenant" -ForegroundColor Green | |
} | |
catch { | |
$Error | |
Write-Host "An error occurred. If it was not caused by you cancelling the deployment process - please capture the logs displayed above and contact the deployment specialist." -ForegroundColor Cyan | |
Read-Host "Press Enter to exit" | |
return | |
} | |
Write-Host "[Success] Application has been deployed." -ForegroundColor Cyan | |
Read-Host "Press Enter to close this window and exit" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ | |
{ | |
"resourceAppId": "00000003-0000-0ff1-ce00-000000000000", | |
"resourceAccess": [ | |
{ | |
"id": "678536fe-1083-478a-9c59-b99265e6b0d3", | |
"type": "Role" | |
}, | |
{ | |
"id": "c8e3537c-ec53-43b9-bed3-b2bd3617ae97", | |
"type": "Role" | |
}, | |
{ | |
"id": "741f803b-c850-494e-b5df-cde7c675a1ca", | |
"type": "Role" | |
} | |
] | |
}, | |
{ | |
"resourceAppId": "00000002-0000-0000-c000-000000000000", | |
"resourceAccess": [ | |
{ | |
"id": "311a71cc-e848-46a1-bdf8-97ff7156d8e6", | |
"type": "Scope" | |
} | |
] | |
} | |
] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment