Skip to content

Rewrite Import PFX module for Version 3.0 - #165

Open
Adam Meltzer (ameltzer-MSFT) wants to merge 17 commits into
microsoft:masterfrom
ameltzer-MSFT:ameltzer/import_pfx_v4
Open

Adam Meltzer (ameltzer-MSFT) wants to merge 17 commits into
microsoft:masterfrom
ameltzer-MSFT:ameltzer/import_pfx_v4

Conversation

@ameltzer-MSFT

@ameltzer-MSFT Adam Meltzer (ameltzer-MSFT) commented Aug 26, 2026

Copy link
Copy Markdown

Version 3.0 moves the operational module to advanced PowerShell functions while preserving the shipped Version 2 command contract. Tenant, application, cloud, schema, and redirect settings can be supplied at the command line. The retained EncryptionUtilities project remains isolated to OnPremValidation.

Impact observed

  • 12 shipped Version 2 commands preserved -- names, positional indexes, pipeline input, common parameter-set names, CNG formats, and Graph paths
  • Version 2 inputs preserved -- intended-purpose numbers, PaddingScheme None, provider/key carry-forward, and deprecated manifest authentication fallback
  • Commercial and GCC High configuration supported from one manifest -- no copied government-cloud manifest
  • PFX output compatibility preserved -- PascalCase properties, legacy PowerShell type name, DateTimeOffset values, Base64 binary conversion, and per-record batch continuation
  • PowerShell 7 and ECC P-384 supported -- keyAlgorithm retained as local metadata and excluded from the Graph payload because it is not part of userPFXCertificate

Fix
Replaces the binary cmdlets with IntunePfxImport.psm1 and explicit Version 3.0 exports. Adds setup-object authentication, command-line settings, modern Graph PowerShell app onboarding, bounded retries, token refresh, OData encoding, safe continuation handling, and WhatIf support.

Adds Examples/Test-IntunePfxImportE2E.ps1 as a clearly marked non-production live-tenant sample. Default cleanup removes the temporary PFX file, machine key, and imported Intune record. The reusable Entra application remains in the tenant.

Updates the README with the operator-versus-target-UPN distinction, direct $setup usage, CNG key purpose, Version 2 migration behavior, Graph read-back redaction, verification, cleanup, and sample usage.

Testing

  • Windows PowerShell 5.1 -- 34 Pester tests pass
  • PowerShell 7 -- 36 Pester tests pass, including ECC P-384, Version 2 compatibility, response normalization, and batch continuation
  • Retained OnPrem solution -- Release build succeeds
  • EncryptionUtilitiesUnitTests -- 17 pass, 9 environment-dependent E2E tests skipped
  • Non-production E2E sample -- parser and release guard covered; live ECC import/read-back/removal workflow previously completed successfully

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ae31ab63-429e-4c7f-9953-64c042fbef56
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ae31ab63-429e-4c7f-9953-64c042fbef56
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ae31ab63-429e-4c7f-9953-64c042fbef56
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: ae31ab63-429e-4c7f-9953-64c042fbef56
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0c68cfbf-e1a0-4973-8242-d3774b2d013c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0c68cfbf-e1a0-4973-8242-d3774b2d013c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0c68cfbf-e1a0-4973-8242-d3774b2d013c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0c68cfbf-e1a0-4973-8242-d3774b2d013c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0c68cfbf-e1a0-4973-8242-d3774b2d013c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0c68cfbf-e1a0-4973-8242-d3774b2d013c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0c68cfbf-e1a0-4973-8242-d3774b2d013c
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0c68cfbf-e1a0-4973-8242-d3774b2d013c
@ameltzer-MSFT Adam Meltzer (ameltzer-MSFT) changed the title Rewrite Import PFX module for Version 4.0 Rewrite Import PFX module for Version 3.0 Aug 27, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Replaces the Version 2 compiled PFX import cmdlets with a PowerShell 3.0 module while retaining compatibility and isolating EncryptionUtilities for validation.

Changes:

  • Adds script-based authentication, Graph operations, CNG handling, onboarding, retries, and ECC support.
  • Adds Pester and non-production E2E coverage.
  • Removes legacy compiled module projects and updates validation builds and documentation.

Reviewed changes

Copilot reviewed 42 out of 45 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
azure-pipelines.yml Builds validation projects and runs Pester tests.
src/PFXImportPowershell/README.md Documents Version 3 usage and migration.
src/PFXImportPowershell/PFXImportPS/IntunePfxImport.psm1 Implements the Version 3 module.
src/PFXImportPowershell/PFXImportPS/IntunePfxImport.psd1 Defines Version 3 exports and defaults.
src/PFXImportPowershell/Tests/IntunePfxImport.Tests.ps1 Adds comprehensive module tests.
src/PFXImportPowershell/Examples/Test-IntunePfxImportE2E.ps1 Adds a live-tenant E2E sample.
src/PFXImportPowershell/PFXImportPS.sln Removes the legacy compiled solution.
src/PFXImportPowershell/PFXImportPS/PFXImportPS.csproj Removes the compiled cmdlet project.
src/PFXImportPowershell/PFXImportPS/packages.config Removes compiled-module dependencies.
src/PFXImportPowershell/PFXImportPS/Properties/AssemblyInfo.cs Removes legacy assembly metadata.
src/PFXImportPowershell/PFXImportPS/Authenticate.cs Removes legacy MSAL authentication.
src/PFXImportPowershell/PFXImportPS/User.cs Removes the compiled user model.
src/PFXImportPowershell/PFXImportPS/UserPFXCertificate.cs Removes the compiled certificate model.
src/PFXImportPowershell/PFXImportPS/LogMessages.resx Removes compiled message resources.
src/PFXImportPowershell/PFXImportPS/LogMessages.Designer.cs Removes generated message code.
src/PFXImportPowershell/PFXImportPS/IntunePfxImport-gov-cloud.psd1 Removes the separate government manifest.
src/PFXImportPowershell/PFXImportPS/Serialization/SerializationHelpers.cs Removes legacy JSON helpers.
src/PFXImportPowershell/PFXImportPS/Serialization/JSONObjectWrapper.cs Removes the object wrapper.
src/PFXImportPowershell/PFXImportPS/Serialization/JSONArrayWrapper.cs Removes the array wrapper.
src/PFXImportPowershell/PFXImportPS/cmdlets/AddKSPKey.cs Removes the compiled key cmdlet.
src/PFXImportPowershell/PFXImportPS/cmdlets/ConvertToBase64EncodedPFXCertificate.cs Removes the compiled conversion cmdlet.
src/PFXImportPowershell/PFXImportPS/cmdlets/ExportPrivateKey.cs Removes the compiled private-key export.
src/PFXImportPowershell/PFXImportPS/cmdlets/ExportPublicKey.cs Removes the compiled public-key export.
src/PFXImportPowershell/PFXImportPS/cmdlets/GetUserId.cs Removes the compiled user lookup.
src/PFXImportPowershell/PFXImportPS/cmdlets/GetUserPFXCertificate.cs Removes the compiled Graph reader.
src/PFXImportPowershell/PFXImportPS/cmdlets/ImportPrivateKey.cs Removes the compiled key import.
src/PFXImportPowershell/PFXImportPS/cmdlets/ImportUserPFXCertificate.cs Removes the compiled certificate import.
src/PFXImportPowershell/PFXImportPS/cmdlets/NewUserPFXCertificate.cs Removes compiled certificate creation.
src/PFXImportPowershell/PFXImportPS/cmdlets/RemoveAuthToken.cs Removes compiled token cleanup.
src/PFXImportPowershell/PFXImportPS/cmdlets/RemoveUserPFXCertificate.cs Removes compiled record removal.
src/PFXImportPowershell/PFXImportPS/cmdlets/SetAuthToken.cs Removes compiled authentication setup.
src/PFXImportPowershell/UnitTests/PFXImportPSUnitTests.csproj Removes legacy cmdlet tests.
src/PFXImportPowershell/UnitTests/Properties/AssemblyInfo.cs Removes test assembly metadata.
src/PFXImportPowershell/UnitTests/packages.config Removes legacy test dependencies.
src/PFXImportPowershell/UnitTests/NewUserPFXCertificateUnitTests.cs Removes ignored compiled-cmdlet tests.
src/PFXImportPowershell/UnitTests/CertificateTestUtil.cs Removes the legacy certificate helper.
src/PFXImportPowershell/UnitTests/TestCertificates/TestBadFile.txt Removes the obsolete test fixture.
src/PFXImportPowershell/OnPremValidation/PFXImportOnPremValidation.sln Repairs paths and includes utility tests.
src/PFXImportPowershell/OnPremValidation/IntunePFXCertConnectorValidationService/IntunePFXCertConnectorValidationService.csproj Targets .NET Framework 4.7.2.
src/PFXImportPowershell/EncryptionUtilities/Source/EncryptionUtilities.csproj Targets .NET Framework 4.7.2.
src/PFXImportPowershell/EncryptionUtilities/Source/ManagedRSAEncryption.cs Updates naming, formatting, and diagnostics.
src/PFXImportPowershell/EncryptionUtilities/UnitTests/EncryptionUtilitiesUnitTests.csproj Updates framework and references.
src/PFXImportPowershell/EncryptionUtilities/UnitTests/packages.config Updates test dependency versions.
Files not reviewed (1)
  • src/PFXImportPowershell/PFXImportPS/LogMessages.Designer.cs: Generated file

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread azure-pipelines.yml
Comment thread src/PFXImportPowershell/PFXImportPS/IntunePfxImport.psm1
Comment thread src/PFXImportPowershell/PFXImportPS/IntunePfxImport.psm1
Comment thread src/PFXImportPowershell/PFXImportPS/IntunePfxImport.psm1
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 27aeb2bc-60d7-477c-9a4c-a66389f2f805

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 42 out of 45 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • src/PFXImportPowershell/PFXImportPS/LogMessages.Designer.cs: Generated file
Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

src/PFXImportPowershell/PFXImportPS/IntunePfxImport.psm1:1533

  • -CreateClientSecret is rejected with AuthenticationMode PublicClient only at line 1652, after this function may already have created/updated the application and service principal. Validate this incompatible combination before any Graph mutation so an invalid invocation cannot leave tenant artifacts behind.
        [switch]$CreateClientSecret,

src/PFXImportPowershell/PFXImportPS/IntunePfxImport.psm1:1199

  • The Version 2 Get-IntuneUserPfxCertificate parameters both belonged to the same default parameter set, so callers could supply both and the cmdlet gave UserThumbprintList precedence. Splitting them into mutually exclusive sets now causes those existing invocations to fail parameter binding, contrary to the stated Version 2 contract preservation. Keep both parameters in a shared set or add a compatible combined set.
    [CmdletBinding(SupportsShouldProcess, PositionalBinding = $false, DefaultParameterSetName = 'FromUsers')]
    param(
        [Parameter(ValueFromPipeline, ParameterSetName = 'FromThumbprints')][object[]]$UserThumbprintList,
        [Parameter(ValueFromPipeline, ParameterSetName = 'FromUsers')][string[]]$UserList

src/PFXImportPowershell/PFXImportPS/IntunePfxImport.psm1:1048

  • The removed Version 2 cmdlet exposed parameter-set names SinglePFXFile and Base64EncodedPfx, but the replacement renames them to Path and Base64. This contradicts the PR's claim that parameter-set names are preserved and breaks scripts or tooling that inspect those names. Restore the legacy names and update the internal branch/test expectations accordingly.
    [CmdletBinding(DefaultParameterSetName = 'Path')]
    param(
        [Parameter(Mandatory, Position = 1, ParameterSetName = 'Path')][string]$PathToPfxFile,
        [Parameter(Mandatory, Position = 1, ParameterSetName = 'Base64')][ValidateNotNullOrEmpty()][string]$Base64EncodedPfx,

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f1fa1d83-c06c-4847-be0b-bb5e526ac214
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: f1fa1d83-c06c-4847-be0b-bb5e526ac214
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