feat: Add SecureString support to Get-D365LcsApiToken -Password param#906
Conversation
Fixes d365collaborative#673. Changes: - Add SecureStringTransformAttribute class that auto-converts a plain [string] to [securestring], preserving backward compatibility for existing callers passing -Password "plaintext" - Change -Password parameter type from [string] to [securestring] - Convert SecureString back to plaintext via NetworkCredential before passing to Invoke-PasswordGrant - Remove PSAvoidUsingPlainTextForPassword suppression (no longer needed) - Update .PARAMETER Password CBH with dual-type guidance - Add new .EXAMPLE showing Read-Host -AsSecureString usage
Fixes d365collaborative#673. Changes: - Add SecureStringTransformAttribute class that auto-converts a plain [string] to [securestring], preserving backward compatibility for existing callers passing -Password "plaintext" - Change -Password parameter type from [string] to [securestring] - Convert SecureString back to plaintext via NetworkCredential before passing to Invoke-PasswordGrant - Remove PSAvoidUsingPlainTextForPassword suppression (no longer needed) - Update .PARAMETER Password CBH with dual-type guidance - Add new .EXAMPLE showing Read-Host -AsSecureString usage
Error: Cannot find the type for custom attribute 'SecureStringTransform'. Make sure that the assembly that contains this type is loaded.
The custom attribute to transform the string password into a secure string is not included in the mock that Pester creates for the function.
We intentionally accept plain text passwords for backward compatibility and ease of use.
This pull request was automatically created by the d365fo.tools-Generate-Text action'
|
When I first tested this, I got the following error:
After changing the name of the attribute to After that, it turned out that the approach is incompatible with the unit testing framework Pester. We use that to run all kinds of tests against the functions. One of them validates the examples from the function documentation. This is not a full functional test. Instead, Pester creates a mock of the function and then validates that the command itself is valid. Unfortunately, the way the mock is created does not support custom attributes (see pester/Pester#1772 for a related issue). So I excluded Note I also rebased on the latest master to include the fixes for the default values of mandatory parameters. I created pr pavankadabala-png#2 for those changes, targeting your feature branch. Note it currently says there is a conflict. You can ignore that and reset your branch to the tip of my branch. Afterwards, the checks for this pull request should be successful. |
|
There is a typo:
|
Closes #673
What this changes
-Passwordpreviously accepted[string], which triggered thePSAvoidUsingPlainTextForPasswordanalyzer rule and exposed credentials in plain text in memory. This PR changes it to[securestring]while preserving full backward compatibility.How it works
SecureStringTransformAttributeclass (new, defined above the function):A custom
ArgumentTransformationAttributethat intercepts the-Passwordbinding. If a plain[string]is passed, it silently converts it to a[securestring]viaConvertTo-SecureString. If a[securestring]is already provided, it passes through unchanged. This means no existing scripts need to be updated.Plaintext recovery before
Invoke-PasswordGrant:The OAuth grant flow still requires a plaintext credential. One line converts the
SecureStringback to plaintext just before the call using the standard[System.Net.NetworkCredential]idiom, which is the accepted safe pattern for this scenario:Summary of changes
SecureStringTransformAttributeclass above the function-Passwordtype from[string]to[securestring], decorated with[SecureStringTransform()]$plainTextPasswordconversion line; pass it toInvoke-PasswordGrantinstead of$PasswordPSAvoidUsingPlainTextForPasswordsuppression (no longer needed).PARAMETER PasswordCBH to document dual-type support.EXAMPLEshowingRead-Host -AsSecureStringusageBackward compatibility
No breaking changes. Callers using
-Password "plaintext"continue to work identically — the argument transform handles the conversion transparently before PowerShell binds the parameter.