1

I've written a PowerShell module that we use in our Azure Pipeline that will bind an SSL Certificate to a custom hostname. I am able to get the module working locally, including the inline script that I use in the pipeline to initialize the module. When I run the script locally, I do not get any errors. When I use the same script in the pipeline I receive the following error:

2019-07-16T23:00:40.3007294Z ##[error]Parameter set cannot be resolved using the specified named parameters.

I'm not using parameter sets, so I'm not sure why it is complaining. What is the reason I am able to execute my code locally and not in the release pipeline? Is the parameter set error really a complaint about something else?

Again, I've tested this locally. All of my parameters are required, so I'm not specifying a ParameterSet, though, I did set one up just in case, and I got the same error.

This is the script I use in the release pipeline using an Azure Powershell Task after I successfully import my module. I know my variable declarations are correct because I have tested them and they output fine (both locally and in the pipeline):

The error happens when the task hits this line in the script: Enable-SslStateOnWebapp -WebappName $webappName -customWebappHostname $webAppCustomHostname -existingKeyvaultName $existingVaultName -existingKeyvaultCertName $certName

$myVars = '$(armDeploymentOutput)' | ConvertFrom-Json
Write-Host "The following variables are available: $($myVars)" -Verbose
$existingVaultName = $myVars.existingKeyVaultName.value
$webappName=$myVars.webappName.value
$webAppCustomHostname=$myVars.webAppCustomHostname.value
$certName=$myVars.existingKeyVaultCertificateName.value

if ($webappName -and $webAppCustomHostname -and $existingVaultName -and $certName) {
    Write-Host "Attempting to enable SSL Binding for $($webappName) on the hostname $($webAppCustomHostname) using cert $($certName) from the existing keyvault of $($existingVaultName)." -Verbose
    Enable-SslStateOnWebapp -WebappName $webappName -customWebappHostname $webAppCustomHostname -existingKeyvaultName $existingVaultName -existingKeyvaultCertName $certName
}
else {
    Write-Host "Insufficient parameters have been provided to complete SSL Binding. To enable SSL binding, please provide a custom hostname, an existing keyvault where your certificate is stored, and the name of your certificate. Please visit the readme for more information." -Verbose
}

This is the PowerShell module that is initialized:

function Enable-SslStateOnWebapp {
    param (
        [Parameter(
            Mandatory = $true,
            HelpMessage = 'A webapp name is required.')]
        [ValidateNotNullOrEmpty()]
        [string] $WebappName,

        [PARAMETER(
            Mandatory = $true,            
            HelpMessage = 'The FQDN of the custom hostname you want to bind.')]
        [ValidateNotNullOrEmpty()]
        [string] $customWebappHostname,

        [Parameter(
            Mandatory = $true,
            HelpMessage = 'A name for an existing Keyvault is required.')]
        [ValidateNotNullOrEmpty()]
        [string] $existingKeyvaultName,

        [PARAMETER(
            Mandatory = $true,            
            HelpMessage = 'A name of the pfx certificate stored in the pre-existing keyvault')]
        [ValidateNotNullOrEmpty()]
        [string] $existingKeyVaultCertName
    )
    #getting webapp resources
    $webapp = Get-AzureRmResource -Name $webappName
    #obtaining resource group resources through the use of resource group name tied to webapp
    $rg = Get-AzureRmResource -ResourceGroupName $webapp.ResourceGroupName 

...

}

My expected result is that the build pipeline would execute the script without errors. Instead, I get passing results locally (which makes this obviously difficult to debug, and then in the pipeline I get the following debug logging:

2019-07-16T23:00:39.1496157Z ##[debug]Caught exception from task script.
2019-07-16T23:00:39.1536232Z ##[debug]Error record:
2019-07-16T23:00:39.1993172Z ##[debug]Enable-SslStateOnWebapp : Parameter set cannot be resolved using the specified named parameters.
2019-07-16T23:00:40.2927954Z ##[debug]At D:\agent3\_work\_temp\7be280f0-5905-4e05-99e0-972c90739a12.ps1:13 char:5
2019-07-16T23:00:40.2930113Z ##[debug]+     Enable-SslStateOnWebapp -WebappName $webappName -customWebappHost ...
2019-07-16T23:00:40.2940404Z ##[debug]+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2019-07-16T23:00:40.2940886Z ##[debug]    + CategoryInfo          : InvalidArgument: (:) [Enable-SslStateOnWebapp],     ParameterBindingException
2019-07-16T23:00:40.2941287Z ##[debug]    + FullyQualifiedErrorId : AmbiguousParameterSet,Enable-SslStateOnWebapp
2019-07-16T23:00:40.2941647Z ##[debug] 
2019-07-16T23:00:40.2941968Z ##[debug]Script stack trace:
2019-07-16T23:00:40.2942368Z ##[debug]at Enable-SslStateOnWebapp, D:\agent3\_work\r6\a\_infra-grs-referenceapp\drop\pwsh-modules\grs-arm\enable-ssl_state_on_webapp\enable-ssl_state_on_webapp.ps1: line 64

I checked if there are hidden unix characters, since I'm developing locally on a Mac, there are none:

Unix-hidden character check

  • my guess is that either [1] you have an invalid character in "something, somewhere" that is causing parameter binding to fail ... OR [2] one of your parameters is not getting the mandatory input - perhaps a blank parameter value? – Lee_Dailey Jul 16 '19 at 23:46
  • I'd probably second this, one of the inputs is blank – 4c74356b41 Jul 17 '19 at 02:13
  • You can refer to this [blog](http://get-cmd.com/?p=4516) – Mengdi Liang Jul 17 '19 at 03:38
  • @Lee_Dailey, are you thinking like an invisible char? I'm developing locally on a Mac. – thecherrytree Jul 17 '19 at 12:23
  • @4c74356b4, all of the inputs are being logged out in a statement before that function is called, so I don't think it is a blank parameter, I'm leaning to the hidden char issue. – thecherrytree Jul 17 '19 at 12:25
  • @MerlinLiang-MSFT, I'm not seeing how this helps. The SPN for the release pipeline is the assumed identity for that PowerShell script. I'm using an AzurePowerShell@3 task with the AzurePowerShellVersion as Latest. I've never seen any script block require -computer name being provided when executing a script block in one of these tasks. Can you be more specific? – thecherrytree Jul 17 '19 at 12:43
  • @thecherrytree - yes, that is one type of invalid character. another is `me dash` instead of a normal dash, or typographic quotes instead of normal straight quotes. ///// however, it looks like your actual problem turned out to be the parameters you used - thank you for posting the "why"! [*grin*] – Lee_Dailey Jul 17 '19 at 22:48
  • @Lee_Dailey thanks for the quick reply. I've seen your responses elsewhere and appreciated your response. Got some juices flowing for sure... – thecherrytree Jul 18 '19 at 03:24

1 Answers1

0

TLDR; This issue is caused by an incompatibility of the versions being used between your local development environment and the version being used by the AzureDevops build agent. Check the build agent versions and ensure they are the same as the version you developed in.

I was inspired by the answer in this post.

The error is thrown from line 64 in the script (which is the first executable line of the script):

2019-07-16T23:00:39.1496157Z ##[debug]Caught exception from task script.
2019-07-16T23:00:39.1536232Z ##[debug]Error record:
2019-07-16T23:00:39.1993172Z ##[debug]Enable-SslStateOnWebapp : Parameter set cannot be resolved using the specified named parameters.
2019-07-16T23:00:40.2927954Z ##[debug]At D:\agent3\_work\_temp\7be280f0-5905-4e05-99e0-972c90739a12.ps1:13 char:5
2019-07-16T23:00:40.2930113Z ##[debug]+     Enable-SslStateOnWebapp -WebappName $webappName -customWebappHost ...
2019-07-16T23:00:40.2940404Z ##[debug]+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2019-07-16T23:00:40.2940886Z ##[debug]    + CategoryInfo          : InvalidArgument: (:) [Enable-SslStateOnWebapp],     ParameterBindingException
2019-07-16T23:00:40.2941287Z ##[debug]    + FullyQualifiedErrorId : AmbiguousParameterSet,Enable-SslStateOnWebapp
2019-07-16T23:00:40.2941647Z ##[debug] 
2019-07-16T23:00:40.2941968Z ##[debug]Script stack trace:
2019-07-16T23:00:40.2942368Z ##[debug]at Enable-SslStateOnWebapp, D:\agent3\_work\r6\a\_infra-grs-referenceapp\drop\pwsh-modules\grs-arm\enable-ssl_state_on_webapp\enable-ssl_state_on_webapp.ps1: line 64

Given that it is the first executable line of the script, I assumed that the error was the result of the parameter binding on the function working incorrectly, especially because line 63 was not being written to the host.

Write-Host "Attempting to get webapp resource..." -Verbose

I have found that this is in fact not the case. I've observed that at times a Write-Host may not be called if the subsequent line fails.

Developing locally, I am using v6.13.1 of AzureRM. If I look at the function I am calling on line 64, this function is:

$webapp = Get-AzureRmResource -Name $webappName

Looking at the documentation (v6.13.1) for this cmdlet:

Get-AzureRmResource
   [[-Name] <String>]
   [-ResourceType <String>]
   [-ODataQuery <String>]
   [-ResourceGroupName <String>]
   [-TagName <String>]
   [-TagValue <String>]
   [-ExpandProperties]
   [-ApiVersion <String>]
   [-Pre]
   [-DefaultProfile <IAzureContextContainer>]
   [<CommonParameters>]

and documentation for the version on my build agent (~v4.6):

Get-AzureRmResource
   [-ResourceName <String>]
   [-ResourceType <String>]
   [-ExtensionResourceName <String>]
   [-ExtensionResourceType <String>]
   [-ExpandProperties]
   [-IsCollection]
   [-Top <Int32>]
   [-ODataQuery <String>]
   [-TenantLevel]
   [-ApiVersion <String>]
   [-Pre]
   [-DefaultProfile <IAzureContextContainer>]
   [<CommonParameters>]

we can see that the -Name and -ResourceName parameters are different. This causes the AmbiguousParameterSet error.

RESOLUTION: Our particular build agent is local and isn't updated as regularly as the Microsoft hosted agents.

I forced an update to our build agent's AzureRM version using a standard powershell task:

- task: PowerShell@2
 inputs:
 targetType: 'inline'
 script: 'Install-PackageProvider -Name NuGet -Force -Scope CurrentUser;
 Install-Module -Name AzureRM -RequiredVersion 6.13.1 -Force -Scope CurrentUser -AllowClobber;'

And then called Get-Module in the subsequent task with my script and specified the version 6.13.1 in the task's preferredAzurePowerShellVersion section (if the version you want is not available on the agent, this will result in an error of version not available, hence why you run the previous PowerShell task.:

- task: AzurePowerShell@3
 inputs:
 azureSubscription: '<subscription>'
 ScriptType: 'InlineScript'
 Inline: 'Get-Module AzureRm;
 Import-Module $(System.DefaultWorkingDirectory)\drop\pwsh-modules\grs-arm;
 $myVars = '$(armDeploymentOutput)' | ConvertFrom-Json
 Write-Host "The following variables are available: $($myVars)" -Verbose

 $existingVaultName = $myVars.existingKeyVaultName.value
 $webappName=$myVars.webappName.value
 $webAppCustomHostname=$myVars.webAppCustomHostname.value
 $certName=$myVars.existingKeyVaultCertificateName.value

 Write-Host "Setting an access policy for the SPN to $($existingVaultName)" -Verbose
 Set-AzureRmKeyVaultAccessPolicy -VaultName $existingVaultName -ServicePrincipalName <spnClientId> -PermissionsToCertificates get -PermissionsToSecrets get

 if ($webappName -and $webAppCustomHostname -and $existingVaultName -and $certName) 
 {Write-Host "Attempting to enable SSL Binding for $($webappName) on the hostname 
 $($webAppCustomHostname) using cert $($certName) from the existing keyvault of 
 $($existingVaultName)." -Verbose
 Enable-SslStateOnWebapp -WebappName $webappName -customWebappHostname 
 $webAppCustomHostname -existingKeyvaultName $existingVaultName - 
 existingKeyvaultCertName $certName -Verbose}
 else {Write-Host "Insufficient parameters have been provided to complete SSL 
 Binding. To enable SSL binding, please provide a custom hostname, an existing 
 keyvault where your certificate is stored, and the name of your certificate. 
 Please visit the readme for more information." -Verbose}

 Write-Host "Removing SPN access to $($existingVaultName)" -Verbose
 Remove-AzureRmKeyVaultAccessPolicy -VaultName $existingVaultName - 
 ServicePrincipalName <spnClientId>
 preferredAzurePowerShellVersion: '6.13.1'

This resolved my issue completely.