Set-AzureSubscription : Cannot bind parameter 'Certificate' - powershell

While changing CurrentStorageAccountName in azure account using PowerShell I am getting following error:
Set-AzureSubscription : Cannot bind parameter 'Certificate'. Cannot convert value
"0EA9BE03CD1C2E5B93DB176F89C2CC2EF147B96C" to type "System.Security.Cryptography.X509Certificates.X509Certificate2".
Error: "The system cannot find the file specified.
Code is :
Set-AzureSubscription -SubscriptionName Enterprise -Certificate 0EA9BE03CD1C2E5B93DB176F89C2CC2EF147B96C -CurrentStorageAccountName btestps -SubscriptionId XXXXXXXXXXXXXXXXXXXXXXXXXXX

I recently needed to do this, you need to actually get or build an X509Certificate2 object that you then pass through to the -certificate parameter.
To set the certificate with a certificate from the local user certificate store by thumbprint you can:
# open the local user certificate store as read-only
$store = new-object System.Security.Cryptography.X509Certificates.X509Store([System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser)
$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadOnly)
# get all the certificates in the store
$certs = $store.Certificates;
# restrict the selection to only currently valid certificates
$currentcerts = $certs.Find([System.Security.Cryptography.X509Certificates.X509FindType]::FindByTimeValid, [System.DateTime]::Now, 0)
# get the first certificate by thumbprint, you could also find by distinguished name, subject name, etc
$signingCert = $currentcerts.Find([System.Security.Cryptography.X509Certificates.X509FindType]::FindByThumbprint,"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",0)[0]
# set the certificate
set-azuresubscription -certificate $signingCert
# open the local user certificate store as read-only
$store = new-object System.Security.Cryptography.X509Certificates.X509Store([System.Security.Cryptography.X509Certificates.StoreLocation]::CurrentUser)

A some what simpler solution is to use this:
$Certificate = Get-Item cert:\\LocalMachine\My\$CertificateThumbprint
Set-AzureSubscription -SubscriptionName Enterprise -Certificate $Certificate
Assuming that the certificate is in LocalMachine\My.

Related

New-AzWebAppSSLBinding - The specified network password is not correct

I trying to Assign Already created SSL Lets Encrypt certificate to azure app service.
DNS zone in app service already configured to (1.test.webapp1)
$Site = Get-AzWebApp -ResourceGroupName "MyRG" -Name "webapp1"
New-AzWebAppSSLBinding `
-Name "1.test.webapp1" `
-WebApp $Site `
-SslState SniEnabled `
-CertificateFilePath "C:\Users\someuser\Downloads\*.test.webapp1.pfx" `
-CertificatePassword 'password'
Error below:
I don't understand how I can put the password correctly
UPD
Certificate generation output
Subject : CN=*.test.webapp1
NotBefore :
NotAfter :
KeyLength : 2048
Thumbprint :
AllSANs : {*.test.webapp1}
CertFile : C:website\cert.cer
KeyFile : C:website\cert.key
ChainFile : C:website\chain.cer
FullChainFile : C:website\fullchain.cer
PfxFile : C:website\cert.pfx
PfxFullChain : C:website\fullchain.pfx
PfxPass : System.Security.SecureString
One of the workaround you can follow to resolve the above issue;
The password and the file path put them into a variable and provide your FQDN(Custom domain) for which you want SSL binding then you can use the moderated script as below.
NOTE:- We can't able to test it due to some restriction in our subscription.
Make sure that your custom domain is verified as per the requirement and you must have the sufficient permissions to do this operation as suggested here in MS Q&A by #SnehaAgrawal-MSFT .
$fqdn="<Replace with your custom domain name>"
$pfxPath="<Replace with path to your .PFX file>"
$pfxPassword="<Replace with your .PFX password>"
New-AzWebAppSSLBinding -WebAppName $webappname -ResourceGroupName $webappname -Name $fqdn `
-CertificateFilePath $pfxPath -CertificatePassword $pfxPassword -SslState SniEnabled
For more information please refer the below links:-
MICROSOFT DOCUMENT|Bind a custom TLS/SSL certificate to a web app using PowerShell .
Blog|To create .pfx certificate with password and config.

Missing cluster cert causes Add-AzServiceFabricClusterCertificate to fail: Object reference not set to an instance of an object

I'm fairly new to Service Fabric, so I'm not sure if this is an issue with the cmdlet or if this is a miss on my part. I am using Az.ServiceFabric module version 2.0.2 and the Az module version 3.8.0.
I am trying to use the Add-AzServiceFabricClusterCertificate cmdlet to add a secondary certificate that I've already created in my Azure KeyVault to my cluster. When I run the cmdlet, it fails with this error (running with Debug gave me more stack detail):
DEBUG: AzureQoSEvent: CommandName - Add-AzServiceFabricClusterCertificate; IsSuccess - False; Duration -
00:00:07.3059582;; Exception - System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Azure.Commands.ServiceFabric.Commands.ServiceFabricClusterCmdlet.GetClusterType(Cluster
clusterResource)
at Microsoft.Azure.Commands.ServiceFabric.Commands.AddAzureRmServiceFabricClusterCertificate.ExecuteCmdlet()
at Microsoft.WindowsAzure.Commands.Utilities.Common.AzurePSCmdlet.ProcessRecord();
Looking at the code for this cmdlet, I noticed that it's probably failing because the cluster resource that gets passed into GetClusterType does not have its Certificate member, so it fails when it tries to check the Certificate.Thumbprint and Certificate.ThumbprintSecondary:
internal ClusterType GetClusterType(Cluster clusterResource)
{
if (string.IsNullOrWhiteSpace(clusterResource.Certificate.Thumbprint) &&
string.IsNullOrWhiteSpace(clusterResource.Certificate.ThumbprintSecondary))
{
return ClusterType.Unsecure;
}
else
{
return ClusterType.Secure;
}
}
The cluster that gets passed into GetClusterType is retrieved in the same manner as in the Get-AzServiceFabricCluster cmdlet, so when I run that cmdlet for the cluster that I'm trying to add the certificate to, I noticed that my Certificate field is empty in the response. I'm guessing that's what's causing the NullRef exception. Here's that relevant snippet:
AzureActiveDirectory :
TenantId : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
ClusterApplication : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
ClientApplication : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Certificate :
CertificateCommonNames : Microsoft.Azure.Management.ServiceFabric.Models.ServerCertificateCommonNames
ClientCertificateCommonNames :
ClientCertificateThumbprints :
I'm wondering if it's expected that the Certificate field would be empty when I'm using the Get-AzServiceFabricCluster cmdlet and if that is indeed the cause of my Add-AzServiceFabricClusterCertificate cmdlet failing. When I look at the cluster's Security blade in Azure Portal, I do see the Primary Cluster Certificate with which I originally created the cluster, and this is the cert that I use when deploying and doing other cluster operations. However, I did notice that the cert thumbprint field is empty when viewing the certificate from the portal. I would expect to see this certificate when using Get-AzServiceFabricCluster, but it comes up empty. Is this certificate missing from my Get-AzServiceFabricCluster cmdlet possible to fix through the portal or with another cmdlet?
It looks like your cluster is configured to find certificates by common name, rather than thumbprint. I'm guessing this based on the fact your portal doesn't show a thumbprint against the certificate, in addition to the snippet you have posted.
If this is the case, there's no need to update your cluster configuration with a new certificate when the old certificate has expired - Instead you need to install the certificate only into your VMSS vault. Once you add the new certificate to the VMSS, Service Fabric will automatically use the later expiring certificate.
You must always ensure you have at least one valid certificate installed on your VMSS with the common name configured in your cluster.
PS to upload certificate KV and install onto VMSS:
$subscriptionId = "sub-id"
$vmssResourceGroupName = "vmss-rg-name"
$vmssName = "vmss-name"
$vaultName = "kv-name"
$primaryCertName = "kv-cert-name"
$certFilePath = "...\.pfx"
$certPassword = ConvertTo-SecureString -String "password" -AsPlainText -Force
# Sign in to your Azure account and select your subscription
Login-AzAccount -SubscriptionId $subscriptionId
# Update primary certificate within the Key Vault
$primary = Import-AzKeyVaultCertificate `
-VaultName $vaultName `
-Name $primaryCertName `
-FilePath $certFilePath `
-Password $certPassword
$certConfig = New-AzVmssVaultCertificateConfig -CertificateUrl $primary.SecretId -CertificateStore "My"
# Get VM scale set
$vmss = Get-AzVmss -ResourceGroupName $vmssResourceGroupName -VMScaleSetName $vmssName
# Add new certificate version
$vmss.VirtualMachineProfile.OsProfile.Secrets[0].VaultCertificates.Add($certConfig)
# Update the VM scale set
Update-AzVmss -ResourceGroupName $vmssResourceGroupName -Verbose `
-Name $vmssName -VirtualMachineScaleSet $vmss
For more info, I wrote a blog post on switching from thumbprint to common name.
The official docs are also a good reference.

How do I authenticate Azure Powershell on Azure VM

I'm wanting to execute a Powershell script from an Azure VM to get its current public IP address (and to write this address to an evironment variable for an application to use).
My question is what the best way to authenticate the Azure Powershell environment is? On AWS credentials get 'baked' into an instance when it gets created. Does the equivalent happen with Azure Virtual Machines?
You can use a Management Certificate contained in your Publish Settings file and 'bake' it yourself
Import-AzurePublishSettingsFile –PublishSettingsFile C:\Store\my.publishsettings
If you already have a certificate for management, you can store it in your vm and use it in PS
# Get management certificate from personal store
$certificate = Get-Item cert:\\CurrentUser\My\$CertificateThumbprint
if ($certificate -eq $null) {
throw “Management certificate for $SubscriptionName was not found in the users personal certificate store. Check thumbprint or install certificate”
}
# Set subscription profile
Set-AzureSubscription -SubscriptionName $SubscriptionName -SubscriptionId $SubscriptionId -Certificate $certificate
# Select subscription as the current context
Select-AzureSubscription -SubscriptionName $SubscriptionName

Set-AzureSubscription : Cannot bind parameter 'Certificate' becuase of illegal characters error

I am running this command on Windows 2012 server R2 with Azure Powershell
I am using following code for setting azure subscription
C:\PS>$subID = <Subscription ID>
C:\PS>$thumbprint = <Certificate Thumbprint>
Getting certificate thumbprint contain using
C:\PS>$myCert = Get-Item cert:\\CurrentUser\My\$thumbprint | Out-String
C:\PS>Set-AzureSubscription –SubscriptionName $subID –SubscriptionId $subID –Certificate `"$myCert`"
But it is failing with following error
Set-AzureSubscription : Cannot bind parameter 'Certificate'. Error: can't convert illegal characters
I have also tried with following code
C:\PS>$myCert = Get-Item cert:\\CurrentUser\My\$thumbprint
C:\PS>Set-AzureSubscription –SubscriptionName $subID –SubscriptionId $subID –Certificate $myCert
Still it is failing with error Cannot bind parameter 'Certificate'
Thanks in advance
You should stop using certificates for Azure PowerShell auth and start using AAD. This works for both the Azure Service Management and Azure Resource Manager modes of PowerShell.
Add-AzureAccount
Select-AzureSubscription ...
Set-AzureSubscription ...
and you're done - never having to worry about certificates again.
You should use:
Get-Item Cert:\CurrentUser\
(i.e. not cert:\\CurrentUser\ with two back slashes)

Automatically sign powershell script using Get-PfxCertificate

I have to sign remote scripts with a certificate from the remote machine from which I have a .pfx file.
I would like to automate the scripting by supplying the password to the Get-PfxCertificate programmatically.
So the question is:
Is it possible to somehow supply programmatically the required password to
Get-PfxCertificate?
$CertPath = "my.pfx"
$CertPass = "mypw"
$Cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2($CertPath, $CertPass)
Set-AuthenticodeSignature -Certificate $Cert -TimeStampServer http://timestamp.verisign.com/scripts/timstamp.dll -FilePath $OutputFilename
Make sure you have the proper permissions otherwise you won't be able to create an instance of the X509Certificate2 object.
I did a bit of checking around on this and couldn't find a clean way to provide the password programmatically. I suspect it is meant to be this way for security reasons. Either that or the PowerShell development team just blew it by not including a Credential parameter for this cmdlet. The only other option I can think of is to use someting like SendKeys to send the individual password character key presses to the PowerShell console at the right time via a background job (blech - just threw up in my mouth a little). :-)
Another way of doing this is by loading your certificate directly from your certificate store using PS Providers. Use Get-PSProviders to determine available PSProviders on your machine.
Once you have cert provider loaded, you can now get the certificate using Get-ChildItem
Launch certmgr.msc from run to launch the certificate store
Assuming that your certificate is stored under Personal folder in your cert store and has "Company Name" set in the subject property of the certificate, and there is only certificate in that folder with Company Name in the subject - you can get the certificate like so
$my_cert = Get-ChildItem cert:\CurrentUser\My | ? {$_.Subject -match "Company Name"}
$my_cert will be your certificate object that you can pass directly to Set-AuthenticodeSignature cmdlet
Set-AuthenticodeSignature -Certificate $my_cert -FilePath fqn_to_dll.dll -Timestampserver "http://timestampurl"
post signing, you can retrieve the sign status by querying on the Status property for "Valid" or not like
$result = Set-AuthenticodeSignature -Certificate $my_cert -FilePath fqn_to_dll.dll -Timestampserver "http://timestampurl" | Select Status
if(-Not ($result -eq "Valid")){
Write-Output "Error Signing file: Status: $($result.Status)"
}