Employee Andreano Lanusse Posted June 28 Employee Share Posted June 28 Check the following article on how to use PKCS12 certificate for secure authentication with UEM API https://techzone.omnissa.com/resource/configuring-workspace-one-uem-api-pkcs12-certificates 3 Quote Link to comment Share on other sites More sharing options...
Employee Glyn Dobson Posted July 25 Employee Share Posted July 25 Here is an example on how to do this in PowerShell. The example uses the search API to find the device with ID 154335 but is really just to illustrate an API being used. The certificate was exported to the personal cert store and has the subject as shown below, which would need to be updated with the approprate subject of the certificate to use. The API server name and API Tenant code would also need to be specified. Add-Type -AssemblyName System.Security function Get-CMSURLAuthorizationHeader { [CmdletBinding()] [OutputType([string])] Param ( [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)] [uri]$URL, [Parameter(Mandatory=$true, ValueFromPipeline)] [System.Security.Cryptography.X509Certificates.X509Certificate2] $Certificate ) Process { TRY { $bytes = [System.Text.Encoding]::UTF8.GetBytes(($Url.AbsolutePath)) $MemStream = New-Object -TypeName System.Security.Cryptography.Pkcs.ContentInfo -ArgumentList (,$bytes) -ErrorAction Stop $SignedCMS = New-Object -TypeName System.Security.Cryptography.Pkcs.SignedCms -ArgumentList $MemStream,$true -ErrorAction Stop $CMSigner = New-Object -TypeName System.Security.Cryptography.Pkcs.CmsSigner -ArgumentList $Certificate -Property @{IncludeOption = [System.Security.Cryptography.X509Certificates.X509IncludeOption]::EndCertOnly} -ErrorAction Stop $null = $CMSigner.SignedAttributes.Add((New-Object -TypeName System.Security.Cryptography.Pkcs.Pkcs9SigningTime)) $SignedCMS.ComputeSignature($CMSigner) $CMSHeader = '{0}{1}{2}' -f 'CMSURL','`1 ',$([System.Convert]::ToBase64String(($SignedCMS.Encode()))) Write-Output -InputObject $CMSHeader } Catch { Write-Error -Exception $_.exception -ErrorAction stop } } } $Certificate = Get-ChildItem -Path Cert:\CurrentUser\my | Where-Object Subject -eq 'CN=8091:APICBA' $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" $headers.Add("Authorization", "$(Get-CMSURLAuthorizationHeader -URL $Url -Certificate $Certificate)") $headers.Add("aw-tenant-code", "****** REST API TENANT CODE GOES HERE ******") $headers.Add("Content-Type", "application/json") $URI = 'https://{api server}.awmdm.com/api/mdm/devices?searchBy=DeviceId&id=154335' try { $response = Invoke-WebRequest -Method Get -Uri $URI -Headers $Headers -ErrorAction Stop $response.content | ConvertFrom-Json } catch { Write-Output $_.Exception.Message } 1 Quote Link to comment Share on other sites More sharing options...
Otto Posted August 9 Share Posted August 9 On 7/25/2024 at 11:56 PM, Glyn Dobson said: Here is an example on how to do this in PowerShell. The example uses the search API to find the device with ID 154335 but is really just to illustrate an API being used. The certificate was exported to the personal cert store and has the subject as shown below, which would need to be updated with the approprate subject of the certificate to use. The API server name and API Tenant code would also need to be specified. Add-Type -AssemblyName System.Security function Get-CMSURLAuthorizationHeader { [CmdletBinding()] [OutputType([string])] Param ( [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)] [uri]$URL, [Parameter(Mandatory=$true, ValueFromPipeline)] [System.Security.Cryptography.X509Certificates.X509Certificate2] $Certificate ) Process { TRY { $bytes = [System.Text.Encoding]::UTF8.GetBytes(($Url.AbsolutePath)) $MemStream = New-Object -TypeName System.Security.Cryptography.Pkcs.ContentInfo -ArgumentList (,$bytes) -ErrorAction Stop $SignedCMS = New-Object -TypeName System.Security.Cryptography.Pkcs.SignedCms -ArgumentList $MemStream,$true -ErrorAction Stop $CMSigner = New-Object -TypeName System.Security.Cryptography.Pkcs.CmsSigner -ArgumentList $Certificate -Property @{IncludeOption = [System.Security.Cryptography.X509Certificates.X509IncludeOption]::EndCertOnly} -ErrorAction Stop $null = $CMSigner.SignedAttributes.Add((New-Object -TypeName System.Security.Cryptography.Pkcs.Pkcs9SigningTime)) $SignedCMS.ComputeSignature($CMSigner) $CMSHeader = '{0}{1}{2}' -f 'CMSURL','`1 ',$([System.Convert]::ToBase64String(($SignedCMS.Encode()))) Write-Output -InputObject $CMSHeader } Catch { Write-Error -Exception $_.exception -ErrorAction stop } } } $Certificate = Get-ChildItem -Path Cert:\CurrentUser\my | Where-Object Subject -eq 'CN=8091:APICBA' $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" $headers.Add("Authorization", "$(Get-CMSURLAuthorizationHeader -URL $Url -Certificate $Certificate)") $headers.Add("aw-tenant-code", "****** REST API TENANT CODE GOES HERE ******") $headers.Add("Content-Type", "application/json") $URI = 'https://{api server}.awmdm.com/api/mdm/devices?searchBy=DeviceId&id=154335' try { $response = Invoke-WebRequest -Method Get -Uri $URI -Headers $Headers -ErrorAction Stop $response.content | ConvertFrom-Json } catch { Write-Output $_.Exception.Message } Using this code, I get "Get-CMSURLAuthorizationHeader : Exception calling "ComputeSignature" with "1" argument(s): "Keyset does not exist". Please advise Quote Link to comment Share on other sites More sharing options...
Employee Glyn Dobson Posted August 9 Employee Share Posted August 9 40 minutes ago, Otto said: Using this code, I get "Get-CMSURLAuthorizationHeader : Exception calling "ComputeSignature" with "1" argument(s): "Keyset does not exist". Please advise Try running this and see if it gives anything extra. Update the URL with the full URL and also change the CN for the cert, left mine in as an example. [uri]$Url = 'https://as1784.awmdm.com/api/mdm/devices?searchBy=DeviceId&id=154335' $Certificate = Get-ChildItem -Path Cert:\CurrentUser\my | Where-Object Subject -eq 'CN=8091:APICBA' $bytes = [System.Text.Encoding]::UTF8.GetBytes(($Url.AbsolutePath)) $MemStream = New-Object -TypeName System.Security.Cryptography.Pkcs.ContentInfo -ArgumentList (,$bytes) -ErrorAction Stop $SignedCMS = New-Object -TypeName System.Security.Cryptography.Pkcs.SignedCms -ArgumentList $MemStream,$true -ErrorAction Stop $CMSigner = New-Object -TypeName System.Security.Cryptography.Pkcs.CmsSigner -ArgumentList $Certificate -Property @{IncludeOption = [System.Security.Cryptography.X509Certificates.X509IncludeOption]::EndCertOnly} -ErrorAction Stop $null = $CMSigner.SignedAttributes.Add((New-Object -TypeName System.Security.Cryptography.Pkcs.Pkcs9SigningTime)) $SignedCMS.ComputeSignature($CMSigner) $CMSHeader = '{0}{1}{2}' -f 'CMSURL','`1 ',$([System.Convert]::ToBase64String(($SignedCMS.Encode()))) Write-Output -InputObject $CMSHeader Quote Link to comment Share on other sites More sharing options...
Otto Posted August 9 Share Posted August 9 45 minutes ago, Glyn Dobson said: Try running this and see if it gives anything extra. Update the URL with the full URL and also change the CN for the cert, left mine in as an example. [uri]$Url = 'https://as1784.awmdm.com/api/mdm/devices?searchBy=DeviceId&id=154335' $Certificate = Get-ChildItem -Path Cert:\CurrentUser\my | Where-Object Subject -eq 'CN=8091:APICBA' $bytes = [System.Text.Encoding]::UTF8.GetBytes(($Url.AbsolutePath)) $MemStream = New-Object -TypeName System.Security.Cryptography.Pkcs.ContentInfo -ArgumentList (,$bytes) -ErrorAction Stop $SignedCMS = New-Object -TypeName System.Security.Cryptography.Pkcs.SignedCms -ArgumentList $MemStream,$true -ErrorAction Stop $CMSigner = New-Object -TypeName System.Security.Cryptography.Pkcs.CmsSigner -ArgumentList $Certificate -Property @{IncludeOption = [System.Security.Cryptography.X509Certificates.X509IncludeOption]::EndCertOnly} -ErrorAction Stop $null = $CMSigner.SignedAttributes.Add((New-Object -TypeName System.Security.Cryptography.Pkcs.Pkcs9SigningTime)) $SignedCMS.ComputeSignature($CMSigner) $CMSHeader = '{0}{1}{2}' -f 'CMSURL','`1 ',$([System.Convert]::ToBase64String(($SignedCMS.Encode()))) Write-Output -InputObject $CMSHeader Hi Glyn, thanks for the quick response. I am wondering if I have to add some extra Add-Type Here is my code and the response: $tenantAPIKey = 'dz52iegnlWe9Mgd1r4xnbYMW9gmzzkWVduUP5abNvqg=' $Certificate = Get-ChildItem -Path Cert:\LocalMachine\my | Where-Object Subject -eq 'CN=12063:RESTAPI4EUD' [uri]$Url = 'https://mdm.airfrance.fr/api/mdm/dep/profiles/search?PageSize=40000' Add-Type -AssemblyName System.Security $bytes = [System.Text.Encoding]::UTF8.GetBytes(($Url.AbsolutePath)) $MemStream = New-Object -TypeName System.Security.Cryptography.Pkcs.ContentInfo -ArgumentList (,$bytes) -ErrorAction Stop $SignedCMS = New-Object -TypeName System.Security.Cryptography.Pkcs.SignedCms -ArgumentList $MemStream,$true -ErrorAction Stop $CMSigner = New-Object -TypeName System.Security.Cryptography.Pkcs.CmsSigner -ArgumentList $Certificate -Property @{IncludeOption = [System.Security.Cryptography.X509Certificates.X509IncludeOption]::EndCertOnly} -ErrorAction Stop $null = $CMSigner.SignedAttributes.Add((New-Object -TypeName System.Security.Cryptography.Pkcs.Pkcs9SigningTime)) $SignedCMS.ComputeSignature($CMSigner) $CMSHeader = '{0}{1}{2}' -f 'CMSURL','`1 ',$([System.Convert]::ToBase64String(($SignedCMS.Encode()))) Write-Output -InputObject $CMSHeader Response 1: CMSURL`1 Response 2: Exception calling "ComputeSignature" with "1" argument(s): "Keyset does not exist " At C:\MDM\Omnissa.ps1:11 char:1 + $SignedCMS.ComputeSignature($CMSigner) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : CryptographicException Exception calling "Encode" with "0" argument(s): "The CMS message is not signed." At C:\MDM\Omnissa.ps1:12 char:46 + ... URL','`1 ',$([System.Convert]::ToBase64String(($SignedCMS.Encode()))) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], MethodInvocationException + FullyQualifiedErrorId : InvalidOperationException Thanks in advance Quote Link to comment Share on other sites More sharing options...
Employee Glyn Dobson Posted August 9 Employee Share Posted August 9 Not sure what going on there. The Add-Type was missing so added it to the code block below. When I run this, $CMSHeader is set correctly. This is pointing to my certificate, if it can't find the certificate it throws an "The recipient certificate is not specified" which would be expected. I couldn't paste and run your code in due to formatting issues but it looks the same as what I have. Only thing I can think is that there is some kind of certificate issue. Looks like the line its failing on is: $SignedCMS.ComputeSignature($CMSigner) After running my code below, $SignedCMS = and $CMSigner = Might be worth checking to see what these two values are set to prior to running ComputeSignature. Side note, I would also recommend editing your post above and removing your tenantAPIKey since you would want to keep this internal only. Add-Type -AssemblyName System.Security [uri]$Url = 'https://mdm.airfrance.fr/api/mdm/dep/profiles/search?PageSize=40000' $Certificate = Get-ChildItem -Path Cert:\CurrentUser\my | Where-Object Subject -eq 'CN=8091:APICBA' $bytes = [System.Text.Encoding]::UTF8.GetBytes(($Url.AbsolutePath)) $MemStream = New-Object -TypeName System.Security.Cryptography.Pkcs.ContentInfo -ArgumentList (,$bytes) -ErrorAction Stop $SignedCMS = New-Object -TypeName System.Security.Cryptography.Pkcs.SignedCms -ArgumentList $MemStream,$true -ErrorAction Stop $CMSigner = New-Object -TypeName System.Security.Cryptography.Pkcs.CmsSigner -ArgumentList $Certificate -Property @{IncludeOption = [System.Security.Cryptography.X509Certificates.X509IncludeOption]::EndCertOnly} -ErrorAction Stop $null = $CMSigner.SignedAttributes.Add((New-Object -TypeName System.Security.Cryptography.Pkcs.Pkcs9SigningTime)) $SignedCMS.ComputeSignature($CMSigner) $CMSHeader = '{0}{1}{2}' -f 'CMSURL','`1 ',$([System.Convert]::ToBase64String(($SignedCMS.Encode()))) Write-Output -InputObject $CMSHeader Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.