CUT-5090: Secure credential reference in settings#744
Conversation
jworkmanjc
left a comment
There was a problem hiding this comment.
Okay this is very close to what we are looking for here. In general yes, this is close to the Acceptance Criteria in the card.
Connect-JCOnline -Select
If no key in Credential Manager or Keychain ends with "api.jc" then we prompt for a key, ask the customer to name it. That's mostly the functionality in the body of work. I love it, it's easy to use needs a bit of work to clean things up but in general works and is easy enough for someone to use.
Really this is solving a big issue for customers, they need to copy & paste their API key in every time the want to use the module. Now they can just select a saved one they have in encrypted storage. Great change.
One issue I saw that needs specific addressing. You can't copy data into the prompt when asked to "Type the api key:" I had to manually try to type my key and I mis-typed it the first time. I had to go edit it in credential manager but did get it to connect.
MacOS Keychain worked for me.
A few other things I think we'd need to do before marking this in the next state for review:
- Removing items from Keychain/CredManager needs to be behind a prompt. I accidentally removed my key in Keychain and certainly didn't mean to.
- We probably need to submit for security review this change, it will be an overall improvement on security posture I believe.
- We'll want to merge this into a release branch, not
masterbranch, we can merge when we get the go-ahead with security.
| Write-Host "Select the JumpCloud Api Key. Press [Escape] to type a new key. Press [Backspace] to remove the selected key" -ForegroundColor Green | ||
| while (@($false, $null) -contains ($vaultKey = Find-Interactive -choices $keys -Callback { | ||
| param($param) | ||
| Remove-FromVault -Key $param; |
There was a problem hiding this comment.
I did accidentally call this function and want to be super careful about how we think about implementing this. IMO there should be a confirmation before deleted any Key.
I wasn't super clear on usage first time so I created a key by accident titled "api.jc.api.jc". Somehow it got deleted when I ran Connect-JCOnline -select "api.jc.api.jc
| )] | ||
| [Switch]$force | ||
| [Switch]$force, | ||
| [Parameter( |
There was a problem hiding this comment.
Okay awesome to see this here, I kind of knew this was going to be a switch without looking at the code based on the PR. Totally fine, thinking about automation scenarios, it would be good for us to include a way to specify the stored key.
We can create a separate card for this but customers should be able to type:
Connect-JCOnline -Select -Credential "myKey.api.jc" and connect to that org
There was a problem hiding this comment.
Added -Credential param Connect-JCOnline -Credential "ok.api.jc".
It will jump the -select param for listing the keys.
| [Parameter(Mandatory=$true)] | ||
| [string]$Key, | ||
| [Parameter(Mandatory=$false)] | ||
| [string]$sufix, |
There was a problem hiding this comment.
Curious about the choice of suffix here over prefix. For my reference, keys are gathered and parsed to see if they end with some suffix.
I think that results in better looking keys as you are selecting them like:
- OrgName.api.jc
- AnotherOrgName.api.jc
- LastOrg.serviceTotken.jc (assuming we add support for service token credentialing later)
Reference Code:
https://github.com/TheJumpCloud/support/pull/744/changes#diff-2283fb1a2772f5d917313a140539f71ffb3860db63e32f4d1c0b4e1fec3549a1R11
https://github.com/TheJumpCloud/support/pull/744/changes#diff-2283fb1a2772f5d917313a140539f71ffb3860db63e32f4d1c0b4e1fec3549a1R20
|
In windows, I Get the compile error in [Unlock-Platform.ps1]. The C# helper is calling Marshal.Copy with a string. Seems like it needs to use UTF-16 bytes instead. |
|
And this absolutely works well with Connect-JCOnline -select |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 4 potential issues.
Reviewed by Cursor Bugbot for commit 8e44e56. Configure here.
|
|
||
| Write-Host "Select the JumpCloud Api Key. Press [Escape] to type a new key. Press [Backspace] to remove the selected key" -ForegroundColor Green | ||
| # Stays in selection loop until user selects a key or abort. | ||
| while (@($false, $null) -contains ($vaultKey = Find-Interactive -choices $keys -Callback { |
There was a problem hiding this comment.
Empty vault list hangs console
Medium Severity
After the initial “add key” path, KeySelector always opens Find-Interactive without verifying that $keys has entries. If vault enumeration still returns nothing, Find-Interactive enters a loop that waits for keypresses with no visible choices.
Additional Locations (1)
- [
PowerShell/JumpCloud Module/Private/Console/Find-Interactive.ps1#L11-L20](https://github.com/TheJumpCloud/support/blob/8e44e5626e9676a1e78f6358e65dc3e60eff814e/PowerShell/JumpCloud Module/Private/Console/Find-Interactive.ps1#L11-L20)
Reviewed by Cursor Bugbot for commit 8e44e56. Configure here.
| cred.lastWritten = 0; | ||
| cred.credentialBlobSize = byteCount; | ||
| cred.credentialBlob = blobPtr; | ||
| cred.persist = CRED_PERSIST_LOCAL_MACHINE; |
There was a problem hiding this comment.
Wrong credential persistence scope
Medium Severity
SetCreds sets cred.persist to CRED_PERSIST_LOCAL_MACHINE, making generic API keys computer-wide rather than user-scoped. That can cause CredWrite failures or store secrets where other local users can see the target entries.
Reviewed by Cursor Bugbot for commit 8e44e56. Configure here.
| // Calcula o endereço de cada item no array de ponteiros | ||
| IntPtr pCurrent = Marshal.ReadIntPtr(pCredentials, i * IntPtr.Size); | ||
| PCREDENTIAL cred = (PCREDENTIAL)Marshal.PtrToStructure(pCurrent, typeof(PCREDENTIAL)); | ||
| targets.Add(cred.targetName); |
There was a problem hiding this comment.
Lists non-generic credentials too
Low Severity
GetTargetList adds every enumerated credential target without checking cred.type against CRED_TYPE_GENERIC, despite the comment implying generic-only results. Unrelated Windows credentials whose target names happen to end with .api.jc can appear in the JumpCloud key picker.
Reviewed by Cursor Bugbot for commit 8e44e56. Configure here.
| try { | ||
| # Not necessary to use same approach as MacOs | ||
| # MacOs is safe to use security command as above | ||
| security add-generic-password -a $env:USER -s ($key_+$sufix) -w $value -T "" 2>$null |
There was a problem hiding this comment.
Suffix appended twice always
Medium Severity
Set-ToVault always concatenates $sufix onto the normalized name. If the user enters a name that already includes .api.jc, the stored target becomes a doubled suffix (for example api.jc.api.jc), which breaks later selection and deletion by vault name.
Additional Locations (1)
- [
PowerShell/JumpCloud Module/Private/Vault/Set-ToVault.ps1#L30-L31](https://github.com/TheJumpCloud/support/blob/8e44e5626e9676a1e78f6358e65dc3e60eff814e/PowerShell/JumpCloud Module/Private/Vault/Set-ToVault.ps1#L30-L31)
Reviewed by Cursor Bugbot for commit 8e44e56. Configure here.



Issues
CUT-5090
Avoid user to directly prompt key on console.
Hide key native console functions.
No external module.
What does this solve?
Gets from the credential manager when asked from module/prompt.
By default needs the
-selectparam or$null -eq $env:JCApikKeyWhen asked from prompt it should:
.api.jcby defaultIs there anything particularly tricky?
Unlock-Platform is used to compile C# code on Win platform.
How should this be tested?
Connect-JCOnline.ps1 -selectAlso can run the :
/PowerShell/JumpCloud Module/Tests/Public/Authentication/Connect-JCOnline.Tests.ps1Screenshots
Note
High Risk
Changes authentication key resolution and writes API secrets to OS credential stores with new Windows P/Invoke and altered Connect-JCOnline default behavior when JCApiKey is unset.
Overview
Connect-JCOnlinenow resolves API keys from the OS credential store instead of always prompting for a raw key. New-Selectand-Credentialparameters drive an interactive picker; when$env:JCApiKeyis empty and no-JumpCloudApiKeywas passed on the command line,KeySelectorruns duringdynamicparamand can populate$env:JCApiKeybefore the dynamicJumpCloudApiKeyparameter is built.Supporting private helpers add a small console UI (
Find-Interactive,Confirm-Console,Clear-Console) and vault operations (Get-VaultKeys,Get-KeyFromVault,Set-ToVault,Remove-FromVault,Request-NewKey). Keys are stored with a.api.jcsuffix by default. Windows uses an inlinedCredManagerC# type (CredRead/CredWrite/CredEnumerateviaUnlock-Platform); macOS usessecuritykeychain commands. Linux is explicitly unsupported for vault access.The interactive flow lets users add keys (Escape), delete the highlighted entry (Backspace + confirm), and pick a stored name; secrets are read with
Read-Host -AsSecureStringwhen adding new entries.Reviewed by Cursor Bugbot for commit 8e44e56. Bugbot is set up for automated code reviews on this repo. Configure here.