1

I'm trying to figure out which method would work best for the following situation.

Example function:

Set-APICredentials {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory)]
        [string]$APIUser,

        [Parameter(Mandatory)]
        [string]$APIKey,

        [Parameter(Mandatory)]
        [string]$PFXFile,

        [Parameter(Mandatory)]
        [string]$PFXPassword,

        [switch]$AsVariable
    )
    begin{
        $PFXPath = (Get-ChildItem -Name $PFXFile).FullName
    }
    process{
        #create basic auth header from APIUser and APIKey
        $basicAuthHeader

        #create certificate object, verify private key, convert back into PFX Collection as bytes string variable
        $clientAuthCertRaw

        #create hashtable with credentials
        $credentials = @{
            basicAuthHeader = $basicAuthHeader
            clienAuthCertRaw = $clientAuthCertRaw
        }

    }
    end{
        if ($AsVariable) {
            Sglobal:APICreds = $credentials
        } else {
            Export-Clixml -InputObject $credentials -Path $PSScriptRoot\APICredentials.xml
        }
    }
}

If (Test-Path -Path $PSScriptRoot\APICredentials.xml) is true and -AsVariable is specified then no other parameters are needed/used.

Otherwise if (Test-Path -Path $PSScriptRoot\APICredentials.xml) is false then everything previously stated as mandatory are required.

Is there some way to create a conditional parameter set?

Should I just create two parameter sets and error out if the previously stated logic is false? Or should I set -AsVariable as a parameter and handle the rest with dynamic parameters?

Because in most cases everything is mandatory and its only under special circumstances that -AsVariable is used on its own. I figured that configuring everything else as dynamic parameters would be wrong.

Bennett
  • 99
  • 9
  • Process block in example is mostly pseudo code and not the actual function. Goal of -AsVariable is to allow temporarily storing credentials to global variable scope for use with other functions in the module instead of storing to file. This also makes it easier to use with remote pssessions. – Bennett Feb 06 '19 at 05:23

1 Answers1

0

Dynamic Parameters are the strict way to handle exactly what you want to do, but I don't think they're worth the effort in most cases.

The most straightforward way to handle this is not to have the string params mandatory and just do the check at the beginning of the function.

You have a process block but the example params don't take pipeline input. If the function is taking pipeline input consider where you put that check; probably in the begin block but it will depend on the params maybe?

I was also toying around with abusing [ValidateScript({})] for this, but it's not quite going to work, because if you add it on the [switch], you can't access/check the other params to check their values, and if you put it on the conditionally mandatory values (to check for the existence of the file) it will only run the validation when the parameter is bound.

This also feels a little bit like a code smell? Curious about your use case.

briantist
  • 45,546
  • 6
  • 82
  • 127
  • I would normally use a begin block for the check, yes. In this case I just stopped writing my example. Not sure what you mean by code smell? Use case is the 4 parameters are actually APIUser, APIKey, PFXFile, PFXPassword. All these get loaded and saved with Clixml for use in a rest API wrapper module. Goal was to add -AsVariable to optionally save credentials for current ishell/passing to psremote sessions instead of always pulling and saving from file. I like PowerShell's built in prompting for things like missing parameters and wanted to figure out the correct use case for this scenario. – Bennett Feb 06 '19 at 04:49