how to use Convert-PemToPfx in Azure automation account? - powershell

Im trying to generate pfx from the pem and key file stored in azure keyvualt from azure powershell automation account. I can generate a pfx with the same key and pem file using openssl but when I try the same in powershell I'm getting an error "Convert-PemToPfx : Exception setting "PrivateKey": "The public key of the certificate does not match the value
specified."".
$secretpem = Get-AzureKeyVaultSecret -VaultName '$vaultname' -Name 'secret-pem'
$secretkey = Get-AzureKeyVaultSecret -VaultName '$vaultname' -Name 'secret-key'
$pem = "certificate.pem"
$secretpem.SecretValueText | Out-File -FilePath $pem
$key = "certificate.key"
$secretkey.SecretValueText | Out-File -FilePath $key
$password = ConvertTo-SecureString "P#ssW0rD!" -asplaintext -for
#Get-Content -Path certificate.pem
#Get-Content -Path certificate.key
Import-Module -Name PSPKI
Convert-PemToPfx -InputPath certificate.pem -KeyPath certificate.key -OutputPath certificate.pfx -
Password $password

Related

Import-PFX as another user - Impersonation

I wanted to reach out and see if anyone has some tips on impersonation/runas cmds. I am working on a script that exports, then imports a .pfx certificate over to the users profile from the admin profile. Right now, I have everything working except for the import portion.
As seen below, I am showing only the import portion. $x and $y variables are defined earlier in the script by user input and that works okay.
Everything works up until the import-pfxcertificate cmdlet and scriptblock. Running that scriptblock as the other use is proving to be difficult. If anyone has any advice on how to structure that scriptblock cmd so that it will runas the user, that would be great!
I have an error log written into the script as well (not shown) Unfortunately, it is not picking up any errors because I believe it is pulling a local machine cert rather than the cert I specified - so no real error messages.
<#Cache credentials in IE and Import new or existing cert as client#>
function importcert
{
certpath = "C:\Temp\$x.pfx"
$password = $y | ConvertTo-SecureString -AsPlainText -Force
<#Enter your credentials#>
Credentials = Get-Credential -Credential corp\$x
<#Export to Secure XML#>
$Credentials | Export-Clixml -path 'C:\Temp\creds.xml'
<#Import credentials and run application using those credentials#>
Set-Location C:\
$creds = Import-Clixml -Path 'C:\Temp\creds.xml'
$ie = Start-Process -FilePath 'C:\Program Files (x86)\Internet Explorer\IEXPLORE.EXE' -Credential $creds
$ie
Start-Sleep -Seconds 30
<#Imports the certificate as the client#>
Start-Job -ScriptBlock { Import-PfxCertificate -FilePath $certpath -Exportable -CertStoreLocation Cert:\CurrentUser\My -Password $password } -Credential $creds
<#Search For Client Credential and if path is false, the credential file was removed successfully.#>
$clientXML = Test-Path -Path "C:\Temp\creds.xml"
Remove-Item -Path "C:\Temp\creds.xml"
if (-not ($clientXML))
{
Write-Output "Credential XML was removed"
}
}
importcert
It looks like all you're missing is some arguments for your Start-Job. I just tested this out locally and got it to install mycert.pfx for the other user TomServo:
<#Cache credentials in IE and Import new or existing cert as client#>
$Certpath = Get-Item "C:\Projects\Sandbox\mycert.pfx"
$Password = '{Password}' | ConvertTo-SecureString -AsPlainText -Force
<#Enter your credentials#>
$Credentials = Get-Credential -UserName TomServo
<#Export to Secure XML#>
$Credentials | Export-Clixml -path 'C:\Projects\Sandbox\creds.xml'
<#Import credentials and run application using those credentials#>
Set-Location C:\
$Creds = Import-Clixml -Path 'C:\Projects\Sandbox\creds.xml'
$Ie = Start-Process -FilePath 'C:\Program Files (x86)\Internet Explorer\IEXPLORE.EXE' -Credential $Creds
$Ie
Start-Sleep -Seconds 30
<#Imports the certificate as the client#>
Start-Job -ScriptBlock {
param($certpath, $Password)
Import-PfxCertificate -FilePath $Certpath -Exportable -CertStoreLocation Cert:\CurrentUser\My -Password $Password
} -Credential $Creds -ArgumentList $Certpath, $Password
<#Search For Client Credential and if path is false, the credential file was removed successfully.#>
$ClientXML = Test-Path -Path "C:\Projects\Sandbox\creds.xml"
Remove-Item -Path "C:\Projects\Sandbox\creds.xml"
if (-not ($ClientXML))
{
Write-Output "Credential XML was removed"
}

powershell code signing: Set-AuthenticodeSignature : Cannot bind parameter 'Certificate'. Cannot convert value

Trying to create a self-signed code signing certificate that I can use to sign powershell scripts... Looks like it works except when I try to use the certificate to sign a powershell scriptit gives me the Error "Set-AuthenticodeSignature : Cannot bind parameter 'Certificate'. Cannot convert value "
Here's the code that reproduces the problem:
# FILE: new_code_signing_cert.ps1
param(
[switch]$trace
)
try {
if ($trace) {
Set-PSDebug -Trace 1
}
$base = "wpmoore_code_signing";
$password = "password123";
$outdir = ".\cert"
$splat = #{
Subject = "CN=Script Automation,E=myemail#gmail.com,O=My Name"
FriendlyName = "$base"
NotAfter = (Get-Date).AddYears(3)
CertStoreLocation = "Cert:\CurrentUser\My"
Type = "CodeSigningCert"
}
write-host "Creating Code Signing Certificate...`n"
$cert = New-SelfSignedCertificate #splat
$cthumb = $cert.Thumbprint
$cpath = "Cert:\CurrentUser\My\$cthumb"
# Backup Certificate with password
$encrypted = ConvertTo-SecureString -String $password -Force -AsPlainText
new-Item -Path $outdir -Type Directory -ErrorAction SilentlyContinue | out-null
$pfx_file = "${outdir}\${base}.${cthumb}.pfx"
Export-PfxCertificate -Cert:$cpath -FilePath:$pfx_file -Password $encrypted | out-null
write-host "Certificate Location : $cpath"
write-host "Certificate Backup : $pfx_file"
# Dir of CertStoreLocation
#Get-ChildItem $cpath
Set-AuthenticodeSignature -Certificate $cpath -FilePath .\new_code_signing_cert.ps1
}
finally {
Set-PSDebug -Trace 0
write-host ""
}
Hwere's what happens when I run...
PS> new_code_signing_cert.ps1
Set-AuthenticodeSignature : Cannot bind parameter 'Certificate'. Cannot convert value
"Cert:\CurrentUser\My\C4C3179BAB17C20F33D3D0E23CF88CF500CDBD68" to type
"System.Security.Cryptography.X509Certificates.X509Certificate2". Error: "The given path's format is not
supported."
At line:1 char:40
+ ... Certificate Cert:\CurrentUser\My\C4C3179BAB17C20F33D3D0E23CF88CF500CD ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Set-AuthenticodeSignature], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.SetAuthenticodeSig
natureCommand
Re-Loading certificate using Cert path:
$cert2 = Get-ChildItem -Path $cpath -CodeSigningCert
Re-Loading certificate from pfx file:
$cert2 = Get-PfxCertificate -FilePath $pfx_file
Once you have the certificate loaded:
Set-AuthenticodeSignature -Certificate $cert2 -FilePath script.ps1
Or use the certificate already loaded:
Set-AuthenticodeSignature -Certificate $cert -FilePath script.ps1

Powershell AzureAD App Registration Permissions New-AzureADApplication -RequiredResourceAccess

I am having a problem with the following code. I am trying to assign the following permissions to an App Registration in AzureAD using the -RequiredResourceAccess property from New-AzureADApplication. I keep getting an invalid value for $reqGraph?
Please help?
New-AzureADApplication : Error occurred while executing NewApplication
Code: Request_BadRequest Message: Invalid value specified for property
'resourceAppId' of resource 'RequiredResourceAccess'. RequestId:
5abf5ea5-8f94-4d14-8e8d-8f12a92bf3e5 DateTimeStamp: Mon, 17 May 2021
07:12:02 GMT Details: PropertyName - resourceAppId, PropertyErrorCode
InvalidValue HttpStatusCode: BadRequest HttpStatusDescription: Bad Request HttpResponseStatus: Completed
$appName = "Test" # Maximum 32 characters
$adalUrlIdentifier = "https://abc.dk/AADGuestLifecycleMgmt"
$appReplyUrl = "https://www.abc.dk"
$pwd = Read-Host -Prompt 'Enter a secure password for your certificate!'
$certStore = "Cert:\CurrentUser\My"
$currentDate = Get-Date
$endDate = $currentDate.AddYears(10) # 10 years is nice and long
$thumb = (New-SelfSignedCertificate -DnsName "abc.dk" -CertStoreLocation $certStore -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotAfter $endDate).Thumbprint
$thumb > cert-thumb.txt # Save to file
$pwd = ConvertTo-SecureString -String $pwd -Force -AsPlainText
Export-PfxCertificate -cert "$certStore\$thumb" -FilePath .\AzureADGuestLifecycleMgmt.pfx -Password $pwd
$path = (Get-Item -Path ".\").FullName
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate("$path\AzureADGuestLifecycleMgmt.pfx", $pwd)
$keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData())
Install-Module AzureAD
Import-Module AzureAD
# Connect to Azure AD as an admin account
Connect-AzureAD
# Store tenantid
$tenant = Get-AzureADTenantDetail
$tenant.ObjectId > tenantid.txt
# Add AuditLog.Read.All access
$svcPrincipal = Get-AzureADServicePrincipal -All $true | ? { $_.DisplayName -match "Microsoft Graph" }
$appRole = $svcPrincipal.AppRoles | ? { $_.Value -eq "AuditLog.Read.All" }
$appPermission = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "$($appRole.Id)", "Role"
#Add Directory.ReadWrite.All access
$appRole2 = $svcPrincipal.AppRoles | ? { $_.Value -eq "Directory.ReadWrite.All" }
$appPermission2 = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "$($appRole2.Id)", "Role"
$reqGraph = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess"
$reqGraph.ResourceAppId = $svcPrincipal.AppId
$reqGraph.ResourceAccess = $appPermission, $appPermission2
Write-Host $reqGraph
# Create Azure Active Directory Application (ADAL App)
$application = New-AzureADApplication -DisplayName "$appName" -IdentifierUris $adalUrlIdentifier -ReplyUrls $appReplyUrl -RequiredResourceAccess $reqGraph
New-AzureADApplicationKeyCredential -ObjectId $application.ObjectId -CustomKeyIdentifier "$appName" -Type AsymmetricX509Cert -Usage Verify -Value $keyValue -StartDate $currentDate -EndDate $endDate.AddDays(-1)
It seems that there are more than one app registration whose name includes "Microsoft Graph" in your tenant. It causes you to get the wrong $svcPrincipal.AppId (in this case, it may be a combination of multiple app ids).
Please directly set $reqGraph.ResourceAppId = "00000003-0000-0000-c000-000000000000".
00000003-0000-0000-c000-000000000000 is the app id of the Microsoft Graph app, which is a fixed value.
Here is the correct code with $_.DisplayName -eq "Microsoft Graph"
appName = "Test" # Maximum 32 characters
$adalUrlIdentifier = "https://abc.dk/AADGuestLifecycleMgmt"
$appReplyUrl = "https://www.abc.dk"
$pwd = Read-Host -Prompt 'Enter a secure password for your certificate!'
$certStore = "Cert:\CurrentUser\My"
$currentDate = Get-Date
$endDate = $currentDate.AddYears(10) # 10 years is nice and long
$thumb = (New-SelfSignedCertificate -DnsName "abc.dk" -CertStoreLocation $certStore -KeyExportPolicy Exportable -Provider "Microsoft Enhanced RSA and AES Cryptographic Provider" -NotAfter $endDate).Thumbprint
$thumb > cert-thumb.txt # Save to file
$pwd = ConvertTo-SecureString -String $pwd -Force -AsPlainText
Export-PfxCertificate -cert "$certStore\$thumb" -FilePath .\AzureADGuestLifecycleMgmt.pfx -Password $pwd
$path = (Get-Item -Path ".\").FullName
$cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate("$path\AzureADGuestLifecycleMgmt.pfx", $pwd)
$keyValue = [System.Convert]::ToBase64String($cert.GetRawCertData())
Install-Module AzureAD
Import-Module AzureAD
# Connect to Azure AD as an admin account
Connect-AzureAD
# Store tenantid
$tenant = Get-AzureADTenantDetail
$tenant.ObjectId > tenantid.txt
# Add AuditLog.Read.All access
$svcPrincipal = Get-AzureADServicePrincipal -All $true | ? { $_.DisplayName -eq "Microsoft Graph" }
$appRole = $svcPrincipal.AppRoles | ? { $_.Value -eq "AuditLog.Read.All" }
$appPermission = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "$($appRole.Id)", "Role"
#Add Directory.ReadWrite.All access
$appRole2 = $svcPrincipal.AppRoles | ? { $_.Value -eq "Directory.ReadWrite.All" }
$appPermission2 = New-Object -TypeName "Microsoft.Open.AzureAD.Model.ResourceAccess" -ArgumentList "$($appRole2.Id)", "Role"
$reqGraph = New-Object -TypeName "Microsoft.Open.AzureAD.Model.RequiredResourceAccess"
$reqGraph.ResourceAppId = $svcPrincipal.AppId
$reqGraph.ResourceAccess = $appPermission, $appPermission2
Write-Host $reqGraph
# Create Azure Active Directory Application (ADAL App)
$application = New-AzureADApplication -DisplayName "$appName" -IdentifierUris $adalUrlIdentifier -ReplyUrls $appReplyUrl -RequiredResourceAccess $reqGraph
New-AzureADApplicationKeyCredential -ObjectId $application.ObjectId -CustomKeyIdentifier "$appName" -Type AsymmetricX509Cert -Usage Verify -Value $keyValue -StartDate $currentDate -EndDate $endDate.AddDays(-1)

I want to import the SSL Certificate when the existing thumbprint of the cert matched to the site

I wrote a PS script where in it will import the certificate to the existing site to the IIS server, but i want a script where in it will match the thumbprint of the Cert which i am having with the thumbprint of the cert in the local machine store, if the thumbprint matches then import that certificate to the store, if not dont import the cert.
Example I have a pfx file with thumbprint = XXXXXX and the script need to be check if there are any thumbprint as same as above in my machine or in any remote server then the Cert which i am having need to be replaced or imported to the location.
Code
Clear-Host
$certPath = 'C:\TEMP\Sample.pfx'
$CertificatePassword = 'XXXXXX'
$SiteName = "SampleTest"
$HostName = "Sitebinding.com"
$SiteFolder = Join-Path -Path 'C:\inetpub\wwwroot' -ChildPath $SiteName
Write-Host 'Import pfx certificate' $certPath
$certRootStore = “LocalMachine”
$certStore = "My"
$pfx = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
$pfx.Import($certPath,$CertificatePassword,"Exportable,PersistKeySet")
$store = New-Object System.Security.Cryptography.X509Certificates.X509Store($certStore,$certRootStore)
$store.Open('ReadWrite')
$store.Add($pfx)
$store.Close()
$certThumbprint = $pfx.Thumbprint
#Write-Host 'Add website' $SiteName
#New-WebSite -Name $SiteName -PhysicalPath $SiteFolder -Force
#$IISSite = "IIS:\Sites\$SiteName"
#Set-ItemProperty $IISSite -name Bindings -value #{protocol="https";bindingInformation="*:443:$HostName"}
#if($applicationPool) { Set-ItemProperty $IISSite -name ApplicationPool -value $applicationPool}
Write-Host 'Bind certificate with Thumbprint' $certThumbprint
#$obj = get-webconfiguration "//sites/site[#name='$SiteName']"
$obj = Get-WebBinding $SiteName -Port 443
#$binding = $obj.bindings.Collection[0]
#$method = $binding.Methods["AddSslCertificate"]
$method = $obj.Methods["AddSslCertificate"]
$methodInstance = $method.CreateInstance()
$methodInstance.Input.SetAttributeValue("certificateHash", $certThumbprint)
$methodInstance.Input.SetAttributeValue("certificateStoreName", $certStore)
$methodInstance.Execute()```
Thanks In Advance.
It seems like you could do an if statement that includes querying the Cert: PSDrive for the thumbprint. Then only update the binding based on the condition.
if (Get-ChildItem Cert:\LocalMachine -Recurse | Where Thumbprint -eq $certThumbprint) {
# Update Binding
}

Passing secure text between two servers with powershell

I'm working on a script that export certificate from Server A to PFX, copy it to Server B and import the PFX to the server.
I'm using the following code to encrypt the password from plain text to secure string:
$pfxPass = "PassW0rd"
$File = "D:\backup_conf\Password.txt"
[Byte[]] $key = (1..16)
$pfxSecure = $pfxPass | ConvertTo-SecureString -AsPlainText -Force
$pfxSecure | ConvertFrom-SecureString -key $key | Out-File $File
dir Cert:\LocalMachine\my | Where-Object { $_.NotAfter -clike "*2019*"} | % { certutil.exe -f -exportPFX -p $pfxSecure $_.Thumbprint D:\backup_conf\certificates\$($_.Thumbprint).pfx }
PFX created and I can see that Password.txt contains the hash string.
The PFX and the Password.txt were copied over to new server and I've used the following code for import:
$file = "D:\backup_conf\Password.txt"
[Byte[]] $key = (1..16)
$pfxSecure = Get-Content $File | ConvertTo-SecureString -Key $key
$certs = (Get-ChildItem -recurse -Path "D:\backup_conf\certificates" -Include *.pfx)|%{Import-PfxCertificate $_.FullName -Exportable -Password $pfxSecure -CertStoreLocation Cert:\LocalMachine\My }
This one fails with the error:
Import-PfxCertificate : The PFX file you are trying to import requires either a different password or membership in an Active
Directory principal to which it is protected.
Any idea why it's not working?
As you're using SecureString object here: certutil.exe -f -exportPFX -p $pfxSecure it's not properly recognized by certutil.exe. Password will be literally
System.Security.SecureString
For cmd applications SecureString is not something it can process so you'll have to convert it to plain text and then pass it to certutil.exe.
Example how you can convert SecureString to plain text (source):
$SecurePassword = ConvertTo-SecureString $pfxPass
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)