views:

332

answers:

3

Say I've got two cmdlets, 'new-foo' and 'do-bar'. Both cmdlets need to authenticate to a service in order to perform their action, and 'do-bar' takes a foo. Today, I can do:

new-foo -host localhost -username user -password password -whateverOtherArgs

And I can do:

do-bar -host localhost -username user -password password -foo myFoo

And I can even chain them passing foo on the pipeline, e.g.:

new-foo <blah blah> | do-bar -host localhost -username user -password password

But I can't figure out how to pass the common parameters, such as the service location and the credentials between elements of the pipeline. If I've got a bunch of my cmdlets chained together I'd like to only pass the credentials the first time, and then re-use those for the rest of the pipeline.

What am I missing, seems like this should be obvious ...

A: 

does Get-Credential cover you need.

rerun
I'm pretty sure I can use that to "bundle up" some of the auth parameters, but I'd still need to say -credential $cred to every command in the pipeline ...
Niniki
A: 

You could have New-Foo spit out an object that contains both the original object that do-bar is interested in as well as the service location and the credentials as properties. Accept this object as a parameter and then pluck out the data you need if the user doesn't supply the ServiceLocation or Credential parameters.

Keith Hill
This is what I do. Alternatively, if do-bar is a helper function being called directly by new-foo, you can use Powershell 2.0's new splat operator -- either on a psobject you project out yourself, or on @args directly.
Richard Berg
Ugh, but what if I'm not in control of the object types per-se? I've been trying to figure out if add-member(?) can work if called from inside my cmdlet, or if I can add a property to an object dynamically ala python or ruby, but I'm a .NET newb. Maybe with .net4 and the dynamic type?
Niniki
A: 

What about using environment variables?
You might modify your cmdlets to use the parameters specified on the command line if any, otherwise check for the environment variable, otherwise use current user's credentials. Something like:

$Env:MyCmdLetUserName = "user"
$Env:MyCmdLetPassword = "12345"
$Env:MyCmdLetHost = "localhost"
new-foo <blah blah> | do-bar
Remove-Item Env:\MyCmdLetUserName 
Remove-Item Env:\MyCmdLetPassword 
Remove-Item Env:\MyCmdLetHost

Then in your CmdLets code you could do something like

if (!string.IsNullOrEmpty(Host)) { // Host is the CmdLet property
    // use property
} else if (null != Environment.GetEnvironmentVariable("MyCmdLetHost")) {
    // use env var
} else {
    // use default
}

Please note, however, that you cannot store complex data type in environment variables, but only strings.

Paolo Tedesco
I don't think putting password into an environment variable is a good practice. It's not secure.
dpurrington
@dpurrington: and why is it not secure?
Paolo Tedesco
because it remains (in plain text) for subsequent processes to discover
dpurrington
@dpurrington: what about the Remove-Item immediately afterwards?
Paolo Tedesco
I stand corrected
dpurrington