Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show-LastPassConsoleGridView + Get-VaultParams changes #23

Merged
merged 12 commits into from
Nov 22, 2020

Conversation

itfranck
Copy link
Collaborator

@itfranck itfranck commented Nov 21, 2020

A "candy" cmdlet that integrate Microsoft.PowerShell.ConsoleGuiTools.
You might know of this module ? If not, see this 😉

I think that will be probably one of my favorite way to go about consulting the vault from now on.
I didn't want to add the module as a required dependency so instead, an error is thrown if it is used without the module installed.
A warning is also thrown if you are using 5.1 or anything below 6.2 for that matter.

All that would be missing is a cute Gif with it in action (using a test vault).
You can create a one line PS script and use it whenever with the KeepOpen parameter and / or use it interactively to select a secret and return it unformatted with PassThru.

I think this tie up everything nicely as you now have a one-liner interface at your fingertips.

Edit: Oh yeah, I changed Get-VaultParams for Get-SelectedVault which does essentially the same thing but return the vault info instead of the parameter since I wanted the error management from that cmdlet into the new cmdlet but I also needed to get back the name of the vault and not its parameters.

@TylerLeonhardt
Copy link
Owner

Love this idea :) should we maybe allow folks to use Out-GridView as a fall back if they don't have ocgv?

@itfranck
Copy link
Collaborator Author

@TylerLeonhardt Done. I love that.

$UseConsoleGridView = $true
}
catch {
Write-Debug "Microsoft.Powershell.ConsoleGuiTools could not be loaded.`n$($_ | Out-String)"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inside of this catch, you still need to check if Out-GridView is available because on macOS & Linux that cmdlet doesn't exist. Perhaps even saying Can't find a grid view cmdlet. Try installing the 'Microsoft.PowerShell.ConsoleGuiTools' module and try again.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SecretManagement.LastPass.psm1 Outdated Show resolved Hide resolved
[CmdletBinding(DefaultParameterSetName='Default')]
Param(
[String]$Vault,
[String]$Filter = '*',
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You add star to the end of $Filter down below so I don't think you need to set this default for this parameter since:

"$filter" -eq ""

when $Filter is undefined

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Parameter(ParameterSetName = 'KeepOpen')]
[Switch]$KeepOpen,
[Parameter(ParameterSetName = 'PassThru')]
[Switch]$PassThru
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need this PassThru? I think it should be the default behavior to emit the result of the choice to the pipeline.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I can do that.
My beef was / is with the multiline notes value.
#24

I can't figure out (yet) how to apply a view formatter for a Idictionary
(This is the only topic where I find there's a lack of examples to do advanced stuff with)

Ideally, I'd have a view formatter in place to auto-expand that property.
I can remove PassThru and instead replace it with a parameter to do the opposite.

Copy link
Collaborator Author

@itfranck itfranck Nov 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TylerLeonhardt What do you think if I do the exact opposite of that commit.
Meaning -Passthru become -Formatted.
By default (without switch), secret is returned as is, perfect for variable assignement.

Formatted will include the extra treatment, which essentially make sure that the Notes field is expanded and readable from the output.

 # By default, return the secret as is, everything will be fine
            if (!$Formatted) {return $Secret}

            # Intended for view, not for assignement. Add secret title and expand multiline notes in the console.
                Write-host $_.Name -ForegroundColor Cyan
                # Expand multiline notes (Ideally replaced by a format view at some point)
                if ($null -ne $Secret.Notes -and $Secret.Notes.IndexOf("`n") -ne -1) {
                    $Notes = $Secret.Notes
                    $Secret.Remove('Notes')
                    $Secret
                    "Notes:`n$Notes"
                }
                else {
                    $Secret
                }

Essentially, this provide the kind of readability that using a view formatter on a collection would do (#24) except that I am not sure how to do a view formatter on a collection.

I would be able to manage on a PSObject but since we have case-sensitivity, I need to stick to ordered dictionaries.

If I could have a type or view formatter that expand the Notes field, then all that Formatted bit would be superfluous.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tl;dr : I'd remove the PassThru, create a Formatted switch so that it reverse the default output.
Default output would be raw secret.
Formatted output would ensure Notes field is expanded so you can read it from the screen.
All of that because I can't come with a way (yet) to solve #24

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would be able to manage on a PSObject but since we have case-sensitivity, I need to stick to ordered dictionaries.

You can cast an OrderedDictionary to a PSObject. [PSObject]$dict or [pscustomobject]$dict. Technically all objects in PowerShell are secretly a PSObject.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm ... Good point.
I'll check if I can do what I want from that.

If I can have a LastPassSecret type inheriting from ordered dictionary and set a view to it so it return the Notes expanded by default without the need of "Format output altering" command, then it would be golden.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something they did in PowerShell for GitHub is have their Format.ps1xmls as normal and then tack on the type name like so:

$item.PSObject.TypeNames.Insert(0, $TypeName)

https://github.com/microsoft/PowerShellForGitHub/blob/9600fc21120e17241e60606c5de3459d973026bb/GitHubGists.ps1#L1750

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah Thanks.
I was playing around this concept just now.

Your "Everything is a PSObject" quote put me on track.
I knew that but it was buried somewhere.

$test  = [System.Collections.Specialized.OrderedDictionary]::new([System.StringComparer]::CurrentCulture)
$test.Add('ss','aa')
$test.Add('aaa','aa')
$test.Add('aaA', 'aa')
$test.PSObject.TypeNames.Insert(0,'LastPassSecret')

I am trying to flesh out some kind of ps1xml that would work and playing around with EzOut helper.

Write-FormatView -TypeName 'LastPassSecret' -Property 'Name','Value' -Width 1,1 | Out-FormatData | Add-FormatData; $test
<Configuration>
  <ViewDefinitions>
    <View>
      <Name>LastPassSecret</Name>
      <ViewSelectedBy>
        <TypeName>LastPassSecret</TypeName>
      </ViewSelectedBy>
      <TableControl>
        <TableHeaders>
          <TableColumnHeader>
            <Alignment>left</Alignment>
            <Width>1</Width>
          </TableColumnHeader>
          <TableColumnHeader>
            <Alignment>left</Alignment>
            <Width>1</Width>
          </TableColumnHeader>
        </TableHeaders>
        <TableRowEntries>
          <TableRowEntry>
            <TableColumnItems>
              <TableColumnItem>
                <PropertyName>Name</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>Value</PropertyName>
              </TableColumnItem>
            </TableColumnItems>
          </TableRowEntry>
        </TableRowEntries>
      </TableControl>
    </View>
  </ViewDefinitions>
</Configuration>

It's not working yet though.
My thought is that if I can mess up the width of the column, I'll have succeeded in getting the proper tree syntax and I'll then dig around the Scriptblock property to get this working.

Maybe I'm owed a visit to the format.xsd schema to see if I can gain more insight in the proper manner to write something that would affect the collection.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was unsuccessful with the view formatter.
This is a concept I'm slowly wrapping my head around but I find there's a lack of content compared to anything else on the matter so that's something I'll look into implementing at a latter time, if I can figure out the proper way to write the formatter.

f695769

if ($null -eq $Result) { break }
$Result | ForEach-Object {
$Secret = Microsoft.Powershell.SecretManagement\Get-Secret -Vault $Vault -Name $_.Name -AsPlainText
if ($PassThru) {return $Secret}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you need this if it gets emitted below?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if still relevant with the last commit.
f695769

The Formatted switch is there to provide a readable expanded output.
Default output is now what the "Passthru" initially did.

}

if ($null -eq $Result) { break }
$Result | ForEach-Object {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$result should be only one item since you specified -OutputMode Single above

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@itfranck
Copy link
Collaborator Author

@TylerLeonhardt I think I addressed the remaining points.
I also added a formatted output if we get a pscredential result (It will happens with the default outputType, which I had not considered)

46ed910

@itfranck
Copy link
Collaborator Author

One last thing, I changed the name from Show-LastPassConsoleGridView to Show-LastPassGridView

  • We won't necessarily use the ConsoleGridView (fallback)
  • ConsoleGridView is still a GridView
  • Show-LastPassGridView is shorter.

Copy link
Owner

@TylerLeonhardt TylerLeonhardt left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Merge the 2 PRs in and I'll get going on a release tonight/tomorrow

@itfranck itfranck merged commit c1981e5 into main Nov 22, 2020
@itfranck itfranck deleted the Feature/Show-LastPassGridView branch November 22, 2020 01:39
@TylerLeonhardt
Copy link
Owner

Released! https://twitter.com/TylerLeonhardt/status/1330335754791239685?s=20

@TylerLeonhardt
Copy link
Owner

btw, you may notice that I added a devcontainer to this repo so you can either use the Remote-Container extension for vscode locally, or use GitHub Codespaces. Both will make sure all the right deps are installed. I was able to start the container, login with lpass (which was already installed) and run the tests and it all worked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants