Skip to content

Implement Context integration for secure API key management - #22

Draft
Marius Storhaug (MariusStorhaug) with Copilot wants to merge 8 commits into
mainfrom
copilot/implement-context-integration
Draft

Implement Context integration for secure API key management#22
Marius Storhaug (MariusStorhaug) with Copilot wants to merge 8 commits into
mainfrom
copilot/implement-context-integration

Conversation

CopilotAI commented Jan 27, 2026

Copy link
Copy Markdown

Implementation Plan for Context Integration

  • Explore repository structure and understand existing codebase
  • Research GitHub module reference implementation for Context patterns
  • Create module-level variables for vault configuration
  • Create initialization function (Initialize-PowerShellGalleryConfig)
  • Implement wrapper functions for Context module
    • Set-PowerShellGalleryContext (private)
    • Get-PowerShellGalleryContext (public)
    • Switch-PowerShellGalleryContext (public)
    • Remove-PowerShellGalleryContext (private)
    • Get-PowerShellGalleryConfig (private helper)
  • Implement Connect-PowerShellGallery function
  • Implement Disconnect-PowerShellGallery function
  • Implement Get-PowerShellGalleryAccessToken function
  • Implement Test-PowerShellGalleryAccess function
  • Create tests for new functions
  • Validate PowerShell syntax for all files
  • Fix PSScriptAnalyzer linting issues
  • Code review and address feedback
    • Add API URL validation for security
    • Document security implications of -AsPlainText
    • Use .Clone() for clearer hashtable copying
    • Use centralized configuration for URLs
  • Security review with codeql_checker
  • Fix UTF-8 BOM encoding issues
  • Fix test file linting issues
    • Add suppression attribute for ConvertTo-SecureString in tests
    • Replace empty catch blocks with Write-Verbose
    • Remove trailing whitespace
  • Enhance test output and fix issues
    • Add descriptive Write-Host output showing what is being tested
    • Fix private function access (Get-PowerShellGalleryConfig)
    • Test default context indirectly through public API
    • Add Write-Host suppression for test file
  • Implementation complete!
Original prompt

This section details on the original issue you should resolve

<issue_title>Implement Context integration for storing API keys</issue_title>
<issue_description># Summary

Implement the Context module integration for PowerShellGallery to securely store and manage API keys for the PowerShell Gallery.

Background

The Context module (PSModule/Context) provides a secure, encrypted storage mechanism for module settings and user credentials. The GitHub module (PSModule/GitHub) serves as a reference implementation showing how to integrate Context.

Requirements

1. Connect-PowerShellGallery Function

Create a function that enables users to connect to the PowerShell Gallery by storing an API key context.

Behavior:

  • When called, it should open the user's browser to the PowerShell Gallery API key management page: https://www.powershellgallery.com/account/apikeys
  • Prompt the user to enter their API key (as SecureString)
  • Store the context using the Context module with the vault name PSModule.PowerShellGallery
  • Support storing multiple contexts (e.g., for different accounts/organizations)
  • Return the created context object when -PassThru is specified

Parameters:

  • -Name - A friendly name/identifier for this connection context
  • -ApiKey - (Optional) The API key as a SecureString. If not provided, prompt the user
  • -PassThru - Return the context object after creation
  • -Silent - Suppress informational output

Example:

# Interactive flow - opens browser and prompts for API keyConnect-PowerShellGallery-Name 'MyAccount'# Programmatic flow - provide API key directlyConnect-PowerShellGallery-Name 'CIAccount'-ApiKey $secureApiKey

2. Test-PowerShellGalleryAccess Function

Create a function that validates the stored API key by testing access to the PowerShell Gallery API.

Behavior:

  • Use the stored context to authenticate
  • Query the PowerShell Gallery API to retrieve packages published by the account
  • Return information about the account's published packages

Parameters:

  • -Context - (Optional) The context to use. If not specified, use the default context

Example:

# Test access using the default contextTest-PowerShellGalleryAccess# Test access using a specific contextTest-PowerShellGalleryAccess-Context 'MyAccount'

3. Supporting Functions

Implement supporting functions following the pattern from the GitHub module:

  • Get-PowerShellGalleryContext - Retrieve stored contexts
  • Switch-PowerShellGalleryContext - Set the default context
  • Disconnect-PowerShellGallery - Remove a stored context
  • Get-PowerShellGalleryAccessToken - Retrieve the API key (as SecureString or plain text with -AsPlainText)

Implementation Details

Context Storage Pattern

Reference the GitHub module's implementation:

# Module-level variable for vault configuration$script:PowerShellGallery=@{
ContextVault='PSModule.PowerShellGallery'DefaultConfig=@{
ID='Module'DefaultContext=$nullGalleryUrl='https://www.powershellgallery.com'ApiUrl='https://www.powershellgallery.com/api/v2'
}
}

Context Object Structure

@{
ID='MyAccount'# Unique identifierName='MyAccount'# Display nameApiKey=<SecureString># The API key (encrypted by Context module)GalleryUrl='https://www.powershellgallery.com'ConnectedAt=<DateTime>
}

Wrapper Functions Pattern

From the Context module's best practices:

functionSet-PowerShellGalleryContext {
param(
[Parameter(Mandatory)]
[string] $ID,
[Parameter(Mandatory)]
[object] $Context
)
Set-Context-ID $ID-Vault $script:PowerShellGallery.ContextVault-Context $Context
}
functionGet-PowerShellGalleryContext {
param(
[string] $ID='*'
)
Get-Context-ID $ID-Vault $script:PowerShellGallery.ContextVault
}

Dependencies

  • Context module (for secure storage)
  • PowerShell Gallery NuGet API v2/v3

References

Testing

Build out tests using the APIKEY secret available in the workflow. We need the function be able to work in a non-interactive way ...


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

CopilotAIand others added 4 commits January 27, 2026 10:39
Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com>
Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com>
Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com>
Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com>
CopilotAI changed the title [WIP] Implement Context integration for storing API keysImplement Context integration for secure API key managementJan 27, 2026
@MariusStorhaug

Copy link
Copy Markdown
Member

Copilot Fix these issues:
Message
Expected $null or empty, because For a file encoded with a format other than ASCII, ensure BOM is present to ensure that any application consuming this file can interpret it correctly., but got '

  • Workspace:/src/functions/public/Auth/Connect-PowerShellGallery.ps1:L:C
  • Workspace:/src/functions/public/Auth/Disconnect-PowerShellGallery.ps1:L:C
  • Workspace:/src/functions/public/Auth/Test-PowerShellGalleryAccess.ps1:L:C
  • Workspace:/src/functions/public/Auth/Context/Switch-PowerShellGalleryContext.ps1:L:C'.
    at $issues -join '' | Should -BeNullOrEmpty -Because $rule.Description, /home/runner/work/_actions/PSModule/Invoke-ScriptAnalyzer/0b13023a981f4c94136bba6193a9abd2d936cbc1/scripts/tests/PSScriptAnalyzer/PSScriptAnalyzer.Tests.ps1:145
    at , /home/runner/work/_actions/PSModule/Invoke-ScriptAnalyzer/0b13023a981f4c94136bba6193a9abd2d936cbc1/scripts/tests/PSScriptAnalyzer/PSScriptAnalyzer.Tests.ps1:145

Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com>

CopilotAI commented Jan 27, 2026

Copy link
Copy Markdown
Author

Copilot Fix these issues:
Message
Expected $null or empty, because For a file encoded with a format other than ASCII, ensure BOM is present to ensure that any application consuming this file can ...

Fixed in f19cfc8. Added UTF-8 BOM encoding to all 4 files to match the existing file encoding standard in the repository.

@MariusStorhaug

Copy link
Copy Markdown
Member

Copilot Fix these

 2026-01-27 11:00:56 [INFO] Linting POWERSHELL items...
Error: -27 11:01:14 [ERROR] Found errors when linting POWERSHELL. Exit code: 1.
2026-01-27 11:01:14 [INFO] Command output for POWERSHELL:
------
RuleName Severity ScriptName Line Message
-------- -------- ---------- ---- -------
PSAvoidUsingEmptyCatchBlock Warning PowerShell 29 Empty catch b
Gallery.Te lock is used.
sts.ps1 Please use W
rite-Error or
throw statem
ents in catch
blocks.
PSAvoidUsingEmptyCatchBlock Warning PowerShell 68 Empty catch b
Gallery.Te lock is used.
sts.ps1 Please use W
rite-Error or
throw statem
ents in catch
blocks.
PSAvoidUsingEmptyCatchBlock Warning PowerShell 111 Empty catch b
Gallery.Te lock is used.
sts.ps1 Please use W
rite-Error or
throw statem
ents in catch
blocks.
PSAvoidUsingEmptyCatchBlock Warning PowerShell 161 Empty catch b
Gallery.Te lock is used.
sts.ps1 Please use W
rite-Error or
throw statem
ents in catch
blocks.
PSAvoidUsingEmptyCatchBlock Warning PowerShell 193 Empty catch b
Gallery.Te lock is used.
sts.ps1 Please use W
rite-Error or
throw statem
ents in catch
blocks.
PSAvoidUsingConvertToSecureStringWi Error PowerShell 35 File 'PowerSh
thPlainText Gallery.Te ellGallery.Te
sts.ps1 sts.ps1' uses
ConvertTo-Se
cureString wi
th plaintext.
This will ex
pose secure i
nformation. E
ncrypted stan
dard strings
should be use
d instead.
PSAvoidUsingConvertToSecureStringWi Error PowerShell 46 File 'PowerSh
thPlainText Gallery.Te ellGallery.Te
sts.ps1 sts.ps1' uses
ConvertTo-Se
cureString wi
th plaintext.
This will ex
pose secure i
nformation. E
ncrypted stan
dard strings
should be use
d instead.
PSAvoidUsingConvertToSecureStringWi Error PowerShell 60 File 'PowerSh
thPlainText Gallery.Te ellGallery.Te
sts.ps1 sts.ps1' uses
ConvertTo-Se
cureString wi
th plaintext.
This will ex
pose secure i
nformation. E
ncrypted stan
dard strings
should be use
d instead.
PSAvoidUsingConvertToSecureStringWi Error PowerShell 99 File 'PowerSh
thPlainText Gallery.Te ellGallery.Te
sts.ps1 sts.ps1' uses
ConvertTo-Se
cureString wi
th plaintext.
This will ex
pose secure i
nformation. E
ncrypted stan
dard strings
should be use
d instead.
PSAvoidUsingConvertToSecureStringWi Error PowerShell 100 File 'PowerSh
thPlainText Gallery.Te ellGallery.Te
sts.ps1 sts.ps1' uses
ConvertTo-Se
cureString wi
th plaintext.
This will ex
pose secure i
nformation. E
ncrypted stan
dard strings
should be use
d instead.
PSAvoidUsingConvertToSecureStringWi Error PowerShell 132 File 'PowerSh
thPlainText Gallery.Te ellGallery.Te
sts.ps1 sts.ps1' uses
ConvertTo-Se
cureString wi
th plaintext.
This will ex
pose secure i
nformation. E
ncrypted stan
dard strings
should be use
d instead.
PSAvoidUsingConvertToSecureStringWi Error PowerShell 153 File 'PowerSh
thPlainText Gallery.Te ellGallery.Te
sts.ps1 sts.ps1' uses
ConvertTo-Se
cureString wi
th plaintext.
This will ex
pose secure i
nformation. E
ncrypted stan
dard strings
should be use
d instead.
PSAvoidUsingConvertToSecureStringWi Error PowerShell 185 File 'PowerSh
thPlainText Gallery.Te ellGallery.Te
sts.ps1 sts.ps1' uses
ConvertTo-Se
cureString wi
th plaintext.
This will ex
pose secure i
nformation. E
ncrypted stan
dard strings
should be use
d instead.
PSAvoidTrailingWhitespace Information PowerShell 98 Line has trai
Gallery.Te ling whitespa
sts.ps1 ce
PSAvoidTrailingWhitespace Information PowerShell 101 Line has trai
Gallery.Te ling whitespa
sts.ps1 ce

Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com>

CopilotAI commented Jan 27, 2026

Copy link
Copy Markdown
Author

Copilot Fix these

...

Fixed in ca3ab8f. Added SuppressMessageAttribute for ConvertTo-SecureString (test data only), replaced empty catch blocks with Write-Verbose, and removed trailing whitespace.

@MariusStorhaug

Copy link
Copy Markdown
Member

Copilot Build more outputs into the tests so we can see what is being tested, and what the results are.
Also, we have the following issue:

Describing PowerShellGallery
Context Function: Get-PSGalleryAPI
[+] Should not throw 160ms (129ms|31ms)
Context Function: Hide-PowerShellGalleryItem
WARNING: This cmdlet is not yet implemented.
[+] Should not throw 6ms (4ms|2ms)
Context Function: Show-PowerShellGalleryItem
WARNING: This cmdlet is not yet implemented.
[+] Should not throw 8ms (5ms|3ms)
Context Context Integration - Connect-PowerShellGallery
[+] Should accept Name parameter 497ms (484ms|13ms)
[+] Should create a context 49ms (48ms|2ms)
✓ Disconnected from PowerShell Gallery context [TestContext_1558798765_2]
[+] Should have PassThru parameter 156ms (155ms|1ms)
✓ Disconnected from PowerShell Gallery context [TestContext_1558798765]
Context Context Integration - Get-PowerShellGalleryContext
[+] Should retrieve context by ID 35ms (32ms|4ms)
[+] Should list available contexts with -ListAvailable 42ms (41ms|1ms)
[+] Should return default context when no parameters provided 25ms (24ms|1ms)
✓ Disconnected from PowerShell Gallery context [GetTestContext_1663904376]
Context Context Integration - Switch-PowerShellGalleryContext
✓ Switched to context [SwitchTestContext1_66426597]
[+] Should switch to specified context 61ms (58ms|2ms)
✓ Switched to context [SwitchTestContext2_228003856]
Error: [-] Should set context as default 1.94s (1.94s|2ms)
Message
CommandNotFoundException: The term 'Get-PowerShellGalleryConfig' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
at <ScriptBlock>, /home/runner/work/PowerShellGallery/PowerShellGallery/tests/PowerShellGallery.Tests.ps1:128
✓ Disconnected from PowerShell Gallery context [SwitchTestContext1_66426597]
✓ Disconnected from PowerShell Gallery context [SwitchTestContext2_228003856]
Context Context Integration - Disconnect-PowerShellGallery
✓ Disconnected from PowerShell Gallery context [DisconnectTestContext_1731268566]
[+] Should disconnect specified context 151ms (148ms|3ms)
✓ Disconnected from PowerShell Gallery context [DisconnectTestContext_567478215]
[+] Should remove context from vault 143ms (141ms|2ms)
Context Context Integration - Get-PowerShellGalleryAccessToken
[+] Should retrieve API key as SecureString by default 54ms (51ms|2ms)
[+] Should retrieve API key as plain text with -AsPlainText 36ms (34ms|1ms)
✓ Disconnected from PowerShell Gallery context [TokenTestContext_1653221932]
Context Context Integration - Test-PowerShellGalleryAccess
✓ API access validated for context [AccessTestContext_1613596706]
[+] Should return a result object 149ms (146ms|3ms)
✓ API access validated for context [AccessTestContext_1613596706]
[+] Should accept Context parameter 2.68s (2.68s|2ms)
✓ Disconnected from PowerShell Gallery context [AccessTestContext_1613596706]
Context Context Integration - Module Initialization

The test harness currently only tests public functions, so functions that are put in "private" folders are not available during testing.

Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com>

CopilotAI commented Jan 27, 2026

Copy link
Copy Markdown
Author

Copilot Build more outputs into the tests so we can see what is being tested, and what the results are.
Also, we have the following issue:

...

Fixed in 2e492c9.

Changes made:

  1. Added detailed Write-Host output to all test contexts showing what is being tested and results (e.g., "→ Connecting to PowerShell Gallery", "✓ Connection succeeded")
  2. Fixed the CommandNotFoundException error by removing the test that called the private function Get-PowerShellGalleryConfig directly
  3. Modified the "Should set context as default" test to verify indirectly by calling Get-PowerShellGalleryContext (public API) instead of accessing private functions
  4. Added Write-Host suppression attribute for test file

The tests now provide clear visibility into what's being tested and what the results are, while properly respecting the public/private API boundaries.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement Context integration for storing API keys

2 participants

@MariusStorhaug