Functions/Public/Add-MsGApplicationCertificate.ps1
|
function Add-MsGApplicationCertificate { <# .SYNOPSIS Adds a specified certificate to an app registration in Entra ID. .DESCRIPTION This function adds a specified certificate to an app registration in Entra ID, allowing it to be used for authentication. .PARAMETER DisplayName Display Name of the app registration. .PARAMETER AppId App/Client Id of the app registration. .PARAMETER ObjectId Object Id of the app registration. .PARAMETER Path Path of the public key certificate. .PARAMETER StoreLocation Certificate Store location of a stored certificate. .PARAMETER Thumbprint Thumbprint of the certificate in the stored location. .PARAMETER Headers Authentication Headers to connect to Microsoft Graph. .PARAMETER Jwt Jwt to connect to Microsoft Graph. .EXAMPLE PS> Add-MsGApplicationCertificate -DisplayName TestApp-01 -Path C:\temp\TestApp-01.cer Adds the specified certificate as an authentication certificate to the app registration. #> [CmdletBinding(SupportsShouldProcess)] param( [parameter(Mandatory = $true, ParameterSetName = 'Name-Path', Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [parameter(Mandatory = $true, ParameterSetName = 'Name-Thumbprint', Position = 0, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [string]$DisplayName, [parameter(Mandatory = $true, ParameterSetName = 'AppId-Path', Position = 1)] [parameter(Mandatory = $true, ParameterSetName = 'AppId-Thumbprint', Position = 1)] [string]$AppId, [parameter(Mandatory = $true, ParameterSetName = 'ObjId-Path', Position = 2)] [parameter(Mandatory = $true, ParameterSetName = 'ObjId-Thumbprint', Position = 2)] [string]$ObjectId, [parameter(Mandatory = $true, ParameterSetName = 'Name-Path', Position = 3)] [parameter(Mandatory = $true, ParameterSetName = 'AppId-Path', Position = 3)] [parameter(Mandatory = $true, ParameterSetName = 'ObjId-Path', Position = 3)] [string]$Path, [parameter(Mandatory = $false, ParameterSetName = 'Name-Path', Position = 4)] [parameter(Mandatory = $false, ParameterSetName = 'AppId-Path', Position = 4)] [parameter(Mandatory = $false, ParameterSetName = 'ObjId-Path', Position = 4)] [ValidateSet('CurrentUser', 'LocalMachine')] [string]$StoreLocation = 'CurrentUser', [parameter(Mandatory = $true, ParameterSetName = 'Name-Thumbprint', Position = 5)] [parameter(Mandatory = $true, ParameterSetName = 'AppId-Thumbprint', Position = 5)] [parameter(Mandatory = $true, ParameterSetName = 'ObjId-Thumbprint', Position = 5)] [string]$Thumbprint, [parameter(Mandatory = $false)][hashtable]$Headers, [parameter(Mandatory = $false)][string]$Jwt ) BEGIN { # Session Checks if ([string]::IsNullOrEmpty($Headers) -and [string]::IsNullOrEmpty($Jwt)) { if ($null -ne $myGraphToken) { Write-Verbose "Setting Jwt to Global: $myGraphToken" $Jwt = $myGraphToken } } if ([string]::IsNullOrEmpty($Headers) -and -not([string]::IsNullOrEmpty($Jwt))) { $Headers = @{ 'Authorization' = 'Bearer {0}' -f $Jwt 'Content-Type' = 'application/json' } } if ([string]::IsNullOrEmpty($Headers)) { $errorMessage = '{0} : Unable to run command. Headers are empty.' -f $MyInvocation.MyCommand.Name throw $errorMessage } # end Session Checks } PROCESS { # Retrieve Application from Entra ID try { switch -Wildcard ($PSCmdlet.ParameterSetName) { "Name-*" { $appEndpoint = "applications?`$filter=displayName eq '{0}'&`$select=displayName,appId,id,keyCredentials" -f $DisplayName } "AppId-*" { $appEndpoint = "applications?`$filter=appId eq '{0}'&`$select=displayName,appId,id,keyCredentials" -f $AppId } "ObjId-*" { $appEndpoint = "applications/{0}?`$select=displayName,appId,id,keyCredentials" -f $ObjectId } } $application = Invoke-MsGRequest -Method Get -Endpoint $appEndpoint -Headers $Headers -ErrorAction 'Stop' if ([string]::IsNullOrEmpty($application)) { $errorMessage = 'Application not found.' throw $errorMessage } } catch { $errorMessage = Get-MsGErrorMessage $_ $errorException = '{0} : Unable to retrieve application from Entra ID. Error: {1}' -f $MyInvocation.MyCommand.Name, $errorMessage throw $errorException } # end region # Set Current Key Credentials $updatedKeyCredentials = New-Object -TypeName System.Collections.Generic.List[psobject] $application.keyCredentials | ForEach-Object { $updatedKeyCredentials.Add($_) } # end region # Format key credential to add. try { switch -Wildcard ($PSCmdlet.ParameterSetName) { "*-Path" { $certificateContent = Get-Content -Path $Path -AsByteStream -ErrorAction 'Stop' } "*-Thumbprint" { $certificateItemPath = 'Cert:\{0}\My\{1}' -f $StoreLocation, $Thumbprint $certificateContent = Get-Item -Path $certificateItemPath | Select-Object -ExpandProperty 'RawData' } } $certificatePublicKey = [convert]::ToBase64String($certificateContent) } catch { $errorMessage = Get-MsGErrorMessage $_ $errorException = '{0} : Unable to retrieve certificate public key from the given {1}. Error: {2}' -f $MyInvocation.MyCommand.Name, $PSCmdlet.ParameterSetName.Split('-')[-1], $errorMessage throw $errorException } $customKeyCredential = [pscustomobject]@{ 'type' = 'AsymmetricX509Cert' 'usage' = 'Verify' 'key' = $certificatePublicKey } $updatedKeyCredentials.Add($customKeyCredential) # end region # Update application if ($PSCmdlet.ShouldProcess($application.displayName, 'Add Application Certificate')) { try { $endpoint = 'applications/{0}' -f $application.id $body = @{ 'keyCredentials' = $updatedKeyCredentials } Invoke-MsGRequest -Method Patch -Endpoint $endpoint -Body $body -Headers $Headers -ErrorAction 'Stop' > $null } catch { $errorMessage = Get-MsGErrorMessage $_ $errorException = '{0} : Unable to upload certificate to the application in Entra ID. Error: {1}' -f $MyInvocation.MyCommand.Name, $errorMessage throw $errorException } } # end region } } |