From 7048b9aa00d4fa092265cd4bdad5a78e10781025 Mon Sep 17 00:00:00 2001 From: Friedrich Weinmann Date: Fri, 23 Oct 2026 12:53:19 +0200 Subject: [PATCH 1/2] Bugfixes & LogAnalytics & Performance --- .../document-powershell-functions/SKILL.md | 135 + PSFramework/PSFramework.psd1 | 5 +- PSFramework/bin/PSFramework.dll | Bin 266240 -> 269824 bytes PSFramework/bin/PSFramework.pdb | Bin 880128 -> 890368 bytes PSFramework/bin/PSFramework.xml | 94 + PSFramework/changelog.md | 18 + PSFramework/en-us/stringsUtility.psd1 | 50 +- .../logging/Import-PSFLoggingProvider.ps1 | 8 +- .../logging/Register-PSFLoggingProvider.ps1 | 9 + .../logging/Set-PSFLoggingProvider.ps1 | 2 +- .../functions/runspace/Invoke-PSFRunspace.ps1 | 1 - .../runspace/Read-PSFRunspaceQueue.ps1 | 14 +- .../functions/utility/Compare-PSFArray.ps1 | 2 + .../utility/Test-PSFHashtableEquality.ps1 | 60 + .../utility/Test-PSFParameterSet.ps1 | 90 + .../azureloganalytics.provider.ps1 | 53 +- .../azureloganalytics2.provider.ps1 | 318 ++ .../loggingProviders/console.provider.ps1 | 15 +- .../loggingProviders/eventlog.provider.ps1 | 5 +- .../loggingProviders/filesystem.provider.ps1 | 182 +- .../loggingProviders/gelf.provider.ps1 | 46 +- .../loggingProviders/logfile.provider.ps1 | 67 +- .../loggingProviders/splunk.provider.ps1 | 40 +- .../loggingProviders/sql.provider.ps1 | 94 +- .../internal/scripts/async-logging2.ps1 | 2 +- .../loggingProviderInstanceModuleCode.ps1 | 6 +- PSFramework/modules/EntraAuth.md | 14 + .../modules/EntraAuth/1.8.56/EntraAuth.psd1 | 139 + .../modules/EntraAuth/1.8.56/EntraAuth.psm1 | 4073 +++++++++++++++++ PSFramework/modules/EntraAuth/1.8.56/LICENSE | 21 + .../modules/EntraAuth/1.8.56/changelog.md | 133 + PSFramework/modules/readme.md | 21 + .../snippets/help_par_EnableException.snippet | 20 - PSFramework/xml/PSFramework.Format.ps1xml | 22 +- .../Commands/ConvertToPSFHashtableCommand.cs | 39 + .../PSFramework/Logging/FileSystemWriter.cs | 111 + library/PSFramework/Logging/Provider.cs | 5 + library/PSFramework/PSFramework.csproj | 1 + library/PSFramework/Runspace/RSQueue.cs | 38 +- library/PSFramework/Utility/UtilityHost.cs | 132 + 40 files changed, 5743 insertions(+), 342 deletions(-) create mode 100644 .github/skills/document-powershell-functions/SKILL.md create mode 100644 PSFramework/functions/utility/Test-PSFHashtableEquality.ps1 create mode 100644 PSFramework/functions/utility/Test-PSFParameterSet.ps1 create mode 100644 PSFramework/internal/loggingProviders/azureloganalytics2.provider.ps1 create mode 100644 PSFramework/modules/EntraAuth.md create mode 100644 PSFramework/modules/EntraAuth/1.8.56/EntraAuth.psd1 create mode 100644 PSFramework/modules/EntraAuth/1.8.56/EntraAuth.psm1 create mode 100644 PSFramework/modules/EntraAuth/1.8.56/LICENSE create mode 100644 PSFramework/modules/EntraAuth/1.8.56/changelog.md create mode 100644 PSFramework/modules/readme.md delete mode 100644 PSFramework/snippets/help_par_EnableException.snippet create mode 100644 library/PSFramework/Logging/FileSystemWriter.cs diff --git a/.github/skills/document-powershell-functions/SKILL.md b/.github/skills/document-powershell-functions/SKILL.md new file mode 100644 index 00000000..57ead932 --- /dev/null +++ b/.github/skills/document-powershell-functions/SKILL.md @@ -0,0 +1,135 @@ +--- +name: document-powershell-functions +description: 'Write or complete PowerShell comment-based help. Use when a module contains top-level functions with no help, undocumented parameters, or parameter sets without examples. Preserve complete help and existing documented segments; add only missing documentation and syntax-check each changed file.' +argument-hint: 'Optionally specify files, folders, or function names' +user-invocable: true +--- + +# Document PowerShell Functions + +Create or complete comment-based help for PowerShell functions without rewriting documentation that already satisfies the requirements. + +## Scope + +- Process functions declared with the `function` keyword. +- Exclude functions nested inside another function. +- Respect any file, folder, module, or function scope supplied by the user. +- When no scope is supplied, inspect the current module or workspace surface relevant to the request. +- Change a function only when it has no comment-based help or when required coverage is missing. +- Leave a function's help unchanged when all required sections, parameters, and parameter sets are already documented. + +## Required Help + +Help created for a previously undocumented function contains only these sections: + +- `.SYNOPSIS`: one sentence summarizing what the function does. +- `.DESCRIPTION`: the command's purpose, behavior, filtering or output details, and other facts a user needs. +- `.PARAMETER `: one entry for every declared parameter, explaining its use. Also generate help for `-WhatIf` and `-Confirm` if the command implements ShouldProcess. +- `.EXAMPLE`: at least one example for every parameter set. Put the command first, followed by a blank line and prose explaining what executing it does. + +Do not add `.NOTES`, `.LINK`, `.INPUTS`, `.OUTPUTS`, or any other unrequested help section. + +## Style + +- Write for users of the command, not maintainers of its implementation. +- Keep the synopsis to one direct sentence. +- For Parameters listed in the help `Parameter Help Override` section below, do not invent your own help text and use the override text instead. +- Keep parameter descriptions concise. Do not narrate parameter-set selection unless that fact helps a user invoke the command correctly. Do not narrate whether it accepts input from the pipeline. +- Parameters that have a default value should explain this in a separate line with `Defaults to: {{value}}`. This does not apply to Switch parameters. +- Use concrete, realistic values in examples. +- Use `PS C:\>` as the example prompt. +- Explain the observable result of each example rather than merely repeating its syntax. +- Follow established wording for recurring parameters. For example, when most commands of a module use a `-ServiceMap`` parameter, prefer its existing documentation text and style over inventing a new variant. +- Match the indentation, line endings, spelling, terminology, and voice of nearby manually maintained help. + +## Procedure + +1. Inventory explicit `function` declarations in scope and identify nesting from the PowerShell AST or surrounding syntax. +2. Read each top-level function's current help, attributes, parameter block, parameter-set declarations, default parameter set, and behavior-controlling implementation. +3. Build a coverage list for each function: + - comment-based help is absent; + - `.SYNOPSIS` is absent or empty; + - `.DESCRIPTION` is absent or empty; + - a declared parameter has no matching `.PARAMETER` section or its section is empty; + - an explicitly assigned parameter default is not described; + - a parameter set has no `.EXAMPLE` that demonstrates a valid invocation and explains its result. +4. Skip functions whose coverage list is empty. +5. For a function with no help, add one complete help block containing only the required sections. +6. For partial help, make additive, localized changes only: + - preserve existing wording and formatting; + - add only missing or empty required sections; + - add only missing parameter documentation; + - add only examples needed for uncovered parameter sets; + - amend a parameter description only when needed to document a newly introduced explicit default; + - do not reorder, normalize, or rewrite already documented sections. +7. Place a new help block immediately beneath the line containing the `function` keyword and above attributes such as `[CmdletBinding()]` and the `param` block. Insert missing sections into an existing block without moving that block. +8. After completing all edits, run `.\tests\pester.ps1 -TestFunctions $false -Include Help*` to verify edits. A Test run without errors implies success. In case of error, use the test results to identify which functions' help needs fixing, fix the issue and test again. + +## Parameter-Set Coverage + +- Count named parameter sets declared through `ParameterSetName` and account for `DefaultParameterSetName`. +- Treat parameters without a `ParameterSetName` as common parameters available across sets. +- An example covers a set only when its arguments form a valid invocation of that set. +- A single example may cover only the set selected by its set-specific arguments. If it uses only common parameters and is ambiguous, count it for the default parameter set only. +- When no named parameter sets exist, require at least one example. + +## Preservation Rules + +- Never replace an entire existing help block merely to improve its prose. +- Never change a documented synopsis, description, parameter, or example unless it is empty, factually invalidated by the current function, or must be minimally amended to describe a new explicit default. +- Do not remove extra sections from pre-existing help during a coverage-only update; the instruction against extra sections applies to newly generated content. +- Do not document nested helper functions unless the user explicitly asks for them. +- Do not modify function behavior while documenting it. +- Do not change files that require no documentation additions. + +## Parameter Help Override + +When documenting the following parameters, always use the override text provided under the parameter's section, rather than inventing your own text. + +### WhatIf + +```text +If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. +``` + +### Confirm + +```text +If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. +``` + +### Cmdlet + +```text +The $PSCmdlet variable of the calling command, used to ensure errors and messages happen within the scope of the caller, hiding this internal helper command from the user. +``` + +### EnableException + +```text +This parameters disables user-friendly warnings and enables the throwing of exceptions. +This is less user friendly, but allows catching exceptions in calling scripts. +``` + +## Syntax Validation + +For each changed file, use the PowerShell parser and fail on parser errors. An equivalent validation is: + +```powershell +$tokens = $null +$errors = $null +$null = [System.Management.Automation.Language.Parser]::ParseFile( + (Resolve-Path $file), + [ref] $tokens, + [ref] $errors +) + +if ($errors.Count) { + $errors | ForEach-Object { Write-Error $_.Message } + throw "PowerShell syntax validation failed for $file" +} +``` + +Validation must run after the final edit of all updated files in scope. +Do not run validation earlz, before going through all files. +Do not claim syntax correctness based only on editor diagnostics or visual review. diff --git a/PSFramework/PSFramework.psd1 b/PSFramework/PSFramework.psd1 index b5ccab66..79c920e2 100644 --- a/PSFramework/PSFramework.psd1 +++ b/PSFramework/PSFramework.psd1 @@ -4,7 +4,7 @@ RootModule = 'PSFramework.psm1' # Version number of this module. - ModuleVersion = '1.14.457' + ModuleVersion = '1.15.472' # ID used to uniquely identify this module GUID = '8028b914-132b-431f-baa9-94a6952f21ff' @@ -42,6 +42,7 @@ 'Clear-PSFMessage' 'Clear-PSFresultCache' 'Compare-PSFArray' + 'ConvertFrom-PSFArray' 'ConvertFrom-PSFClixml' 'ConvertTo-PSFClixml' @@ -170,8 +171,10 @@ 'Test-PSFFeature' 'Test-PSFFilter' 'Test-PSFFunctionInterrupt' + 'Test-PSFHashtableEquality' 'Test-PSFLanguageMode' 'Test-PSFParameterBinding' + 'Test-PSFParameterSet' 'Test-PSFPowerShell' 'Test-PSFTaskEngineCache' 'Test-PSFTaskEngineTask' diff --git a/PSFramework/bin/PSFramework.dll b/PSFramework/bin/PSFramework.dll index 2d8de705a09c1793d30f93dac48faebded3a07da..7c3e237ab4894375d353acaa0f90d36b58e01376 100644 GIT binary patch literal 269824 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

G{>6kqbkb?+T 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 (e5u~z)gnsCFv*0g2`pC&NQI=7&VuCc|e+z7T zbLiT8$ZQ;Ny+OFSVYA0Qj7W#$QM~yP4CpkLkKLIKv>tB=*qgvjzuHZAf-kU`lii~k z|5o7YF@voC8Mu?O*x2EJ7w#1Gs%$~z}QvAhyU3>E)sb4^g^N34N4UKvnqBC6n3 z?)Rawqg?pdn7C1gVzxIID2yI^DY4_;ydZic^_~}-`X4PD^)#Mk-90PC7hyS4mzbQ& z6u&94hv7tq7vL3Scn7h)g^Wa92@xpfm26J7&yz|ZI~?&lE!i(I3ThBJ5_Gy_AjM^PDQA& z#*|7bppt4*$#L}mrFg*5oK}XgMNCPh$1#L+Ey7TyNs0;#49#h0D4WYFmFzf%Ff$-j zI+|3JA?XKggFsVZdG>I7Hb;)f?%r6#uB3Fic5y}jYR`5gP^ za~4iAY1_LD(Yxbg^RXP#uxlT6Dl_~mK+w|dDmR}ayFMd(Rh%t3na9`l$dx9$PS-bI2lb49b!pN)rVWKqRge{TRR9Q*>y(znD6)V}INr0NW{-2LIKzJh)Rh9ejq`*NuO zl?Ph~c7)>{04(;P9hivoVEs7KXR?+2lD3(i2SX1R;Ex=Lk(TU9T?fZ@XFEq%>p)|0 zlp!uA;Y)5G9^OGDT4UHSP~7nYs!d!i152{G_QS+UF>X4)YJbJWd# z9zA5P`dl#1I|ykw@%q7dDgPMY;UtZ+&`i9T>E(<$MnduGp-lZSJc@n(6)0$wF!Gf! z@5CEYl(YO>S^QGw{(HqK1%EiAxUd9aGQ+%d%4aFPf_nr4#*WWeGXgd5--Afp;3Ool zcqvq5t&)Vc4fgrJ5{!POux)U<{|5o=qUV#gxkrMe{NKaw3T*qDpKB3G==eSw0t9wHu$0{Lt7dGS>7^j#fTz!CfL4{V!B(8s#)} zsCfnDW~@InO=?$ZX8p^BWN#?E)BLLifQc{>UJ*^1kAi07oHz8qgrY}!ENT{_)s>JU z$EJxo%M$z4_UKA@7^pZ2?>NXyd8pw%9$suVsl5((b=C*mx6sYPL&Q#CYFiLFzNIl= z_8Q{G>#yZ2QD<}}�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.A|iG=4A-6F_Tw_Z#86g^Io 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�nSc-5SElsO!XQz+wP zB*d+D^N9=$Y=}iBiH>CixxJDK-MY%70`34l$m6LcDXdqa14B9WB_GSQak(PH#(@{u zI28&?9uAahTuaHGR(kLU<3_G1g6FV7BZa)gt)UGSZer+(5hkgDtE$Z-9CCF+H2b%7 zdJy8kQiN#KK18Es%Y4f{*yU0ahS;ni6e`EDjm*8JXnBaHnIx~BLiZ_D!Xlgn@zYFP zTzRe%DlhCSv8m$?vZw{KIOO|q8&|ZTgi?^|NI~PwlhX3pUL>p3k5ffA)=W=u7F^Jh zwt9qk-NLzU1*fO231RY3WJt~vq)D5+n`2v0#PMi&&nn*uQ?o3jS~+kQ`^D} zsuL;XG)x$d7t`o1(`<8?q-Aa#G#bsqF$|xD!`j1%alVeW<8a8XP;W7(90%e!3t+m^ zgS~l+q$yiznM215vW}5Q4zh#cz_0>p1Ug9J01f9Rrbri^AeO?Qczhui%}Kds4za9z zxX}18PDxqFsBDBBO&#e`vk0BTh7_7UMTkM=2n8r*E4+DTP~jsOp`A$R>>hm+N-G;D z6rAR73C9)t8`?Mq+4I(m17@Lp)b~^lCTKjdqr|39EFuGFp5)JR2S?4sOcPim=qQ`4 zX=vnf07Yw|D-Sn^c-g}#5{XGK3eTsI{bvqx2?Uv<4yp7k!Y%}YRPRt=Dr~tKf!c;> z%7Ud~B#r4Gx>z^ENNbX_eK1|TQ>ety6LMW7O3of;&ho=yX3A>z>1w&mhm#xBpos3L zQR<)@w@WmJ4No&1Zm~wzntMDlN7X^N7GxenOsaH6ODPP#kcXa3%IQyrD|B5$60-<+ zbr5AO^{!?(5x5i)%>`2$fJ1TKS92hAipwFxwIKs3!*bp-Elbsk$6wLyZ~$7Rh-qJ01}?CCI+H^U*jr+M z%fp1q3Jt~@Ng*n5gw^1>L~_{SWEX=KhNcTN!EV>{(qLXv5f5vl+^b6Q04%Q|G*zx6 zLLRfo!eWg2Tcr+jdWLe~m6gS?;qxqNV-n3%M$bBMASkQEk1mM$i*d9dO}r~uzqrWP zwt_h{1!hKYLRV>!w+>IxCAf`%_Zfa>j1`6+m*VybhkWL9z=CeZvDHUn)DlCVt}$SF zBh(w#SkQjoq-T2S1O68OBA5c+*|B$qsPjN@H{$w$3hC@UYf zmu{=zJjt_Qs|J%*;%a8)<*ocj?zHIw8nYO8mrR+=ocR^98?g zqa-ig_&Wo}IRb8K8cDv!9cUt}L7ujJ+#bcOW@F7IkQBU8ED8Mhm1G!u2N@t+Z%Kiz z2yB*Q7^ec(=a<;3TV-h07Byo{qZuKS6;2*o3ona{1#gue;WXU{;}VGrSLF5jSKyW% z_wn33)-d+f4d@){Q^+Ql)~FiiGjb&}bgXc-wajV7@u#699JXww(ZF<3hn{j31#$0I z2Y&-5wy7BtBVgP`xEsPzbPE;^&GJuoEJG_K zFN@)5s_M7J6$KhG5qy}y#_HN9t#lZ_E!Hem#QGi1INYk?$NVg@M$206ufma*!D!rG zh2xBKH2GviE3>oV%zlff82nWl(u0~5xj(KjAxo)p(B~zC8kV5{h zQCN*>m_lZz!7Q33u_<((sIXqc8wsm6+Zop2Q3%qXj`;3K(XaO%q+?vQ1)w zd|M{u6A>&i6Gps_q)5S3k0k)R9*&ve@%lqz@SR)9#`F3mYULkZ#3WhaGgzU+8X1l} ztg$46^^hT2^5_5;>dSocFE7mGy>dO!y`YE}a)c#|mViDilA>uEIA#H+@8Gm&t ztOpCK4AhcAlq7r;NkkZva2h_oq83HNbACjl7E%HSZzf4?X_yEZH+vBrs0a>{MT8sV z$-ERd4!%e|wx*KD-vW^2a_-jf_ZPT_<6?p6hU%QB68@{tVpooe^Gf97+3rOcVoEsC=L=`RNo|W!~P?#4Z9@-(< zKCI9xz`LffC|Zf1awzxHlh`4J)$T_2aY8v;!n5#&Hi%j{B`(~D$TL1SZc1>_Aity{ zED!CNZeIBIMWD4qS22A0hr1NM_@rEMY}i^??{&4b%wEJ!VFjKbTM3%#k1KU<5c*3` z{E_8nLT&~)$o{k?Z0v5raZ_Px@E98@DPTf)U#|+8C$gOP#EV~zz zWljsM9f2SnL(OzGH z8>*`LoB-V=DT*d1tlW|>XF}(-q1Z~duMwH!j;Uq72LyMMBx(0qzqAxjj4!rygK3Z1>6MW%^^!n+ zi(2YE9?k|=rgf+}Hi>w!Lip>JpvUGwjPNjAI)V9Z%P5vYTUEQ*htq+@~Cx4RSV}KH#Olf#g^mgQrrr)g}Jpe z=h6YTJjUkEHx30PmyeT}^x;^H&Xy!!R^5=HYbZ&wag!vQ2uY&0;m}Mh^7DLNJR>{H zFQeJIOEO?&9`?@AbW}P_GA5`J=v%({;9g;mJsjl88xCTO(t~kfhV|lv4NU}tv|Dag zSil;_&cPb2l?!783#Eji3*W?Gkl-6_5e&Z7vU2D!$?aZBYm#Ie=XtH(rKZXWq1k9ycPIG&kalpUSx;AoqQU+#5p=$(YqVoKArpx1F z0^LftkW7A9O9iPjmD#85D+jR3h1MXP(`G^n`W6<0^(4|p` z&u()ij-Ue2PYn@%B$gY)67)CMPQ^DaAX4fZC%1j{(abCW6K| z+$?6Ab>jeCJ80Znm15F9-=VM*mg1P zp^{Nq&8KhVB(f}`VsA0hyuc(<@dDbkS z6z6s@$k09vP1fLPH5!YbxnPIMC#Y*M326FQCY5zIiD|89O>C0*dKORc`2^OB7QT_? z5M8m5Pm@U+hPPt&D06E;RiavleSJ||hEoiB zTAJSb0Y{V7)f&EzIRp7Q3yzVSR`aWOZ0M;Qy!8E6(r)BgjqgQbnQ5a3rxwGEg`(-o zkJc6z<_?hG6A!zk5wSDdXhAc?t@9n;jqx-WeZPwDs=^$;f~7}x%5YmPS0l4vmRrNH zx#BjlJP0dy09J-kEqVk2pB4P&pnxntb7FiDi%466TGbCHx&7Y>}E8@VDX# zck`VE^u2ORsI(5P?xP7wlW7?qp$~;HY|MvdMC~Hp(fgZ29NJ&tF)`!uAUrbwMdp)0 za2Dv>xbA?3MI*rytg0@P&pD9!Lr!oJQ2-DqfDwrJ+Bf_`<68i<8}o=F%D-%|%Z~GfVN< zF1-!xJW=vgu{Ah*5#M2kGnMXOIBd+QFau4@E@zlyxQk&17N>B41`lnP!yNPOi2OGT zH^Q2S`EvIZHr3%6d6#*<7^BAwHwI7ThPpsbWICvm-+iGIv~VojA==@ES@=dY3g!=x z+fh_c+s|+u&TX4q_)@L$2Ap8wLL9bL0wK&(Jzw>-c zef||bI)t-){kq0at~Sc#2E{Ie8_#`MJX02EZo?n`9u_T+A?KWEdglwhnS~>0-Z5c5 ztI7d7ftBgxgFJ==f74vjI3{Bv>~9z{hSS6$ImArAgITnx3Xfu`!mzc5g76DzLhoHnlTD=z9M$x@pmEXt& zf2pTx@RxS4bZQL}(`_mJrGT-E2aUzV4Dgz4x`;TWStbvN;aVETx!R3^>q7sO;Cug6 zPaLVq4(H0@e2kvmlwHFd+0quKoP=~f?G6a+cEc2Xwb2MsrzY9zll**cH$_FapMr5+#>A7xEwsikxOh7~Z;kFg_rRcNVajGPLEe1hwk_)!y5{#&uk2qSeixZjxe4-LzKLxM?>NX)MJQO<9sH zJ62*^l5HaTvq{?HCn*|=Y>6F_Y^s~I#7T_pZpyoBY=V)21TUE}9!7XJHo?kx@`DC% zf@kAR9uhnUn|&JtF%SbW*2c~P2{y*sz+`s~ILUtBIaRmr?QTk*wD3uT!T^ zopb8csoO3j%#%hyh1#MoxFZxe?fVo5?-N)~tOcGvnRgN0h`HEfBi?S~(g2QXT@4A~ z5H2k&8_)$gw0e(Y62L<($Hv5p-7NIsD;!v>>wGY!QK=%k5%$7Gc~zM8<7nVZsOWtk34%3bsjP26ag+Wm!R} zP&7r#$b}pl!NbMs6Is%20qe>(NoMKb0{|*F-RA%Vda)CSx(mlym!2NMP*u?nm5wCr zDRSqdrT6m6I6moBp41X zLPbRzKR%6vFQ2IPZXc)d)5mthleIYG<8JNv6lDkA`CodGWUX?yYdI>(f?9-*ACh3ls z1l9;A)2+OR?B0J6lLm^A<0za%K%lr;L`3hBg%Y^yLBC?_2_-|jQjCPs=J3@%A?gS7 zQ{zt+iqJf$?}|DBW*(#l?7_7gq=`9L>V7tuLkT@IgMbH<-7)^rUsqU zge~LU{565M8_tYcPj}!fR6j5VX`0jiG=}kMfKbVPmY5fQ<70VAV~JyO#}c*=+Kg?v z`m|#cJOKA)pwM8CHL(C&FKSHqARDwNmVpW{JvSt>r0VZi$dY}6Z-{lAubJB*Nb3!W z+Hym3-ED=toLesj5&Dj(+n8W(ul}w4riK02aiX9741dKk)VJDX0EB$K7fQqsH@6?(xMJl!xT?-VF!?Q%W{1kdWxI>=daLLZIDMxv->xS4 zO8ta!nxwe35!E32pm?)z(&UQcuK>~bHq6t)hLiu1q+<%9+@LK0i%*jLh=3B zz!u8&bsADtX9g;`g7o_u0ymCdgQE&aSg7jxvLg=N*2&!|e+n|-R1<|T8nf)fCz8uI zByvH(1jbJfL`ya#f_`vn;tK)MKEllLv!S@2A0uHNSQ@}|=Aq4jyFZ1ye!-wzHsuUN zD7-*zzHXaQCrA-E>poM@xmM!yKX4#ZXm_lkRFn){&q7~2H+8=!V&j+y_YsdWOcD4N zCw;Pbunz*#O?27sM3Kh3cgRC8RzenhNozPmp|iA}GlyPFTmT5-KI%PI(Pfly9ty=z zVtPVRXur604mSh(;!!zf9s4DTaMJK0!8j=>RM3qnl!X35u{qx;JN93M6s)?%jFrV7 z9RQNtd|OW>b(JgY$@9Y8GPycqzOmpi&{aR?F6AjzTawk?b6J>mT@qon5ZPY6Q`EN$D6vQ)a}9W%DK4Os%CsQ>U_g3uySubFH(xvn+r!l2K%JnnAdzJB z%feweRN4J|9$ z$g-fLxd@hi@l5EB9O#8Vz{ACX3y|vSi^lZhrh3v_LSt49_6g%mRXft?RH2M71#drg zY@VS&*G4Z>!8P95~XOA$I+m^dXs;i(OX`(i*ufk*uSJ@2#*wy3xP6p35UdQB61 znHCj---8p#!n7t}9ojlx ze_4xMM6!k2G#FV9LB-G_W*>I$!>OoekH8gQ&UT?OOa4AFv<7@4@ns3$C$eNiqB2om z$gW7Az@`9_8dDVp`^iX=A1*9kIS@axAcd;s$q{(R%)2D90=q~sPui&LE;Ptv1`X*c zgN7koW&f`<;A56(#6AO=C8qeYd|euI<`_E_OxtE45JW|=QYe(j0SnIyrQrkK_Bb|_ zC^~@k_Y5UR<~@}DFpm?h`Hia*#|VXR3j0+f5!Xg=0aiYj4z=2vH_BZ4;#2^VgjT1x zkwvD6u|f0}khe|Zc~8k_`w$v0+Y`8Yc`4FzWI>LVB@Ddth*{>|g(Kf0gl)@;RVnYn za{o&W6SAO`p0IB1HM4+jUs(Kha0TLL)?-xE|U zq z+pS{aw9&b;4WK(4VslEKHi7gONr+yV2vrNM1)-I2{7X1D4#(LIJSg}@U6>tc0pXFa zogr`$98l<~0M8cT_JVvYOFBw&1LW8r_QJ+(1+c=XlVUQ0H3*-B(63st0P02xL|m6x zfIOOsIAli5{UQy+gxKv@l%FxR+%%PCE&q-dZAg@obryfuuI^O4$=^ZYgjh6(kTlO> zA5aXVkVFz#B6JYo0H{mSb|PN~mhmff_~wsc-C|olZyKz0l2~srVBwNrnT&Hk*v4n@Sz|$IEX}Z+=Y7l039%< zaoY=oSH@PB&4iQ~M^E1N7JQ<_$_E4HM%jn2%J3^GvZP>)E@>jv-XH|Bgf|ZrHx>_l z-w)R{ibIoM0ppe&kc$(Z4zI;hD8*hfQIa0#vQmQ9p#3N>R5lq4&kSsMPLnwE7VoZk z7q!-eup9-7Cv=k3Q(5n2gi_hua2cqFD+)#>1_eEa7qh}7wn9*+IaADM>An0t8%&D| zd>ex^j%WkUxTX=gysbg;{@0*rfEt88P@1;|u;n^6hr0mU%jgttmCvDXjmqUB!IOrd z=U8@9A3p&q&@=)I%K?5X#>ed^BE%BReOpl5M_5fQM?t1QtTF383u_WJo;(c&un6DkCJywHb;6rQU2I1$1YkZOGZEj91Z2(P=~cj42c-EWjW|to$|` zeAoVtnRaHA)w|qA2FoS~l=l2p$^BpOvZB}vY* zC8W|kXndML`TMbke4NLq!97fgaITz^CJ9sqaFIpA)YjV{xUW8~~@ua++=}98A z71@BlT%^UqR4*yvyA+b(mX}0SxwchRbMcZ!lE>!ddpQ#3h56Mp~iNZ~rGJevCx;Lm697uzt1PvW1s`oEej}==sE~Ral#ceP`l{zJK zbfy+AZ!1seq98;h0kSa(SiA?ho-s(0ifs`bsBZVmAXwc0EG?Kh7f{uZ>GMqAU4F`a z7z8vdRKm9q11AxTZ{ieF#9Yb1zM^Iyz}vG1sp0s9Ib#`yY(~z=uiWiDD?f0D7dR`P zTp3IgR*C>;jJyEBaegRCEW!r+mHb&F_N1s%tGbJU@9Dx>xzYCEB5v!#sS|Io-tk4K zJhCA0<{n1F(y~=&RG%j9744vtQ`jBP+H~$c7iCoZw5tT5Hi?Abd+#j285K}Z^y-kke zuzOLyXX|55<9!I;lFVg8fgc-AMDPh{AGOv^pD=12QhmxJU|MWPjZUHkU}G%iSBNe7 z-7kufy*Ly^p-@I35F|&o|Mu_@GXsi7ZQKEAsOAKN=6Ht@jSn9peQKC9hp$Ch$9R6n zX?{_5X{v~;>nEH@W!H0Be@Rt#L$mne)i}(gmH_li;KHs1TMmOm;S8$qy#I=eTI2dD zu!z2G*`1*e!KtAWBGW)aCHVfZAInfYj|_j~-5r8CUh%km9>jq+jF0Ngy9jw0&xH7E zGqMCC33fK+bOX0?d7B1T(D^+;OWZ!}HmTA`5WyN$|IbKD_=iM-3`ld#dJqM5oUyj< zAdRhQ-5?3tQGL>(5jg9)qh2hqN#1+%aom&Px9x%!q*2{qQ*MY36=VjwVvs_(g2e|BRMA0Vh!=TzAu(3LhOz4+0mH#=&S> z`i*(wA*2-mR~|Vzz*xldDWv&%$(#F-_Ej@zp2nNlWDVTKM(G?d$+?@C`I?n-TT#y3 zxgQwT5@nRhW7GxA(xS9bU#riU@jrCbtpB(`QASTnNuzidK?y}rp~?TDJv5)m0inkO z80|Fvn$vqR+a>f^!btPxtc;wrMvR?AS`@bmX%3k3RB|P3e--nwPA z!^G6sZ*;h12D&KvjA^;u#M%h0`RetLibPffvFV5i`3b~1JtTzaL~vwfA@JKRS^>eX zM}P-1nWvCjGGhpHM7vR6$)3!O?J%`|A)DLDp!TB#*&a)f@r|LhVv=}esyY0J5@chW zdu0B`K@|V#AUY(MjS>VWw0XBV43DHU1>kaK69%9>vxGJ{Av*X8kOJwO9D3etMtTw4 z{40o0AYKNy&S4!kuJ>8HJ{~jI>JS*4YY&WBd z=BbYcbNV@BZg}e>m{d~lDTCH0{t(!`j8;a`Y~<+Uq2{J=6szv7Tlz+8LSWsNfCv@3fcL=bLF};gW>ZX=Mtr>IHqqJbnFjbKv}ho^Ytf zLjFvmDhS^v7oJ0?C|tgTQ5S@Nt2%HOHIkTV8H8Tmh-2#PWV)(M)I&cm;}PvKkuzUI z%yfr!E`wBZe$&R;Ff9XE9sl*q5LJiK=oa&5kh5FN{{l62i@DbvMFY*#o24E>onxp& zboQIOMZIcP?kGgwCUXRg@8j-uGZ@~4+GTLGh@W+7oqch8Eb^0`^_%U zbQu^Tb(6q!4RKYSkX7}Ntc|T$8{0A3`%vzy<{rfELF{U!*~it&Xp3y0E#4<^U3;Co zrOwsLuMCbIXmb-Fxmv5l1mPy*TUigpugoglJ_waMUa5fmkJ9z8Zaz z3a=gaod3;e_de8GNj=gUYq9PL2&J8Xi)}35Go=Hu#94RYjgj#IwUo z?GM`Aa9b37x(?VfV;oIAuVRYgkNodzD5sFHyu&M{RP$6yF6M1R4@w<3w*8e+4@a+a zc4MLVs7FaI`9;e!zXsmFnf(8mM?Yn%R}vRo44*R9dqq`UUZ^@zawR6jGLCULtbWQ= zKV_;aaQ^Wy)!4sy|DV?G?rYG<8zp{N-g^nJ3;vVa?B1$RPRb1nF#97F{es^nCOswu%Ad z2>SAH%eJWU@BZ-&Cw69c=%BzE>UnzT5AVHE`vg?|ddCWyzUN^|FTu3VgV|Xe3h>lj zP3?V18%CNsr>H?)%;78QH+n?ClV-xicHF_nS7owzsLOL~_RmvpJuN3pEKloz>ELAE z2Uix;#oF46SIxeBu~V9)RltXJ5zvx12ngcfk5|~ z$IKo~Q$wl z0GvFIxQNk*eYqY(DqSWBC!JDw&bJSxCJ@K3lwh3n6(E7onZoR#?-wqOMEqumdR=%V zptH!QcNu#cMO!1r^brzV*TER0z3oH0f`iSYC_jhNd2#8$540epXIyN31hok@AXxV> zprKC#;p4*Ab1u_;Oi~JX;_T_@wUh7|+U4An{1?q5XpayPUrb|b>M8aRatJ*fLyq0Z z)(;7;I5wV8isQ)*h5j+LN$-qAYlY{|VRtWb5S~%1{~36|0_!?I z8~Ro*e^O1(qcrEwsU36YdUbAO$|9WrAoGiQWMW0E*OkjNU-CI!QR3;CCL`uNQs^<) ztY3EZZC);?u?>aO3&}4)Jjv;E4?QW!UEPU1XcB3hMdH_u#k3qTW~kXYIlV-+tny^~ zLCpb+bRLSf3z31d=uO5XHbYDz)ja zjChRi<+OK33p*G@0aaHs4=Nqj$nGP+j;ss1U0cRl#X;8M`LceUxXFeX4KIbgwU%KI~Obf!Z8X6 zC`u{f;bye<%Q!u{-F!yQdENO_tnD*Mi**EL7nK}1Qe`aaCpjgfq911-rfDveB0^M8 zW)Y$qG$DlJ#_kmzE~lt#$?XATx1%2YCl{gE#JcZCTRL+X(QRC!#56JD3DdDivyLQ9 z;wR0hlR2FU&AnqNPe-0P{3X$oEs;Tvgv#dtfwEdKOPZBAt9Oicw=)z&=9YR5dM}_M^Tl}9`u;+xw<$}A zN{Dd2Lc7HZ1irZy<(twvW;c^AJvO5wA!ATIL*LVYK=n*|G}GTMx~p($vzA74QbK1! z*^Sawc)WdZ!EPpP6<=fyIrD^!{S@|S+!dS=89NM&61HYAx&ETx1)lO6MBV`j*@ zy{kUGtr_P$=FmFvOqNFhN|wn{5{hy3uPc#T(Q!#JqVKkPZu)x)*Ku!=jf2As?KAWydOZ>76w;Q%EjZ` z(uv@}a~4sP7`_{H)WhGk#cASp1QW2n+3*R8v8uZtCsPN|3m5bp!pbO!e8R=$$FWai zBS%fn##XsvnK?B4tPajcrK&ppx|(8n&6y77eogE)k$yzR@9PO zNbQb)I>8&ga?l6e?SK6!fO*h@SU;;u#@7beUw#yTMODWrj#mQQM}jpDm=i>ncAe9? zyPjctnszLU!wfT>h7BVebv>(TR#sV`5*jzCY%K>i4sz=9b-CdP_rqD|#)i5sx0hsQ zx>l$%V9WAwn8-Z=bNv;uo~U6esVnPVmZVRAxrs`mqvlrBExFGGn;Ej$u$kvGfQAM- zjx7frcq{&^@Cjc#Jc5m08Rjvt@t(t0oE=3uYZcvCKNEW~N-kTD--#LO=}vTUgUTy$ zG%!pWZrEI@Fqfq%%InRX32v%$)XO(hLw0bpA95vUIOMq1<_hh(I^JzM!PuN$$35!? zXcGF@=@XnvqMXdWF?Se^Q}fwu*cQ(uw4T!x9RUyEsuRH=0MuZpPf`SgH$(o8#nC1` zIXE_>?l6YM{U@i4dMDvNfpOrcg|7rpDQ3 z9l>(JslfA^g--Dz(&xF1K3`8f-1O4)JdL?<~&r#oJe)FjYV&_)yvk#jbtC}$GX5h1a@(6+=KSQ)U3>3kAk?bpjJtC z$|cS@HtQdOwfH`)xEVaT?-&3~{A+r-@*YPS{QLq&!1AO%-GG~(#$3}yoBdZ%63P$4 z#EOQw*Tcuy!1&DG-O?i0E}0UiPgSoOJ6)=TsiH$B?Jcx^qfQ|}xEfn=RP1ezWdG*y z0YFl3t!&R74-GR#t3 z*?dy_rY=VQql*?0on7#ox)KeUunOpxZ3qP^)v?*h5QN6zmlnYS}|n$>C| zQt5-UlVM`Mes)X1fZwNIY36*dW(!xV&LHm{x!defigEJ8j8NF}7?|ff+?w!=M{!El zS&|I`HyPn=6VEJ2aV*L26Y%ZJaxFEEr5SFOvQ6QjtV&fnltxDZ6?;+1qju~wmY&^6 zh#l@kh*5;TanDIV?l&Rj(Il3AN#X z-_7hn+dBS61KADlt&5nUDg~~4_{NXM;oU5JoTCbQy@B%+wE3~jPte=M%4nY&?fq62 z{{nPW$Fsu@0BV}hGaxxF+!5WdsD4ZeFfl$!=F$%E5(!t}ApT<(Z0{oF? z{hedh51W{Y8`Uo9DvTe0^V=-ks6IUG?rR`d==EW)VYl;flu(Zs-=hDbh1Wa<^Isjp zocl8^r7P~M+!s_xU&QZ8OG~cJ0nDqPVaEfb5OD9H^Wwa>xVE`cx(x6_y({5UprNdFt3YepeOn81TEJsljzRjkdg`)idR(0P51lwc zaqCH+;hxmzq23mnM3sU#ns9CoS2m+5W=FJieQR2yKGm#q zYeQS-zFZ)?#ihF%E(dVkt{j9%{y95J-tnWp$6dI)_h;@1m-F~&S{A-OTXCZE=gkEw z30##~GA1IbBDc$1$IX_*P>?*^ z9f0d832h1pyAOXKLkm<=CP7qiqr%kQiPrT_GjCawY?Xk3!tT#NY2{(6cx2e)RT80= z_zZkmHXv+T;I9!JzH-WG%{sU-tQ zr+@V3;P{#;s%~fxu6@4sj=ZbkT=FrVwR@p{sG&){p(t?7;pnD>s-ahTxKPM4)TreI zj&p!@^7lwlyMUI2ph(`9OP(|3^dPf1I zOwG5nfl=HiEXX{1wH4dQgu}-thlDYDhgiS`mZWVfYi7@)*ldfkYc1p9b>(~t*mNC> zudjm=2^E|sLH>em-GYvpJ#u~XoSZa6+>u)}_Y#YmnCj_Vm5=aDC?E2pHivz$%~U8= z7V0^mTN77mxeo_2+P1@L<7XEg=3I{Q3Hcyn_hFbKz5v!vv0&Q1ApUiGfD88Nwr5l& zP22seND}rzXEpPSx zd_0!7hF(7cyVX2qhf7J_N+2S7?ibsIw}RtzqXh!4M@gP`_5+x1)-m1TgKo1_R=1$!4#>(Ahjnm&deX22*2 z6CG{L>SKtpE|m+~$qr#OPVYBj+3{mHm46$Rm_(C1Tc`Ps5>w6JVWR>4Ke?qNaw%cC zHPJOszD<+1ZVxE=$p5)|G(-iC+=-|1(+Cqi)M2WAu6zdGPA{gPZ!zj||JBB5?HoO@fLBHIHnZBsrOkJ_AufBbPQ$6lE zDZJhL&G4wn+@=l`6ByBgU?RNCv9OS@?Jkr5+4}nR2jyr3Wuk2~FGH+(IO^RUnzhrU z%=&tGh&geVMNSloAg2KbyyNF-#oSWg=3eBg!O`?^zd}0LhZ!L=!sQi78^>&f()tF3 zM!Y9GkMqOhHEF`x%YXr%UNZsXH&eunF4Xx&ES>Y;uaUl5=XVl&>R z1^@5ijSzoum4h<@?^1XZ7KuRj-h@Zx0^~#&HPkIoFh+12y&4s*qy*>8%Rx~_D@8dg z66wYHX*dd1QAav(s5l7yWG_la+aLw2h){nD(y_V4DdM_`QV~mK8yjfrJN`8QFPm@i zd>KJ2q3v|#&zEyk8|r#(s!?u3-> znY9XsGo0v|o$2D-?HuFoGae$P zz7&Ox)a;G6oQ1|ZDu~^gHs_S|)Q5q-7;UT>#&7&UAFCUpE=xzujh1GUk3xB^L)OLN z+S6V2a`tN=<6*Ug-UkZOzgr-c_k;ZP=OF5LpUy>=YDx}Y4&mRY=_{X5HG;=Vn`HVX zge`ID@BjuSuz+xO(7_W4?(I#QKbFJ%K)B$FHBS@F$n999;WG`+kcvdVtE9tQquq1a z-gjMpn}EHAkmmp!|C-efXA?U1E^keaRsLLm1BiM%>5?W8E^g(aI*Hs3@Zy8>=OZnL z4g7tGambuX?lhbUpY?c@Lr(3!RY0jpjllb@s4>JToH)G-U%*rsV=gh*sCS-c<0_i9 zLA^ce9N}r_ah*@0Q??Oy#CJ9z4pl{oE=k8KHLVZJ@Bbc^of8}2^wU_%uIXvw8uUPM z)#`4Fe4b-Jj=Jy>YJnH%h`~4xoJWs~e6vnBM4epvM$PPkkRI5q#|-yjX^jHV^&a z?qzbsN2qC?yYVe6b4#?fG1+L__Lj+$7MICu)+Rmm7i3caGfZ8*5y0+tJ?6G3ETh0B zw+YVJUZ3wgU0u2Q{P03JOmo%k(e`yV)JG#PE0B9}NO;_=4r7?*u8ke>jxjG|V4Pi~ zBfVAQ4o`oFJ=*W=-YS;(9oX6LObn($zq%czHr|B5M$+!i?sK~{w7|b?iS6>{FGW7{ z53pOSno{WHm+RmYB#PoSH~(p{-lAVIlCS#GB0uwni*7Z>q!9PYQ15t8H6W=SI`t4 zyJh*2KulZ@{)lZd3CY z1aliVAI>#QZG)=t+K-s*U5-_fu5<*HHdkq->E~MV*fMZyqILwOL(&@^;`R2Pd1k5c zMjlf-#96`J@vpyI$Gcon19QLJ#_O<8y|veTV65AShLzQ?H|;vrXl1R0?E=@=g6`0G zQ$cZdZJ2Y%94o68CaRUyyfWz!X1zS-%snp|m1;kw$|mFZOJ?P_#%&Mit{*U|aeDpdWnJl#5Q z0>6IlbLN3-UNwXuylZDX)^ku;^n-XhyEX+0&oi901a1=d_#3p1{Fujk6iI49;p#o+ z^ciT5npf{s_5f}^aBNOEnZ&5{Xu7F6bH73L$E>Cx@~1%jG9h;(Tj~^@*t)%dKo6|w z#q4aC=26ub-M)c+I7~i*zRM7DJS5Z8c^X=10#NIIUV2s?(<@@Jt-k+9?hVcet#H4^nzSgA zrrdpcM-58xT$|3CO4$9p4@6Y0SU24zscQ~{TJ)=Nx{sv8*Ydxpd}AR}?2`7Jn^~;f z92bQCM&g2YQyL<;505Q;JbjLULwQPwE&GMd8#_|+15(Z++&qR63R9@*X_WG&oBYIi z)tj`=ky=k=kBRlfHQ`fuILa*g2R}; ztBoW!yxe5EJ#+YkTP+`MCmLn#bS$JtfOoEg87J+mC9V!V1f0TQwvip4z=+fYxd)7q z{&)1BTLcE90!ziJ*>)wovkXm#6h(dpu#~R<)GXX&qb{~`U}B#o!Z|H!aweHf%D$Y4 zCUP)sm{2;6pJ_k>t$LcH9Mrj9)g#NK-LYA~32)=cJT+)aalOzHwi)s^>NF;RIt%;v z&h#Wl8eh0OqP5oNH1yhVqsX7YQsz5n$yxNmg`o#@wBPZ(jV!1B)0)ld>%BzlwE;bu z&^c|yOZJl{wng)lz{5EVhc%Q5j#*sue1Ey%=tgwWujXL&;_)Q4Pqj{$B}|z_v*Ya; z1I=D)LE~;AeCAJ=NowYLD&QEF9w$W2Rou7rE7y_ zsSj#>m)eJ~T@n}dXEB@yci&wNam{W0f|*k}VBddlPLIYoe#*4^QxJEsLd}+^9q!vk zEPb_;5Lg{oN5zua5|#$;l!^CTJ+*lnbCzj6Cbsm0V>!7RvesWa>I7u^*Yx>R-u==# zMjG-EfPsv1=($XqvT3n|RY!<-}fH zS)Fa2drk3tx;-jz4q`4yDZG}XYtxon$2IHSQ%U(OXDZ*IHyUk|1tjsPtBmCE(U-T~ z(m{s)tW7dDRwm?EwgX%ta3)|n(@t)W|&5=xOV{@`18Mrb>O$>{rk@#X=zJysz0v!!8 z_@kf-o}ar^er|)UegQ{S$XQ+ISG$h5REEGa87DeS(Jx5991p`!QkOY>J^0(HykB=1 zbE&EP5u2lk@5NtD;V)}3<)Dr8H(-y7{^u4pf1wzDBM&!UXdIavZ7#qCJrTI%>lZh+ z+F!b!c07(;U&K|cI?@dN^_?~^6Xg%h$`F;VyJkZpie0`(bt5?_@?E+|4JX6bZw7&z zrpCIQwky}w32m&&3HCLqh({+nwy{wScPH6goO)Io>mCMsquq%N#H^31ufCk=Ie;>h z*JnVQWF;uQZWJN1Djsg}sa7|WupX08pQ+QiUw4s@I<97#`<4vU>ES1&Z!%iy4&3l? zX|PouMpBZ~3&{CLkQ6!N?$-^J_~plW);h~_`1IF(+SYAc{8t&()~E1MZ*?{+_kG48 zj3)fKOX4Ezzg-f|NjE9#iw=x*QPH!w9j&>RiRQ6ab;3ysq!4E*3P%( z;;~eUaQ5OEk7ct7h6zm~o*7H;Z#QVEH`~1?7LTL7t+89pt){gzmfpV#Nhw0Yw3Y-$ zi*3|WtkobH(G;+fYG?E5JVutOjWZ?QZdy_)^kU-iOd(SsB+n9(bATbrg0Krol&)MzFQq%!L*)Yg5h8Th z%6_w{L|bO*Yil#7W2xR$GSwy_)bDKp04aH*VL+PXG<`pw!XyGMH}`}PAQ`uscuQw2 z)k*vays1>8MOs^%S%_s8vt79u3jSvVd$Vkdp=1tYTR;bxWEMilJqCdH_85nW%4^9) zD?xuI3xsBtdROP#ve|TXOJ-?fZx-=3_9%I^*V!)6m+i!)t<5ZL)|M;Zh-EPYSzsx? zrpFL#obACb_Fnxl(A*QlgvNRUOt&WDSxgNEx+b2$cv%8yLlda`ome)P=*%pg!$?xu zOyxz;WoGGLWhyVpASy3smcEYp%pwakY(PA(axmY=7+#I92j1*-1}|g*dz@XAlxcbu zA)ySR#cVHzM-*}ZXcV)75d!w5dr^h!KpKBpn|QekL*ZH?9pbHpFq=Jwt1z48QsfK( z;gy$_o>Lgt9u$bTCqY<1ej<^=pYCK5qwekoih*O)OJPaJQ^{mI*4mF_Nu(sZNr{iN zn^u^vb5o9WFU|Q3aH-#$SlIJ@l)3G+Lt85z@sr-t`OMB%xtOML1 z%Pc+0K}bLbk@PuFx|}Da&Um}5mMoTIW(-r<%@s!AyStM@C5(3x=u|QhPgmZ>KhOp8 z0NMM%NOestbBJpcm{`TN1k935v*@177+j!2STJ z0brT=HPWb0iLdHZt}6MRJ|mfnV-c?Lhl2FShC9~_L22I zC>Dd;8C1fBV zxD--YB*|n;JlVo^(8860Adp$@h!NBAmaasr#*mJ1FTm)|RMRQ)vD&US%t>3S1JssT z`c``BI|kWpt;O=Fg%{?NwGct6jzoJZ-kSm>WL1FkLcG1D z1Na2uzySae-(b#3uo;f1I*$6_BkUY}H3eo0qR)cO0AC=*Om#hYE`&p-+Dn9!Syp>d zGrjZ@t5i3#ig2pxM#Lno&!_ces(lG8>uO(bR{7a8=w?%*JF|#hf%T0^{LfT3BgnD{ zX9%yQZ`ANLK4GVFVp&c;TM|B z@ku@zyr>jQuUY~-??zgA0kET!^GUXsu9C+}CK>p7rMvTMz-bh((&DXj#FerXFSZUT zcImrZ&@&=!!BD}4VvwMmToMwLf==iOC{cN#Ezy#VXEEb=0_S8q-4vjp$I4~=ixWPo z29?Wp6qUki{@AN^kKL33LIZtj~ZIQ5*wL)CQ0X za5G~upK4kUXnnqLy*Q)m@_b>>{G7yOj2Sj5P->hGHvI9nxV{clB`T zzm~526i?95F3=g)85VB}I3xCYiD9=8d)qJvR2|THGQ8HZNYAFA@uB1lRxTufU?ML1 z3g(9Lk}m?0!m5jtJD_x@G!7N4S|9~3y&=F>kM<;z0B0PMQ!&l3s0P(>41s_J(~A^k zH+dz)3rW=>E_5VXfQr+Z>Vjh6O|JIL(tiftTF~KQruwvI{0c89M(^H))lz*{JIsQ) z{+Lr2kivT^M&AeeenSD1$`VIQ67R^hGLGd=^|87h&48-4fi8iU5}@)nq+O<3%~ZeP zGUE{YTzOR;_j-VcNGgsf-dM3v286VQ5{5d_Pi7{St}SHyz)LfSl9?IICKk|hSY1*O z^kh4x`u-i4tjp~=2v-E+C ze0?wtAKKMX`7otI9gF8y^vxHMMb+@uSUZF|N|08df~Q(L@#s}TyRp@rt|8r--9=drO@T~@c$(dt0Yva^vIxg&oTsob)|Gb^yjD>klN41I7ZY1 zHOM4^e4dp_;*cR|-d+ntH-fr~+nFlabf)?ewAD5yC+`|U zyXordI{8>aR^B3nl_Yb{#9lm-_)k)*yeY%So9m8TbUkxH4iZq@R9E2*-L=PbkuN<< z{jJ9YIwrPn?L7wE!1d5$Tox1=n!B5 zMK21?klmBK-?Hy_?0X1rnF*Ejn3L*TBm)Wfw0B(EJ3ej5rLhg^)91bK^4{N?z$l~# zE%bh-`o4zVLRT7kCsTdLHX##@y`##zU)h%5SDwgy20P*)_EXe z-A_bviuy$bsY+Zlv)`a4qUEY~7V5X(w9tgCPF{uA3SlcoxJEhrEJDe{QX#fPTkQs{KUhR+Q_v zWA7Ichx9ZR5so1TG1-r$$Py9{xLi)r)sMWjmW3=zVM&LYvCg)!XbZY@C}6!=vaPX9 zfeK|ZDQoe50E4|srg}fRB4@fEWgsb_FPO}^UW_E0x;dfbS4(GVKoOqn<(XFKYH1y6 zpT0Iq&CPt)MD?tt?VQ!pGH0Q9Cpmg8-MI?;MasO>{rfx*_;LF8CJ^)4L=ls@23Fws@77 z)=)i{NH44?NDyk?ECLvt!9`h_wF2X{0^`DrX~3$zi{+{TEYqN9J}7YRs4Z~rs8r9h zjO)CX4|QIXEZ6zp39`na9?I0oR%QpSyMZl`hEKAhUni+=LnzHy47LVD|8x*)3qsW( z^b8fCT5CJ_5MI=+ldx|l0i7&L?GkNL8th2wI?)Xa*i(&6lYFX{Tmx;p){lQ+dqd!n z6j=bQwh7`mQv=h%IuR~$?sU7@eNs2AiM8msXr%@MH$$m}Zc0)Fe{ic&+DX@PuBYv? zrnfWtEHx>Pgn`;kL1;q|x)}>6+8jt3wj?E24hja*%F9G^O}cXTyK^7QG*TAfHb@Kdx(-i9&C)CCh3#ALWPH!-+kjf!cs2E0~>oQSFI zlR2pE%hdK+;PwT>+y`t>c1acnRomBVrBH3uSJM!f`KWDRlnqcO*Ca#^G^!kE)HTSW zY;bflxXn4t66dtBO|+x6*_74NYXTpW_i3a1WM7{Q?a|Jmbx60`19oz`SB5MH6NS-? zZ}1D)eP}c7&EAseq7{xCMQ&Rnc*cxq2DiIZ5B?~TKpCOB{uDwk9~gC5Tk0q2TMSdi z4(U)I@bJ_gu)}{qra?fJLZbZzQ)BT#%t9ztxw?3AD8we6}z zZC#$vJ9buMHv~e+{-W*WqJS$4{9>kd(bc-hUCMJj`l?;Bh{Y)wl>)qI5HHyJmwdsC zw_^i%4i*_y1P-NtykrqwL@IX3=mGywl|aPx9k)6FGtmKGZsaV_17lOD>@P$-b%!R^sEO%npIBlr? z@big|%sD8xT=jsSV7w-Sz#Fse!WUIm)LyZ9uORQ00L!nr9$!-kUUMUR&5kT6a8V0f z45~^aq^nmn=M`7=6H!!p|rWMFGqNsAt8P4r4*PIESa=XP>1CHqb0eT)~8)S z3pS{Wuzx|#?9HM~6GeZ-DofL{8I!o7HqH5fNGYV>@ zFfIdtrT&cx)s3YeFnj3YP|a{e_r7h0N2fcX+*3z`RW#n4O;gzgRHtKEwB3s;;FaCX z$6MNlogb%2sr0$O27^kbm+qIoc2ZHS?!Z6V{As^qa_!qFlNrOwCHFAjPv^jgWxU*n zoqM%63vGtGt<0Dp8P-OS8`WU!cZp4ygOzToKhKgK;05Gi_aVx|n5?@WVV9Dr{UCkr zN1}|M`*8yC>W^S8K%dngwHm`+AxxAzl-<$@3Ud|4@9XC z9r;q$t&?-Fi>k>XRNkiP)| z)Uh3s$}rqveg4Q!=R=89=G+4UT;*lKE*2;j{>#w9!DdzX9nI8^BK}hw&1bmDsQ%1G zb)zK2Pqz~kq?iM4 zVo$PkZnDkaME49yyA><@`_w9z&e~c_XPs)abXF!4FLWTh41Fw}#XsBL(phb9=`6Sp zP7KfTf09LHeBci_c*sU!*}Eq0LeIEgo)iYXFGJ! zrORBYa7&>v;yIi_a2dWRNc!vK|Mh1_9$&xx?Prr)|DTsK5~3Kz(<7-gDR~CRa)^E|4^{ipkV9oZ^L6ZqYotTzz-l(w4g4KKmA?-f&??VL zPelG03%=yD-(#Ks!NgxUpg}2_$}b%*e(eHp+e+Bj5Zvmfpphzggs6JeRcz=DpOKYA z3_1MZF_M;AY?pV|ReH+>-f;mSI8(iek3pBzFO6~p)!+Ew2QK@!C|rv%Mzr70Seiio z2}6o#jg6TB-pJ z;JGZ?FNpsZ*s2d<>43j#1r&2ckQoc`2BQu^VYTgSWv9>C;Da}VlnF}ZMV8sb$2a(R z&cTADbnSi@8)R$`ACK^H!~%eAD*CFSuj-I*dmkJ66XYnNy^m<+EvB`FXY?G~5c7c4 z6bz60My8le+66~Q*S^NbS++6fi_FQXeXw-=I;mk^GPTWoJnxG?&o*A*`gbO7?uS?=jTcLO6PHSvYQC(VqnI zA*oNCFOd~4{XEEd(pP#?Rw#`M((o@>@NGW+jt|U3X6e^_yvN7i^YK6U_%LW|)VH;d zO`L1xBN^mR5sGuGg18{++!`0B9R&F|@o}?DtX=SpUI+k8*=(9Nf|9TKk{5mO6(79h zgO>$9WwyW__FU|>-?deFL-Ge*y!Mvs5yT<56wxUg5LVpD$NjD}RBgnU{?x^xMKgbo zi$kS#!P-qpW+K zsm#ra6(3$`bZAOu9!bI;_z3^fFo+l2Md8khtuLN%XhjT#B&`$AP8$}VC@I^G!g4+` z1HlSd_NQ~uF?FYl!=gAg)~j-~5|X0h@pyNz5k_9z?_Mw}Y`&n?pyM$(q2hHY!!sP% zV&4TccxFZk)hI&fD04^@O?a!a#QO>QTtHR99urz3H~hJF9@@}Nlre7Ypgmlm0~6V7 zvV#R}NR!~H>eA9vf}BYrXOe%39J~ZMlY*Q{hnz_wXHt=)VL^_R?aoZL;b07|rrgy) z>=RnN1awIhRX`GtaAIhmnCr$NGC;F#sNAn28UIk3N0ji32A7Aw05x>DTBhLd9Ea;R z|0OZgS*V!ES&NR=!?i1$!k&@DKvzV#Ap!}Y4u+sE!f29$+av5Cpp6UIL&Jnhpv{2r}HRv?RM&cUv3)5a$0D_8wRe2oFKea*+|quAR9%)zNG3kPY~gxWBP zVh8HV!8a7>f@O&0ENN?c+t%P0g_24!AlKG77Q{?4*+X=BM=&H-lPQ~q9-qNKhyQA8SFR0>5RZq@ z1X_eep!yQq1|08!;>0ERJ(&-&_aGG!B|jEH%duV|MyU{XZPFH$)KX&6Ak9_Y1H`Nd zHiR`wTw|qTyuVy!XY>#iUMA7a2p1BvGSuo2CK;24H?8?Pda6lGgl`wpfom5;5pWg6 zekpnDrMV4wLRAKVkQ}LhcVdfY$)*+Hj0ren*pUgr!EMOEOC?i%Q-~N2kH9}#rjZg> z1+))ql6a(Ks=w;N>Aw=7-EBZ=R=@{20L=Hh>h6*g>`OJxf0xd60QD_-)!O7${eCb> zIdQ7Q0$5yS67V67C&4$x(8K;n;&{bdfk_Z0Aj@(n1#K*iY>cp$77rAV`XLFVZJ>Gx zSr{Ca(WnCPTdlWQU*FW%d3|ls7yT`u4DZm_y=ahJsd|JhSC1eJ>c$goN>XiCruwIn z_ovYQwGv-+g1`&Fam7Iqv3WxYG!G4INQ>^Z(Y*@hl)%3?Q!YN+z&u$(gOcql@kXluuc2{DzjO*;M281{t4Zjm*>}o-B!_xDfFnqZIYOD zakmAWncAXyOn&GkQ|)OVuJ-zHtt}L;hQiN)Xfjo@a)?4W1_2T{HiX>8cBn*ybb54C zE`!SnwN+d@N|nG0_N3rA^gTvRtd)MqV7Zx5>(^KEW`itod9bxupLMnvSUr==wMb`X znh>E?qIxzyXnL->G+@ZewJ$XOtl)PEYYM6y4nNxE4T&o}6yQ4%kDwH-f%!t{*0!%U z?dX08chj&j2EgFt&|8!+AqqGVb|kAAMM)Re+1ixJiL<>V+j@{^q7{sxNmt9YFS5Qi zs6gF z3(O&)UB~J3My6@yJLsu)Udn9F)V?W!EexP1m=1UtK?(j#EJqMA5%fIRtm5(cl<)$Z z%hgJyBvXK4!OjRaZK)hbnki_Ni#mt)1;et*)Gj5s)Gpzos1hK;l73OrFXFfyuz=!G zj>;NxAuMY@M8mdCHXje7muwV{MNlIxJZo~Ts2G9+iib@AT@xIZ#-RBUNz7b{UqW1Z z{Hc!rr{Gsqu(5=H1|8M~TQSMd8d@YS*n>8Ch@iv9foX@;ekYW3Xp4x;hNCz~Q=iWbhZsTov9 z?i*dXc4{G_gmfaD(jaodOsJ1i-|xxct}B*2R~9dULQS7po9n{89<26AYAV-(37Nt9 zE=$JOup$m$g9HGoH#>1gGlK<$>i8!EQaAKpaIDnQ`0k{%A(bu7!4r`Hyo}MycTh=A4z>np6{^oAxVB8 zzmFqK3r%$5e|Hjb-5A>dcEg*%(dVW3yPZjL3y~~sNl>JbI06STJWO;Dtg#9=w^10}gpP?1`0gdq4j6fL6_T<50_++gX`;Z&wY1bYFVC+#NTBo(07`(o zgk-_6eDzU3KDxtVY z{MCLa&!4iD+G#?J)sFC@;`ry%`Y)0(C_4OeD~^}UX#Af&Q5v5+P@LU+b|ODFUntIw zPL+yh$}yDV0hlpsVy5fR$U~*^nf#ez=@fn>iKk;`UCd;57v~mBg_BeBx&QZjx!hfY zTkkPubIfd*9K0t#xOMxsEq86bcjuPv6DRK4GJfLT!7ay63=Zxb-gR>e$W z>%buX;uos+$4qwMz~0fIpZ>@5r82)AI|Z{I1#j!hC6bx<7YFdiYX)aTK_k-F5t)d&YN6 z?6`aDz1z0u2Y23!Z-pogr5_)kUdTUGD$X1#%;l#Gv-#NPVrF9)qhs?5-=T35(tN%& zlAq`F;S*(PZKPxW`0V8Pe6h3`>nDCk`^0E~-$0C}_y63OKVD`oQo~s6X9F6U zkD0b+Q%H9tRBzVFUEPZkGe3KOMbxp-oJV4^s4=ZP~A8>jC4 z;yyfw_w2fB@ZNg{x9uEFt*d9fR&FG0`si5YycKbf9}ovK5bpy+3-d*c7wmc9vHVPN z9;|=&_}sY4$o|}wDtNiL?ONsHwynocY}>ix?(xZOcW=*c+mUJPlW1M1bCDW>l;0BI z2<8x=du$G(FP}#0Xnt-EsGgh7t8}>~W;%8kXP?4sj22g+z$4@3srm8a(|Kb`+G4?u zXLoUW8d%4u%L75F8!Yj`we95h02VN$dGwf{w8TM$a_z{%92J@J$W(D*dJ;vbpWq8F zrk!|sDxW~b1K@#Bo&F0FNAd)^1BpsBTs+IodZQrzhco>AVS-oC>7@OooLqTQC9-T)w^vOX607n-5BFN1B0Y) zw_g~DlKa5$$=PBlZ*|YTrBV?;)&(`FDa&jbEzU)lJ0&sMmzBh-`ZaRD_6LjeU;vS- zpg)W-s<&}f&aL136~4*3vuOL<8(Ph`+gr_JBYQ@kdhWo_e)NCr8u~xK_4>Qpw%_`{ zvFqLU9ob!+%pW-kU4G&Ck-72-H_{`}s!QXg#Ur87A1NOH%8|!F;p63eIDKGl@;H0_ zhxz9h8&yyc`v1mouK75A87gPYvE9Yep6TiRD zF%T0XxEZ1$iUt*QgH6&|?h*X|lLuN&KecuHr@w`svyYn*{QAt}W-orpWyB2Q)2Ig! zAI9?`g!$*y*8loD-7jk&;&zMlFG?;vaq%W^2>;oGNDQs=E9dTulkU^5EVn^wjUrdS zD#!9gV_lfOPlUiH$8yNtr=>Qda+N$9E-x1M^3y84G^%M!!jojkNsv zOel|E$DYMU=MUh`uW7nJ513Ub<@)3IKFj#{FyY{@AKM>;L*eEh(Kmnr*8QNqewf&O zJCl8E#aEUG?SI&I%mbL!7_iQ7XY(7O{8IOH2&(4&4B+dZ{E0ZuZwB@Gg8}*#aDIn# z4&x%kC(RUE1z&DR%bD+ispRm>+=GA!rYZ9|v=VMdXJ``b@^ic;eCpX@k$n>8gSHQT z?UXP(oVjm}FNY%!`%b~Nep8;mG{}$mhv%dD*bRQylQ@pntH*Rbo_9)}`ky$+fl`Te dKSTBPfSOP4Pp%ahf=IvnlLO(?ou>&DEfX70=V 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�PlPLTSKS=@9mP!ej+QzCqhD1H+LkN1 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 delta 167897 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 SWtR9U^0fO%o~#G+)c=2M7H{hS diff --git a/PSFramework/bin/PSFramework.xml b/PSFramework/bin/PSFramework.xml index 91457488..344457d1 100644 --- a/PSFramework/bin/PSFramework.xml +++ b/PSFramework/bin/PSFramework.xml @@ -525,6 +525,21 @@ Enables adding empty keys for explicitly included keys that were not found on the input + +

+ Exclude keys whose value is null + + + + + Exclude keys whose value is an empty string + + + + + Exclude keys whose value is an empty collection + + Specifically designed for use in a command when passing through parameters with default values. @@ -3524,6 +3539,41 @@ Instance of the Logging Provider with the issue The Issue + + + Helper class used by the FileSystem logging provider to write data at max performance + + + + + The Path to where is written. Changing this recalculates converters and establishes a filestream + + + + + Size of the logfile. + Defaults to 0 if file not present. + Used to determine file-split based on size. + + + + + Writes a line to the logfile + + The line of text to write + + + + Writes an object to the logfile. + Will convert it to csv first. + + The item to write + + + + Clean up both converter and writer + + The data format to log to in the logfile logging provider @@ -3599,6 +3649,11 @@ Each logging provider has a name. Make sure it's unique + + + A description for the logging provider + + Whether the logging provider is enabled. Only when this is set to true will the logging script execute its events. @@ -8380,6 +8435,14 @@ Remove all content in the queue + + + Get all contents as an Array. + Possibly also clearing it out afterwards. + + If true, clear after reading as one threadsafe operation. + To content of the queued items + Take a look without removing anything @@ -12683,6 +12746,37 @@ How many levels to go down the script callstack Metadata describing who called + + + Compare two hashtables. + Value comparison uses C#-based comparison logic. + + First Hashtable to compare + Second Hashtable to compare + Whether the two tables are equal + + + + Compare two hashtables. + Value comparison uses PowerShell-based comparison logic. + + First Hashtable to compare + Second Hashtable to compare + Whether the comparison is case sensitive + Whether to recursively compare nested hashtables + If enabled, all entries in Table1 must be present in Table2, but not necessarily all entries in Table2 in Table1 + Whether the two tables are equal + + + + Checks, whether the specified parameters would resolve to one of the selected parameter sets. + Will return false, if the provided parameters would lead to an ambiguous parameter set, even if the specified sets would be among the still valid sets. + + The command for the parameters of which the test should be performed. + The names of the parameters specified. + The sets checked for. The resultant parameter set must be one of those specified. + Whether the specified parameters would resolve to one of the selected parameter sets + Stored scriptblocks that can be retrieved on demand anywhere within the process diff --git a/PSFramework/changelog.md b/PSFramework/changelog.md index 349198cf..296973aa 100644 --- a/PSFramework/changelog.md +++ b/PSFramework/changelog.md @@ -1,5 +1,23 @@ # CHANGELOG +## 1.15.472 (2026-10-23) + +- New: Logging Provider: Azure LogAnalytics V2 - sends logs to Log Analytics via Data Collection Rule +- New: Test-PSFParameterSet - Tests, whether the command specified would resolve to the specified parameter set with the parameters provided. +- New: Test-PSFHashtableEquality - Compares hashtables on a per-entry (key and value) basis. +- Upd: Logging Provider FileSystem - Significantly improved performance of builtin default debug log. +- Upd: ConvertTo-PSFHashtable - added `-ExcludeNull` parameter, to remove keys whose value is $null +- Upd: ConvertTo-PSFHashtable - added `-ExcludeEmptyString` parameter, to remove keys whose value is an empty string +- Upd: ConvertTo-PSFHashtable - added `-ExcludeEmptyCollection` parameter, to remove keys whose value is an empty collection +- Upd: Register-PSFLoggingProvider - added `-Description` parameter. +- Upd: Logging Providers - updated the `Get-ConfigValue` command available to Logging Providers to support `-Fallback` parameter, defining a fallback value in case the provider setting is $null. +- Fix: Compare-PSFArray - fails to accept empty arrays +- Fix: Read-PSFRunspaceQueue - the `-Continual` parameter will wait and immediately close +- Fix: Read-PSFRunspaceQueue - the `-Continual` parameter will not wait correctly even with the previous issue fixed +- Fix: Read-PSFRunspaceQueue - rare concurrency issue when reading all data from a queue that might have lead to a lost item +- Fix: Invoke-PSFRunspace - specifying a function as scriptblock leads to an error +- Fix: Set-PSFLoggingProvider - tries to register a Logging Provider from config when it doesn't contain a Name. + ## 1.14.457 (2026-07-02) - New: ConfigValidation rstimeout - Validates input as a legal setting for the Runspace Workflow Worker's timeout diff --git a/PSFramework/en-us/stringsUtility.psd1 b/PSFramework/en-us/stringsUtility.psd1 index d50c1211..8382e8ee 100644 --- a/PSFramework/en-us/stringsUtility.psd1 +++ b/PSFramework/en-us/stringsUtility.psd1 @@ -3,8 +3,8 @@ 'Import-PSFPowerShellDataFile.Error.Syntax' = 'File has an invalid PowerShell syntax: {0}' # $LiteralPath 'Import-PSFPowerShellDataFile.Error.Unsafe' = 'File is not safe to execute: {0}' # $LiteralPath - 'New-PSFSupportPackage.Error.PathNotFound' = 'Path not found: "$Path". Ensure the path exists or use -Force to create it.' # $Path - 'New-PSFSupportPackage.Header' = @" + 'New-PSFSupportPackage.Error.PathNotFound' = 'Path not found: "$Path". Ensure the path exists or use -Force to create it.' # $Path + 'New-PSFSupportPackage.Header' = @' Gathering information... Will write the final output to: {0} {1} @@ -13,26 +13,26 @@ Please make sure no sensitive data (such as passwords) can be caught this way. Ideally start a new console, perform the minimal steps required to reproduce the issue, then run this command. This will make it easier for us to troubleshoot and you won't be sending us the keys to your castle. -"@ # $filePathZip, (Get-PSFConfigValue -FullName 'psframework.supportpackage.contactmessage' -Fallback '') - 'New-PSFSupportPackage.Messages' = "Collecting PSFramework logged messages (Get-PSFMessage)" # - 'New-PSFSupportPackage.MsgErrors' = "Collecting PSFramework logged errors (Get-PSFMessage -Errors)" # - 'New-PSFSupportPackage.ConsoleBuffer' = "Trying to collect copy of console buffer (what you can see on your console)" # - 'New-PSFSupportPackage.OperatingSystem' = "Collecting Operating System information (Win32_OperatingSystem)" # - 'New-PSFSupportPackage.CPU' = "Collecting CPU information ({0})" # - 'New-PSFSupportPackage.RAM' = "Collecting Ram information ({0})" # +'@ # $filePathZip, (Get-PSFConfigValue -FullName 'psframework.supportpackage.contactmessage' -Fallback '') + 'New-PSFSupportPackage.Messages' = 'Collecting PSFramework logged messages (Get-PSFMessage)' # + 'New-PSFSupportPackage.MsgErrors' = 'Collecting PSFramework logged errors (Get-PSFMessage -Errors)' # + 'New-PSFSupportPackage.ConsoleBuffer' = 'Trying to collect copy of console buffer (what you can see on your console)' # + 'New-PSFSupportPackage.OperatingSystem' = 'Collecting Operating System information (Win32_OperatingSystem)' # + 'New-PSFSupportPackage.CPU' = 'Collecting CPU information ({0})' # + 'New-PSFSupportPackage.RAM' = 'Collecting Ram information ({0})' # 'New-PSFSupportPackage.PSVersion' = "Collecting PowerShell & .NET Version (`$PSVersionTable)" # - 'New-PSFSupportPackage.History' = "Collecting Input history (Get-History)" # - 'New-PSFSupportPackage.Modules' = "Collecting list of loaded modules (Get-Module)" # - 'New-PSFSupportPackage.Snapins' = "Collecting list of loaded snapins (Get-PSSnapin)" # - 'New-PSFSupportPackage.Assemblies' = "Collecting list of loaded assemblies (Name, Version, and Location)" # - 'New-PSFSupportPackage.Variables' = "Adding variables specified for export: {0}" # ($Variables -join ", ") + 'New-PSFSupportPackage.History' = 'Collecting Input history (Get-History)' # + 'New-PSFSupportPackage.Modules' = 'Collecting list of loaded modules (Get-Module)' # + 'New-PSFSupportPackage.Snapins' = 'Collecting list of loaded snapins (Get-PSSnapin)' # + 'New-PSFSupportPackage.Assemblies' = 'Collecting list of loaded assemblies (Name, Version, and Location)' # + 'New-PSFSupportPackage.Variables' = 'Adding variables specified for export: {0}' # ($Variables -join ", ") 'New-PSFSupportPackage.PSErrors' = "Adding content of `$Error" # - 'New-PSFSupportPackage.DbaTools.Messages' = "Collecting dbatools logged messages (Get-DbatoolsLog)" # - 'New-PSFSupportPackage.DbaTools.Errors' = "Collecting dbatools logged errors (Get-DbatoolsLog -Errors)" # - 'New-PSFSupportPackage.Export.Failed' = "Failed to export dump to file!" # + 'New-PSFSupportPackage.DbaTools.Messages' = 'Collecting dbatools logged messages (Get-DbatoolsLog)' # + 'New-PSFSupportPackage.DbaTools.Errors' = 'Collecting dbatools logged errors (Get-DbatoolsLog -Errors)' # + 'New-PSFSupportPackage.Export.Failed' = 'Failed to export dump to file!' # 'New-PSFSupportPackage.Extension.Collecting' = 'Collecting Extension Debugging Data: {0}' # $pair.Key 'New-PSFSupportPackage.Extension.Collecting.Failed' = 'Failed to collect Extension Debugging Data: {0}' # $pair.Key - 'New-PSFSupportPackage.ZipCompression.Failed' = "Failed to pack dump-file into a zip archive. Please do so manually before submitting the results as the unpacked xml file will be rather large." # + 'New-PSFSupportPackage.ZipCompression.Failed' = 'Failed to pack dump-file into a zip archive. Please do so manually before submitting the results as the unpacked xml file will be rather large.' # 'New-PSFThrottle.Error.InvalidLimit' = 'Invalid throttle limit: {0} / {1}' # $pair.Key, $pair.Value @@ -41,9 +41,13 @@ This will make it easier for us to troubleshoot and you won't be sending us the 'Resolve-PSFItem.Path.Found' = 'Found {1} items under {0}' # $entry, @($results).Count 'Resolve-PSFItem.Path.Summary' = 'Searched {0} paths, finding {1} items. {2} paths could not be resolved.' # (@($Path).Count + @($LiteralPath).Count), $foundItems.Count, $badPaths.Count - 'Resolve-PSFPath.Path.ParentExistsNot' = "Failed to resolve path" # - 'Resolve-PSFPath.Path.MultipleParents' = "Could not resolve to only a single parent path!" # - 'Resolve-PSFPath.Path.WrongProvider' = "Resolved provider is {0} when it should be {1}" # $parentPath.Provider.Name, $Provider - 'Resolve-PSFPath.Path.ExistsNot' = "Failed to resolve path" # - 'Resolve-PSFPath.Path.MultipleItems' = "Could not resolve to only a single path!" # + 'Resolve-PSFPath.Path.ParentExistsNot' = 'Failed to resolve path' # + 'Resolve-PSFPath.Path.MultipleParents' = 'Could not resolve to only a single parent path!' # + 'Resolve-PSFPath.Path.WrongProvider' = 'Resolved provider is {0} when it should be {1}' # $parentPath.Provider.Name, $Provider + 'Resolve-PSFPath.Path.ExistsNot' = 'Failed to resolve path' # + 'Resolve-PSFPath.Path.MultipleItems' = 'Could not resolve to only a single path!' # + + 'Test-PSFParameterSet.Error.FailedToResolve' = 'Unable to resolve command "{0}"! Check your spelling and consider using the "-Command" parameter instead, in case the command is not visible from within PSFramework.' # $Name + 'Test-PSFParameterSet.Error.AliasNullTarget' = 'Unable to resolve command! The Alias "{0}" points to "{1}" which could not be resolved. Ensure the Alias is configured correctly!' # $commandInfo.Name, , $commandInfo.Definition + 'Test-PSFParameterSet.Error.BadCommandType' = 'Unable to evaluate command "{0}". It is of type "{1}", but only Functions, Cmdlets or Aliases pointing at either can have their parametersets tested.' # $commandInfo.Name, $commandInfo.CommandType } \ No newline at end of file diff --git a/PSFramework/functions/logging/Import-PSFLoggingProvider.ps1 b/PSFramework/functions/logging/Import-PSFLoggingProvider.ps1 index 67695f25..54be34a7 100644 --- a/PSFramework/functions/logging/Import-PSFLoggingProvider.ps1 +++ b/PSFramework/functions/logging/Import-PSFLoggingProvider.ps1 @@ -32,7 +32,7 @@ A relative path would be relative to the path of the json file originally retrieved. If calling this command with the "-Data" parameter, relative paths are not supported. The scriptfile must be valid PowerShell code, however the original extension matters not. - The file will be run as untrusted code, so it will fail in Constraiend Language Mode, unless you sign the provider script with a whitelisted publisher certificate. + The file will be run as untrusted code, so it will fail in Constrained Language Mode, unless you sign the provider script with a whitelisted publisher certificate. # ProviderName #--------------- @@ -173,7 +173,7 @@ try { - if ($uri.Scheme -eq 'file') { [string]$dataReceived = Get-Content -Path $uri -ErrorAction Stop -Raw } + if ($uri.Scheme -eq 'file') { [string]$dataReceived = Get-PSFFileContent -Path $uri -ErrorAction Stop -ReadCount -1 } else { [string]$dataReceived = Invoke-WebRequest -Uri $uri -UseBasicParsing -ErrorAction Stop } } catch { throw } @@ -190,7 +190,7 @@ [System.IO.File]::WriteAllText($scriptPath, $dataReceived, $encoding) # Loading a file from within the module context runs the provider script from within that (trusted) context as well. - # This has various nasty consequences in Constrained language Mode + # This has various nasty consequences in Constrained Language Mode # We avoid this by rehoming the scriptblock to the global sessionstate $scriptBlock = { & $args[0] } [PSFramework.Utility.UtilityHost]::ImportScriptBlock($scriptBlock, $true) # $true = Import into global, rather than local sessionstate @@ -237,7 +237,7 @@ } foreach ($datum in $dataReceived) { - try { Import-ProviderData -Data $datum } + try { Import-ProviderData -Data $datum -ConfigPath $effectivePath } catch { Stop-PSFFunction -String 'Import-PSFLoggingProvider.Datum.Error' -EnableException $EnableException -ErrorRecord $_ -Continue -Target $datum } } } diff --git a/PSFramework/functions/logging/Register-PSFLoggingProvider.ps1 b/PSFramework/functions/logging/Register-PSFLoggingProvider.ps1 index 03d3a347..f902a33e 100644 --- a/PSFramework/functions/logging/Register-PSFLoggingProvider.ps1 +++ b/PSFramework/functions/logging/Register-PSFLoggingProvider.ps1 @@ -43,6 +43,10 @@ This reduces the complexity and improves the overall user experience while adding multi-instance capability to the service. All new providers should be built as version2 providers. Generation 1 legacy providers are still supported under the PSFramework Reliability Promise + + .PARAMETER Description + A description for your logging provider. + Helps users understand what the provider is meant for. .PARAMETER Enabled Setting this will enable the provider on registration. @@ -154,6 +158,9 @@ [Parameter(ParameterSetName = 'Version2')] [switch] $Version2, + + [string] + $Description, [switch] $Enabled, @@ -250,6 +257,7 @@ { $provider = New-Object PSFramework.Logging.Provider $provider.Name = $Name + $provider.Description = $Description $provider.BeginEvent = $BeginEvent $provider.StartEvent = $StartEvent $provider.MessageEvent = $MessageEvent @@ -301,6 +309,7 @@ $provider = New-Object PSFramework.Logging.ProviderV2 $provider.Name = $Name + $provider.Description = $Description $provider.ConfigurationRoot = $ConfigurationRoot.Trim('.') $provider.InstanceProperties = $InstanceProperties $provider.ConfigurationDefaultValues = $ConfigurationDefaultValues diff --git a/PSFramework/functions/logging/Set-PSFLoggingProvider.ps1 b/PSFramework/functions/logging/Set-PSFLoggingProvider.ps1 index ff398dec..7adb3e77 100644 --- a/PSFramework/functions/logging/Set-PSFLoggingProvider.ps1 +++ b/PSFramework/functions/logging/Set-PSFLoggingProvider.ps1 @@ -263,7 +263,7 @@ if ($null -eq $entry) { continue } $params = $entry | ConvertTo-PSFHashtable if (-not $params.Name) { - Stop-PSFFunction -String 'Set-PSFLoggingProvider.Error.ConfigNoName' -StringValues $params -EnableException $EnableException -Category InvalidArgument -Target $entry + Stop-PSFFunction -String 'Set-PSFLoggingProvider.Error.ConfigNoName' -StringValues $params -EnableException $EnableException -Category InvalidArgument -Target $entry -Continue } if ($params.Keys -notcontains 'Enabled') { $params.Enabled = $true } if ($Wait -and $entry -eq $last) { $params.Wait = $true } diff --git a/PSFramework/functions/runspace/Invoke-PSFRunspace.ps1 b/PSFramework/functions/runspace/Invoke-PSFRunspace.ps1 index 8fc5c843..efce55a8 100644 --- a/PSFramework/functions/runspace/Invoke-PSFRunspace.ps1 +++ b/PSFramework/functions/runspace/Invoke-PSFRunspace.ps1 @@ -162,7 +162,6 @@ } if ($pair.Value -is [ScriptBlock]) { $runspaceWrapper.AddFunction($pair.Key, $pair.Value) - $functionsResolved[$pair.Key] = $pair.Value continue } $runspaceWrapper.AddFunction($pair.Key, [scriptblock]::Create($pair.Value)) diff --git a/PSFramework/functions/runspace/Read-PSFRunspaceQueue.ps1 b/PSFramework/functions/runspace/Read-PSFRunspaceQueue.ps1 index d49c6ecb..b4635a37 100644 --- a/PSFramework/functions/runspace/Read-PSFRunspaceQueue.ps1 +++ b/PSFramework/functions/runspace/Read-PSFRunspaceQueue.ps1 @@ -82,8 +82,14 @@ #region Continual Streaming Mode if ($Continual) { - $queue = $resolvedWorkflow.Queues.$Name - while ($queue.Count -gt 1 -and -not $queue.Closed) { + $queue = @($resolvedWorkflows)[0].Queues.$Name + while ( + -not $queue.Closed -or + ( + $queue.Closed -and + $queue.Count -gt 0 + ) + ) { $result = $null $success = $queue.TryDequeue([ref]$result) if (-not $success) { @@ -99,9 +105,7 @@ foreach ($resolvedWorkflow in $resolvedWorkflows) { if ($All) { # Cache Results so downstream pipeline commands do not interfere with the clearing - $results = $resolvedWorkflow.Queues.$Name.ToArray() - if (-not $Peek) { $resolvedWorkflow.Queues.$Name.Clear() } - $results + $resolvedWorkflow.Queues.$Name.ToArray((-not $Clear)) continue } if ($Peek) { $result = $resolvedWorkflow.Queues.$Name.Peek() } diff --git a/PSFramework/functions/utility/Compare-PSFArray.ps1 b/PSFramework/functions/utility/Compare-PSFArray.ps1 index 9a12344c..cfd1f410 100644 --- a/PSFramework/functions/utility/Compare-PSFArray.ps1 +++ b/PSFramework/functions/utility/Compare-PSFArray.ps1 @@ -33,10 +33,12 @@ [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 0)] + [AllowEmptyCollection()] [object[]] $ReferenceObject, [Parameter(Mandatory = $true, Position = 1)] + [AllowEmptyCollection()] [object[]] $DifferenceObject, diff --git a/PSFramework/functions/utility/Test-PSFHashtableEquality.ps1 b/PSFramework/functions/utility/Test-PSFHashtableEquality.ps1 new file mode 100644 index 00000000..cc0534f9 --- /dev/null +++ b/PSFramework/functions/utility/Test-PSFHashtableEquality.ps1 @@ -0,0 +1,60 @@ +function Test-PSFHashtableEquality { + <# + .SYNOPSIS + Compares hashtables on a per-entry (key and value) basis. + + .DESCRIPTION + Compares hashtables on a per-entry basis. + It ensures both keys and values are equal as PowerShell considers equality. + + .PARAMETER Table1 + The first hashtable to compare. + + .PARAMETER Table2 + The second hashtable to compare. + + .PARAMETER CaseSensitive + Whether the value-comparison is case sensitive. + + .PARAMETER Recurse + Whether nested hashtables should be compared. + Beware: Recursive nesting can lead to an infinite depth recursion. + + .PARAMETER OneDirectional + If enabled, all entries in $Table1 must be present in $Table2, but not necessarily all entries in Table2 in Table1 + By default, all entries in both hashtables must match the other hashtable's. + + .EXAMPLE + PS C:\> Test-PSFHashtableEquality -Table1 $param -Table2 $oldParam + + Returns whether $param is equal to $oldParam on a per-entry key & value basis. + + .EXAMPLE + PS C:\> Test-PSFHashtableEquality -Table1 $param -Table2 $oldParam -Recurse + + Returns whether $param is equal to $oldParam on a per-entry key & value basis. + #> + [OutputType([bool])] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [hashtable] + $Table1, + + [Parameter(Mandatory = $true)] + [hashtable] + $Table2, + + [switch] + $CaseSensitive, + + [switch] + $Recurse, + + [switch] + $OneDirectional + ) + process { + [PSFramework.Utility.UtilityHost]::ComparePS($Table1, $Table2, $CaseSensitive.ToBool(), $Recurse.ToBool(), $OneDirectional.ToBool()) + } +} \ No newline at end of file diff --git a/PSFramework/functions/utility/Test-PSFParameterSet.ps1 b/PSFramework/functions/utility/Test-PSFParameterSet.ps1 new file mode 100644 index 00000000..f62ba892 --- /dev/null +++ b/PSFramework/functions/utility/Test-PSFParameterSet.ps1 @@ -0,0 +1,90 @@ +function Test-PSFParameterSet { + <# + .SYNOPSIS + Tests, whether the command specified would resolve to the specified parameter set with the parameters provided. + + .DESCRIPTION + Tests, whether the command specified would resolve to the specified parameter set with the parameters provided. + This compares the parametersets on the command metadata with the names of the parameters you intend to provide, + then resolves the effective parameterset they would lead to. + + Then compares them to the list of Parametersets provided and returns, whether the resolved parameterset would be one of them. + + Note: + - If the command would not resolve to a legal parameterset, it will return $false. + - If the command would not be able to resolve to exactly one parameterset, it will return $false. This takes the DefaultParameterSetName into account. This is true even if the remaining Parametersets would include one or multiple of the looked-for Parametersets. + + In consequence, this command cannot take input by pipeline into account (but specifying the name you would bind by pipeline as if explicit should work in most scenarios). + This command also cannot reliably evaluate dynamic parameters or Parametersets, as those are determined at runtime, not from Metadata. + + .PARAMETER Name + Name of the command to test Parametersets for. + WARNING: This may easily fail, if PSFramework cannot find the command (e.g. an internal command of another module). + For best reliability, use the "-Command" parameter instead. + + .PARAMETER Command + The command object to evaluate. + Expects an object as returned by "Get-Command". + This is the more reliable option as opposed to "-Name" and generally preferred, if slightly less convenient to use. + + .PARAMETER Parameters + The names of the parameters provided to the command. + These are used to determine, which parameterset would be viable. + + .PARAMETER Sets + The names of the Parametersets to check for. + If the effective Parameterset is any one of them the command returns $true. + + .EXAMPLE + PS C:\> Test-PSFParameterSet -Name Connect-EntraService -Parameters $param.Keys -Sets 'Browser','DeviceCode' + + Returns whether with the specified parameters, Connect-EntraService would end up using either the 'DeviceCode' or 'Browser' Parameterset. + + .EXAMPLE + PS C:\> Test-PSFParameterSet -Command (Get-Command -Name Resolve-TaskCredential) -Parameters $param.Keys -Sets 'Certificate' + + Returns whether with the specified parameters, Resolve-TaskCredential would end up using the 'Certificate' Parameterset. + As the caller is resolving Resolve-TaskCredential before calling Test-PSFParameterSet, the command is resolved within the context of the caller and may be invisible to PSFramework without causing any issues. + #> + [OutputType([bool])] + [CmdletBinding(DefaultParameterSetName = 'ByName')] + param ( + [Parameter(Mandatory = $true, ParameterSetName = 'ByName')] + [string] + $Name, + + [Parameter(Mandatory = $true, ParameterSetName = 'ByCommand')] + [System.Management.Automation.CommandInfo] + $Command, + + [Parameter(Mandatory = $true)] + [string[]] + $Parameters, + + [Parameter(Mandatory = $true)] + [string[]] + $Sets + ) + process { + if ($Command) { + $commandInfo = $Command + } + else { + try { $commandInfo = Get-Command -Name $Name -ErrorAction Stop } + catch { + Stop-PSFFunction -String 'Test-PSFParameterSet.Error.FailedToResolve' -StringValues $Name -EnableException $true -Cmdlet $PSCmdlet -Target $Name + } + } + if ($commandInfo -is [System.Management.Automation.AliasInfo]) { + $commandInfo = $commandInfo.ResolvedCommand + } + if ($null -eq $commandInfo) { + Stop-PSFFunction -String 'Test-PSFParameterSet.Error.AliasNullTarget' -StringValues $commandInfo.Name, $commandInfo.Definition -EnableException $true -Cmdlet $PSCmdlet -Target $commandInfo + } + if ($commandInfo -isnot [System.Management.Automation.CmdletInfo] -and $commandInfo -isnot [System.Management.Automation.FunctionInfo]) { + Stop-PSFFunction -String 'Test-PSFParameterSet.Error.BadCommandType' -StringValues $commandInfo.Name, $commandInfo.CommandType -EnableException $true -Cmdlet $PSCmdlet -Target $commandInfo + } + + [PSFramework.Utility.UtilityHost]::TestParameterSetAny($commandInfo, $Parameters, $Sets) + } +} \ No newline at end of file diff --git a/PSFramework/internal/loggingProviders/azureloganalytics.provider.ps1 b/PSFramework/internal/loggingProviders/azureloganalytics.provider.ps1 index 70f38088..ad144a62 100644 --- a/PSFramework/internal/loggingProviders/azureloganalytics.provider.ps1 +++ b/PSFramework/internal/loggingProviders/azureloganalytics.provider.ps1 @@ -60,10 +60,10 @@ $FunctionDefinitions = { $bodyAsJson = ConvertTo-Json $loggingMessage -Compress $body = [System.Text.Encoding]::UTF8.GetBytes($bodyAsJson) - $restMethod = "POST" - $restContentType = "application/json" - $restResource = "/api/logs" - $date = [DateTime]::UtcNow.ToString("r") + $restMethod = 'POST' + $restContentType = 'application/json' + $restResource = '/api/logs' + $date = [DateTime]::UtcNow.ToString('r') $contentLength = $body.Length $signatureArgs = @{ @@ -81,10 +81,10 @@ $FunctionDefinitions = { # RestAPI headers $headers = @{ - "Authorization" = $signature - "Log-Type" = $logType - "x-ms-date" = $date - "time-generated-field" = "TimeStamp" + 'Authorization' = $signature + 'Log-Type' = $logType + 'x-ms-date' = $date + 'time-generated-field' = 'TimeStamp' } try { @@ -93,23 +93,23 @@ $FunctionDefinitions = { switch ($webResponse.StatusCode) { '400' { switch ($webResponse.StatusDescription) { - 'InactiveCustomer' { throw "Sucessful Post to Azure Workspace" } - 'InvalidApiVersion' { throw "The API version that you specified was not recognized by the service." } - 'InvalidCustomerId' { throw "The workspace ID specified is invalid." } - 'InvalidDataFormat' { throw "Invalid JSON was submitted. The response body might contain more information about how to resolve the error." } - 'InvalidLogType' { throw "The log type specified contained special characters or numerics." } + 'InactiveCustomer' { throw 'Sucessful Post to Azure Workspace' } + 'InvalidApiVersion' { throw 'The API version that you specified was not recognized by the service.' } + 'InvalidCustomerId' { throw 'The workspace ID specified is invalid.' } + 'InvalidDataFormat' { throw 'Invalid JSON was submitted. The response body might contain more information about how to resolve the error.' } + 'InvalidLogType' { throw 'The log type specified contained special characters or numerics.' } 'MissingApiVersion' { throw "The API version wasn't specified." } 'MissingContentType' { throw "The content type wasn't specified." } 'MissingLogType' { throw "The required value log type wasn't specified." } - 'UnsupportedContentType' { throw "The content type was not set to application/json." } + 'UnsupportedContentType' { throw 'The content type was not set to application/json.' } } } - '403' { throw "The service failed to authenticate the request. Verify that the workspace ID and connection key are valid." } - '404' { throw "Either the URL provided is incorrect, or the request is too large." } - '429' { throw "The service is experiencing a high volume of data from your account. Please retry the request later." } - '500' { throw "The service encountered an internal error. Please retry the request." } - '503' { throw "The service currently is unavailable to receive requests. Please retry your request." } + '403' { throw 'The service failed to authenticate the request. Verify that the workspace ID and connection key are valid.' } + '404' { throw 'Either the URL provided is incorrect, or the request is too large.' } + '429' { throw 'The service is experiencing a high volume of data from your account. Please retry the request later.' } + '500' { throw 'The service encountered an internal error. Please retry the request.' } + '503' { throw 'The service currently is unavailable to receive requests. Please retry your request.' } } } catch { throw } @@ -171,7 +171,7 @@ $FunctionDefinitions = { ) process { - $xHeaders = "x-ms-date:" + $DateAndTime + $xHeaders = 'x-ms-date:' + $DateAndTime $stringToHash = $RestMethod + "`n" + $ContentLength + "`n" + $RestContentType + "`n" + $xHeaders + "`n" + $RestResource $bytesToHash = [Text.Encoding]::UTF8.GetBytes($stringToHash) $keyBytes = [Convert]::FromBase64String($sharedKey) @@ -245,17 +245,18 @@ $message_event = { # Configuration values for the logging provider $configuration_Settings = { - Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalytics.WorkspaceId' -Value "" -Initialize -Validation 'secret' -Description "WorkspaceId for the Azure Workspace we are logging our data objects to." - Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalytics.SharedKey' -Value "" -Initialize -Validation 'secret' -Description "SharedId for the Azure Workspace we are logging our data objects to." - Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalytics.LogType' -Value "Message" -Initialize -Validation 'string' -Description "Log type we will log information to." - Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalytics.TimeFormat' -Value "" -Initialize -Validation 'string' -Description "Format timestamps will be written with." - Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalytics.Headers' -Value 'Message', 'Timestamp', 'Level', 'Tags', 'Data', 'ComputerName', 'Runspace', 'UserName', 'ModuleName', 'FunctionName', 'File', 'CallStack', 'TargetObject', 'ErrorRecord' -Initialize -Validation 'stringarray' -Description "The properties of the message to log." + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalytics.WorkspaceId' -Value '' -Initialize -Validation 'secret' -Description 'WorkspaceId for the Azure Workspace we are logging our data objects to.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalytics.SharedKey' -Value '' -Initialize -Validation 'secret' -Description 'SharedId for the Azure Workspace we are logging our data objects to.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalytics.LogType' -Value 'Message' -Initialize -Validation 'string' -Description 'Log type we will log information to.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalytics.TimeFormat' -Value '' -Initialize -Validation 'string' -Description 'Format timestamps will be written with.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalytics.Headers' -Value 'Message', 'Timestamp', 'Level', 'Tags', 'Data', 'ComputerName', 'Runspace', 'UserName', 'ModuleName', 'FunctionName', 'File', 'CallStack', 'TargetObject', 'ErrorRecord' -Initialize -Validation 'stringarray' -Description 'The properties of the message to log.' } # Registered parameters for the logging provider. # ConfigurationDefaultValues are used for all instances of the azure logging provider $paramRegisterPSFAzureLogAnalyticsProvider = @{ - Name = "AzureLogAnalytics" + Name = 'AzureLogAnalytics' + Description = '[Deprecated] Logs to Azure Log Analytics through the legacy Data Collector API' Version2 = $true ConfigurationRoot = 'PSFramework.Logging.AzureLogAnalytics' InstanceProperties = 'WorkspaceId', 'SharedKey', 'LogType', 'TimeFormat', 'Headers' diff --git a/PSFramework/internal/loggingProviders/azureloganalytics2.provider.ps1 b/PSFramework/internal/loggingProviders/azureloganalytics2.provider.ps1 new file mode 100644 index 00000000..1ea916c1 --- /dev/null +++ b/PSFramework/internal/loggingProviders/azureloganalytics2.provider.ps1 @@ -0,0 +1,318 @@ +#region Functions +$functionDefinitions = { + function Update-LAToken { + [CmdletBinding()] + param () + + trap { + [PSFramework.PSFCore.PSFCoreHost]::WriteDebug('Error Getting Tokens', @{ Config = $config; Error = $_; Param = $param; ActualParam = $actualParam }) + throw $_ + } + + $param = @{} + $eaParam = 'ClientID', 'TenantID', 'Scopes', 'Browser', 'RedirectUri', 'RefreshToken', 'RefreshTokenObject', 'Certificate', 'CertificateThumbprint', 'CertificateName', 'CertificatePath', 'CertificatePassword', 'ClientSecret', 'Credential', 'VaultName', 'SecretName', 'Identity', 'IdentityID', 'IdentityType', 'FallBackAzAccount', 'AsAzAccount', 'ShowDialog', 'Federated', 'FederationProvider', 'Assertion', 'Environment', 'AuthenticationUrl', 'AzureToken', 'MonitorToken' + $config = Select-PSFConfig -FullName "$($script:configRoot).*"| Where-Object _FullName -eq $script:configRoot + foreach ($paramName in $eaParam) { + if ($config.$paramName -notin $null, '', @()) { + $param.$paramName = $config.$paramName + } + } + + $isEqual = [PSFramework.Utility.UtilityHost]::ComparePS( + $param, + $script:eaConfig, + $false, # CaseSensitive + $false, # Recursive + $false # Monodirectional + ) + if ($isEqual) { return } + + [PSFramework.PSFCore.PSFCoreHost]::WriteDebug('Recalculating Tokens', @{ New = $param; Old = $script:eaConfig }) + + $actualParam = $param.Clone() + # Cleanup to make sure they are not passed through, but used to determine whether a reconnect should be done (above). + $actualParam.Remove('AzureToken') + $actualParam.Remove('MonitorToken') + + $paramCount = $actualParam.Count + + if (-not $actualParam.ClientID -and -not (Test-PSFParameterSet -Command $script:eaConnectCmd -Parameters $actualParam.Keys -Sets 'RefreshObject', 'Identity', 'AzAccount')) { $actualParam.ClientID = 'Azure' } + if ($actualParam.CertificatePassword -and $actualParam.CertificatePassword -is [string]) { $actualParam.CertificatePassword = $actualParam.CertificatePassword | ConvertTo-SecureString -AsPlainText -Force } + if ($actualParam.CertificatePassword -and $actualParam.CertificatePassword -is [PSCredential]) { $actualParam.CertificatePassword = $actualParam.CertificatePassword.Password } + if ($actualParam.ClientSecret -and $actualParam.ClientSecret -is [string]) { $actualParam.ClientSecret = $actualParam.ClientSecret | ConvertTo-SecureString -AsPlainText -Force } + if ($actualParam.ClientSecret -and $actualParam.ClientSecret -is [PSCredential]) { $actualParam.ClientSecret = $actualParam.ClientSecret.Password } + + $token = $null + $script:eaToken = $null + + if ($config.AzureToken) { + if ('Azure' -ne $config.AzureToken.Service) { Write-Error -Message "Invalid Azure Token | Expected Service: Azure | Received Service: $($config.AzureToken.Service)" -TargetObject $config.AzureToken -ErrorAction Stop } + + try { Import-EntraToken -Token $config.AzureToken -NoRenew -ErrorAction Stop } + catch { Write-Error -Message "Failed to import Azure Token: $_" -TargetObject $config.AzureToken -ErrorAction Stop } + + $azureToken = Get-EntraToken -Service Azure + + # The bare minimum needed to reuse a RefreshToken, or reuse a Certificate/ClientSecret from the Azure token + if ($paramCount -lt 1) { $actualParam.ClientID = $azureToken.ClientID } + if ($paramCount -lt 1) { $actualParam.TenantID = $azureToken.TenantID } + + <# + In case we only specify an Azure token and not a Monitor token. + + - Delegate flows use the refresh token + - Identity flows have no need to specify a token to begin with + #> + if ($azureToken.Certificate -and $paramCount -lt 1) { $actualParam.Certificate = $azureToken.Certificate } + if ($azureToken.ClientSecret -and $paramCount -lt 1) { $actualParam.ClientSecret = $azureToken.ClientSecret } + } + else { + try { Connect-EntraService @actualParam -Service Azure -ErrorAction Stop } + catch { throw } + } + + if (Test-PSFParameterSet -Command $script:eaConnectCmd -Parameters $actualParam.Keys -Sets 'Browser', 'DeviceCode') { + $actualParam.UseRefreshToken = $true + } + + if ($config.MonitorToken) { + try { $token = Import-EntraToken -Token $config.MonitorToken -NoRenew -PassThru -ErrorAction Stop } + catch { Write-Error -Message "Failed to import Azure Monitor Token: $_" -TargetObject $config.MonitorToken -ErrorAction Stop } + } + else { + try { $token = Connect-EntraService @actualParam -Resource 'https://monitor.azure.com/' -ErrorAction Stop } + catch { throw } + } + + if ($token) { + $script:eaToken = $token + $script:eaConfig = $param + } + } + + function Update-LAWorkspacePath { + [CmdletBinding()] + param () + + $param = @{ + Subscription = Get-ConfigValue -Name Subscription + ResourceGroup = Get-ConfigValue -Name ResourceGroup + Stream = Get-ConfigValue -Name Stream + DcrName = Get-ConfigValue -Name DcrName + DceName = Get-ConfigValue -Name DceName + Table = Get-ConfigValue -Name Table + } + + $isEqual = [PSFramework.Utility.UtilityHost]::ComparePS( + $param, # Table1 + $script:laConfig, # Table2 + $false, # CaseSensitive + $false, # Recursive + $false # Monodirectional + ) + if ($isEqual) { return } + + if (-not $param.DcrName) { throw 'No Data Collection Rule (DcrName) specified!' } + if (-not $param.DceName) { throw 'No Data Collection Endpoint (DceName) specified!' } + + [PSFramework.PSFCore.PSFCoreHost]::WriteDebug('Recalculating LA Request Path', @{ New = $param; Old = $script:laConfig }) + + $script:laConfig = @{} + $script:laPath = '' + + try { + $dceObject = Invoke-EntraRequest -Service Azure -Path "subscriptions/$($param.Subscription)/resourceGroups/$($param.ResourceGroup)/providers/Microsoft.Insights/dataCollectionEndpoints/$($param.DceName)" -Query @{ + 'api-version' = '2024-03-11' + } + } + catch { throw "Failed to resolve Data Collection Endpoint $($param.DceName): $_`nPath: subscriptions/$($param.Subscription)/resourceGroups/$($param.ResourceGroup)/providers/Microsoft.Insights/dataCollectionEndpoints/$($param.DceName)" } + + try { + $dcrObject = Invoke-EntraRequest -Service Azure -Path "subscriptions/$($param.Subscription)/resourceGroups/$($param.ResourceGroup)/providers/Microsoft.Insights/dataCollectionRules/$($param.DcrName)" -Query @{ + 'api-version' = '2024-03-11' + } + } + catch { throw "Failed to resolve Data Collection Rule $($param.DcrName): $_`nPath: subscriptions/$($param.Subscription)/resourceGroups/$($param.ResourceGroup)/providers/Microsoft.Insights/dataCollectionRules/$($param.DcrName)" } + + $streamName = $null + if ($param.Stream) { $streamName = $param.Stream } + else { + $streams = $dcrObject.properties.dataFlows.streams | Sort-Object -Unique + if (@($streams).Count -eq 1) { + $streamName = $($streams) + } + elseif ($param.Table -and @($streams | Where-Object { $_ -match $param.Table }).Count -eq 1) { + $streamName = $streams | Where-Object { $_ -match $param.Table } + } + } + + if (-not $streamName) { throw "Unable to resolve stream for $($param.Table) in $($param.DcrName)" } + + $script:laConfig = $param + + $script:laPath = "$($dceObject.properties.logsIngestion.endpoint)/dataCollectionRules/$($dcrObject.properties.ImmutableId)/streams/$streamName" + } + + function Write-LAMessage { + [CmdletBinding()] + param ( + [PSFramework.Message.LogEntry] + $Message, + + [int] + $BatchSize, + + [System.Collections.ArrayList] + $Messages, + + [switch] + $Flush + ) + + # If we failed to calculate the path to push log analytics data, no point in attempting to do so + # The failed Start phase handles the error logging, no point flooding it with extra-messages to muddle the water. + if (-not $script:laPath) { + return + } + + if ($null -ne $Message) { $null = $Messages.Add($Message) } + if (-not $Flush -and $Messages.Count -lt $BatchSize) { + return + } + if ($Flush -and $Messages.Count -lt 1) { return } + + $payload = $Messages | Select-PSFObject -Property $script:laHeaders + $script:lastPayload = $payload + $payloadJson = ConvertTo-Json -InputObject @($payload) -Compress -Depth 3 + $Messages.Clear() + Invoke-EntraRequest -Method Post -Path $script:laPath -Token $script:eaToken -Query @{ + 'api-version' = '2023-01-01' + } -ContentType 'application/json' -Body $payloadJson -Header @{ charset = 'utf-8' } + } +} +#endregion Functions +#region Main Events +$begin_event = { + $modulePath = Join-Path -Path ([PSFramework.PSFCore.PSFCoreHost]::ModuleRoot) -ChildPath 'modules/EntraAuth/*/EntraAuth.psd1' + Import-Module -Name (Get-Item -Path $modulePath).FullName -ErrorAction Stop + + $script:configRoot = $script:Instance.ConfigurationRoot + if ($script:Instance.Name -and $script:Instance.Name -ne 'Default') { + $script:configRoot += ".$($script:Instance.Name)" + } + + $script:eaToken = $null + $script:eaConfig = @{} + $script:laConfig = @{} + $script:laPath = '' + $script:laHeaders = @() + $script:laLastHeaders = @() + $script:eaConnectCmd = Get-Command Connect-EntraService +} +$start_event = { + trap { + throw $_ + } + $script:messages = [System.Collections.ArrayList]@() + $script:batchsize = Get-ConfigValue -Name BatchSize + if (-not $script:batchsize -or $script:batchsize -lt 1) { + $script:batchsize = 25 + } + $newHeaders = Get-ConfigValue -Name Headers + if (-not [System.Management.Automation.LanguagePrimitives]::Equals($newHeaders, $script:laLastHeaders)) { + [PSFramework.PSFCore.PSFCoreHost]::WriteDebug('Recalculating Headers', @{ New = $newHeaders; Old = $script:laLastHeaders }) + $script:laHeaders = $newHeaders | ForEach-Object { + if ($_ -is [hashtable]) { return $_ } + + if ( + $_ -notmatch '^[a-zA-Z\d]+$' -and + $_ -notmatch '^[a-zA-Z\d]+ as [a-zA-Z\d]+$' -and + $_ -notmatch '^[a-zA-Z\d]+ as [a-zA-Z\d]+ to (string|int)$' + ) { throw "Unsupported Header format: $_ | Cannot use special letters, access subproperties or invoke methods or typeconvert to anything other than string or int" } + + switch -regex ($_) { + '^Message$' { $_ -replace 'Message', 'LogMessage as Message'; break } + '^Message' { $_ -replace '^Message', 'LogMessage' } + '^Timestamp$' { 'Timestamp.ToUniversalTime().ToString("o") as Timestamp' } + '^Level$' { 'Level to String' } + '^Callstack$' { 'Callstack to String' } + default { $_ } + } + } + $script:laLastHeaders = $newHeaders + } + + Update-LAToken -ErrorAction Stop + Update-LAWorkspacePath +} +$message_event = { + param ( + $Message + ) + + Write-LAMessage -Message $Message -BatchSize $script:batchsize -Messages $script:messages +} +$end_event = { + Write-LAMessage -Flush -Messages $script:messages +} +#endregion Main Events + +# Configuration values for the logging provider +$configuration_Settings = { + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.Subscription' -Value '' -Initialize -Validation string -Description 'Mandatory. The Subscription (by its ID, not name) the Data Collection Endpoint & Rule are in. Both must be in the same Resource Group.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.ResourceGroup' -Value '' -Initialize -Validation string -Description 'Mandatory. The resource Group the Data Collection Endpoint & Rule are in. Both must be in the same Resource Group.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.DceName' -Value '' -Initialize -Validation string -Description 'Mandatory. Name of the Data Collection Endpoint determining the request url used.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.DcrName' -Value '' -Initialize -Validation string -Description 'Mandatory. Name of the Data Collection Rule to send data to.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.Stream' -Value '' -Initialize -Validation string -Description 'The specific name of the Data Stream on the Data Collection Rule to send data to. Overrides Automatic Stream selection or selection by Table name.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.Table' -Value '' -Initialize -Validation string -Description 'The name of the table in Azure Log Analytics. Optional, used as tie breaker if the Data Collection Rule has multiple dataflows / streams to select from. By default, if the DCR only has one Data Flow configured, this can be omitted.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.Headers' -Value 'Message', 'Timestamp', 'Level', 'Tags', 'Data', 'ComputerName', 'Runspace', 'UserName', 'ModuleName', 'FunctionName', 'File', 'Line', 'CallStack', 'TargetObject', 'ErrorRecord' -Initialize -Validation stringarray -Description 'The properties on the messages to push to Log Analytics table. Supports renaming by specifying properties like this: "Timestamp as Time"' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.BatchSize' -Value 25 -Initialize -Validation integerpositive -Description 'Up to how many messages are uploaded in one request. Larger improves throughput but may lead to lost requests when sending too much data.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.ClientID' -Value $null -Initialize -Validation string -Description 'Authentication Info. The Client ID of the Application to use for authentication. Defaults to the same application used for Connect-AzAccount.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.TenantID' -Value $null -Initialize -Validation string -Description 'Authentication Info. The Tenant ID of the Application to use for authentication. Defaults to the tenant of the user if in delegate mode, must be specified in Application mode, other than for MSI authentication.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.Browser' -Value $null -Initialize -Validation bool -Description 'Authentication Info. Explicitly authenticate in Delegate Authorization Code flow - will use the default browser to have you log in as yourself.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.RedirectUri' -Value $null -Initialize -Validation string -Description 'Authentication Info. Override the automatic redirect to localhost in Authorization Code flow. Usually needs not be adjusted.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.RefreshToken' -Value $null -Initialize -Validation string -Description 'Authentication Info. A refresh token (as string) to use for authenticating by reusing an existing token.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.RefreshTokenObject' -Value $null -Initialize -Description 'Authentication Info. A resfresh token (as EntraAuth token object) to use for authenticating by reusing an existing token.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.Certificate' -Value $null -Initialize -Description 'Authentication Info. A certificate (as X509Certificate2 object) to use for authenticating in application mode.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.CertificateThumbprint' -Value $null -Initialize -Validation string -Description 'Authentication Info. A certificate (selected by its thumbprint from your windows certificate stores) to use for authenticating in application mode.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.CertificateName' -Value $null -Initialize -Validation string -Description 'Authentication Info. A certificate (selected by its CN from your windows certificate stores) to use for authenticating in application mode.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.CertificatePath' -Value $null -Initialize -Validation string -Description 'Authentication Info. Path to .pfx file containing the certificate to use for authenticating in application mode. Use together with CertificatePassword' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.CertificatePassword' -Value $null -Initialize -Validation secret -Description 'Authentication Info. Password to the .pfx file containing the certificate to use for authenticating in application mode. Use together with CertificatePath' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.ClientSecret' -Value $null -Initialize -Validation secret -Description 'Authentication Info. The clientsecret to use for authenticating in application mode.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.Identity' -Value $null -Initialize -Validation bool -Description 'Authentication Info. Authenticate as the Managed Identity - System-Managed or User-Assigned. Will default to System-Managed unloss also specifying an IdentityID' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.IdentityID' -Value $null -Initialize -Validation string -Description 'Authentication Info. Id of the System-Assigned identity to use. Use together with IdentityType to determine whether it is a ClientID, PrincipalID or ResourceID.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.IdentityType' -Value $null -Initialize -Validation string -Description 'Authentication Info. Use together with IdentityID to specify whether the user-assigned identity is a ClientID, PrincipalID or ResourceID.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.FallBackAzAccount' -Value $null -Initialize -Validation bool -Description 'Authentication Info. Fallback to using the currently established AzContext from Connect-AzAccount. Intended for use with Identity & Federated flows as a local fallback when testing on your own machine.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.AsAzAccount' -Value $null -Initialize -Validation bool -Description 'Authentication Info. Reuse the connection established with Connect-AzAccount. Requires the connection having previously established.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.ShowDialog' -Value $null -Initialize -Validation string -Description 'Authentication Info. When using the AzAccount session, should the interactive UI be shown? "auto": Only when needed. "always": Show no matter what. "never": Don''t show, but will error the logging if required.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.Federated' -Value $null -Initialize -Validation bool -Description 'Authentication Info. Use Federated credentials to authenticate. Use when running on a system supporting Managed Identities but your organization requires the use of an App Registration & Enterprise Application.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.FederationProvider' -Value $null -Initialize -Validation string -Description 'Authentication Info. Which Federation Provider to use. Overrides the default autodetection.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.Assertion' -Value $null -Initialize -Validation string -Description 'Authentication Info. The credentials from the federated identity provider to use in an Federated Credentials authentication flow. Highly optional.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.Environment' -Value $null -Initialize -Validation string -Description 'Authentication Info. What environment the tenant runs in. Defaults to "Global", options: Global, USGov, USGovDOD, China.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.AuthenticationUrl' -Value $null -Initialize -Validation string -Description 'Authentication Info. The url used for the authentication requests to retrieve tokens. Generally provided by the Environment parameter, but can be overridden in case of need.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.AzureToken' -Value $null -Initialize -Description 'Authentication Info. A previously established token using Connect-EntraService to the "Azure" service, NOT a plain access token string.' + Set-PSFConfig -Module PSFramework -Name 'Logging.AzureLogAnalyticsV2.MonitorToken' -Value $null -Initialize -Description 'Authentication Info. A previously established token using Connect-EntraService to the "https://monitor.azure.com/" resource (or environment-specific alternatives), NOT a plain access token string.' +} + +# Registered parameters for the logging provider. +# ConfigurationDefaultValues are used for all instances of the azure logging provider +$paramRegisterPSFAzureLogAnalyticsProvider = @{ + Name = 'AzureLogAnalyticsV2' + Version2 = $true + Description = 'Logs to Azure Log Analytics through the Logs Ingestion API' + ConfigurationRoot = 'PSFramework.Logging.AzureLogAnalyticsV2' + InstanceProperties = 'Subscription', 'ResourceGroup', 'DceName', 'DcrName', 'Stream', 'Table', 'Headers', 'BatchSize', 'ClientID', 'TenantID', 'Browser', 'RedirectUri', 'RefreshToken', 'RefreshTokenObject', 'Certificate', 'CertificateThumbprint', 'CertificateName', 'CertificatePath', 'CertificatePassword', 'ClientSecret', 'Identity', 'IdentityID', 'IdentityType', 'FallBackAzAccount', 'AsAzAccount', 'ShowDialog', 'Federated', 'FederationProvider', 'Assertion', 'Environment', 'AuthenticationUrl', 'AzureToken', 'MonitorToken' + BeginEvent = $begin_event + StartEvent = $start_event + MessageEvent = $message_Event + EndEvent = $end_event + ConfigurationSettings = $configuration_Settings + FunctionDefinitions = $functionDefinitions + ConfigurationDefaultValues = @{ + Headers = 'Message', 'Timestamp', 'Level', 'Tags', 'Data', 'ComputerName', 'Runspace', 'UserName', 'ModuleName', 'FunctionName', 'File', 'Line', 'CallStack', 'TargetObject', 'ErrorRecord' + BatchSize = 25 + } +} + +# Register the Azure logging provider +Register-PSFLoggingProvider @paramRegisterPSFAzureLogAnalyticsProvider \ No newline at end of file diff --git a/PSFramework/internal/loggingProviders/console.provider.ps1 b/PSFramework/internal/loggingProviders/console.provider.ps1 index a155d048..b21750b3 100644 --- a/PSFramework/internal/loggingProviders/console.provider.ps1 +++ b/PSFramework/internal/loggingProviders/console.provider.ps1 @@ -3,7 +3,7 @@ $Message ) $style = Get-ConfigValue -Name Style - $string = $style.Replace('%Time%',$Message.Timestamp.ToString('HH:mm:ss.fff')).Replace('%Date%',$Message.Timestamp.ToString('yyyy-MM-dd')).Replace('%Level%', $Message.Level).Replace('%Module%', $Message.ModuleName).Replace('%FunctionName%', $Message.FunctionName).Replace('%Line%', $Message.Line).Replace('%File%', $Message.File).Replace('%Tags%', ($Message.Tags -join ",")).Replace('%Message%', $Message.LogMessage) + $string = $style.Replace('%Time%', $Message.Timestamp.ToString('HH:mm:ss.fff')).Replace('%Date%', $Message.Timestamp.ToString('yyyy-MM-dd')).Replace('%Level%', $Message.Level).Replace('%Module%', $Message.ModuleName).Replace('%FunctionName%', $Message.FunctionName).Replace('%Line%', $Message.Line).Replace('%File%', $Message.File).Replace('%Tags%', ($Message.Tags -join ',')).Replace('%Message%', $Message.LogMessage) [System.Console]::WriteLine($string) } @@ -11,12 +11,13 @@ $configuration_Settings = { Set-PSFConfig -Module 'PSFramework' -Name 'Logging.Console.Style' -Value '%Message%' -Initialize -Validation string -Description 'The style in which the message is printed. Supports several placeholders: %Message%, %Time%, %Date%, %Tags%, %Level%, %Module%, %FunctionName%, %Line%, %File%. Supports newline and tabs.' } $paramRegisterPSFLoggingProvider = @{ - Name = "console" - Version2 = $true - ConfigurationRoot = 'PSFramework.Logging.Console' - InstanceProperties = 'Style' - MessageEvent = $message_Event - ConfigurationSettings = $configuration_Settings + Name = 'console' + Description = 'Writes messages to the console screen. Intended for use in orchestration tools that report what is written to screen.' + Version2 = $true + ConfigurationRoot = 'PSFramework.Logging.Console' + InstanceProperties = 'Style' + MessageEvent = $message_Event + ConfigurationSettings = $configuration_Settings ConfigurationDefaultValues = @{ Style = '%Message%' } diff --git a/PSFramework/internal/loggingProviders/eventlog.provider.ps1 b/PSFramework/internal/loggingProviders/eventlog.provider.ps1 index a129b6c0..c616a252 100644 --- a/PSFramework/internal/loggingProviders/eventlog.provider.ps1 +++ b/PSFramework/internal/loggingProviders/eventlog.provider.ps1 @@ -36,7 +36,7 @@ $Message.Timestamp.ToUniversalTime().ToString((Get-ConfigValue -Name TimeFormat)) $Message.FunctionName $Message.ModuleName - ($Message.Tags -join ",") + ($Message.Tags -join ',') $Message.Level $Message.Runspace $Message.TargetObject @@ -139,7 +139,8 @@ $message_event = { } $paramRegisterPSFLoggingProvider = @{ - Name = "eventlog" + Name = 'eventlog' + Description = 'Sends messages to the Windows Eventlog on the local computer.' Version2 = $true ConfigurationRoot = 'PSFramework.Logging.EventLog' InstanceProperties = 'LogName', 'Source', 'UseFallback', 'Category', 'InfoID', 'WarningID', 'ErrorID', 'ErrorTag', 'TimeFormat', 'NumericTagAsID', 'TagToID' diff --git a/PSFramework/internal/loggingProviders/filesystem.provider.ps1 b/PSFramework/internal/loggingProviders/filesystem.provider.ps1 index 5e56a0c0..b2e58136 100644 --- a/PSFramework/internal/loggingProviders/filesystem.provider.ps1 +++ b/PSFramework/internal/loggingProviders/filesystem.provider.ps1 @@ -7,10 +7,9 @@ $registrationEvent = { # Action that is performed when starting the logging script (or the very first time if enabled after launching the logging script) $begin_event = { #region Helper Functions - function Clean-FileSystemErrorXml - { + function Clean-FileSystemErrorXml { [CmdletBinding()] - Param ( + param ( $Path ) @@ -20,8 +19,7 @@ $begin_event = { if (([PSFramework.Message.LogHost]::MaxErrorFileBytes) -gt $totalLength) { return } $removed = 0 - foreach ($file in $files) - { + foreach ($file in $files) { $removed += $file.Length Remove-Item -Path $file.FullName -Force -Confirm:$false @@ -29,10 +27,9 @@ $begin_event = { } } - function Clean-FileSystemMessageLog - { + function Clean-FileSystemMessageLog { [CmdletBinding()] - Param ( + param ( $Path ) @@ -42,8 +39,7 @@ $begin_event = { if (([PSFramework.Message.LogHost]::MaxMessagefileCount) -ge $files.Count) { return } $removed = 0 - foreach ($file in $files) - { + foreach ($file in $files) { $removed++ Remove-Item -Path $file.FullName -Force -Confirm:$false @@ -51,10 +47,9 @@ $begin_event = { } } - function Clean-FileSystemGlobalLog - { + function Clean-FileSystemGlobalLog { [CmdletBinding()] - Param ( + param ( $Path ) @@ -69,8 +64,7 @@ $begin_event = { if (([PSFramework.Message.LogHost]::MaxTotalFolderSize) -gt $totalLength) { return } $removed = 0 - foreach ($file in $files) - { + foreach ($file in $files) { $removed += $file.Length Remove-Item -Path $file.FullName -Force -Confirm:$false @@ -80,7 +74,7 @@ $begin_event = { #endregion Helper Functions $filesystem_SelectTargetObject = @{ - Name = 'TargetObject' + Name = 'TargetObject' Expression = { if ($null -eq $_.TargetObject) { return } if ([PSFramework.Message.LogHost]::FileSystemSerializationDepth -lt 0) { return $_.TargetObject } @@ -89,69 +83,68 @@ $begin_event = { } } $filesystem_SelectTimestamp = @{ - Name = 'Timestamp' + Name = 'Timestamp' Expression = { $_.Timestamp.ToString([PSFramework.Message.LogHost]::TimeFormat) } } + + $filesystem_selectproperties = 'ComputerName', 'Timestamp', 'Level', 'LogMessage as Message', 'Type', 'FunctionName', 'ModuleName', 'File', 'Line', @{ n = 'Tags'; e = { $_.Tags -join ',' } }, $filesystem_SelectTargetObject, 'Runspace' + if ([PSFramework.Message.LogHost]::FileSystemModernLog) { + $filesystem_selectproperties = 'ComputerName', 'Username', $filesystem_SelectTimestamp, 'Level', 'LogMessage as Message', 'Type', 'FunctionName', 'ModuleName', 'File', 'Line', @{ n = 'Tags'; e = { $_.Tags -join ',' } }, $filesystem_SelectTargetObject, 'Runspace', @{ n = 'Callstack'; e = { $_.CallStack.ToString().Split("`n") -join ' þ ' } } + } + $filesystem_Selecter = { Select-PSFObject -Property $filesystem_selectproperties }.GetSteppablePipeline() + $filesystem_Selecter.Begin($true) + + $filesystem_oldRootPath = $null + $filesystem_writer = New-Object PSFramework.Logging.FileSystemWriter } # Action that is performed at the beginning of each logging cycle $start_event = { $filesystem_path = [PSFramework.Message.LogHost]::LoggingPath - if (-not (Test-Path $filesystem_path)) - { - $filesystem_root = New-Item $filesystem_path -ItemType Directory -Force -ErrorAction Stop + if ($filesystem_oldRootPath -ne $filesystem_path) { + if (-not (Test-Path $filesystem_path)) { + $filesystem_root = New-Item $filesystem_path -ItemType Directory -Force -ErrorAction Stop + } + else { $filesystem_root = Get-Item -Path $filesystem_path } + + try { [int]$filesystem_num_Error = (Get-ChildItem -Path $filesystem_root.FullName -Filter "$($env:ComputerName)_$($pid)_error_*.xml" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 -ExpandProperty Name | Select-String -Pattern '(\d+)' -AllMatches).Matches[-1].Value } + catch { } + try { [int]$filesystem_num_Message = (Get-ChildItem -Path $filesystem_root.FullName -Filter "$($env:ComputerName)_$($pid)_message_*.log" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 -ExpandProperty Name | Select-String -Pattern '(\d+)' -AllMatches).Matches[-1].Value } + catch { } + if (-not ($filesystem_num_Error)) { $filesystem_num_Error = 0 } + if (-not ($filesystem_num_Message)) { $filesystem_num_Message = 0 } + $filesystem_CurrentFile = Join-Path $filesystem_root.FullName "$($env:ComputerName)_$($pid)_message_$($filesystem_num_Message).log" + $filesystem_writer.Path = $filesystem_CurrentFile + $filesystem_oldRootPath = $filesystem_path } - else { $filesystem_root = Get-Item -Path $filesystem_path } - - try { [int]$filesystem_num_Error = (Get-ChildItem -Path $filesystem_root.FullName -Filter "$($env:ComputerName)_$($pid)_error_*.xml" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 -ExpandProperty Name | Select-String -Pattern "(\d+)" -AllMatches).Matches[-1].Value } - catch { } - try { [int]$filesystem_num_Message = (Get-ChildItem -Path $filesystem_root.FullName -Filter "$($env:ComputerName)_$($pid)_message_*.log" | Sort-Object LastWriteTime -Descending | Select-Object -First 1 -ExpandProperty Name | Select-String -Pattern "(\d+)" -AllMatches).Matches[-1].Value } - catch { } - if (-not ($filesystem_num_Error)) { $filesystem_num_Error = 0 } - if (-not ($filesystem_num_Message)) { $filesystem_num_Message = 0 } } # Action that is performed for each message item that is being logged $message_Event = { - Param ( + param ( $Message ) + + if (-not $Message) { return } - $filesystem_CurrentFile = Join-Path $filesystem_root.FullName "$($env:ComputerName)_$($pid)_message_$($filesystem_num_Message).log" - if (Test-Path $filesystem_CurrentFile) - { - $filesystem_item = Get-Item $filesystem_CurrentFile - if ($filesystem_item.Length -gt ([PSFramework.Message.LogHost]::MaxMessagefileBytes)) - { - $filesystem_num_Message++ - $filesystem_CurrentFile = Join-Path $($filesystem_root.FullName) "$($env:ComputerName)_$($pid)_message_$($filesystem_num_Message).log" - } - } - - if ($Message) - { - if ([PSFramework.Message.LogHost]::FileSystemModernLog) - { - if (-not (Test-Path $filesystem_CurrentFile)) - { - $Message | Select-PSFObject ComputerName, Username, $filesystem_SelectTimestamp, Level, 'LogMessage as Message', Type, FunctionName, ModuleName, File, Line, @{ n = "Tags"; e = { $_.Tags -join "," } }, $filesystem_SelectTargetObject, Runspace, @{ n = "Callstack"; e = { $_.CallStack.ToString().Split("`n") -join " þ "} } | Export-Csv -Path $filesystem_CurrentFile -NoTypeInformation - } - else { Add-Content -Path $filesystem_CurrentFile -Value (ConvertTo-Csv ($Message | Select-PSFObject ComputerName, Username, $filesystem_SelectTimestamp, Level, 'LogMessage as Message', Type, FunctionName, ModuleName, File, Line, @{ n = "Tags"; e = { $_.Tags -join "," } }, $filesystem_SelectTargetObject, Runspace, @{ n = "Callstack"; e = { $_.CallStack.ToString().Split("`n") -join " þ " } }) -NoTypeInformation)[1] } - } - else { Add-Content -Path $filesystem_CurrentFile -Value (ConvertTo-Csv ($Message | Select-PSFObject ComputerName, Timestamp, Level, 'LogMessage as Message', Type, FunctionName, ModuleName, File, Line, @{ n = "Tags"; e = { $_.Tags -join "," } }, $filesystem_SelectTargetObject, Runspace) -NoTypeInformation)[1] } + if ($filesystem_writer.Size -gt ([PSFramework.Message.LogHost]::MaxMessagefileBytes)) { + $filesystem_num_Message++ + $filesystem_CurrentFile = Join-Path $($filesystem_root.FullName) "$($env:ComputerName)_$($pid)_message_$($filesystem_num_Message).log" + $filesystem_writer.Path = $filesystem_CurrentFile } + + $filesystem_writer.WriteObject($filesystem_Selecter.Process($Message)[0]) } # Action that is performed for each error item that is being logged $error_Event = { - Param ( + param ( $ErrorItem ) - if ($ErrorItem) - { + if ($ErrorItem) { $ErrorItem | Export-Clixml -Path (Join-Path $filesystem_root.FullName "$($env:ComputerName)_$($pid)_error_$($filesystem_num_Error).xml") -Depth 3 $filesystem_num_Error++ } @@ -167,43 +160,41 @@ $end_event = { # Action that is performed when stopping the logging script $final_event = { - + $filesystem_Selecter.End() + if ($filesystem_writer) { $filesystem_writer.End() } } #endregion Logging Execution #region Function Extension / Integration # Script that generates the necessary dynamic parameter for Set-PSFLoggingProvider $configurationParameters = { - $configroot = "PSFramework.Logging.FileSystem" + $configroot = 'PSFramework.Logging.FileSystem' $configurations = Get-PSFConfig -FullName "$configroot.*" $RuntimeParamDic = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary - foreach ($config in $configurations) - { + foreach ($config in $configurations) { $ParamAttrib = New-Object System.Management.Automation.ParameterAttribute $ParamAttrib.ParameterSetName = '__AllParameterSets' $AttribColl = New-Object System.Collections.ObjectModel.Collection[System.Attribute] $AttribColl.Add($ParamAttrib) - $RuntimeParam = New-Object System.Management.Automation.RuntimeDefinedParameter(($config.FullName.Replace($configroot, "").Trim(".")), $config.Value.GetType(), $AttribColl) + $RuntimeParam = New-Object System.Management.Automation.RuntimeDefinedParameter(($config.FullName.Replace($configroot, '').Trim('.')), $config.Value.GetType(), $AttribColl) - $RuntimeParamDic.Add(($config.FullName.Replace($configroot, "").Trim(".")), $RuntimeParam) + $RuntimeParamDic.Add(($config.FullName.Replace($configroot, '').Trim('.')), $RuntimeParam) } return $RuntimeParamDic } # Script that is executes when configuring the provider using Set-PSFLoggingProvider $configurationScript = { - $configroot = "PSFramework.Logging.FileSystem" + $configroot = 'PSFramework.Logging.FileSystem' $configurations = Get-PSFConfig -FullName "$configroot.*" - foreach ($config in $configurations) - { - if ($PSBoundParameters.ContainsKey(($config.FullName.Replace($configroot, "").Trim(".")))) - { - Set-PSFConfig -Module $config.Module -Name $config.Name -Value $PSBoundParameters[($config.FullName.Replace($configroot, "").Trim("."))] + foreach ($config in $configurations) { + if ($PSBoundParameters.ContainsKey(($config.FullName.Replace($configroot, '').Trim('.')))) { + Set-PSFConfig -Module $config.Module -Name $config.Name -Value $PSBoundParameters[($config.FullName.Replace($configroot, '').Trim('.'))] } } } @@ -226,40 +217,41 @@ $installationScript = { # Configuration settings to initialize $configuration_Settings = { - Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.MaxMessagefileBytes' -Value 5MB -Initialize -Validation "long" -Handler { [PSFramework.Message.LogHost]::MaxMessagefileBytes = $args[0] } -Description "The maximum size of a given logfile. When reaching this limit, the file will be abandoned and a new log created. Set to 0 to not limit the size. This setting is on a per-Process basis. Runspaces share, jobs or other consoles counted separately." - Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.MaxMessagefileCount' -Value 5 -Initialize -Validation "integerpositive" -Handler { [PSFramework.Message.LogHost]::MaxMessagefileCount = $args[0] } -Description "The maximum number of logfiles maintained at a time. Exceeding this number will cause the oldest to be culled. Set to 0 to disable the limit. This setting is on a per-Process basis. Runspaces share, jobs or other consoles counted separately." - Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.MaxErrorFileBytes' -Value 20MB -Initialize -Validation "long" -Handler { [PSFramework.Message.LogHost]::MaxErrorFileBytes = $args[0] } -Description "The maximum size all error files combined may have. When this number is exceeded, the oldest entry is culled. This setting is on a per-Process basis. Runspaces share, jobs or other consoles counted separately." - Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.MaxTotalFolderSize' -Value 100MB -Initialize -Validation "long" -Handler { [PSFramework.Message.LogHost]::MaxTotalFolderSize = $args[0] } -Description "This is the upper limit of length all items in the log folder may have combined across all processes." - Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.MaxLogFileAge' -Value (New-TimeSpan -Days 7) -Initialize -Validation "timespan" -Handler { [PSFramework.Message.LogHost]::MaxLogFileAge = $args[0] } -Description "Any logfile older than this will automatically be cleansed. This setting is global." - Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.MessageLogFileEnabled' -Value $true -Initialize -Validation "bool" -Handler { [PSFramework.Message.LogHost]::MessageLogFileEnabled = $args[0] } -Description "Governs, whether a log file for the system messages is written. This setting is on a per-Process basis. Runspaces share, jobs or other consoles counted separately." - Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.ErrorLogFileEnabled' -Value $true -Initialize -Validation "bool" -Handler { [PSFramework.Message.LogHost]::ErrorLogFileEnabled = $args[0] } -Description "Governs, whether log files for errors are written. This setting is on a per-Process basis. Runspaces share, jobs or other consoles counted separately." - Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.ModernLog' -Value $false -Initialize -Validation "bool" -Handler { [PSFramework.Message.LogHost]::FileSystemModernLog = $args[0] } -Description "Enables the modern, more powereful version of the filesystem log, including headers and extra columns" - Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.LogPath' -Value $script:path_Logging -Initialize -Validation "string" -Handler { [PSFramework.Message.LogHost]::LoggingPath = $args[0] } -Description "The path where the PSFramework writes all its logs and debugging information." - Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.TimeFormat' -Value "$([System.Globalization.CultureInfo]::CurrentUICulture.DateTimeFormat.ShortDatePattern) $([System.Globalization.CultureInfo]::CurrentUICulture.DateTimeFormat.LongTimePattern)" -Initialize -Validation string -Handler { [PSFramework.Message.LogHost]::TimeFormat = $args[0] } -Description "The format used for timestamps in the logfile" - Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.TargetSerializationDepth' -Value -1 -Initialize -Validation "integer" -Handler { [PSFramework.Message.LogHost]::FileSystemSerializationDepth = $args[0] } -Description "Whether the target object should be stored as a serialized object. 0 or less will see it logged as string, 1 or greater will see it logged as compressed CLIXML." + Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.MaxMessagefileBytes' -Value 5MB -Initialize -Validation 'long' -Handler { [PSFramework.Message.LogHost]::MaxMessagefileBytes = $args[0] } -Description 'The maximum size of a given logfile. When reaching this limit, the file will be abandoned and a new log created. Set to 0 to not limit the size. This setting is on a per-Process basis. Runspaces share, jobs or other consoles counted separately.' + Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.MaxMessagefileCount' -Value 5 -Initialize -Validation 'integerpositive' -Handler { [PSFramework.Message.LogHost]::MaxMessagefileCount = $args[0] } -Description 'The maximum number of logfiles maintained at a time. Exceeding this number will cause the oldest to be culled. Set to 0 to disable the limit. This setting is on a per-Process basis. Runspaces share, jobs or other consoles counted separately.' + Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.MaxErrorFileBytes' -Value 20MB -Initialize -Validation 'long' -Handler { [PSFramework.Message.LogHost]::MaxErrorFileBytes = $args[0] } -Description 'The maximum size all error files combined may have. When this number is exceeded, the oldest entry is culled. This setting is on a per-Process basis. Runspaces share, jobs or other consoles counted separately.' + Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.MaxTotalFolderSize' -Value 100MB -Initialize -Validation 'long' -Handler { [PSFramework.Message.LogHost]::MaxTotalFolderSize = $args[0] } -Description 'This is the upper limit of length all items in the log folder may have combined across all processes.' + Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.MaxLogFileAge' -Value (New-TimeSpan -Days 7) -Initialize -Validation 'timespan' -Handler { [PSFramework.Message.LogHost]::MaxLogFileAge = $args[0] } -Description 'Any logfile older than this will automatically be cleansed. This setting is global.' + Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.MessageLogFileEnabled' -Value $true -Initialize -Validation 'bool' -Handler { [PSFramework.Message.LogHost]::MessageLogFileEnabled = $args[0] } -Description 'Governs, whether a log file for the system messages is written. This setting is on a per-Process basis. Runspaces share, jobs or other consoles counted separately.' + Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.ErrorLogFileEnabled' -Value $true -Initialize -Validation 'bool' -Handler { [PSFramework.Message.LogHost]::ErrorLogFileEnabled = $args[0] } -Description 'Governs, whether log files for errors are written. This setting is on a per-Process basis. Runspaces share, jobs or other consoles counted separately.' + Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.ModernLog' -Value $false -Initialize -Validation 'bool' -Handler { [PSFramework.Message.LogHost]::FileSystemModernLog = $args[0] } -Description 'Enables the modern, more powereful version of the filesystem log, including headers and extra columns' + Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.LogPath' -Value $script:path_Logging -Initialize -Validation 'string' -Handler { [PSFramework.Message.LogHost]::LoggingPath = $args[0] } -Description 'The path where the PSFramework writes all its logs and debugging information.' + Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.TimeFormat' -Value "$([System.Globalization.CultureInfo]::CurrentUICulture.DateTimeFormat.ShortDatePattern) $([System.Globalization.CultureInfo]::CurrentUICulture.DateTimeFormat.LongTimePattern)" -Initialize -Validation string -Handler { [PSFramework.Message.LogHost]::TimeFormat = $args[0] } -Description 'The format used for timestamps in the logfile' + Set-PSFConfig -Module PSFramework -Name 'Logging.FileSystem.TargetSerializationDepth' -Value -1 -Initialize -Validation 'integer' -Handler { [PSFramework.Message.LogHost]::FileSystemSerializationDepth = $args[0] } -Description 'Whether the target object should be stored as a serialized object. 0 or less will see it logged as string, 1 or greater will see it logged as compressed CLIXML.' - Set-PSFConfig -Module LoggingProvider -Name 'FileSystem.Enabled' -Value $true -Initialize -Validation "bool" -Handler { if ([PSFramework.Logging.ProviderHost]::Providers['filesystem']) { [PSFramework.Logging.ProviderHost]::Providers['filesystem'].Enabled = $args[0] } } -Description "Whether the logging provider should be enabled on registration" - Set-PSFConfig -Module LoggingProvider -Name 'FileSystem.AutoInstall' -Value $false -Initialize -Validation "bool" -Handler { } -Description "Whether the logging provider should be installed on registration" - Set-PSFConfig -Module LoggingProvider -Name 'FileSystem.InstallOptional' -Value $true -Initialize -Validation "bool" -Handler { } -Description "Whether installing the logging provider is mandatory, in order for it to be enabled" - Set-PSFConfig -Module LoggingProvider -Name 'FileSystem.IncludeModules' -Value @() -Initialize -Validation "stringarray" -Handler { if ([PSFramework.Logging.ProviderHost]::Providers['filesystem']) { [PSFramework.Logging.ProviderHost]::Providers['filesystem'].IncludeModules = ($args[0] | Write-Output) } } -Description "Module whitelist. Only messages from listed modules will be logged" - Set-PSFConfig -Module LoggingProvider -Name 'FileSystem.ExcludeModules' -Value @() -Initialize -Validation "stringarray" -Handler { if ([PSFramework.Logging.ProviderHost]::Providers['filesystem']) { [PSFramework.Logging.ProviderHost]::Providers['filesystem'].ExcludeModules = ($args[0] | Write-Output) } } -Description "Module blacklist. Messages from listed modules will not be logged" - Set-PSFConfig -Module LoggingProvider -Name 'FileSystem.IncludeTags' -Value @() -Initialize -Validation "stringarray" -Handler { if ([PSFramework.Logging.ProviderHost]::Providers['filesystem']) { [PSFramework.Logging.ProviderHost]::Providers['filesystem'].IncludeTags = ($args[0] | Write-Output) } } -Description "Tag whitelist. Only messages with these tags will be logged" - Set-PSFConfig -Module LoggingProvider -Name 'FileSystem.ExcludeTags' -Value @() -Initialize -Validation "stringarray" -Handler { if ([PSFramework.Logging.ProviderHost]::Providers['filesystem']) { [PSFramework.Logging.ProviderHost]::Providers['filesystem'].ExcludeTags = ($args[0] | Write-Output) } } -Description "Tag blacklist. Messages with these tags will not be logged" + Set-PSFConfig -Module LoggingProvider -Name 'FileSystem.Enabled' -Value $true -Initialize -Validation 'bool' -Handler { if ([PSFramework.Logging.ProviderHost]::Providers['filesystem']) { [PSFramework.Logging.ProviderHost]::Providers['filesystem'].Enabled = $args[0] } } -Description 'Whether the logging provider should be enabled on registration' + Set-PSFConfig -Module LoggingProvider -Name 'FileSystem.AutoInstall' -Value $false -Initialize -Validation 'bool' -Handler { } -Description 'Whether the logging provider should be installed on registration' + Set-PSFConfig -Module LoggingProvider -Name 'FileSystem.InstallOptional' -Value $true -Initialize -Validation 'bool' -Handler { } -Description 'Whether installing the logging provider is mandatory, in order for it to be enabled' + Set-PSFConfig -Module LoggingProvider -Name 'FileSystem.IncludeModules' -Value @() -Initialize -Validation 'stringarray' -Handler { if ([PSFramework.Logging.ProviderHost]::Providers['filesystem']) { [PSFramework.Logging.ProviderHost]::Providers['filesystem'].IncludeModules = ($args[0] | Write-Output) } } -Description 'Module whitelist. Only messages from listed modules will be logged' + Set-PSFConfig -Module LoggingProvider -Name 'FileSystem.ExcludeModules' -Value @() -Initialize -Validation 'stringarray' -Handler { if ([PSFramework.Logging.ProviderHost]::Providers['filesystem']) { [PSFramework.Logging.ProviderHost]::Providers['filesystem'].ExcludeModules = ($args[0] | Write-Output) } } -Description 'Module blacklist. Messages from listed modules will not be logged' + Set-PSFConfig -Module LoggingProvider -Name 'FileSystem.IncludeTags' -Value @() -Initialize -Validation 'stringarray' -Handler { if ([PSFramework.Logging.ProviderHost]::Providers['filesystem']) { [PSFramework.Logging.ProviderHost]::Providers['filesystem'].IncludeTags = ($args[0] | Write-Output) } } -Description 'Tag whitelist. Only messages with these tags will be logged' + Set-PSFConfig -Module LoggingProvider -Name 'FileSystem.ExcludeTags' -Value @() -Initialize -Validation 'stringarray' -Handler { if ([PSFramework.Logging.ProviderHost]::Providers['filesystem']) { [PSFramework.Logging.ProviderHost]::Providers['filesystem'].ExcludeTags = ($args[0] | Write-Output) } } -Description 'Tag blacklist. Messages with these tags will not be logged' } $paramRegisterPSFLoggingProvider = @{ - Name = "filesystem" - RegistrationEvent = $registrationEvent - BeginEvent = $begin_event - StartEvent = $start_event - MessageEvent = $message_Event - ErrorEvent = $error_Event - EndEvent = $end_event - FinalEvent = $final_event + Name = 'filesystem' + Description = 'The default debuglog, enabled by default.' + RegistrationEvent = $registrationEvent + BeginEvent = $begin_event + StartEvent = $start_event + MessageEvent = $message_Event + ErrorEvent = $error_Event + EndEvent = $end_event + FinalEvent = $final_event ConfigurationParameters = $configurationParameters - ConfigurationScript = $configurationScript - IsInstalledScript = $isInstalledScript - InstallationScript = $installationScript + ConfigurationScript = $configurationScript + IsInstalledScript = $isInstalledScript + InstallationScript = $installationScript InstallationParameters = $installationParameters ConfigurationSettings = $configuration_Settings } diff --git a/PSFramework/internal/loggingProviders/gelf.provider.ps1 b/PSFramework/internal/loggingProviders/gelf.provider.ps1 index 821a2e93..3d0a4ea3 100644 --- a/PSFramework/internal/loggingProviders/gelf.provider.ps1 +++ b/PSFramework/internal/loggingProviders/gelf.provider.ps1 @@ -3,7 +3,7 @@ $start_event = { $script:paramSendPsgelfTcp = @{ 'GelfServer' = Get-ConfigValue -Name 'GelfServer' - 'Port' = Get-ConfigValue -Name 'Port' + 'Port' = Get-ConfigValue -Name 'Port' 'Encrypt' = Get-ConfigValue -Name 'Encrypt' } } @@ -19,8 +19,7 @@ $message_Event = { $gelf_params['HostName'] = $Message.ComputerName $gelf_params['DateTime'] = $Message.Timestamp - $gelf_params['Level'] = switch ($Message.Level) - { + $gelf_params['Level'] = switch ($Message.Level) { 'Critical' { 1 } 'Important' { 1 } 'Output' { 3 } @@ -34,8 +33,7 @@ $message_Event = { default { 7 } } - if ($Message.ErrorRecord) - { + if ($Message.ErrorRecord) { $gelf_params['FullMessage'] = $Message.ErrorRecord | ConvertTo-Json } @@ -45,8 +43,7 @@ $message_Event = { } $gelf_params['AdditionalField'] = @{ } - foreach ($gelf_property in $gelf_properties) - { + foreach ($gelf_property in $gelf_properties) { $gelf_params['AdditionalField'][$gelf_property.Name] = $gelf_property.Value } @@ -65,12 +62,12 @@ $installationParameters = { $validateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute('CurrentUser', 'AllUsers') $attributesCollection.Add($validateSetAttribute) - $runtimeParam = New-Object System.Management.Automation.RuntimeDefinedParameter("Scope", [string], $attributesCollection) - $results.Add("Scope", $runtimeParam) + $runtimeParam = New-Object System.Management.Automation.RuntimeDefinedParameter('Scope', [string], $attributesCollection) + $results.Add('Scope', $runtimeParam) $attributesCollection2 = New-Object System.Collections.ObjectModel.Collection[System.Attribute] - $runtimeParam2 = New-Object System.Management.Automation.RuntimeDefinedParameter("Repository", [string], $attributesCollection2) - $results.Add("Repository", $runtimeParam2) + $runtimeParam2 = New-Object System.Management.Automation.RuntimeDefinedParameter('Repository', [string], $attributesCollection2) + $results.Add('Repository', $runtimeParam2) $results } @@ -97,22 +94,23 @@ $isInstalled_script = { # Configuration settings to initialize $configuration_Settings = { - Set-PSFConfig -Module PSFramework -Name 'Logging.GELF.GelfServer' -Value "" -Initialize -Validation string -Description "The GELF server to send logs to" - Set-PSFConfig -Module PSFramework -Name 'Logging.GELF.Port' -Value "" -Initialize -Validation string -Description "The port number the GELF server listens on" - Set-PSFConfig -Module PSFramework -Name 'Logging.GELF.Encrypt' -Value $true -Initialize -Validation bool -Description "Whether to use TLS encryption when communicating with the GELF server" + Set-PSFConfig -Module PSFramework -Name 'Logging.GELF.GelfServer' -Value '' -Initialize -Validation string -Description 'The GELF server to send logs to' + Set-PSFConfig -Module PSFramework -Name 'Logging.GELF.Port' -Value '' -Initialize -Validation string -Description 'The port number the GELF server listens on' + Set-PSFConfig -Module PSFramework -Name 'Logging.GELF.Encrypt' -Value $true -Initialize -Validation bool -Description 'Whether to use TLS encryption when communicating with the GELF server' } $paramRegisterPSFLoggingProvider = @{ - Name = "gelf" - Version2 = $true - ConfigurationRoot = 'PSFramework.Logging.GELF' - InstanceProperties = 'GelfServer', 'Port', 'Encrypt' - StartEvent = $start_event - MessageEvent = $message_Event - IsInstalledScript = $isInstalled_script - InstallationScript = $installation_script - InstallationParameters = $installationParameters - ConfigurationSettings = $configuration_Settings + Name = 'gelf' + Description = 'Log to a Graylog server' + Version2 = $true + ConfigurationRoot = 'PSFramework.Logging.GELF' + InstanceProperties = 'GelfServer', 'Port', 'Encrypt' + StartEvent = $start_event + MessageEvent = $message_Event + IsInstalledScript = $isInstalled_script + InstallationScript = $installation_script + InstallationParameters = $installationParameters + ConfigurationSettings = $configuration_Settings ConfigurationDefaultValues = @{ Encrypt = $true } diff --git a/PSFramework/internal/loggingProviders/logfile.provider.ps1 b/PSFramework/internal/loggingProviders/logfile.provider.ps1 index 9acbb4e0..1dc4eff8 100644 --- a/PSFramework/internal/loggingProviders/logfile.provider.ps1 +++ b/PSFramework/internal/loggingProviders/logfile.provider.ps1 @@ -68,7 +68,7 @@ #region Type-Based Output switch ($FileType) { #region Csv - "Csv" { + 'Csv' { if (-not $CsvDelimiter) { $CsvDelimiter = ',' } @@ -92,7 +92,7 @@ } #endregion Csv #region Json - "Json" { + 'Json' { if (-not $script:JsonSettings.JsonString) { $data = $Message | ConvertTo-Json -Compress:$script:JsonSettings.JsonCompress } else { $data = $Message | ConvertFrom-Enumeration | ConvertTo-Json -Compress:$script:JsonSettings.JsonCompress } @@ -101,20 +101,20 @@ } else { if (-not $script:firstEntry -or (-not $script:JsonSettings.JsonNoEmptyFirstLine)) { - $script:writer.WriteLine(",") + $script:writer.WriteLine(',') } $script:writer.Write($data) } } #endregion Json #region XML - "XML" { + 'XML' { [xml]$xml = $message | ConvertTo-Xml -NoTypeInformation $script:writer.WriteLine($xml.Objects.InnerXml) } #endregion XML #region Html - "Html" { + 'Html' { [xml]$xml = $message | ConvertTo-Html -Fragment if ($script:firstEntry -and $IncludeHeader) { @@ -124,14 +124,14 @@ } #endregion Html #region CMTrace - "CMTrace" { + 'CMTrace' { $cType = 1 if ($MessageItem.Level -eq 'Warning') { $cType = 2 } if ($MessageItem.ErrorRecord) { $cType = 3 } $fileEntry = '' if ($MessageItem.File) { $fileEntry = Split-Path -Path $MessageItem.File -Leaf } - $component = "{0}:{1} > {2}" -f $fileEntry, $MessageItem.Line, $MessageItem.FunctionName + $component = '{0}:{1} > {2}' -f $fileEntry, $MessageItem.Line, $MessageItem.FunctionName if ($script:cmTraceSettings.CMTraceOverrideComponent -and $MessageItem.Data.Component) { $component = $MessageItem.Data.Component } @@ -189,7 +189,7 @@ #endregion Resolve Paths $minimumRetention = (Get-ConfigValue -Name 'LogRetentionTime') -as [PSFTimeSpan] -as [Timespan] - if (-not $minimumRetention) { throw "No minimum retention defined" } + if (-not $minimumRetention) { throw 'No minimum retention defined' } if ($minimumRetention.TotalSeconds -le 0) { throw "Minimum retention must be positive! Retention: $minimumRetention" } # Don't logrotate more than every 5 minutes @@ -300,7 +300,7 @@ $start_event = { 'Tags' { @{ Name = 'Tags' - Expression = { $_.Tags -join "," } + Expression = { $_.Tags -join ',' } } } 'Message' { @@ -326,13 +326,13 @@ $start_event = { } 'DataCompact' { @{ - Name = "DataCompact" + Name = 'DataCompact' Expression = { if (-not $_.Data) { return } $lines = foreach ($pair in $_.Data.GetEnumerator()) { '{0}={1}' -f $pair.Key, $pair.Value } - $lines -join ", " + $lines -join ', ' } } } @@ -341,7 +341,7 @@ $start_event = { $code = switch ($value) { Tags { - { $_.Tags -join "," } + { $_.Tags -join ',' } } Message { { $_.LogMessage } @@ -364,7 +364,7 @@ $start_event = { $lines = foreach ($pair in $_.Data.GetEnumerator()) { '{0}={1}' -f $pair.Key, $pair.Value } - $lines -join ", " + $lines -join ', ' } } default { [ScriptBlock]::Create("`$_.$value") } @@ -467,32 +467,33 @@ $final_event = { #endregion Events $configuration_Settings = { - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.FilePath' -Value "" -Initialize -Validation string -Description "The path to where the logfile is written. Supports some placeholders such as %Date% to allow for timestamp in the name. For full documentation on the supported wildcards, see the documentation on https://psframework.org" - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.Logname' -Value "" -Initialize -Validation string -Description "A special string you can use as a placeholder in the logfile path (by using '%logname%' as placeholder)" - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.IncludeHeader' -Value $true -Initialize -Validation bool -Description "Whether a written csv file will include headers" - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.Headers' -Value @('ComputerName', 'File', 'FunctionName', 'Level', 'Line', 'Message', 'ModuleName', 'Runspace', 'Tags', 'TargetObject', 'Timestamp', 'Type', 'Username') -Initialize -Validation stringarray -Description "The properties to export, in the order to select them." - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.FileType' -Value "CSV" -Initialize -Validation psframework.logfilefiletype -Description "In what format to write the logfile. Supported styles: CSV, XML, Html, Json, TXT or CMTrace. Html, XML and Json will be written as fragments." - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.CsvDelimiter' -Value "," -Initialize -Validation string -Description "The delimiter to use when writing to csv." - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.TimeFormat' -Value "$([System.Globalization.CultureInfo]::CurrentUICulture.DateTimeFormat.ShortDatePattern) $([System.Globalization.CultureInfo]::CurrentUICulture.DateTimeFormat.LongTimePattern)" -Initialize -Validation string -Description "The format used for timestamps in the logfile" - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.Encoding' -Value "UTF8" -Initialize -Validation string -Description "In what encoding to write the logfile." - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.UTC' -Value $false -Initialize -Validation bool -Description "Whether the timestamp in the logfile should be converted to UTC" - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.LogRotatePath' -Value "" -Initialize -Validation string -Description "The path where to logrotate. Specifying this setting will cause the logging provider to also rotate older logfiles" - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.LogRetentionTime' -Value "30d" -Initialize -Validation timespan -Description "The minimum age for a logfile to be considered for deletion as part of logrotation" - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.LogRotateFilter' -Value "*" -Initialize -Validation string -Description "A filter to apply to all files logrotated" - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.LogRotateRecurse' -Value $false -Initialize -Validation bool -Description "Whether the logrotate aspect should recursively look for files to logrotate" - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.MutexName' -Value '' -Initialize -Validation string -Description "Name of a mutex to use. Use this to handle parallel logging into the same file from multiple processes, by picking the same name in each process." - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.JsonCompress' -Value $false -Initialize -Validation bool -Description "Will compress the json entries, condensing each entry into a single line." + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.FilePath' -Value '' -Initialize -Validation string -Description 'The path to where the logfile is written. Supports some placeholders such as %Date% to allow for timestamp in the name. For full documentation on the supported wildcards, see the documentation on https://psframework.org' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.Logname' -Value '' -Initialize -Validation string -Description "A special string you can use as a placeholder in the logfile path (by using '%logname%' as placeholder)" + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.IncludeHeader' -Value $true -Initialize -Validation bool -Description 'Whether a written csv file will include headers' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.Headers' -Value @('ComputerName', 'File', 'FunctionName', 'Level', 'Line', 'Message', 'ModuleName', 'Runspace', 'Tags', 'TargetObject', 'Timestamp', 'Type', 'Username') -Initialize -Validation stringarray -Description 'The properties to export, in the order to select them.' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.FileType' -Value 'CSV' -Initialize -Validation psframework.logfilefiletype -Description 'In what format to write the logfile. Supported styles: CSV, XML, Html, Json, TXT or CMTrace. Html, XML and Json will be written as fragments.' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.CsvDelimiter' -Value ',' -Initialize -Validation string -Description 'The delimiter to use when writing to csv.' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.TimeFormat' -Value "$([System.Globalization.CultureInfo]::CurrentUICulture.DateTimeFormat.ShortDatePattern) $([System.Globalization.CultureInfo]::CurrentUICulture.DateTimeFormat.LongTimePattern)" -Initialize -Validation string -Description 'The format used for timestamps in the logfile' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.Encoding' -Value 'UTF8' -Initialize -Validation string -Description 'In what encoding to write the logfile.' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.UTC' -Value $false -Initialize -Validation bool -Description 'Whether the timestamp in the logfile should be converted to UTC' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.LogRotatePath' -Value '' -Initialize -Validation string -Description 'The path where to logrotate. Specifying this setting will cause the logging provider to also rotate older logfiles' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.LogRetentionTime' -Value '30d' -Initialize -Validation timespan -Description 'The minimum age for a logfile to be considered for deletion as part of logrotation' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.LogRotateFilter' -Value '*' -Initialize -Validation string -Description 'A filter to apply to all files logrotated' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.LogRotateRecurse' -Value $false -Initialize -Validation bool -Description 'Whether the logrotate aspect should recursively look for files to logrotate' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.MutexName' -Value '' -Initialize -Validation string -Description 'Name of a mutex to use. Use this to handle parallel logging into the same file from multiple processes, by picking the same name in each process.' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.JsonCompress' -Value $false -Initialize -Validation bool -Description 'Will compress the json entries, condensing each entry into a single line.' Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.JsonString' -Value $false -Initialize -Validation bool -Description "Will convert all enumerated properties to string values when converting to json. This causes the level property to be 'Debug','Host', ... rather than 8,2,..." - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.JsonNoComma' -Value $false -Initialize -Validation bool -Description "Prevent adding commas between two json entries." - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.JsonNoEmptyFirstLine' -Value $false -Initialize -Validation bool -Description "Prevent the empty first line when commas have not been disabled." + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.JsonNoComma' -Value $false -Initialize -Validation bool -Description 'Prevent adding commas between two json entries.' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.JsonNoEmptyFirstLine' -Value $false -Initialize -Validation bool -Description 'Prevent the empty first line when commas have not been disabled.' Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.CMTraceOverrideComponent' -Value $false -Initialize -Validation bool -Description 'When Enabled, messages that include a "Data" hashtable with a "Component" entry will use that Entry for the log message Component element, rather than the auto-calculated one.' Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.TXTPattern' -Value '%Timestamp% [%Level%] %Message%' -Initialize -Validation string -Description 'The pattern of any given line in the TXT-based logfile. Use %PROPERTYNAME% as placeholder, e.g. "%Message%". Same properties as with the headers configuration - you need to specify both settings, if your pattern includes non-default properties such as "Data".' - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.MoveOnFinal' -Value '' -Initialize -Validation string -Description "Path to a target folder to move logfiles to when shutting down the logging provider instance. This happens automatically when PSFramework ends or the provider instance is disabled again." - Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.CopyOnFinal' -Value '' -Initialize -Validation string -Description "Path to a target folder to copy logfiles to when shutting down the logging provider instance. This happens automatically when PSFramework ends or the provider instance is disabled again." + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.MoveOnFinal' -Value '' -Initialize -Validation string -Description 'Path to a target folder to move logfiles to when shutting down the logging provider instance. This happens automatically when PSFramework ends or the provider instance is disabled again.' + Set-PSFConfig -Module PSFramework -Name 'Logging.LogFile.CopyOnFinal' -Value '' -Initialize -Validation string -Description 'Path to a target folder to copy logfiles to when shutting down the logging provider instance. This happens automatically when PSFramework ends or the provider instance is disabled again.' } $paramRegisterPSFLoggingProvider = @{ - Name = "logfile" + Name = 'logfile' + Description = 'The universal logfile provider, useful for any given logfile format' Version2 = $true ConfigurationRoot = 'PSFramework.Logging.LogFile' InstanceProperties = 'CsvDelimiter', 'FilePath', 'FileType', 'Headers', 'IncludeHeader', 'Logname', 'TimeFormat', 'Encoding', 'UTC', 'LogRotatePath', 'LogRetentionTime', 'LogRotateFilter', 'LogRotateRecurse', 'MutexName', 'JsonCompress', 'JsonString', 'JsonNoComma', 'JsonNoEmptyFirstLine', 'CMTraceOverrideComponent', 'TXTPattern', 'MoveOnFinal', 'CopyOnFinal' diff --git a/PSFramework/internal/loggingProviders/splunk.provider.ps1 b/PSFramework/internal/loggingProviders/splunk.provider.ps1 index 1df26cf2..fac9d6ea 100644 --- a/PSFramework/internal/loggingProviders/splunk.provider.ps1 +++ b/PSFramework/internal/loggingProviders/splunk.provider.ps1 @@ -1,7 +1,6 @@ $functionDefinitions = { - function Send-SplunkData - { -<# + function Send-SplunkData { + <# .SYNOPSIS Writes data to a splunk http event collector. @@ -47,8 +46,7 @@ [string] $Token ) - process - { + process { # Splunk events can have a 'time' property in epoch time. If it's not set, use current system time. $unixEpochStart = New-Object -TypeName DateTime -ArgumentList 1970, 1, 1, 0, 0, 0, ([DateTimeKind]::Utc) $unixEpochTime = [int]($Timestamp.ToUniversalTime() - $unixEpochStart).TotalSeconds @@ -57,7 +55,7 @@ $eventData = @{ event = $InputObject host = $HostName - time = $unixEpochTime + time = $unixEpochTime } if ($index = Get-ConfigValue -Name Index) { $eventData.index = $index } if ($source = Get-ConfigValue -Name Source) { $eventData.source = $source } @@ -71,8 +69,7 @@ } } - function Invoke-RestMethodCustom - { + function Invoke-RestMethodCustom { [CmdletBinding()] param ( [string] @@ -94,8 +91,7 @@ $IgnoreCert ) - process - { + process { $request = [System.Net.WebRequest]::Create($Uri) foreach ($key in $Headers.Keys) { $request.Headers[$key] = $Headers[$key] } $request.Method = $Method @@ -106,8 +102,7 @@ $requestWriter.Write($Body) $requestWriter.Close() - try - { + try { $responseStream = $request.GetResponse().GetResponseStream() $reader = New-Object System.IO.StreamReader($responseStream) $reader.ReadToEnd() @@ -117,8 +112,7 @@ } } - function Write-SplunkMessage - { + function Write-SplunkMessage { [CmdletBinding()] param ( $Message @@ -129,8 +123,7 @@ $properties = Get-ConfigValue -Name 'Properties' $name = Get-ConfigValue -Name 'LogName' - $selectProps = switch ($properties) - { + $selectProps = switch ($properties) { 'Message' { 'LogMessage as Message' } 'Timestamp' { 'Timestamp.ToUniversalTime().ToString("yyyy-MM-dd_HH:mm:ss.fff") as Timestamp' } 'Level' { 'Level to String' } @@ -164,13 +157,14 @@ $configuration_Settings = { } $paramRegisterPSFLoggingProvider = @{ - Name = "splunk" - Version2 = $true - ConfigurationRoot = 'PSFramework.Logging.Splunk' - InstanceProperties = 'Url', 'Token', 'Properties', 'LogName', 'IgnoreCert', 'Index', 'Source', 'SourceType' - MessageEvent = $message_Event - ConfigurationSettings = $configuration_Settings - FunctionDefinitions = $functionDefinitions + Name = 'splunk' + Description = 'Log to a splunk instance.' + Version2 = $true + ConfigurationRoot = 'PSFramework.Logging.Splunk' + InstanceProperties = 'Url', 'Token', 'Properties', 'LogName', 'IgnoreCert', 'Index', 'Source', 'SourceType' + MessageEvent = $message_Event + ConfigurationSettings = $configuration_Settings + FunctionDefinitions = $functionDefinitions ConfigurationDefaultValues = @{ Properties = 'Timestamp', 'Message', 'Level', 'Tags', 'FunctionName', 'ModuleName', 'Runspace', 'Username', 'ComputerName', 'TargetObject', 'Data' LogName = 'Undefined' diff --git a/PSFramework/internal/loggingProviders/sql.provider.ps1 b/PSFramework/internal/loggingProviders/sql.provider.ps1 index 03cf9477..8fa8f6b6 100644 --- a/PSFramework/internal/loggingProviders/sql.provider.ps1 +++ b/PSFramework/internal/loggingProviders/sql.provider.ps1 @@ -32,7 +32,7 @@ } function Export-DataToSql { - <# + <# .SYNOPSIS Function to send logging data to a Sql database @@ -59,11 +59,11 @@ process { $queryParameters = @{ } - foreach ($header in $script:sql_headers) { - if ($header -is [string]) { $queryParameters[$header] = $($ObjectToProcess.$header) } - elseif ($header.Name) { $queryParameters[$header.Name] = $(([PsfScriptBlock]$header.Expression).InvokeEx($false, $ObjectToProcess, $ObjectToProcess, $ObjectToProcess, $false, $false, $ObjectToProcess)) } - else { $queryParameters[$header.Label] = $(([PsfScriptBlock]$header.Expression).InvokeEx($false, $ObjectToProcess, $ObjectToProcess, $ObjectToProcess, $false, $false, $ObjectToProcess)) } - } + foreach ($header in $script:sql_headers) { + if ($header -is [string]) { $queryParameters[$header] = $($ObjectToProcess.$header) } + elseif ($header.Name) { $queryParameters[$header.Name] = $(([PsfScriptBlock]$header.Expression).InvokeEx($false, $ObjectToProcess, $ObjectToProcess, $ObjectToProcess, $false, $false, $ObjectToProcess)) } + else { $queryParameters[$header.Label] = $(([PsfScriptBlock]$header.Expression).InvokeEx($false, $ObjectToProcess, $ObjectToProcess, $ObjectToProcess, $false, $false, $ObjectToProcess)) } + } $insertQuery = Get-Query -Parameters $queryParameters try { @@ -107,7 +107,7 @@ VALUES ($($propAdd -join ',')) } function New-DefaultSqlDatabaseAndTable { - <# + <# .SYNOPSIS This function will create a default sql database object @@ -142,13 +142,13 @@ VALUES ($($propAdd -join ',')) process { try { $dbaconnection = Get-DatabaseConnection - $database = Get-DbaDatabase -SqlInstance $dbaconnection | Where-Object Name -eq $SqlDatabaseName - if (-NOT $database) { + $database = Get-DbaDatabase -SqlInstance $dbaconnection | Where-Object Name -EQ $SqlDatabaseName + if (-not $database) { $database = New-DbaDatabase -SqlInstance $dbaconnection -Name $SqlDatabaseName } - if (-NOT ($database.Tables | Where-Object Name -eq $SqlTable)) { + if (-not ($database.Tables | Where-Object Name -EQ $SqlTable)) { $createtable = "CREATE TABLE $SqlSchema.$SqlTable (Message VARCHAR(max), Level VARCHAR(max), TimeStamp [DATETIME], FunctionName VARCHAR(max), ModuleName VARCHAR(max), Tags VARCHAR(max), Runspace VARCHAR(36), ComputerName VARCHAR(max), Username VARCHAR(max), TargetObject VARCHAR(max), [File] VARCHAR(max), Line BIGINT, ErrorRecord VARCHAR(max), CallStack VARCHAR(max), [Data] VARCHAR(max))" - Invoke-dbaquery -SQLInstance $dbaconnection -Database $SqlDatabaseName -Query $createtable + Invoke-DbaQuery -SqlInstance $dbaconnection -Database $SqlDatabaseName -Query $createtable } } catch { @@ -169,12 +169,12 @@ $installationParameters = { $validateSetAttribute = New-Object System.Management.Automation.ValidateSetAttribute('CurrentUser', 'AllUsers') $attributesCollection.Add($validateSetAttribute) - $runtimeParam = New-Object System.Management.Automation.RuntimeDefinedParameter("Scope", [string], $attributesCollection) - $results.Add("Scope", $runtimeParam) + $runtimeParam = New-Object System.Management.Automation.RuntimeDefinedParameter('Scope', [string], $attributesCollection) + $results.Add('Scope', $runtimeParam) $attributesCollection2 = New-Object System.Collections.ObjectModel.Collection[System.Attribute] - $runtimeParam2 = New-Object System.Management.Automation.RuntimeDefinedParameter("Repository", [string], $attributesCollection2) - $results.Add("Repository", $runtimeParam2) + $runtimeParam2 = New-Object System.Management.Automation.RuntimeDefinedParameter('Repository', [string], $attributesCollection2) + $results.Add('Repository', $runtimeParam2) $results } @@ -230,11 +230,10 @@ $start_event = { if (-not $changePending) { return } $script:sql_headers = switch ($script:cfgHeaders) { - 'Tags' - { + 'Tags' { @{ - Name = 'Tags' - Expression = { ($_.Tags -join ",") -as [string] } + Name = 'Tags' + Expression = { ($_.Tags -join ',') -as [string] } } } 'Message' { @{ Name = 'Message'; Expression = { $_.LogMessage } } } @@ -243,19 +242,17 @@ $start_event = { 'TargetObject' { @{ Name = 'TargetObject'; Expression = { $_.TargetObject -as [string] } } } 'ErrorRecord' { @{ Name = 'ErrorRecord'; Expression = { $_.ErrorRecord -as [string] } } } 'CallStack' { @{ Name = 'CallStack'; Expression = { $_.CallStack -as [string] } } } - 'Timestamp' - { + 'Timestamp' { @{ - Name = 'Timestamp' - Expression = { + Name = 'Timestamp' + Expression = { $_.Timestamp.ToUniversalTime() } } } - 'Data' - { + 'Data' { @{ - Name = 'Data' + Name = 'Data' Expression = { if (-not $_.Data) { return 'null' } $_.Data | ConvertTo-Json -Compress @@ -288,34 +285,35 @@ $final_event = { # Configuration values for the logging provider $configuration_Settings = { - Set-PSFConfig -Module PSFramework -Name 'Logging.Sql.Credential' -Initialize -Validation 'credential' -Description "Credentials used for connecting to the SQL server." - Set-PSFConfig -Module PSFramework -Name 'Logging.Sql.Database' -Value "LoggingDatabase" -Initialize -Validation 'string' -Description "SQL server database." - Set-PSFConfig -Module PSFramework -Name 'Logging.Sql.Table' -Value "LoggingTable" -Initialize -Validation 'string' -Description "SQL server database table." - Set-PSFConfig -Module PSFramework -Name 'Logging.Sql.SqlServer' -Value "" -Initialize -Description "SQL server hosting logs." - Set-PSFConfig -Module PSFramework -Name 'Logging.Sql.Schema' -Value "dbo" -Initialize -Description "SQL server schema." - Set-PSFConfig -Module PSFramework -Name 'Logging.Sql.Headers' -Value 'Message', 'Timestamp', 'Level', 'Tags', 'Data', 'ComputerName', 'Runspace', 'UserName', 'ModuleName', 'FunctionName', 'File', 'Line', 'CallStack', 'TargetObject', 'ErrorRecord' -Initialize -Description "SQL server schema." + Set-PSFConfig -Module PSFramework -Name 'Logging.Sql.Credential' -Initialize -Validation 'credential' -Description 'Credentials used for connecting to the SQL server.' + Set-PSFConfig -Module PSFramework -Name 'Logging.Sql.Database' -Value 'LoggingDatabase' -Initialize -Validation 'string' -Description 'SQL server database.' + Set-PSFConfig -Module PSFramework -Name 'Logging.Sql.Table' -Value 'LoggingTable' -Initialize -Validation 'string' -Description 'SQL server database table.' + Set-PSFConfig -Module PSFramework -Name 'Logging.Sql.SqlServer' -Value '' -Initialize -Description 'SQL server hosting logs.' + Set-PSFConfig -Module PSFramework -Name 'Logging.Sql.Schema' -Value 'dbo' -Initialize -Description 'SQL server schema.' + Set-PSFConfig -Module PSFramework -Name 'Logging.Sql.Headers' -Value 'Message', 'Timestamp', 'Level', 'Tags', 'Data', 'ComputerName', 'Runspace', 'UserName', 'ModuleName', 'FunctionName', 'File', 'Line', 'CallStack', 'TargetObject', 'ErrorRecord' -Initialize -Description 'SQL server schema.' } # Registered parameters for the logging provider. # ConfigurationDefaultValues are used for all instances of the sql log provider $paramRegisterPSFSqlProvider = @{ - Name = "Sql" - Version2 = $true - ConfigurationRoot = 'PSFramework.Logging.Sql' - InstanceProperties = 'Database', 'Schema', 'Table', 'SqlServer', 'Credential', 'Headers' - MessageEvent = $message_Event - BeginEvent = $begin_event - StartEvent = $start_event - EndEvent = $end_event - FinalEvent = $final_event - IsInstalledScript = $isInstalled_script - InstallationScript = $installation_script - ConfigurationSettings = $configuration_Settings - InstallationParameters = $installationParameters - FunctionDefinitions = $functionDefinitions + Name = 'Sql' + Description = 'Use dbatools to log to a MS SQL Database. Creates & configures the table if needed.' + Version2 = $true + ConfigurationRoot = 'PSFramework.Logging.Sql' + InstanceProperties = 'Database', 'Schema', 'Table', 'SqlServer', 'Credential', 'Headers' + MessageEvent = $message_Event + BeginEvent = $begin_event + StartEvent = $start_event + EndEvent = $end_event + FinalEvent = $final_event + IsInstalledScript = $isInstalled_script + InstallationScript = $installation_script + ConfigurationSettings = $configuration_Settings + InstallationParameters = $installationParameters + FunctionDefinitions = $functionDefinitions ConfigurationDefaultValues = @{ - 'Database' = "LoggingDatabase" - 'Table' = "LoggingTable" + 'Database' = 'LoggingDatabase' + 'Table' = 'LoggingTable' 'Schema' = 'dbo' Headers = 'Message', 'Timestamp', 'Level', 'Tags', 'Data', 'ComputerName', 'Runspace', 'UserName', 'ModuleName', 'FunctionName', 'File', 'Line', 'CallStack', 'TargetObject', 'ErrorRecord' } diff --git a/PSFramework/internal/scripts/async-logging2.ps1 b/PSFramework/internal/scripts/async-logging2.ps1 index 2c18dbfe..8a051049 100644 --- a/PSFramework/internal/scripts/async-logging2.ps1 +++ b/PSFramework/internal/scripts/async-logging2.ps1 @@ -3,7 +3,7 @@ { $script:___ScriptName = 'PSFramework.Logging' - Import-Module (Join-Path ([PSFramework.PSFCore.PSFCoreHost]::ModuleRoot) 'PSFramework.psd1') + Import-Module (Join-Path ([PSFramework.PSFCore.PSFCoreHost]::ModuleRoot) 'PSFramework.psd1') -Global while ($true) { diff --git a/PSFramework/internal/scripts/loggingProviderInstanceModuleCode.ps1 b/PSFramework/internal/scripts/loggingProviderInstanceModuleCode.ps1 index 6d63dd3c..7ede0742 100644 --- a/PSFramework/internal/scripts/loggingProviderInstanceModuleCode.ps1 +++ b/PSFramework/internal/scripts/loggingProviderInstanceModuleCode.ps1 @@ -45,7 +45,9 @@ [CmdletBinding()] param ( [string] - $Name + $Name, + + $FallBack ) $rootPath = $script:Instance.ConfigurationRoot @@ -54,7 +56,7 @@ $rootPath += ".$($script:Instance.Name)" } - Get-PSFConfigValue -FullName "$rootPath.$Name" + Get-PSFConfigValue -FullName "$rootPath.$Name" -Fallback $FallBack } Set-Content -Path "function:\$(${ functionNames }.Begin)" -Value $LoggingProviderInstance.Provider.BeginEvent.ToString() diff --git a/PSFramework/modules/EntraAuth.md b/PSFramework/modules/EntraAuth.md new file mode 100644 index 00000000..99bb60d4 --- /dev/null +++ b/PSFramework/modules/EntraAuth.md @@ -0,0 +1,14 @@ +# EntraAuth + +> Source + +https://github.com/FriedrichWeinmann/EntraAuth + +> Purpose + +Used in the Azure LogAnalytics (v2) Logging Provider. + +> Adjustments + +Removed Format-XML file and its reference in the module manifest. +No human is ever going to see the objects from this module, no need to risk a conflict with other EntraAuth versions loaded into the main runspace. diff --git a/PSFramework/modules/EntraAuth/1.8.56/EntraAuth.psd1 b/PSFramework/modules/EntraAuth/1.8.56/EntraAuth.psd1 new file mode 100644 index 00000000..708a2e72 --- /dev/null +++ b/PSFramework/modules/EntraAuth/1.8.56/EntraAuth.psd1 @@ -0,0 +1,139 @@ +@{ + +# Script module or binary module file associated with this manifest. +RootModule = 'EntraAuth.psm1' + +# Version number of this module. +ModuleVersion = '1.8.56' + +# Supported PSEditions +# CompatiblePSEditions = @() + +# ID used to uniquely identify this module +GUID = '3d8957b7-643a-48ad-97af-6a342483d578' + +# Author of this module +Author = 'Friedrich Weinmann' + +# Company or vendor of this module +CompanyName = ' ' + +# Copyright statement for this module +Copyright = '(c) Friedrich Weinmann. All rights reserved.' + +# Description of the functionality provided by this module +Description = 'Get Tokens from Entra ID' + +# Minimum version of the PowerShell engine required by this module +# PowerShellVersion = '' + +# Name of the PowerShell host required by this module +# PowerShellHostName = '' + +# Minimum version of the PowerShell host required by this module +# PowerShellHostVersion = '' + +# Minimum version of Microsoft .NET Framework required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# DotNetFrameworkVersion = '' + +# Minimum version of the common language runtime (CLR) required by this module. This prerequisite is valid for the PowerShell Desktop edition only. +# ClrVersion = '' + +# Processor architecture (None, X86, Amd64) required by this module +# ProcessorArchitecture = '' + +# Modules that must be imported into the global environment prior to importing this module +# RequiredModules = @() + +# Assemblies that must be loaded prior to importing this module +# RequiredAssemblies = @() + +# Script files (.ps1) that are run in the caller's environment prior to importing this module. +# ScriptsToProcess = @() + +# Type files (.ps1xml) to be loaded when importing this module +# TypesToProcess = @() + +# Format files (.ps1xml) to be loaded when importing this module +# FormatsToProcess = @('EntraAuth.Formats.ps1xml') + +# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess +# NestedModules = @() + +# Functions to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no functions to export. +FunctionsToExport = @( + 'Assert-EntraConnection' + 'Connect-EntraService' + 'Get-EntraFederationProvider' + 'Get-EntraService' + 'Get-EntraToken' + 'Import-EntraToken' + 'Invoke-EntraRequest' + 'New-EntraCustomToken' + 'New-EntraFilterBuilder' + 'New-EntraServiceSelector' + 'Register-EntraFederationProvider' + 'Register-EntraService' + 'Resolve-EntraFederationProvider' + 'Set-EntraService' +) + +# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export. +# CmdletsToExport = '*' + +# Variables to export from this module +# VariablesToExport = '*' + +# Aliases to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no aliases to export. +# AliasesToExport = '*' + +# DSC resources to export from this module +# DscResourcesToExport = @() + +# List of all modules packaged with this module +# ModuleList = @() + +# List of all files packaged with this module +# FileList = @() + +# Private data to pass to the module specified in RootModule/ModuleToProcess. This may also contain a PSData hashtable with additional module metadata used by PowerShell. +PrivateData = @{ + + PSData = @{ + + # Tags applied to this module. These help with module discovery in online galleries. + Tags = @('EntraID', 'Token') + + # A URL to the license for this module. + LicenseUri = 'https://github.com/FriedrichWeinmann/EntraAuth/blob/master/LICENSE' + + # A URL to the main website for this project. + ProjectUri = 'https://github.com/FriedrichWeinmann/EntraAuth' + + # A URL to an icon representing this module. + # IconUri = '' + + # ReleaseNotes of this module + # ReleaseNotes = '' + + # Prerelease string of this module + # Prerelease = '' + + # Flag to indicate whether the module requires explicit user acceptance for install/update/save + # RequireLicenseAcceptance = $false + + # External dependent modules of this module + # ExternalModuleDependencies = @() + + } # End of PSData hashtable + +} # End of PrivateData hashtable + +# HelpInfo URI of this module +# HelpInfoURI = '' + +# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. +# DefaultCommandPrefix = '' + +} + diff --git a/PSFramework/modules/EntraAuth/1.8.56/EntraAuth.psm1 b/PSFramework/modules/EntraAuth/1.8.56/EntraAuth.psm1 new file mode 100644 index 00000000..effdff8d --- /dev/null +++ b/PSFramework/modules/EntraAuth/1.8.56/EntraAuth.psm1 @@ -0,0 +1,4073 @@ +$script:ModuleRoot = $PSScriptRoot + +class FederationProvider { + [string]$Name + [string]$Description + [int]$Priority + [scriptblock]$Test + [scriptblock]$Code + [string]$Assertion + [string]$Type = 'Custom' + + [string]ToString() { + return $this.Name + } +} + +enum Environment { + Global = 1 + USGov = 2 + USGovDOD = 3 + China = 4 +} + +class FilterBuilder { + [System.Collections.ArrayList]$Entries = @() + [System.Collections.ArrayList]$CustomFilter = @() + + [ValidateSet('AND','OR')][string]$Logic = 'AND' + + FilterBuilder() { } + FilterBuilder([string]$Logic) { + $this.Logic = $Logic + } + + [void]Add([string]$Property, [string]$Operator, $Value) { + $this.Add($Property, $Operator, $Value, $false) + } + [void]Add([string]$Property, [string]$Operator, $Value, [bool]$NoQuotes) { + $null = $this.Entries.Add( + @{ + Property = $Property + Operator = $Operator + Value = $Value + NoQuotes = $NoQuotes + } + ) + } + [void]Add([string]$CustomFilter) { + $null = $this.Entries.Add($CustomFilter) + } + [void]Add([FilterBuilder]$NestedFilter) { + $null = $this.Entries.Add($NestedFilter) + } + + [int]Count() { + $myCount = $this.Entries.Count + if ($this.CustomFilter) { $myCount += $this.CustomFilter.Count } + return $myCount + } + [string]GetHelp() { + return @' +OData Filter Builder Guidance + +This tool _mostly_ maps / implements the OData filter system, as adapted by the Microsoft Graph API. +It may be relevant to any other API supporting OData filters, but that's what it was built for. + +Filter Docs: +https://learn.microsoft.com/en-us/graph/filter-query-parameter + +Adding Filter Conditions: +There are two ways to provide filter conditions: + +A) .Add(property, operator, value) +The .Add method adds individual filter clauses, simple comparisons or some special behaviors. +For these special rules, see below. +But any operator that has a simple " " from this list should be valid: +https://learn.microsoft.com/en-us/graph/filter-query-parameter?tabs=http#operators-and-functions-supported-in-filter-expressions +Strings need not be provided in quotes. + +B) .Add(customFilter) +Specifying a single string allows providing custom filter terms/expressions. +This can be any valid fragment of OData filter, giving you greater control ... but requires you to write the filter yourself. + +All conditions from A) and B) are finally combined with an AND condition. + + +Special Rules: + +eq +The "eq" Operator is converted into a 'startswith' or 'endswith' operator, depending on wildcard use. + +leq +The "leq" Operator is not an actual OData operator, but was added by this tool. +It means "Literal Equals" and is converted into an "eq" operator, but without automatic conversion to 'startswith' or 'endswith'. + +any +The "any" Operator is the OData equivalent to the PowerShell -contains. + +none +The "none" fake-Operator is the OData equivalent to the PowerShell -notcontains. +It translates into an OData all(...) logic with the "ne" operator applied. +'@ + } + [string]Get() { + $segments = :entries foreach ($entry in $this.Entries) { + # Nested Filters + if ($entry -is [FilterBuilder]) { + '(' + $entry.Get() + ')' + continue + } + # Custom Filters + if ($entry -is [string]) { + '(' + $entry + ')' + continue + } + + + $quotes = "'" + if ($entry.NoQuotes) { $quotes = "" } + + $valueString = $entry.Value -as [string] + if ($null -eq $entry.Value) { $valueString = "null" } + if ( + $entry.Value -is [string] -or + $entry.Value -is [guid] + ) { + $valueString = "$($quotes)$($entry.Value)$($quotes)" + } + if ($entry.Value -is [DateTime]) { + $valueString = $entry.Value.ToString('u') -replace ' ', 'T' + } + + switch ($entry.Operator) { + 'eq' { + # Case: eq with Wildcard + if ($entry.Value -match '\*$' -and $entry.Operator -eq 'eq') { + "startswith($($entry.Property), $($quotes)$($entry.Value.TrimEnd('*'))$($quotes))" + continue entries + } + if ($entry.Value -match '^\*' -and $entry.Operator -eq 'eq') { + "endswith($($entry.Property), $($quotes)$($entry.Value.TrimStart('*'))$($quotes))" + continue entries + } + '{0} eq {1}' -f $entry.Property, $valueString + } + 'leq' { + '{0} eq {1}' -f $entry.Property, $valueString + } + 'in' { + '{0} in ({1})' -f $entry.Property, (@($entry.Value).ForEach{ "$($quotes)$_$($quotes)" } -join ', ') + } + 'any' { + '{0}/any(x:x eq {1})' -f $entry.Property, $valueString + } + 'none' { + '{0}/all(x:x ne {1})' -f $entry.Property, $valueString + } + default { + '{0} {1} {2}' -f $entry.Property, $entry.Operator, $valueString + } + } + } + if ($this.CustomFilter) { + if ($segments) { $segments = @($segments) + $this.CustomFilter } + else { $segments = $this.CustomFilter } + } + + if ($this.Logic -eq 'OR') { return $segments -join ' or ' } + return $segments -join ' and ' + } + [hashtable]GetHeader() { + return @{ '$filter' = $this.Get() } + } +} + +class ServiceSelector { + [hashtable]$DefaultServices = @{ } + + ServiceSelector([Hashtable]$Services) { + $this.DefaultServices = $Services + } + + [string]GetService([hashtable]$ServiceMap, [string]$Name) { + if ($ServiceMap[$Name]) { return $ServiceMap[$Name] } + + return $this.DefaultServices[$Name] + } + [hashtable]GetServiceMap([hashtable]$ServiceMap) { + $map = $this.DefaultServices.Clone() + if ($ServiceMap) { + foreach ($pair in $ServiceMap.GetEnumerator()) { + $map[$pair.Key] = $pair.Value + } + } + return $map + } +} + +class EntraToken { + #region Token Data + [string]$AccessToken + [System.DateTime]$ValidAfter + [System.DateTime]$ValidUntil + [string[]]$Scopes + [string]$RefreshToken + [string]$Audience + [string]$Issuer + [PSObject]$TokenData + #endregion Token Data + + #region Connection Data + [string]$Service + [string]$Type + [string]$ClientID + [string]$TenantID + [string]$ServiceUrl + [string]$AuthenticationUrl + [Hashtable]$Header = @{} + [Hashtable]$Query = @{} + [bool]$RawOnly + + [string]$IdentityID + [string]$IdentityType + + # Workflow: Browser + [string]$RedirectUri + + # Workflow: Client Secret + [System.Security.SecureString]$ClientSecret + + # Workflow: Certificate + [System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate + + # Workflow: Username & Password + [PSCredential]$Credential + + # Workflow: Key Vault + [string]$VaultName + [string]$SecretName + + # Workflow: Az.Accounts + [string]$ShowDialog + + # Workflow: Federated + [FederationProvider]$FederationProvider + + # Workflow: Custom Token + [scriptblock]$HeaderCode + [hashtable]$Data = @{} + + #endregion Connection Data + + #region Constructors + EntraToken([string]$Service, [string]$ClientID, [string]$TenantID, [Securestring]$ClientSecret, [string]$ServiceUrl, [string]$AuthenticationUrl) { + $this.Service = $Service + $this.ClientID = $ClientID + $this.TenantID = $TenantID + $this.ClientSecret = $ClientSecret + $this.ServiceUrl = $ServiceUrl + $this.AuthenticationUrl = $AuthenticationUrl + $this.Type = 'ClientSecret' + } + + EntraToken([string]$Service, [string]$ClientID, [string]$TenantID, [FederationProvider]$Provider, [string]$ServiceUrl, [string]$AuthenticationUrl) { + $this.Service = $Service + $this.ClientID = $ClientID + $this.TenantID = $TenantID + $this.ServiceUrl = $ServiceUrl + $this.AuthenticationUrl = $AuthenticationUrl + $this.FederationProvider = $Provider + $this.Type = 'Federated' + } + + EntraToken([string]$Service, [string]$ClientID, [string]$TenantID, [System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate, [string]$ServiceUrl, [string]$AuthenticationUrl) { + $this.Service = $Service + $this.ClientID = $ClientID + $this.TenantID = $TenantID + $this.Certificate = $Certificate + $this.ServiceUrl = $ServiceUrl + $this.AuthenticationUrl = $AuthenticationUrl + $this.Type = 'Certificate' + } + + EntraToken([string]$Service, [string]$ClientID, [string]$TenantID, [pscredential]$Credential, [string]$ServiceUrl, [string]$AuthenticationUrl) { + $this.Service = $Service + $this.ClientID = $ClientID + $this.TenantID = $TenantID + $this.Credential = $Credential + $this.ServiceUrl = $ServiceUrl + $this.AuthenticationUrl = $AuthenticationUrl + $this.Type = 'UsernamePassword' + } + + EntraToken([string]$Service, [string]$ClientID, [string]$TenantID, [string]$ServiceUrl, [bool]$IsDeviceCode, [string]$AuthenticationUrl) { + $this.Service = $Service + $this.ClientID = $ClientID + $this.TenantID = $TenantID + $this.ServiceUrl = $ServiceUrl + $this.AuthenticationUrl = $AuthenticationUrl + if ($IsDeviceCode) { $this.Type = 'DeviceCode' } + else { $this.Type = 'Browser' } + } + + EntraToken([string]$Service, [string]$ClientID, [string]$TenantID, [string]$ServiceUrl, [string]$VaultName, [string]$SecretName, [string]$AuthenticationUrl) { + $this.Service = $Service + $this.ClientID = $ClientID + $this.TenantID = $TenantID + $this.ServiceUrl = $ServiceUrl + $this.VaultName = $VaultName + $this.SecretName = $SecretName + $this.AuthenticationUrl = $AuthenticationUrl + $this.Type = 'KeyVault' + } + + EntraToken([string]$Service, [string]$ServiceUrl, [string]$IdentityID, [string]$IdentityType) { + $this.Service = $Service + $this.ServiceUrl = $ServiceUrl + $this.Type = 'Identity' + + if ($IdentityID) { + $this.IdentityID = $IdentityID + $this.IdentityType = $IdentityType + } + } + + EntraToken([string]$Service, [string]$ServiceUrl, [string]$ShowDialog) { + $this.Service = $Service + $this.ServiceUrl = $ServiceUrl + $this.ShowDialog = $ShowDialog + $this.Type = 'AzAccount' + } + + # Empty Constructor for Import-EntraToken + EntraToken() {} + #endregion Constructors + + [void]SetTokenMetadata([PSObject] $AuthToken) { + $this.AccessToken = $AuthToken.AccessToken + $this.ValidAfter = $AuthToken.ValidAfter + $this.ValidUntil = $AuthToken.ValidUntil + $this.Scopes = $AuthToken.Scopes + if ($AuthToken.RefreshToken) { $this.RefreshToken = $AuthToken.RefreshToken } + + $tokenPayload = $AuthToken.AccessToken.Split(".")[1].Replace('-', '+').Replace('_', '/') + while ($tokenPayload.Length % 4) { $tokenPayload += "=" } + $bytes = [System.Convert]::FromBase64String($tokenPayload) + $localData = [System.Text.Encoding]::ASCII.GetString($bytes) | ConvertFrom-Json + + if ($localData.roles) { $this.Scopes = $localData.roles } + elseif ($localData.scp) { $this.Scopes = $localData.scp -split " " } + + $this.Audience = $localData.aud + $this.Issuer = $localData.iss + $this.TokenData = $localData + $this.TenantID = $localData.tid + } + + [hashtable]GetHeader() { + if ($this.HeaderCode) { + $newHeader = $this.Header.Clone() + $results = @(& $this.HeaderCode $this)[0] + foreach ($pair in $results.GetEnumerator()) { + $newHeader[$pair.Key] = $pair.Value + } + return $newHeader + } + + if ($this.ValidUntil -lt (Get-Date).AddMinutes(5)) { + $this.RenewToken() + } + + $currentHeader = @{} + if ($this.Header.Count -gt 0) { + $currentHeader = $this.Header.Clone() + } + $currentHeader.Authorization = "Bearer $($this.AccessToken)" + + return $currentHeader + } + + [void]RenewToken() { + $defaultParam = @{ + TenantID = $this.TenantID + ClientID = $this.ClientID + Resource = $this.Audience + AuthenticationUrl = $this.AuthenticationUrl + } + switch ($this.Type) { + Certificate { + $result = Connect-ServiceCertificate @defaultParam -Certificate $this.Certificate + $this.SetTokenMetadata($result) + } + ClientSecret { + $result = Connect-ServiceClientSecret @defaultParam -ClientSecret $this.ClientSecret + $this.SetTokenMetadata($result) + } + UsernamePassword { + $result = Connect-ServicePassword @defaultParam -Credential $this.Credential + $this.SetTokenMetadata($result) + } + DeviceCode { + if ($this.RefreshToken) { + Connect-ServiceRefreshToken -Token $this + return + } + + $result = Connect-ServiceDeviceCode @defaultParam + $this.SetTokenMetadata($result) + } + Browser { + if ($this.RefreshToken) { + Connect-ServiceRefreshToken -Token $this + return + } + + $result = Connect-ServiceBrowser @defaultParam -SelectAccount -RedirectUri $this.RedirectUri + $this.SetTokenMetadata($result) + } + Refresh { + Connect-ServiceRefreshToken -Token $this + } + KeyVault { + $secret = Get-VaultSecret -VaultName $this.VaultName -SecretName $this.SecretName + $result = switch ($secret.Type) { + Certificate { Connect-ServiceCertificate @defaultParam -Certificate $secret.Certificate } + ClientSecret { Connect-ServiceClientSecret @defaultParam -ClientSecret $secret.ClientSecret } + } + $this.SetTokenMetadata($result) + } + Identity { + $result = Connect-ServiceIdentity -Resource $this.Audience -IdentityID $this.IdentityID -IdentityType $this.IdentityType + $this.SetTokenMetadata($result) + } + AzAccount { + $result = Connect-ServiceAzure -Resource $this.Audience -ShowDialog $this.ShowDialog + $this.SetTokenMetadata($result) + } + Federated { + $result, $provider = Connect-ServiceFederated @defaultParam -Provider $this.FederationProvider.Name -Assertion $this.FederationProvider.Assertion + $this.SetTokenMetadata($result) + } + } + } +} + +function Connect-ServiceAzure { + <# + .SYNOPSIS + Authenticates using the established session from Az.Accounts. + + .DESCRIPTION + Authenticates using the established session from Az.Accounts. + This limits the scopes available to what is configured on the Az Application, but makes it easy to authenticate without active interaction. + + Pretty useful for authenticating to custom apps that do not actually implement scopes. + + .PARAMETER Resource + The resource owning the api permissions / scopes requested. + + .PARAMETER ShowDialog + Whether to show a dialog in case of interaction being needed. + Defaults to: auto + + .EXAMPLE + PS C:\> Connect-ServiceAzure -Resource 'https://graph.microsoft.com' + + Connect to graph using the existing az.accounts session. + #> + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $Resource, + + [ValidateSet('Auto', 'Always', 'Never')] + [string] + $ShowDialog = 'Auto' + ) + process { + try { $azContext = Get-AzContext -ErrorAction Stop } + catch { Invoke-TerminatingException -Cmdlet $PSCmdlet -Message 'Error accessing azure context. Ensure the module "Az.Accounts" is installed and you have connected via "Connect-AzAccount"!' -ErrorRecord $_ } + + try { + $result = [Microsoft.Azure.Commands.Common.Authentication.AzureSession]::Instance.AuthenticationFactory.Authenticate( + $azContext.Account, + $azContext.Environment, + "$($azContext.Tenant.id)", + $null, + $ShowDialog, + $null, + $Resource + ) + + } + catch { Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "Error retrieving token from Azure for '$Resource': $_" -ErrorRecord $_ } + + $tokenData = Read-TokenData -Token $result.AccessToken + + # A Fake AuthResponse result - Should keep the same layout as the result of Read-AuthResponse + [PSCustomObject]@{ + AccessToken = $result.AccessToken + ValidAfter = Get-Date + ValidUntil = $result.ExpiresOn.LocalDateTime + Scopes = $tokenData.scp -split ' ' + RefreshToken = $null + + # For Initial Connect Metadata + ClientID = $tokenData.appid + TenantID = $tokenData.tid + } + } +} + +function Connect-ServiceBrowser { + <# + .SYNOPSIS + Interactive logon using the Authorization flow and browser. Supports SSO. + + .DESCRIPTION + Interactive logon using the Authorization flow and browser. Supports SSO. + + This flow requires an App Registration configured for the platform "Mobile and desktop applications". + Its redirect Uri must be "http://localhost" + + On successful authentication + + .PARAMETER ClientID + The ID of the registered app used with this authentication request. + + .PARAMETER TenantID + The ID of the tenant connected to with this authentication request. + + .PARAMETER SelectAccount + Forces account selection on logon. + As this flow supports single-sign-on, it will otherwise not prompt for anything if already signed in. + This could be a problem if you want to connect using another (e.g. an admin) account. + + .PARAMETER Scopes + Generally doesn't need to be changed from the default '.default' + + .PARAMETER LocalPort + The local port that should be redirected to. + In order to process the authentication response, we need to listen to a local web request on some port. + Usually needs not be redirected. + Defaults to: 8080 + + .PARAMETER Resource + The resource owning the api permissions / scopes requested. + + .PARAMETER RedirectUri + The Redirect URI to send with the request. + May be different from the actual local port you want to listen on (e.g. when redirecting to an alternative name on top of localhost). + + .PARAMETER Browser + The path to the browser to use for the authentication flow. + Provide the full path to the executable. + The browser must accept the url to open as its only parameter. + Defaults to your default browser. + + .PARAMETER BrowserMode + How the browser used for authentication is selected. + Options: + + Auto (default): Automatically use the default browser. + + PrintLink: The link to open is printed on console and user selects which browser to paste it into (must be used on the same machine) + + .PARAMETER NoReconnect + Disables automatic reconnection. + By default, this module will automatically try to reaquire a new token before the old one expires. + + .PARAMETER AuthenticationUrl + The url used for the authentication requests to retrieve tokens. + + .EXAMPLE + PS C:\> Connect-ServiceBrowser -ClientID '' -TenantID '' + + Connects to the specified tenant using the specified client, prompting the user to authorize via Browser. + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "")] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $TenantID, + + [Parameter(Mandatory = $true)] + [string] + $ClientID, + + [Parameter(Mandatory = $true)] + [string] + $Resource, + + [switch] + $SelectAccount, + + [AllowEmptyCollection()] + [string[]] + $Scopes, + + [int] + $LocalPort = 8080, + + [AllowEmptyString()] + [string] + $RedirectUri, + + [string] + $Browser, + + [Parameter(ParameterSetName = 'Browser')] + [ValidateSet('Auto', 'PrintLink')] + [string] + $BrowserMode = 'Auto', + + [switch] + $NoReconnect, + + [Parameter(Mandatory = $true)] + [string] + $AuthenticationUrl + ) + process { + Add-Type -AssemblyName System.Web + if (-not $Scopes) { $Scopes = @('.default') } + + $localUri = "http://localhost:$LocalPort" + if (-not $RedirectUri) { $RedirectUri = $localUri } + $actualScopes = $Scopes | Resolve-ScopeName -Resource $Resource + + if (-not $NoReconnect) { + $actualScopes = @($actualScopes) + 'offline_access' + } + + $uri = "$AuthenticationUrl/$TenantID/oauth2/v2.0/authorize?" + $state = Get-Random + $parameters = @{ + client_id = $ClientID + response_type = 'code' + redirect_uri = $RedirectUri + response_mode = 'query' + scope = $actualScopes -join ' ' + state = $state + } + if ($SelectAccount) { + $parameters.prompt = 'select_account' + } + + $paramStrings = foreach ($pair in $parameters.GetEnumerator()) { + $pair.Key, ([System.Web.HttpUtility]::UrlEncode($pair.Value)) -join '=' + } + $uriFinal = $uri + ($paramStrings -join '&') + Write-Verbose "Authorize Uri: $uriFinal" + + #$redirectTo = 'https://raw.githubusercontent.com/FriedrichWeinmann/EntraAuth/master/nothing-to-see-here.txt' + #$redirectTo = (Join-Path -Path $script:ModuleRoot -ChildPath 'nothing-to-see-here.txt') -replace '\\','/' + $redirectTo = "http://localhost:$(Get-Random -Minimum 9800 -Maximum 9999)/" + if ((Get-Random -Minimum 10 -Maximum 99) -eq 66) { + $redirectTo = 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' + } + + # Start local server to catch the redirect + $http = [System.Net.HttpListener]::new() + $http.Prefixes.Add(("$RedirectUri/" -replace '//$', '/')) + if ($localUri -ne $RedirectUri) { $http.Prefixes.Add(("$localUri/" -replace '//$', '/')) } + try { $http.Start() } + catch { Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "Failed to create local http listener on port $LocalPort. Use -LocalPort to select a different port. $_" -Category OpenError } + + switch ($BrowserMode) { + Auto { + # Execute in default browser + if ($Browser) { & $Browser $uriFinal } + else { Start-Process $uriFinal } + } + PrintLink { + Write-Host @" +Ready to authenticate. Paste the following link into the browser of your choice on the local computer: +$uriFinal +"@ + } + } + + # Get Result + $task = $http.GetContextAsync() + $authorizationCode, $stateReturn, $sessionState = $null + try { + while (-not $task.IsCompleted) { + Start-Sleep -Milliseconds 200 + } + $http2 = [System.Net.HttpListener]::new() + $http2.Prefixes.Add($redirectTo) + $http2.Start() + + $context = $task.Result + $context.Response.Redirect($redirectTo) + $context.Response.Close() + $authorizationCode, $stateReturn, $sessionState = $context.Request.Url.Query -split "&" + + $task2 = $http2.GetContextAsync() + while (-not $task2.IsCompleted) { + Start-Sleep -Milliseconds 200 + } + $context2 = $task2.Result + $bytes = [System.Text.Encoding]::UTF8.GetBytes('Authentication flow completed, you can close the tab now.') + $context2.Response.ContentEncoding = [System.Text.Encoding]::UTF8 + $context2.Response.OutputStream.Write($bytes,0,$bytes.Length) + $context2.Response.Close() + } + finally { + $http.Stop() + $http.Dispose() + if ($http2.IsListening) { + $http2.Stop() + $http2.Dispose() + } + } + + if (-not $stateReturn) { + Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "Authentication failed (see browser for details)" -Category AuthenticationError + } + + if ($stateReturn -match '^error_description=') { + $message = $stateReturn -replace '^error_description=' -replace '\+',' ' + $message = [System.Web.HttpUtility]::UrlDecode($message) + Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "Error processing the request: $message" -Category InvalidOperation + } + + if ($state -ne $stateReturn.Split("=")[1]) { + Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "Received invalid authentication result. Likely returned from another flow redirecting to the same local port!" -Category InvalidOperation + } + + $actualAuthorizationCode = $authorizationCode.Split("=")[1] + + $body = @{ + client_id = $ClientID + scope = $actualScopes -join " " + code = $actualAuthorizationCode + redirect_uri = $RedirectUri + grant_type = 'authorization_code' + } + $uri = "$AuthenticationUrl/$TenantID/oauth2/v2.0/token" + try { $authResponse = Invoke-RestMethod -Method Post -Uri $uri -Body $body -ErrorAction Stop } + catch { + if ($_ -notmatch '"error":\s*"invalid_client"') { Invoke-TerminatingException -Cmdlet $PSCmdlet -ErrorRecord $_ } + Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "The App Registration $ClientID has not been configured correctly. Ensure you have a 'Mobile and desktop applications' platform with redirect to 'http://localhost' configured (and not a 'Web' Platform). $_" -Category $_.CategoryInfo.Category + } + Read-AuthResponse -AuthResponse $authResponse + } +} + +function Connect-ServiceCertificate { + <# + .SYNOPSIS + Connects to AAD using a application ID and a certificate. + + .DESCRIPTION + Connects to AAD using a application ID and a certificate. + + .PARAMETER Resource + The resource owning the api permissions / scopes requested. + + .PARAMETER Certificate + The certificate to use for authentication. + + .PARAMETER TenantID + The ID of the tenant/directory to connect to. + + .PARAMETER ClientID + The ID of the registered application used to authenticate as. + + .PARAMETER AuthenticationUrl + The url used for the authentication requests to retrieve tokens. + + .EXAMPLE + PS C:\> Connect-ServiceCertificate -Certificate $cert -TenantID $tenantID -ClientID $clientID + + Connects to the specified tenant using the specified app & cert. + + .LINK + https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-certificate-credentials +#> + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $Resource, + + [Parameter(Mandatory = $true)] + [System.Security.Cryptography.X509Certificates.X509Certificate2] + $Certificate, + + [Parameter(Mandatory = $true)] + [string] + $TenantID, + + [Parameter(Mandatory = $true)] + [string] + $ClientID, + + [Parameter(Mandatory = $true)] + [string] + $AuthenticationUrl + ) + + #region Build Signature Payload + $jwtHeader = @{ + alg = "RS256" + typ = "JWT" + x5t = [Convert]::ToBase64String($Certificate.GetCertHash()) -replace '\+', '-' -replace '/', '_' -replace '=' + } + $encodedHeader = $jwtHeader | ConvertTo-Json | ConvertTo-Base64 + $claims = @{ + aud = "$AuthenticationUrl/$TenantID/oauth2/v2.0/token" + exp = ((Get-Date).AddMinutes(5).ToUniversalTime() - (Get-Date -Date '1970-01-01')).TotalSeconds -as [int] + iss = $ClientID + jti = "$(New-Guid)" + nbf = ((Get-Date).ToUniversalTime() - (Get-Date -Date '1970-01-01')).TotalSeconds -as [int] + sub = $ClientID + } + $encodedClaims = $claims | ConvertTo-Json | ConvertTo-Base64 + $jwtPreliminary = $encodedHeader, $encodedClaims -join "." + $jwtSigned = ($jwtPreliminary | ConvertTo-SignedString -Certificate $Certificate) -replace '\+', '-' -replace '/', '_' -replace '=' + $jwt = $jwtPreliminary, $jwtSigned -join '.' + #endregion Build Signature Payload + + $body = @{ + client_id = $ClientID + client_assertion = $jwt + client_assertion_type = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer' + scope = '{0}/.default' -f $Resource + grant_type = 'client_credentials' + } + $header = @{ + Authorization = "Bearer $jwt" + } + $uri = "$AuthenticationUrl/$TenantID/oauth2/v2.0/token" + + try { $authResponse = Invoke-RestMethod -Method Post -Uri $uri -Body $body -Headers $header -ContentType 'application/x-www-form-urlencoded' -ErrorAction Stop } + catch { throw } + + Read-AuthResponse -AuthResponse $authResponse +} + +function Connect-ServiceClientSecret { + <# + .SYNOPSIS + Connets using a client secret. + + .DESCRIPTION + Connets using a client secret. + + .PARAMETER Resource + The resource owning the api permissions / scopes requested. + + .PARAMETER ClientID + The ID of the registered app used with this authentication request. + + .PARAMETER TenantID + The ID of the tenant connected to with this authentication request. + + .PARAMETER ClientSecret + The actual secret used for authenticating the request. + + .PARAMETER AuthenticationUrl + The url used for the authentication requests to retrieve tokens. + + .EXAMPLE + PS C:\> Connect-ServiceClientSecret -ClientID '' -TenantID '' -ClientSecret $secret -Resource '' -AuthenticationUrl 'https://login.microsoftonline.com' + + Connects to the specified tenant using the specified client and secret. +#> + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $Resource, + + [Parameter(Mandatory = $true)] + [string] + $ClientID, + + [Parameter(Mandatory = $true)] + [string] + $TenantID, + + [Parameter(Mandatory = $true)] + [securestring] + $ClientSecret, + + [Parameter(Mandatory = $true)] + [string] + $AuthenticationUrl + ) + + process { + $body = @{ + resource = $Resource + client_id = $ClientID + client_secret = [PSCredential]::new('NoMatter', $ClientSecret).GetNetworkCredential().Password + grant_type = 'client_credentials' + } + try { $authResponse = Invoke-RestMethod -Method Post -Uri "$AuthenticationUrl/$TenantId/oauth2/token" -Body $body -ErrorAction Stop } + catch { throw } + + Read-AuthResponse -AuthResponse $authResponse + } +} + +function Connect-ServiceDeviceCode { + <# + .SYNOPSIS + Connects to Azure AD using the Device Code authentication workflow. + + .DESCRIPTION + Connects to Azure AD using the Device Code authentication workflow. + + .PARAMETER Resource + The resource owning the api permissions / scopes requested. + + .PARAMETER ClientID + The ID of the registered app used with this authentication request. + + .PARAMETER TenantID + The ID of the tenant connected to with this authentication request. + + .PARAMETER Scopes + The scopes to request. + Automatically scoped to the service specified via Service Url. + Defaults to ".Default" + + .PARAMETER NoReconnect + Disables automatic reconnection. + By default, this module will automatically try to reaquire a new token before the old one expires. + + .PARAMETER AuthenticationUrl + The url used for the authentication requests to retrieve tokens. + + .EXAMPLE + PS C:\> Connect-ServiceDeviceCode -Resource 'https://graph.microsoft.com' -ClientID '' -TenantID '' -AuthenticationUrl 'https://login.microsoftonline.com' + + Connects to the specified tenant using the specified client, prompting the user to authorize via Device Code workflow. + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "")] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $Resource, + + [Parameter(Mandatory = $true)] + [string] + $ClientID, + + [Parameter(Mandatory = $true)] + [string] + $TenantID, + + [AllowEmptyCollection()] + [string[]] + $Scopes, + + [switch] + $NoReconnect, + + [Parameter(Mandatory = $true)] + [string] + $AuthenticationUrl + ) + + if (-not $Scopes) { $Scopes = @('.default') } + $actualScopes = $Scopes | Resolve-ScopeName -Resource $Resource + + if (-not $NoReconnect) { + $actualScopes = @($actualScopes) + 'offline_access' + } + + try { + $initialResponse = Invoke-RestMethod -Method POST -Uri "$AuthenticationUrl/$TenantID/oauth2/v2.0/devicecode" -Body @{ + client_id = $ClientID + scope = $actualScopes -join " " + } -ErrorAction Stop + } + catch { + throw + } + + Write-Host $initialResponse.message + + $paramRetrieve = @{ + Uri = "$AuthenticationUrl/$TenantID/oauth2/v2.0/token" + Method = "POST" + Body = @{ + grant_type = "urn:ietf:params:oauth:grant-type:device_code" + client_id = $ClientID + device_code = $initialResponse.device_code + } + ErrorAction = 'Stop' + } + $limit = (Get-Date).AddSeconds($initialResponse.expires_in) + while ($true) { + if ((Get-Date) -gt $limit) { + Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "Timelimit exceeded, device code authentication failed" -Category AuthenticationError + } + Start-Sleep -Seconds $initialResponse.interval + try { $authResponse = Invoke-RestMethod @paramRetrieve } + catch { + if ($_ -match '"error":\s*"authorization_pending"') { continue } + $PSCmdlet.ThrowTerminatingError($_) + } + if ($authResponse) { + break + } + } + + Read-AuthResponse -AuthResponse $authResponse +} + +function Connect-ServiceFederated { + <# + .SYNOPSIS + Authenticate using the Federated Credentials flow. + + .DESCRIPTION + Authenticate using the Federated Credentials flow. + + .PARAMETER Resource + The resource owning the api permissions / scopes requested. + + .PARAMETER ClientID + The ID of the registered app used with this authentication request. + + .PARAMETER TenantID + The ID of the tenant connected to with this authentication request. + + .PARAMETER Provider + The name of the provider to use. + Overrides auto-selection if provided. + + .PARAMETER Assertion + An externally provided assertion from the federated authentication provider. + This skips the internal assertion resolution process and moves straight to the authentication to Entra + + .PARAMETER AuthenticationUrl + The url used for the authentication requests to retrieve tokens. + + .EXAMPLE + PS C:\> Connect-ServiceFederated -ClientID '' -TenantID '' -Resource '' -AuthenticationUrl 'https://login.microsoftonline.com' + + Connects to the specified tenant using the specified client and automatically calculated federated credential. + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseOutputTypeCorrectly", "")] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $Resource, + + [Parameter(Mandatory = $true)] + [string] + $ClientID, + + [Parameter(Mandatory = $true)] + [string] + $TenantID, + + [AllowEmptyString()] + [string] + $Provider, + + [AllowEmptyString()] + [string] + $Assertion, + + [Parameter(Mandatory = $true)] + [string] + $AuthenticationUrl + ) + process { + $providerObject = $null + $myAssertion = $Assertion + if (-not $myAssertion) { + if ($Provider) { $providerObject = $script:_FederationProviders[$Provider] } + else { $providerObject = Resolve-EntraFederationProvider } + + if (-not $providerObject) { + Invoke-TerminatingException -Cmdlet $PSCmdlet -Category AuthenticationError -Message "Unable to find an applicable Federation Provider! Ensure you have a Federation Provider registered and are running in an environment where detection can work." + } + + try { $myAssertion = & $providerObject.Code } + catch { Invoke-TerminatingException -Cmdlet $PSCmdlet -ErrorRecord $_ -Message "Failed to access a token from the federated identity provider! $_" } + } + + $body = @{ + resource = $Resource + client_id = $ClientID + client_assertion_type = 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer' + client_assertion = $myAssertion + grant_type = 'client_credentials' + } + try { $authResponse = Invoke-RestMethod -Method Post -Uri "$AuthenticationUrl/$TenantId/oauth2/token" -Body $body -ContentType 'application/x-www-form-urlencoded' -ErrorAction Stop } + catch { throw } + + Read-AuthResponse -AuthResponse $authResponse + if ($providerObject) { return $providerObject } + [FederationProvider]@{ + Assertion = $myAssertion + } + } +} + +function Connect-ServiceIdentity { + <# + .SYNOPSIS + Connect as the current Managed Identity. + + .DESCRIPTION + Connect as the current Managed Identity. + Only works from within the context of a managed environment, such as Azure Functions with enabled MSI. + + .PARAMETER Resource + The resource to get a token for. + + .PARAMETER IdentityID + ID of the User-Managed Identity to connect as. + + .PARAMETER IdentityType + Type of the User-Managed Identity. + + .PARAMETER Cmdlet + The $PSCmdlet of the calling command. + If specified, errors are triggered in the caller's context. + + .EXAMPLE + PS C:\> Connect-ServiceIdentity -Resource 'https://vault.azure.net' + + Connect as the current managed identity, retrieving a token for the Azure Key Vault. + + .LINK + https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity + #> + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $Resource, + + [AllowEmptyString()] + [AllowNull()] + [string] + $IdentityID, + + [AllowEmptyString()] + [AllowNull()] + [string] + $IdentityType, + + $Cmdlet = $PSCmdlet + ) + process { + # Logic for Azure VMs + try { + $vmMetadata = $null + $vmMetadata = Invoke-RestMethod -Headers @{Metadata = "true" } -Method GET -NoProxy -Uri "http://169.254.169.254/metadata/instance?api-version=2021-02-01" + } + catch { + $vmMetadata = $null + } + if ($vmMetadata.compute.azEnvironment -like "*Azure*") { + Write-Verbose "We are running on an Azure VM. Setting Environment Variables" + $isAzureVM = $true + $env:IDENTITY_ENDPOINT = "http://169.254.169.254/metadata/identity/oauth2/token" + $env:IDENTITY_API_VERSION = "2018-02-01" + } + + if ((-not $env:IDENTITY_ENDPOINT) -or (-not $env:IDENTITY_HEADER)) { + Invoke-TerminatingException -Cmdlet $Cmdlet -Message "Cannot identify a Managed Identity. MSI logon not possible!" -Category ConnectionError + } + + $apiVersion = $env:IDENTITY_API_VERSION + if (-not $apiVersion) { $apiVersion = '2019-08-01' } + + $url = "$($env:IDENTITY_ENDPOINT)?resource=$Resource&api-version=$apiVersion" + if ($IdentityID) { + $labels = @{ + ClientID = 'client_id' + ResourceID = 'mi_res_id' + PrincipalID = 'principal_id' + } + $url = $url + "&$($labels[$IdentityType])=$($IdentityID)" + } + + try { + Write-Verbose "$url" + if ($isAzureVM) { + $headers = @{Metadata = 'true' } + } + else { + $headers = @{'X-IDENTITY-HEADER' = $env:IDENTITY_HEADER } + } + $authResponse = Invoke-RestMethod -Uri $url -Headers $headers -ErrorAction Stop + } + catch { + Invoke-TerminatingException -Cmdlet $Cmdlet -Message "Failed to connect via Managed Identity: $_" -ErrorRecord $_ + } + + Read-AuthResponse -AuthResponse $authResponse + } +} + +function Connect-ServicePassword { + <# + .SYNOPSIS + Connect to graph using username and password. + + .DESCRIPTION + Connect to graph using username and password. + This logs into graph as a user, not as an application. + Only cloud-only accounts can be used for this workflow. + Consent to scopes must be granted before using them, as this command cannot show the consent prompt. + + .PARAMETER Resource + The resource owning the api permissions / scopes requested. + + .PARAMETER Credential + Credentials of the user to connect as. + + .PARAMETER TenantID + The Guid of the tenant to connect to. + + .PARAMETER ClientID + The ClientID / ApplicationID of the application to use. + + .PARAMETER Scopes + The permission scopes to request. + + .PARAMETER AuthenticationUrl + The url used for the authentication requests to retrieve tokens. + + .EXAMPLE + PS C:\> Connect-ServicePassword -Credential max@contoso.com -ClientID $client -TenantID $tenant -Scopes 'user.read','user.readbasic.all' -Resource 'https://graph.microsoft.com' -AuthenticationUrl 'https://login.microsoftonline.com' + + Connect as max@contoso.com with the rights to read user information. + #> + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $Resource, + + [Parameter(Mandatory = $true)] + [System.Management.Automation.PSCredential] + $Credential, + + [Parameter(Mandatory = $true)] + [string] + $ClientID, + + [Parameter(Mandatory = $true)] + [string] + $TenantID, + + [string[]] + $Scopes = '.default', + + [Parameter(Mandatory = $true)] + [string] + $AuthenticationUrl + ) + + $actualScopes = $Scopes | Resolve-ScopeName -Resource $Resource + + $request = @{ + client_id = $ClientID + scope = $actualScopes -join " " + username = $Credential.UserName + password = $Credential.GetNetworkCredential().Password + grant_type = 'password' + } + + try { $authResponse = Invoke-RestMethod -Method POST -Uri "$AuthenticationUrl/$TenantID/oauth2/v2.0/token" -Body $request -ErrorAction Stop } + catch { throw } + + Read-AuthResponse -AuthResponse $authResponse +} + +function Connect-ServiceRefreshToken { + <# + .SYNOPSIS + Connect with the refresh token provided previously. + + .DESCRIPTION + Connect with the refresh token provided previously. + Used mostly for delegate authentication flows to avoid interactivity. + + Can also be resolved to from the outside, when trying to get multiple tokens with a single delegate flow. + + .PARAMETER Token + The EntraToken object with the refresh token to use. + The token is then refreshed in-place with no output provided. + + .PARAMETER RefreshToken + The RefreshToken to use for authenticating. + + .PARAMETER TenantID + ID of the tenant to connect to. + + .PARAMETER ClientID + ID of the application to connect as. + + .PARAMETER Resource + Resource we want the scopes for. + + .PARAMETER Scopes + Scopes we want to use. + + .PARAMETER AuthenticationUrl + The url used for the authentication requests to retrieve tokens. + + .EXAMPLE + PS C:\> Connect-ServiceRefreshToken -Token $token + + Connect with the refresh token provided previously. + + .EXAMPLE + PS C:\> Connect-ServiceRefreshToken -RefreshToken $refreshToken -TenantID '' -ClientID '' -Resource 'https://graph.microsoft.com' -Scopes @('User.Read', 'Mail.Read') -AuthenticationUrl 'https://login.microsoftonline.com' + + Connect using specific refresh token details with custom scopes for Microsoft Graph. + + #> + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, ParameterSetName = 'Token')] + $Token, + + [Parameter(Mandatory = $true, ParameterSetName = 'Details')] + [string] + $RefreshToken, + + [Parameter(Mandatory = $true, ParameterSetName = 'Details')] + [string] + $TenantID, + + [Parameter(Mandatory = $true, ParameterSetName = 'Details')] + [string] + $ClientID, + + [Parameter(Mandatory = $true, ParameterSetName = 'Details')] + [string] + $Resource, + + [Parameter(ParameterSetName = 'Details')] + [string[]] + $Scopes = '.default', + + [Parameter(Mandatory = $true, ParameterSetName = 'Details')] + [string] + $AuthenticationUrl + ) + process { + switch ($PSCmdlet.ParameterSetName) { + 'Token' { + if (-not $Token.RefreshToken) { + throw "Failed to refresh token: No refresh token found!" + } + + $effectiveScopes = $Token.Scopes + + $body = @{ + client_id = $Token.ClientID + scope = @($effectiveScopes).ForEach{"$($Token.Audience)/$($_)"} -join " " + refresh_token = $Token.RefreshToken + grant_type = 'refresh_token' + } + $uri = "$($Token.AuthenticationUrl)/$($Token.TenantID)/oauth2/v2.0/token" + $authResponse = Invoke-RestMethod -Method Post -Uri $uri -Body $body + $Token.SetTokenMetadata((Read-AuthResponse -AuthResponse $authResponse)) + } + 'Details' { + $effectiveScopes = foreach ($scope in $Scopes) { + if ($scope -like "$Resource*") { $scope } + else { "$Resource/$scope" } + } + + $body = @{ + client_id = $ClientID + scope = $effectiveScopes -join " " + refresh_token = $RefreshToken + grant_type = 'refresh_token' + } + $uri = "$($AuthenticationUrl)/$($TenantID)/oauth2/v2.0/token" + $authResponse = Invoke-RestMethod -Method Post -Uri $uri -Body $body + Read-AuthResponse -AuthResponse $authResponse + } + } + } +} + +function Get-VaultSecret { + <# + .SYNOPSIS + Retrieve a secret from Azure Key Vault. + + .DESCRIPTION + Retrieve a secret from Azure Key Vault. + Works for both certificates and secrets. + + Requires one of ... + - An established connection with the AzureKeyVault service. + - An established AZ session via Az.Accounts with the Az.KeyVault module present. + + .PARAMETER VaultName + Name of the Vault to query. + + .PARAMETER SecretName + Name of the Secret to retrieve. + + .PARAMETER Cmdlet + The $PSCmdlet object of the caller, enabling errors to happen within the scope of the caller. + Defaults to the current command's $PSCmdlet + + .EXAMPLE + PS C:\> Get-VaultSecret -VaultName myvault -SecretName mysecret + + Retrieves the latest enabled version of mysecret from myvault + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingConvertToSecureStringWithPlainText", "")] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $VaultName, + + [Parameter(Mandatory = $true)] + [string] + $SecretName, + + $Cmdlet = $PSCmdlet + ) + + process { + #region Via EntraAuth + if (Get-EntraToken -Service AzureKeyVault) { + try { + $secretVersion = Invoke-EntraRequest -Service AzureKeyVault -Path "secrets/$SecretName/versions" -VaultName $VaultName -ErrorAction Stop | Where-Object { + $_.attributes.enabled + } | Sort-Object { $_.attributes.created } -Descending | Select-Object -First 1 + + if (-not $secretVersion) { + Invoke-TerminatingException -Cmdlet $Cmdlet -ErrorRecord $_ -Message "Secret '$SecretName' does not exist in vault '$VaultName'! $_" + } + $secretData = Invoke-EntraRequest -Service AzureKeyVault -Path $secretVersion.id -VaultName $VaultName -ErrorAction Stop + } + catch { + Invoke-TerminatingException -Cmdlet $Cmdlet -ErrorRecord $_ -Message "Failed to retrieve secret '$SecretName' from '$VaultName'! $_" + } + + if ($secretVersion.contentType) { + $secretBytes = [convert]::FromBase64String($secretData) + $certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($secretBytes) + [PSCustomObject]@{ + Type = 'Certificate' + Certificate = $certificate + ClientSecret = $null + } + } + else { + [PSCustomObject]@{ + Type = 'ClientSecret' + Certificate = $null + ClientSecret = $secretData | ConvertTo-SecureString -AsPlainText -Force + } + } + + return + } + #endregion Via EntraAuth + + #region Via Az.KeyVault + if ((Get-Module Az.Accounts -ListAvailable) -and (Get-AzContext) -and (Get-Module Az.KeyVault -ListAvailable)) { + try { $secret = Get-AzKeyVaultSecret -VaultName $VaultName -Name $SecretName } + catch { Invoke-TerminatingException -Cmdlet $Cmdlet -ErrorRecord $_ -Message "Error accessing the secret '$Secretname' from Vault '$VaultName'. $_" } + + $type = 'Certificate' + if (-not $secret.ContentType) { $type = 'ClientSecret' } + + $certificate = $null + $clientSecret = $secret.SecretValue + + if ($type -eq 'Certificate') { + $certString = [PSCredential]::New("irrelevant", $secret.SecretValue).GetNetworkCredential().Password + $bytes = [convert]::FromBase64String($certString) + $certificate = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($bytes) + $clientSecret = $null + } + + [PSCustomObject]@{ + Type = $type + Certificate = $certificate + ClientSecret = $clientSecret + } + + return + } + #endregion Via Az.KeyVault + + Invoke-TerminatingException -Cmdlet $Cmdlet -Message "Not connected to azure yet! Either use 'Connect-EntraService -Service AzureKeyVault' or 'Connect-AzAccount' before trying to connect via KeyVault!" -Category ConnectionError + } +} + +function Read-AuthResponse { + <# + .SYNOPSIS + Produces a standard output representation of the authentication response received. + + .DESCRIPTION + Produces a standard output representation of the authentication response received. + This streamlines the token processing and simplifies the connection code. + + .PARAMETER AuthResponse + The authentication response received. + + .EXAMPLE + PS C:\> Read-AuthResponse -AuthResponse $authResponse + + Reads the authentication details received. + #> + [CmdletBinding()] + param ( + $AuthResponse + ) + process { + if ($AuthResponse.expires_in) { + $after = (Get-Date).AddMinutes(-5) + $until = (Get-Date).AddSeconds($AuthResponse.expires_in) + } + else { + if ($AuthResponse.not_before) { $after = (Get-Date -Date '1970-01-01').AddSeconds($AuthResponse.not_before).ToLocalTime() } + else { $after = Get-Date } + $until = (Get-Date -Date '1970-01-01').AddSeconds($AuthResponse.expires_on).ToLocalTime() + } + $scopes = @() + if ($AuthResponse.scope) { $scopes = $authResponse.scope -split " " } + + # If updating this layout, also update in Connect-ServiceAzure, which fakes this object + [pscustomobject]@{ + AccessToken = $AuthResponse.access_token + ValidAfter = $after + ValidUntil = $until + Scopes = $scopes + RefreshToken = $AuthResponse.refresh_token + } + } +} + +function ConvertTo-Base64 { +<# + .SYNOPSIS + Converts the input-string to its base 64 encoded string form. + + .DESCRIPTION + Converts the input-string to its base 64 encoded string form. + + .PARAMETER Text + The text to convert. + + .PARAMETER Encoding + The encoding of the input text. + Used to correctly translate the input string into bytes before converting those to base 64. + Defaults to UTF8 + + .EXAMPLE + PS C:\> Get-Content .\code.ps1 -Raw | ConvertTo-Base64 + + Reads the input file and converts its content into base64. +#> + [OutputType([string])] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [string[]] + $Text, + + [System.Text.Encoding] + $Encoding = [System.Text.Encoding]::UTF8 + ) + + process { + foreach ($entry in $Text) { + $bytes = $Encoding.GetBytes($entry) + [Convert]::ToBase64String($bytes) + } + } +} + +function ConvertTo-Hashtable { + <# + .SYNOPSIS + Converts input objects into hashtables. + + .DESCRIPTION + Converts input objects into hashtables. + Allows explicitly including some properties only and remapping key-names as required. + + .PARAMETER Include + Only select the specified properties. + + .PARAMETER Mapping + Remap hashtable/property keys. + This allows you to rename parameters before passing them through to other commands. + Example: + @{ Select = '$select' } + This will map the "Select"-property/key on the input object to be '$select' on the output item. + + .PARAMETER InputObject + The object to convert. + + .EXAMPLE + PS C:\> $__body = $PSBoundParameters | ConvertTo-Hashtable -Include Name, UserID -Mapping $__mapping + + Converts the object $PSBoundParameters into a hashtable, including the keys "Name" and "UserID" and remapping them as specified in $__mapping + #> + [OutputType([hashtable])] + [CmdletBinding()] + param ( + [AllowEmptyCollection()] + [string[]] + $Include, + + [Hashtable] + $Mapping = @{ }, + + [Parameter(ValueFromPipeline = $true)] + $InputObject + ) + + process { + $result = @{ } + if ($InputObject -is [System.Collections.IDictionary]) { + foreach ($pair in $InputObject.GetEnumerator()) { + if ($pair.Key -notin $Include) { continue } + if ($Mapping[$pair.Key]) { $result[$Mapping[$pair.Key]] = $pair.Value } + else { $result[$pair.Key] = $pair.Value } + } + } + else { + foreach ($property in $InputObject.PSObject.Properties) { + if ($property.Name -notin $Include) { continue } + if ($Mapping[$property.Name]) { $result[$Mapping[$property.Name]] = $property.Value } + else { $result[$property.Name] = $property.Value } + } + } + $result + } +} + +function ConvertTo-QueryString { + <# + .SYNOPSIS + Convert conditions in a hashtable to a Query string to append to a webrequest. + + .DESCRIPTION + Convert conditions in a hashtable to a Query string to append to a webrequest. + + .PARAMETER QueryHash + Hashtable of query modifiers - usually filter conditions - to include in a web request. + + .PARAMETER DefaultQuery + Default query parameters defined in the service configuration. + Default query settings are overriden by explicit query parameters. + + .EXAMPLE + PS C:\> ConvertTo-QueryString -QueryHash $Query + + Converts the conditions in the specified hashtable to a Query string to append to a webrequest. + #> + [OutputType([string])] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [Hashtable] + $QueryHash, + + [AllowNull()] + [hashtable] + $DefaultQuery + ) + + process { + if ($DefaultQuery) { $query = $DefaultQuery.Clone() } + else { $query = @{} } + + foreach ($key in $QueryHash.Keys) { + $query[$key] = $QueryHash[$key] + } + if ($query.Count -lt 1) { return '' } + + + $elements = foreach ($pair in $query.GetEnumerator()) { + '{0}={1}' -f $pair.Name, ($pair.Value -join ",") + } + '?{0}' -f ($elements -join '&') + } +} + +function ConvertTo-SignedString { +<# + .SYNOPSIS + Signs input string with the offered certificate. + + .DESCRIPTION + Signs input string with the offered certificate. + + .PARAMETER Text + The text to sign. + + .PARAMETER Certificate + The certificate to sign with. + The Private Key must be available. + + .PARAMETER Padding + What RSA Signature padding to use. + Defaults to Pkcs1 + + .PARAMETER Algorithm + What algorithm to use for signing. + Defaults to SHA256 + + .PARAMETER Encoding + The encoding to use for transforming the text to bytes before signing it. + Defaults to UTF8 + + .EXAMPLE + PS C:\> ConvertTo-SignedString -Text $token + + Signs the specified token +#> + [OutputType([string])] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [string[]] + $Text, + + [System.Security.Cryptography.X509Certificates.X509Certificate2] + $Certificate, + + [Security.Cryptography.RSASignaturePadding] + $Padding = [Security.Cryptography.RSASignaturePadding]::Pkcs1, + + [Security.Cryptography.HashAlgorithmName] + $Algorithm = [Security.Cryptography.HashAlgorithmName]::SHA256, + + [System.Text.Encoding] + $Encoding = [System.Text.Encoding]::UTF8 + ) + + begin { + $privateKey = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($Certificate) + } + process { + foreach ($entry in $Text) { + $inBytes = $Encoding.GetBytes($entry) + $outBytes = $privateKey.SignData($inBytes, $Algorithm, $Padding) + [convert]::ToBase64String($outBytes) + } + } +} + +function Invoke-TerminatingException { + <# + .SYNOPSIS + Throw a terminating exception in the context of the caller. + + .DESCRIPTION + Throw a terminating exception in the context of the caller. + Masks the actual code location from the end user in how the message will be displayed. + + .PARAMETER Cmdlet + The $PSCmdlet variable of the calling command. + + .PARAMETER Message + The message to show the user. + + .PARAMETER Exception + A nested exception to include in the exception object. + + .PARAMETER Category + The category of the error. + + .PARAMETER ErrorRecord + A full error record that was caught by the caller. + Use this when you want to rethrow an existing error. + + .EXAMPLE + PS C:\> Invoke-TerminatingException -Cmdlet $PSCmdlet -Message 'Unknown calling module' + + Terminates the calling command, citing an unknown caller. +#> + [CmdletBinding()] + Param ( + [Parameter(Mandatory = $true)] + $Cmdlet, + + [string] + $Message, + + [System.Exception] + $Exception, + + [System.Management.Automation.ErrorCategory] + $Category = [System.Management.Automation.ErrorCategory]::NotSpecified, + + [System.Management.Automation.ErrorRecord] + $ErrorRecord + ) + + process { + if ($ErrorRecord -and -not $Message) { + $Cmdlet.ThrowTerminatingError($ErrorRecord) + } + + $exceptionType = switch ($Category) { + default { [System.Exception] } + 'InvalidArgument' { [System.ArgumentException] } + 'InvalidData' { [System.IO.InvalidDataException] } + 'AuthenticationError' { [System.Security.Authentication.AuthenticationException] } + 'InvalidOperation' { [System.InvalidOperationException] } + } + + + if ($Exception) { $newException = $Exception.GetType()::new($Message, $Exception) } + elseif ($ErrorRecord) { + try { $newException = $ErrorRecord.Exception.GetType()::new($Message, $ErrorRecord.Exception) } + catch { $newException = [System.Exception]::new($Message, $ErrorRecord.Exception) } + } + else { $newException = $exceptionType::new($Message) } + $record = [System.Management.Automation.ErrorRecord]::new($newException, (Get-PSCallStack)[1].FunctionName, $Category, $Target) + $Cmdlet.ThrowTerminatingError($record) + } +} + +function Read-TokenData { + <# + .SYNOPSIS + Reads a JWT token and converts it into a custom object showing its properties. + + .DESCRIPTION + Reads a JWT token and converts it into a custom object showing its properties. + + .PARAMETER Token + The JWT Token to parse + + .EXAMPLE + PS C:\> Read-TokenData -Token $authresponse.access_token + + Reads the settings on the returned access token. + #> + [CmdletBinding()] + param ( + [Parameter(Mandatory=$true)] + [string] + $Token + ) + process { + $tokenPayload = $Token.Split(".")[1].Replace('-', '+').Replace('_', '/') + # Pad with "=" until string length modulus 4 reaches 0 + while ($tokenPayload.Length % 4) { $tokenPayload += "=" } + $bytes = [System.Convert]::FromBase64String($tokenPayload) + [System.Text.Encoding]::ASCII.GetString($bytes) | ConvertFrom-Json + } +} + +function Resolve-Certificate { + <# + .SYNOPSIS + Helper function to resolve certificate input. + + .DESCRIPTION + Helper function to resolve certificate input. + This function expects the full $PSBoundParameters from the calling command and will (in this order) look for these parameter names: + + + Certificate: A full X509Certificate2 object with private key + + CertificateThumbprint: The thumbprint of a certificate to use. Will look first in the user store, then the machine store for it. + + CertificateName: The subject of the certificate to look for. Will look first in the user store, then the machine store for it. Will select the certificate with the longest expiration period. + + CertificatePath: Path to a PFX file to load. Also expects a CertificatePassword parameter to unlock the file. + + .PARAMETER BoundParameters + The $PSBoundParameter variable of the caller to simplify passthrough. + See Description for more details on what the command expects, + + .EXAMPLE + PS C:\> $certificateObject = Resolve-Certificate -BoundParameters $PSBoundParameters + + Resolves the certificate based on the parameters provided to the calling command. + #> + [OutputType([System.Security.Cryptography.X509Certificates.X509Certificate2])] + [CmdletBinding()] + param ( + $BoundParameters + ) + + if ($BoundParameters.Certificate) { return $BoundParameters.Certificate } + if ($BoundParameters.CertificateThumbprint) { + if (Test-Path -Path "cert:\CurrentUser\My\$($BoundParameters.CertificateThumbprint)") { + return Get-Item "cert:\CurrentUser\My\$($BoundParameters.CertificateThumbprint)" + } + if (Test-Path -Path "cert:\LocalMachine\My\$($BoundParameters.CertificateThumbprint)") { + return Get-Item "cert:\LocalMachine\My\$($BoundParameters.CertificateThumbprint)" + } + Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "Unable to find certificate with thumbprint '$($BoundParameters.CertificateThumbprint)'" + } + if ($BoundParameters.CertificateName) { + if ($certificate = @(Get-ChildItem 'Cert:\CurrentUser\My\').Where{ $_.Subject -eq $BoundParameters.CertificateName -and $_.HasPrivateKey }) { + return $certificate | Sort-Object NotAfter -Descending | Select-Object -First 1 + } + if ($certificate = @(Get-ChildItem 'Cert:\LocalMachine\My\').Where{ $_.Subject -eq $BoundParameters.CertificateName -and $_.HasPrivateKey }) { + return $certificate | Sort-Object NotAfter -Descending | Select-Object -First 1 + } + Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "Unable to find certificate with subject '$($BoundParameters.CertificateName)'" + } + if ($BoundParameters.CertificatePath) { + try { [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($BoundParameters.CertificatePath, $BoundParameters.CertificatePassword) } + catch { + Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "Unable to load certificate from file '$($BoundParameters.CertificatePath)': $_" -ErrorRecord $_ + } + } +} + +function Resolve-RequestUri { + <# + .SYNOPSIS + Resolves the actual Uri used for a request in Invoke-EntraRequest. + + .DESCRIPTION + Resolves the actual Uri used for a request in Invoke-EntraRequest. + If the path provided is a full url, it will be returned as is. + Otherwise, any present parameters will be resolved in the base service url before merging it with the specified path. + + .PARAMETER TokenObject + The object representing the token used for the request. + + .PARAMETER ServiceObject + The service object (if any) used with the request. + The parameters to be inserted into the query will be read from here. + + .PARAMETER BoundParameters + The parameters provided to Invoke-EntraRequest. + + .EXAMPLE + PS C:\> Resolve-RequestUri -TokenObject $tokenObject -ServiceObject $script:_EntraEndpoints.$($tokenObject.Service) -BoundParameters $PSBoundParameters + + Resolves the uri for the needed request based on token, service and parameters provided + #> + [OutputType([string])] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + $TokenObject, + + [Parameter(Mandatory = $true)] + [AllowNull()] + $ServiceObject, + + [Parameter(Mandatory = $true)] + $BoundParameters + ) + process { + if ($BoundParameters.Path -match '^https{0,1}://') { + return $BoundParameters.Path + } + + $serviceUrlBase = $TokenObject.ServiceUrl.Trim() + foreach ($key in $ServiceObject.Parameters.Keys) { + $serviceUrlBase = $serviceUrlBase -replace "%$key%", $BoundParameters.$key + } + + "$($serviceUrlBase.TrimEnd('/'))/$($Path.TrimStart('/'))" + } +} + +function Resolve-ScopeName { + <# + .SYNOPSIS + Normalizes scope names. + + .DESCRIPTION + Normalizes scope names. + To help manage correct scopes naming with services that don't map directly to their urls. + + .PARAMETER Scopes + The scopes to normalize. + + .PARAMETER Resource + The Resource the scopes are meant for. + + .EXAMPLE + PS C:\> $scopes | Resolve-ScopeName -Resource $Resource + + Resolves all them scopes + #> + [CmdletBinding()] + param ( + [Parameter(ValueFromPipeline = $true)] + [string[]] + $Scopes, + + [Parameter(Mandatory = $true)] + [string] + $Resource + ) + process { + foreach ($scope in $Scopes) { + foreach ($scope in $Scopes) { + if ($scope -like 'https://*/*') { $scope } + elseif ($scope -like 'api:/') { $scope } + else { "{0}/{1}" -f $Resource, $scope } + } + } + } +} + +function Assert-ServiceName { + <# + .SYNOPSIS + Asserts a service name actually exists. + + .DESCRIPTION + Asserts a service name actually exists. + Used in validation scripts to ensure proper service names were provided. + + .PARAMETER Name + The name of the service to verify. + + .PARAMETER IncludeTokens + Also include registered token's services in the assertion. + By default, the assertion will only verify the existence of registered services. + + .EXAMPLE + PS C:\> Assert-ServiceName -Name $_ + + Returns $true if the service exists and throws a terminating exception if not so. + #> + [OutputType([bool])] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [AllowEmptyString()] + [AllowNull()] + [string] + $Name, + + [switch] + $IncludeTokens + ) + process { + if ($script:_EntraEndpoints.Keys -contains $Name) { return $true } + if ($IncludeTokens -and $script:_EntraTokens.Keys -contains $Name) { return $true } + + $serviceNames = $script:_EntraEndpoints.Keys -join ', ' + Write-Warning "Invalid service name: '$Name'. Legal service names: $serviceNames" + Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "Invalid service name: '$Name'. Legal service names: $serviceNames" + } +} + +function global:Get-ServiceCompletion { + <# + .SYNOPSIS + Returns the values to complete for.service names. + + .DESCRIPTION + Returns the values to complete for.service names. + Use this command in argument completers. + + .PARAMETER ArgumentList + The arguments an argumentcompleter receives. + The third item will be the word to complete. + + .EXAMPLE + PS C:\> Get-ServiceCompletion -ArgumentList $args + + Returns the values to complete for.service names. + #> + [OutputType([System.Management.Automation.CompletionResult])] + [CmdletBinding()] + param ( + $ArgumentList + ) + process { + $wordToComplete = $ArgumentList[2].Trim("'`"") + foreach ($service in Get-EntraService) { + if ($service.Name -notlike "$($wordToComplete)*") { continue } + + $text = if ($service.Name -notmatch '\s') { $service.Name } else { "'$($service.Name)'" } + [System.Management.Automation.CompletionResult]::new( + $text, + $text, + 'Text', + $service.ServiceUrl + ) + } + } +} +$ExecutionContext.InvokeCommand.GetCommand("Get-ServiceCompletion","Function").Visibility = 'Private' + +function Assert-EntraConnection +{ +<# + .SYNOPSIS + Asserts a connection has been established. + + .DESCRIPTION + Asserts a connection has been established. + Fails the calling command in a terminating exception if not connected yet. + + .PARAMETER Service + The service to which a connection needs to be established. + + .PARAMETER Cmdlet + The $PSCmdlet variable of the calling command. + Used to execute the terminating exception in the caller scope if needed. + + .PARAMETER RequiredScopes + Scopes needed, for better error messages. + + .EXAMPLE + PS C:\> Assert-EntraConnection -Service 'Endpoint' -Cmdlet $PSCmdlet + + Silently does nothing if already connected to the specified defender for endpoint service. + Kills the calling command if not yet connected. +#> + [CmdletBinding()] + param ( + [ArgumentCompleter({ Get-ServiceCompletion $args })] + [Parameter(Mandatory = $true)] + [string] + $Service, + + [Parameter(Mandatory = $true)] + $Cmdlet, + + [AllowEmptyCollection()] + [string[]] + $RequiredScopes + ) + + process + { + if ($script:_EntraTokens["$Service"]) { return } + + $message = "Not connected yet! Use Connect-EntraService to establish a connection to '$Service' first." + if ($RequiredScopes) { $message = $message + " Scopes required for this call: $($RequiredScopes -join ', ')"} + Invoke-TerminatingException -Cmdlet $Cmdlet -Message $message -Category ConnectionError + } +} + +function Connect-EntraService { + <# + .SYNOPSIS + Establish a connection to an Entra Service. + + .DESCRIPTION + Establish a connection to an Entra Service. + Prerequisite before executing any requests / commands. + + .PARAMETER ClientID + ID of the registered/enterprise application used for authentication. + + Supports providing special labels as "ID": + + Azure: Resolves to the actual ID of the first party app used by Connect-AzAccount + + Graph: Resolves to the actual ID of the first party app used by Connect-MgGraph + + .PARAMETER TenantID + The ID of the tenant/directory to connect to. + + .PARAMETER Scopes + Any scopes to include in the request. + Only used for interactive/delegate workflows, ignored for Certificate based authentication or when using Client Secrets. + + .PARAMETER Browser + Use an interactive logon in your default browser. + This is the default logon experience. + + .PARAMETER RedirectUri + The Redirect URI to send with the request. + May be different from the actual local port you want to listen on (e.g. when redirecting to an alternative name on top of localhost). + + .PARAMETER BrowserMode + How the browser used for authentication is selected. + Options: + + Auto (default): Automatically use the default browser. + + PrintLink: The link to open is printed on console and user selects which browser to paste it into (must be used on the same machine) + + .PARAMETER DeviceCode + Use the Device Code delegate authentication flow. + This will prompt the user to complete login via browser. + + .PARAMETER RefreshToken + Use an already existing RefreshToken to authenticate. + Can be used to connect to multiple services using a single interactive delegate auth flow. + + .PARAMETER RefreshTokenObject + Use the full token object of a delegate session with a refresh token, to authenticate to another service with this object. + Can be used to connect to multiple services using a single interactive delegate auth flow. + + .PARAMETER Certificate + The Certificate object used to authenticate with. + + Part of the Application Certificate authentication workflow. + + .PARAMETER CertificateThumbprint + Thumbprint of the certificate to authenticate with. + The certificate must be stored either in the user or computer certificate store. + + Part of the Application Certificate authentication workflow. + + .PARAMETER CertificateName + The name/subject of the certificate to authenticate with. + The certificate must be stored either in the user or computer certificate store. + The newest certificate with a private key will be chosen. + + Part of the Application Certificate authentication workflow. + + .PARAMETER CertificatePath + Path to a PFX file containing the certificate to authenticate with. + + Part of the Application Certificate authentication workflow. + + .PARAMETER CertificatePassword + Password to use to read a PFX certificate file. + Only used together with -CertificatePath. + + Part of the Application Certificate authentication workflow. + + .PARAMETER ClientSecret + The client secret configured in the registered/enterprise application. + + Part of the Client Secret Certificate authentication workflow. + + .PARAMETER Credential + The username / password to authenticate with. + + Part of the Resource Owner Password Credential (ROPC) workflow. + + .PARAMETER VaultName + Name of the Azure Key Vault from which to retrieve the certificate or client secret used for the authentication. + Secrets retrieved from the vault are not cached, on token expiration they will be retrieved from the Vault again. + In order for this flow to work, please ensure that you either have an active AzureKeyVault service connection, + or are connected via Connect-AzAccount. + + .PARAMETER SecretName + Name of the secret to use from the Azure Key Vault specified through the '-VaultName' parameter. + In order for this flow to work, please ensure that you either have an active AzureKeyVault service connection, + or are connected via Connect-AzAccount. + Supports specifying _multiple_ secret names, in which case the first one that works will be used. + + .PARAMETER Identity + Log on as the Managed Identity of the current system. + Only works in environments with managed identities, such as Azure Function Apps or Runbooks. + + .PARAMETER IdentityID + ID of the User-Managed Identity to connect as. + https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity + + .PARAMETER IdentityType + Type of the User-Managed Identity. + + .PARAMETER FallBackAzAccount + When logon as Managed Identity fails, try logging in as current AzAccount. + This is intended to allow easier local testing of code intended for an MSI environment, such as an Azure Function App. + + .PARAMETER AsAzAccount + Reuse the existing Az.Accounts session to authenticate. + This is convenient as no further interaction is needed, but also limited in what scopes are available. + This authentication flow requires the 'Az.Accounts' module to be present, loaded and connected. + Use 'Connect-AzAccount' to connect first. + + .PARAMETER ShowDialog + Whether to show an interactive dialog when connecting using the existing Az.Accounts session. + Defaults to: "auto" + + Options: + - auto: Shows dialog only if needed. + - always: Will always show the dialog, forcing interaction. + - never: Will never show the dialog. Authentication will fail if interaction is required. + + .PARAMETER Federated + Use federated credentials to authenticate. + This authentication flow is specific to a given environment and can for example enable a Github Action in a specific repository on a specific branch to authenticate, without needing to provide (and manage) a credential. + Some setup is required. + + By default, this command is going to check all provided configurations ("Federation Providers") registered to EntraAuth and use the first that applies. + Use "-FederationProvider" to pick a specific one to use. + Use "-Assertion" to handle the federated identity provider outside of EntraAuth and simply provide the result for logon. + + .PARAMETER FederationProvider + The name of the Federation Provider to use. Overrides the automatic selection. + Federation Providers are an EntraAuth concept and used to automatically do what is needed to access and use a Federated Credential, based on its environment. + See the documentation on Register-EntraFederationProvider for more details. + + .PARAMETER Assertion + The credentials from the federated identity provider to use in an Federated Credentials authentication flow. + + .PARAMETER Service + The service to connect to. + Individual commands using Invoke-EntraRequest specify the service to use and thus identify the token needed. + Defaults to: Graph + + .PARAMETER ServiceUrl + The base url for requests to the service connecting to. + Overrides the default service url configured with the service settings. + + .PARAMETER Resource + The resource to authenticate to. + Used to authenticate to a service without requiring a full service configuration. + Automatically implies PassThru. + This token is not registered as a service and cannot be implicitly used by Invoke-EntraRequest. + Also provide the "-ServiceUrl" parameter, if you later want to use this token explicitly in Invoke-EntraRequest. + + .PARAMETER UseRefreshToken + Use a refresh token if available. + Only applicable when connecting using a delegate authentication flow. + If specified, it will look to reuse an existing refresh token for that same client ID & tenant ID, if present, + making the authentication process non-interactive. + By default, it would always do the fully interactive authentication flow via Browser. + + .PARAMETER MakeDefault + Makes this service the new default service for all subsequent Connect-EntraService & Invoke-EntraRequest calls. + + .PARAMETER PassThru + Return the token received for the current connection. + + .PARAMETER Environment + What environment this service should connect to. + Defaults to: 'Global' + + .PARAMETER AuthenticationUrl + The url used for the authentication requests to retrieve tokens. + Usually determined by service connected to or the "Environment" parameter, but may be overridden in case of need. + + .EXAMPLE + PS C:\> Connect-EntraService -ClientID $clientID -TenantID $tenantID + + Establish a connection to the graph API, prompting the user for login on their default browser. + + .EXAMPLE + PS C:\> connect-EntraService -AsAzAccount + + Establish a connection to the graph API, using the current Az.Accounts session. + + .EXAMPLE + PS C:\> Connect-EntraService -ClientID $clientID -TenantID $tenantID -Certificate $cert + + Establish a connection to the graph API using the provided certificate. + + .EXAMPLE + PS C:\> Connect-EntraService -ClientID $clientID -TenantID $tenantID -CertificatePath C:\secrets\certs\mde.pfx -CertificatePassword (Read-Host -AsSecureString) + + Establish a connection to the graph API using the provided certificate file. + Prompts you to enter the certificate-file's password first. + + .EXAMPLE + PS C:\> Connect-EntraService -Service Endpoint -ClientID $clientID -TenantID $tenantID -ClientSecret $secret + + Establish a connection to Defender for Endpoint using a client secret. + + .EXAMPLE + PS C:\> Connect-EntraService -ClientID $clientID -TenantID $tenantID -VaultName myVault -Secretname GraphCert + + Establish a connection to the graph API, after retrieving the necessary certificate from the specified Azure Key Vault. +#> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "")] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidDefaultValueForMandatoryParameter", "")] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "")] + [CmdletBinding(DefaultParameterSetName = 'Browser')] + param ( + [Parameter(Mandatory = $true, ParameterSetName = 'Browser')] + [Parameter(Mandatory = $true, ParameterSetName = 'DeviceCode')] + [Parameter(Mandatory = $true, ParameterSetName = 'Refresh')] + [Parameter(Mandatory = $true, ParameterSetName = 'AppCertificate')] + [Parameter(Mandatory = $true, ParameterSetName = 'AppSecret')] + [Parameter(Mandatory = $true, ParameterSetName = 'UsernamePassword')] + [Parameter(Mandatory = $true, ParameterSetName = 'KeyVault')] + [Parameter(Mandatory = $true, ParameterSetName = 'Federated')] + [ArgumentCompleter({ 'Graph', 'Azure' })] + [string] + $ClientID, + + [Parameter(ParameterSetName = 'Browser')] + [Parameter(Mandatory = $true, ParameterSetName = 'DeviceCode')] + [Parameter(Mandatory = $true, ParameterSetName = 'Refresh')] + [Parameter(Mandatory = $true, ParameterSetName = 'AppCertificate')] + [Parameter(Mandatory = $true, ParameterSetName = 'AppSecret')] + [Parameter(Mandatory = $true, ParameterSetName = 'UsernamePassword')] + [Parameter(Mandatory = $true, ParameterSetName = 'KeyVault')] + [Parameter(Mandatory = $true, ParameterSetName = 'Federated')] + [string] + $TenantID = 'organizations', + + [Parameter(ParameterSetName = 'Browser')] + [Parameter(ParameterSetName = 'DeviceCode')] + [Parameter(ParameterSetName = 'Refresh')] + [Parameter(ParameterSetName = 'RefreshObject')] + [string[]] + $Scopes, + + [Parameter(ParameterSetName = 'Browser')] + [switch] + $Browser, + + [Parameter(ParameterSetName = 'Browser')] + [string] + $RedirectUri, + + [Parameter(ParameterSetName = 'Browser')] + [ValidateSet('Auto', 'PrintLink')] + [string] + $BrowserMode = 'Auto', + + [Parameter(Mandatory = $true, ParameterSetName = 'DeviceCode')] + [switch] + $DeviceCode, + + [Parameter(Mandatory = $true, ParameterSetName = 'Refresh')] + [string] + $RefreshToken, + + [Parameter(Mandatory = $true, ParameterSetName = 'RefreshObject')] + [EntraToken] + $RefreshTokenObject, + + [Parameter(ParameterSetName = 'AppCertificate')] + [System.Security.Cryptography.X509Certificates.X509Certificate2] + $Certificate, + + [Parameter(ParameterSetName = 'AppCertificate')] + [string] + $CertificateThumbprint, + + [Parameter(ParameterSetName = 'AppCertificate')] + [string] + $CertificateName, + + [Parameter(ParameterSetName = 'AppCertificate')] + [string] + $CertificatePath, + + [Parameter(ParameterSetName = 'AppCertificate')] + [System.Security.SecureString] + $CertificatePassword, + + [Parameter(Mandatory = $true, ParameterSetName = 'AppSecret')] + [System.Security.SecureString] + $ClientSecret, + + [Parameter(Mandatory = $true, ParameterSetName = 'UsernamePassword')] + [PSCredential] + $Credential, + + [Parameter(Mandatory = $true, ParameterSetName = 'KeyVault')] + [string] + $VaultName, + + [Parameter(Mandatory = $true, ParameterSetName = 'KeyVault')] + [string[]] + $SecretName, + + [Parameter(Mandatory = $true, ParameterSetName = 'Identity')] + [switch] + $Identity, + + [Parameter(ParameterSetName = 'Identity')] + [string] + $IdentityID, + + [Parameter(ParameterSetName = 'Identity')] + [ValidateSet('ClientID', 'ResourceID', 'PrincipalID')] + [string] + $IdentityType = 'ClientID', + + [Parameter(ParameterSetName = 'Identity')] + [Parameter(ParameterSetName = 'Federated')] + [switch] + $FallBackAzAccount, + + [Parameter(Mandatory = $true, ParameterSetName = 'AzAccount')] + [switch] + $AsAzAccount, + + [Parameter(ParameterSetName = 'AzAccount')] + [ValidateSet('Auto', 'Always', 'Never')] + [string] + $ShowDialog = 'Auto', + + [Parameter(ParameterSetName = 'Federated')] + [switch] + $Federated, + + [Parameter(ParameterSetName = 'Federated')] + [ArgumentCompleter({ + param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) + foreach ($provider in Get-EntraFederationProvider) { + if ($provider.Name -notlike "$wordToComplete*") { continue } + $text = $provider.Name + if ($text -match '\s') { $text = "'$($provider.Name -replace "'", "''")'" } + + [System.Management.Automation.CompletionResult]::new($text, $text, 'ParameterValue', $provider.Description) + } + })] + [ValidateScript({ + $providers = (Get-EntraFederationProvider).Name + if ($_ -in $providers) { return $true } + + $message = "Unknown Federation Provider! '$_' - known providers: $($providers -join ', ')" + Write-Warning $message + throw $message + })] + [string] + $FederationProvider, + + [Parameter(ParameterSetName = 'Federated')] + [string] + $Assertion, + + [ArgumentCompleter({ Get-ServiceCompletion $args })] + [ValidateScript({ Assert-ServiceName -Name $_ })] + [string[]] + $Service = $script:_DefaultService, + + [string] + $ServiceUrl, + + [string] + $Resource, + + [Parameter(ParameterSetName = 'Browser')] + [Parameter(ParameterSetName = 'DeviceCode')] + [switch] + $UseRefreshToken, + + [switch] + $MakeDefault, + + [switch] + $PassThru, + + [Environment] + $Environment, + + [string] + $AuthenticationUrl + ) + begin { + $doRegister = $PSBoundParameters.Keys -notcontains 'Resource' + $doPassThru = $PassThru -or $Resource + + switch ($ClientID) { + 'Graph' { $ClientID = '14d82eec-204b-4c2f-b7e8-296a70dab67e' } + 'Azure' { $ClientID = '1950a258-227b-4e31-a9cf-717495945fc2' } + } + } + process { + #region UseRereshToken + $availableToken = $null + if ($UseRefreshToken) { + $availableToken = Get-EntraToken | Where-Object { + $_.ClientID -eq $ClientID -and + ( + $_.TenantID -eq $TenantID -or + $TenantID -eq 'organizations' + ) -and + $_.RefreshToken + } | Sort-Object ValidUntil -Descending | Select-Object -First 1 + } + if ($availableToken) { + $param = @{ } + foreach ($parameterName in $PSCmdlet.MyInvocation.MyCommand.ParameterSets.Where{ $_.Name -eq 'RefreshObject' }.Parameters.Name) { + if ($PSBoundParameters.Keys -contains $parameterName) { $param[$parameterName] = $PSBoundParameters[$parameterName] } + } + Connect-EntraService @param -RefreshTokenObject $availableToken + return + } + #endregion UseRereshToken + + foreach ($serviceName in $Service) { + $serviceObject = $null + if (-not $Resource) { + $serviceObject = Get-EntraService -Name $serviceName + } + else { + $serviceName = '' + } + + #region AuthenticationUrl + $authUrl = switch ("$Environment") { + 'China' { 'https://login.chinacloudapi.cn' } + 'USGov' { 'https://login.microsoftonline.us' } + 'USGovDOD' { 'https://login.microsoftonline.us' } + default { 'https://login.microsoftonline.com' } + } + if ($AuthenticationUrl) { $authUrl = $AuthenticationUrl.TrimEnd('/') } + + if ( + $serviceObject.AuthenticationUrl -and + $PSBoundParameters.Keys -notcontains 'Environment' -and + $PSBoundParameters.Keys -notcontains 'AuthenticationUrl' + ) { + $authUrl = $serviceObject.AuthenticationUrl + } + #endregion AuthenticationUrl + + $commonParam = @{ + ClientID = $ClientID + TenantID = $TenantID + Resource = $serviceObject.Resource + AuthenticationUrl = $authUrl + } + + #region Service Url + $effectiveServiceUrl = $ServiceUrl + if (-not $ServiceUrl -and $serviceObject) { $effectiveServiceUrl = $serviceObject.ServiceUrl } + if ($Resource) { $commonParam.Resource = $Resource } + + # If users explicitly provide a service URL, who are we to override that? + if (-not $ServiceUrl) { + if ('USGovDOD' -eq $Environment) { $effectiveServiceUrl = $effectiveServiceUrl -replace '^https://graph.microsoft.com', 'https://dod-graph.microsoft.us' -replace '^https://manage.azure.com', 'https://manage.usgovcloudapi.net' } + elseif ($authUrl -eq 'https://login.microsoftonline.us') { $effectiveServiceUrl = $effectiveServiceUrl -replace '^https://graph.microsoft.com', 'https://graph.microsoft.us' -replace '^https://manage.azure.com', 'https://manage.usgovcloudapi.net' } + elseif ($authUrl -eq 'https://login.chinacloudapi.cn') { $effectiveServiceUrl = $effectiveServiceUrl -replace '^https://graph.microsoft.com', 'https://microsoftgraph.chinacloudapi.cn' -replace '^https://manage.azure.com', 'https://management.core.chinacloudapi.cn' } + } + #endregion Service Url + + #region Connection + :main switch ($PSCmdlet.ParameterSetName) { + #region Browser + Browser { + $scopesToUse = $Scopes + if (-not $Scopes) { $scopesToUse = $serviceObject.DefaultScopes } + + Write-Verbose "[$serviceName] Connecting via Browser ($($scopesToUse -join ', '))" + try { $result = Connect-ServiceBrowser @commonParam -SelectAccount -Scopes $scopesToUse -NoReconnect:$($serviceObject.NoRefresh) -BrowserMode $BrowserMode -RedirectUri $RedirectUri -ErrorAction Stop } + catch { + Write-Warning "[$serviceName] Failed to connect: $_" + $PSCmdlet.ThrowTerminatingError($_) + } + + $token = [EntraToken]::new($serviceName, $ClientID, $TenantID, $effectiveServiceUrl, $false, $authUrl) + $token.RedirectUri = $RedirectUri + $token.SetTokenMetadata($result) + Write-Verbose "[$serviceName] Connected via Browser ($($token.Scopes -join ', '))" + } + #endregion Browser + + #region DeviceCode + DeviceCode { + $scopesToUse = $Scopes + if (-not $Scopes) { $scopesToUse = $serviceObject.DefaultScopes } + + Write-Verbose "[$serviceName] Connecting via DeviceCode ($($scopesToUse -join ', '))" + try { $result = Connect-ServiceDeviceCode @commonParam -Scopes $scopesToUse -NoReconnect:$($serviceObject.NoRefresh) -ErrorAction Stop } + catch { + Write-Warning "[$serviceName] Failed to connect: $_" + $PSCmdlet.ThrowTerminatingError($_) + } + + $token = [EntraToken]::new($serviceName, $ClientID, $TenantID, $effectiveServiceUrl, $true, $authUrl) + $token.SetTokenMetadata($result) + Write-Verbose "[$serviceName] Connected via DeviceCode ($($token.Scopes -join ', '))" + } + #endregion DeviceCode + + #region RefreshToken + Refresh { + $scopesToUse = $Scopes + if (-not $Scopes) { $scopesToUse = $serviceObject.DefaultScopes } + if (-not $scopesToUse) { $scopesToUse = '.default' } + + Write-Verbose "[$serviceName] Connecting via RefreshToken ($($scopesToUse -join ', '))" + try { $result = Connect-ServiceRefreshToken @commonParam -RefreshToken $RefreshToken -Scopes $scopesToUse -ErrorAction Stop } + catch { + Write-Warning "[$serviceName] Failed to connect: $_" + $PSCmdlet.ThrowTerminatingError($_) + } + + $token = [EntraToken]::new($serviceName, $ClientID, $TenantID, $effectiveServiceUrl, $false, $authUrl) + $token.Type = 'Refresh' + $token.SetTokenMetadata($result) + Write-Verbose "[$serviceName] Connected via RefreshToken ($($token.Scopes -join ', '))" + } + #endregion RefreshToken + + #region RefreshObject + RefreshObject { + $scopesToUse = $Scopes + if (-not $Scopes) { $scopesToUse = $serviceObject.DefaultScopes } + if (-not $scopesToUse) { $scopesToUse = '.default' } + + Write-Verbose "[$serviceName] Connecting via RefreshToken ($($scopesToUse -join ', '))" + try { $result = Connect-ServiceRefreshToken -ClientID $RefreshTokenObject.ClientID -TenantID $RefreshTokenObject.TenantID -Resource $commonParam.Resource -AuthenticationUrl $RefreshTokenObject.AuthenticationUrl -RefreshToken $RefreshTokenObject.RefreshToken -Scopes $scopesToUse -ErrorAction Stop } + catch { + Write-Warning "[$serviceName] Failed to connect: $_" + $PSCmdlet.ThrowTerminatingError($_) + } + + $token = [EntraToken]::new($serviceName, $RefreshTokenObject.ClientID, $RefreshTokenObject.TenantID, $effectiveServiceUrl, $false, $RefreshTokenObject.AuthenticationUrl) + $token.Type = 'Refresh' + $token.SetTokenMetadata($result) + Write-Verbose "[$serviceName] Connected via RefreshToken ($($token.Scopes -join ', '))" + } + #endregion RefreshObject + + #region ROPC + UsernamePassword { + Write-Verbose "[$serviceName] Connecting via Credential" + try { $result = Connect-ServicePassword @commonParam -Credential $Credential -ErrorAction Stop } + catch { + Write-Warning "[$serviceName] Failed to connect: $_" + $PSCmdlet.ThrowTerminatingError($_) + } + + $token = [EntraToken]::new($serviceName, $ClientID, $TenantID, $Credential, $effectiveServiceUrl, $authUrl) + $token.SetTokenMetadata($result) + Write-Verbose "[$serviceName] Connected via Credential ($($token.Scopes -join ', '))" + } + #endregion ROPC + + #region AppSecret + AppSecret { + Write-Verbose "[$serviceName] Connecting via AppSecret" + try { $result = Connect-ServiceClientSecret @commonParam -ClientSecret $ClientSecret -ErrorAction Stop } + catch { + Write-Warning "[$serviceName] Failed to connect: $_" + $PSCmdlet.ThrowTerminatingError($_) + } + + $token = [EntraToken]::new($serviceName, $ClientID, $TenantID, $ClientSecret, $effectiveServiceUrl, $authUrl) + $token.SetTokenMetadata($result) + Write-Verbose "[$serviceName] Connected via AppSecret ($($token.Scopes -join ', '))" + } + #endregion AppSecret + + #region AppCertificate + AppCertificate { + Write-Verbose "[$serviceName] Connecting via Certificate" + try { $certificateObject = Resolve-Certificate -BoundParameters $PSBoundParameters } + catch { + Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "Cannot resolve certificate" -ErrorRecord $_ -Category InvalidArgument + } + + try { $result = Connect-ServiceCertificate @commonParam -Certificate $certificateObject -ErrorAction Stop } + catch { + Write-Warning "[$serviceName] Failed to connect: $_" + $PSCmdlet.ThrowTerminatingError($_) + } + + $token = [EntraToken]::new($serviceName, $ClientID, $TenantID, $certificateObject, $effectiveServiceUrl, $authUrl) + $token.SetTokenMetadata($result) + Write-Verbose "[$serviceName] Connected via Certificate ($($token.Scopes -join ', '))" + } + #endregion AppCertificate + + #region KeyVault + KeyVault { + Write-Verbose "[$serviceName] Connecting via KeyVault" + $failure = $null + foreach ($secretEntry in $SecretName) { + try { $secret = Get-VaultSecret -VaultName $VaultName -SecretName $secretEntry } + catch { + Write-Warning "[$serviceName] Failed to retrieve secret from KeyVault: $_" + $PSCmdlet.ThrowTerminatingError($_) + } + try { + $result = switch ($secret.Type) { + Certificate { Connect-ServiceCertificate @commonParam -Certificate $secret.Certificate -ErrorAction Stop } + ClientSecret { Connect-ServiceClientSecret @commonParam -ClientSecret $secret.ClientSecret -ErrorAction Stop } + } + } + catch { + Write-Verbose "[$serviceName] Failed to connect using secret $($secretEntry): $_" + if (-not $failure) { $failure = $_ } + continue + } + $token = [EntraToken]::new($serviceName, $ClientID, $TenantID, $effectiveServiceUrl, $VaultName, $secretEntry, $authUrl) + $token.SetTokenMetadata($result) + + Write-Verbose "[$serviceName] Connected via KeyVault ($($token.Scopes -join ', '))" + break main + } + # Only reached if all secrets failed + $PSCmdlet.ThrowTerminatingError($failure) + } + #endregion KeyVault + + #region Identity + Identity { + Write-Verbose "[$serviceName] Connecting via Managed Identity" + + try { $result = Connect-ServiceIdentity -Resource $commonParam.Resource -IdentityID $IdentityID -IdentityType $IdentityType -ErrorAction Stop } + catch { + if (-not $FallBackAzAccount) { $PSCmdlet.ThrowTerminatingError($_) } + + try { + $newParam = @{} + $validParam = $PSCmdlet.MyInvocation.MyCommand.ParameterSets.Where{$_.Name -eq 'AzAccount'}.Parameters.Name + foreach ($pair in $PSBoundParameters.GetEnumerator()) { + if ($pair.Key -notin $validParam) { continue } + $newParam[$pair.Key] = $pair.Value + } + $newParam.AsAzAccount = $true + Connect-EntraService @newParam + + break main # Successfully connected + } + catch { + Write-Warning "Fallback to AzAccount failed: $_" + } + + $PSCmdlet.ThrowTerminatingError($_) + } + + $token = [EntraToken]::new($serviceName, $effectiveServiceUrl, $IdentityID, $IdentityType) + $token.SetTokenMetadata($result) + + Write-Verbose "[$serviceName] Connected via Managed Identity ($($token.Scopes -join ', '))" + } + #endregion Identity + + #region Federated + Federated { + Write-Verbose "[$serviceName] Connecting via Federated Credential" + + try { $result,$provider = Connect-ServiceFederated @commonParam -Assertion $Assertion -Provider $FederationProvider -ErrorAction Stop } + catch { + if (-not $FallBackAzAccount) { $PSCmdlet.ThrowTerminatingError($_) } + + try { + $newParam = @{} + $validParam = $PSCmdlet.MyInvocation.MyCommand.ParameterSets.Where{$_.Name -eq 'AzAccount'}.Parameters.Name + foreach ($pair in $PSBoundParameters.GetEnumerator()) { + if ($pair.Key -notin $validParam) { continue } + $newParam[$pair.Key] = $pair.Value + } + $newParam.AsAzAccount = $true + Connect-EntraService @newParam + + break main # Successfully connected + } + catch { + Write-Warning "Fallback to AzAccount failed: $_" + } + + $PSCmdlet.ThrowTerminatingError($_) + } + + $token = [EntraToken]::new($serviceName, $ClientID, $TenantID, $provider, $effectiveServiceUrl, $authUrl) + $token.SetTokenMetadata($result) + + Write-Verbose "[$serviceName] Connected via Federated Credential ($($token.Scopes -join ', '))" + } + #endregion Federated + + #region AzAccount + AzAccount { + Write-Verbose "[$serviceName] Connecting via existing Az.Accounts session" + + try { $result = Connect-ServiceAzure -Resource $commonParam.Resource -ShowDialog $ShowDialog -ErrorAction Stop } + catch { + Write-Warning "[$serviceName] Failed to connect: $_" + $PSCmdlet.ThrowTerminatingError($_) + } + + $token = [EntraToken]::new($serviceName, $effectiveServiceUrl, $ShowDialog) + $token.TenantID = $result.TenantID + $token.ClientID = $result.ClientID + $token.SetTokenMetadata($result) + + Write-Verbose "[$serviceName] Connected via existing Az.Accounts session ($($token.Scopes -join ', '))" + } + #endregion AzAccount + } + #endregion Connection + + #region Copy Service Metadata + if ($serviceObject) { + if ($serviceObject.Query.Count -gt 0) { + $token.Query = $serviceObject.Query.Clone() + } + if ($serviceObject.Header.Count -gt 0) { + $token.Header = $serviceObject.Header.Clone() + } + if ($serviceObject.RawOnly) { + $token.RawOnly = $true + } + } + if ($doRegister) { $script:_EntraTokens[$serviceName] = $token } + #endregion Copy Service Metadata + + if ($MakeDefault -and -not $Resource) { + $script:_DefaultService = $serviceName + } + if ($doPassThru) { $token } + } + } +} + +function Get-EntraService { + <# + .SYNOPSIS + Returns the list of available Entra ID services that can be connected to. + + .DESCRIPTION + Returns the list of available Entra ID services that can be connected to. + Includes for each the endpoint/service url and the default requested scopes. + + .PARAMETER Name + Name of the service to return. + Defaults to: * + + .EXAMPLE + PS C:\> Get-EntraService + + List all available services. + #> + [CmdletBinding()] + param ( + [ArgumentCompleter({ Get-ServiceCompletion $args })] + [string] + $Name = '*' + ) + process { + $script:_EntraEndpoints.Values | Where-Object Name -like $Name + } +} + +function Get-EntraToken { + <# + .SYNOPSIS + Returns the session token of an Entra ID connection. + + .DESCRIPTION + Returns the session token of an Entra ID connection. + The main use for those token objects is calling their "GetHeader()" method to get an authentication header + that automatically refreshes tokens as needed. + + .PARAMETER Service + The service for which to retrieve the token. + Defaults to: * + + .EXAMPLE + PS C:\> Get-EntraToken + + Returns all current session tokens + #> + [CmdletBinding()] + param ( + [ArgumentCompleter({ Get-ServiceCompletion $args })] + [string] + $Service = '*' + ) + process { + $script:_EntraTokens.Values | Where-Object Service -like $Service + } +} + +function Import-EntraToken { + <# + .SYNOPSIS + Imports a token into the local token store. + + .DESCRIPTION + Imports a token into the local token store. + This command is intended for use in a runspace scenario, for passing tokens from the main runspace into background environments. + The input-token object is cloned into a runspace-local token object and registered to its service. + + After performing the conversion, it will try to renew the token object. + + .PARAMETER Token + The token object to import. + Should be a token object created by EntraAuth's Connect-EntraService command. + Usually returned by Get-EntraToken, after finishing the connection. + + .PARAMETER PassThru + Rather than registering the token into the Entra token store in memory, return it as an object. + Useful for ronspace-localizing a token not associated with any given service. + + .PARAMETER NoRenew + Do not renew the token after importing it. + By default, newly localized tokens will try to renew themselves, to avoid parallel use of the same access token instance. + + .EXAMPLE + PS C:\> Import-EntraToken -Token $using:tokens + + Imports all tokens stored in $tokens of the calling runspace. + For use in scenarios such as background runspaces within "ForEach-Object -Parallel" + #> + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [object[]] + $Token, + + [switch] + $PassThru, + + [switch] + $NoRenew + ) + process { + foreach ($tokenObject in $Token) { + $newToken = [EntraToken]::new() + foreach ($propertyName in $newToken.PSObject.Properties.Name) { + if ($null -eq $tokenObject.$propertyName) { continue } + if ($tokenObject.$propertyName -is [hashtable]) { + $newToken.$propertyName = $tokenObject.$propertyName.Clone() + } + else { + $newToken.$propertyName = $tokenObject.$propertyName + } + } + + if ( + -not $newToken.Service -or + -not $newToken.AccessToken -or + -not $newToken.ClientID -or + -not $newToken.TenantID + ) { + Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "Invalid Input Object! An Entra token object must have a Service, AccessToken, ClientID and TenantID. Item received: $tokenObject" + } + + #region Renew Token + if ( + -not $NoRenew -and + ( + $newToken.Type -notin 'DeviceCode', 'Browser' -or + $newToken.RefreshToken + ) + ) { + $newToken.RenewToken() + } + #endregion Renew Token + + if ($PassThru) { $newToken } + else { $script:_EntraTokens[$newToken.Service] = $newToken } + } + } +} + +function New-EntraCustomToken { + <# + .SYNOPSIS + Create a custom token compatible with EntraAuth. + + .DESCRIPTION + Create a custom token compatible with EntraAuth. + This allows directly integrating APIs that do not operate with default OAuth into the EntraAuth toolset. + + .PARAMETER ServiceUrl + The URL requests are sent against. + + .PARAMETER HeaderCode + The code that calculates the header (including authentication information) to include in the request. + The scriptblock receives one argument: The token itself. + Must return a single hashtable. + + .PARAMETER Service + The name of the service to register the token under. + Does not have to be a formally registered service, can be an arbitrary name. + Specifying this parameter prevents the token from being returned as output, unless combined with -PassThru. + + .PARAMETER PassThru + Return the token as output. + By default, when specifying a service name, this command produces no output. + + .PARAMETER TenantID + TenantID to connect to. + Purely cosmetic, unless accessed from the header code. + + .PARAMETER ClientID + ClientID to connect as. + Purely cosmetic, unless accessed from the header code. + + .PARAMETER Header + Header information to include in all requests against this API. + Additional header entries to include in every request. + Will be added to those returned from the HeaderCode and need not be considered within that code. + + .PARAMETER Query + Additional query parameters to include in all requests against this API. + + .PARAMETER Data + Additional information to store in the token object. + Used by the HeaderCode scriptblock. + Use this parameter to include information such as PATs, API keys or similar pieces of information. + + .PARAMETER RawOnly + All requests throug this token should not use the default response processing. + This will prevent Invoke-EntraRequest from providing most of its usual assistance. + + .EXAMPLE + PS C:\> New-EntraCustomToken -Service AzDevMyProject -ServiceUrl 'https://dev.azure.com/contoso/myproject/_apis/wit' -Data @{ PAT = $pat } -HeaderCode { + param ($Token) + $base64AuthInfo = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes(':' + $($Token.Data.PAT | ConvertFrom-SecureString -AsPlainText))) + return @{ + Authorization = "Basic $base64AuthInfo" + 'Content-Type' = 'application/json' + } + } + + Registers a new token for Azure DevOps, using PAT to authenticate. + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $ServiceUrl, + + [Parameter(Mandatory = $true)] + [scriptblock] + $HeaderCode, + + [string] + $Service, + + [switch] + $PassThru, + + [string] + $TenantID = '', + + [string] + $ClientID = '', + + [hashtable] + $Header = @{}, + + [hashtable] + $Query = @{}, + + [hashtable] + $Data = @{}, + + [switch] + $RawOnly + ) + process { + $newToken = [EntraToken]::new() + $newToken.Type = 'Custom' + $newToken.ServiceUrl = $ServiceUrl + $newToken.HeaderCode = $HeaderCode + if ($Service) { $newToken.Service = $Service } + else { $newToken.Service = '' } + $newToken.TenantID = $TenantID + $newToken.ClientID = $ClientID + $newToken.Header = $Header.Clone() + $newToken.Query = $Query.Clone() + $newToken.Data = $Data.Clone() + $newToken.RawOnly = $RawOnly.ToBool() + + if ($Service) { + $script:_EntraTokens[$Service] = $newToken + } + if ($PassThru -or -not $Service) { + $newToken + } + } +} + +function Register-EntraService { + <# + .SYNOPSIS + Define a new Entra ID Service to connect to. + + .DESCRIPTION + Define a new Entra ID Service to connect to. + This allows defining new endpoints to connect to ... or overriding existing endpoints to a different configuration. + + .PARAMETER Name + Name of the Service. + + .PARAMETER ServiceUrl + The base Url requests will use. + + .PARAMETER Resource + The Resource ID. Used when connecting to identify which scopes of an App Registration to use. + + .PARAMETER DefaultScopes + Default scopes to request. + Used in interactive delegate flows to provide a good default user experience. + Default scopes should usually include common read scenarios. + + .PARAMETER Header + Header data to include in each request. + + .PARAMETER HelpUrl + Link for more information about this service. + Ideally to documentation that helps setting up the connection. + + .PARAMETER NoRefresh + Delegate authentication flows should not request refresh tokens. + By default, delegate authentication flows will automatically request offline_access to get a refresh token. + This refresh token allows requesting new tokens when the current one is expiring without requiring additional + interactive logon actions. + However, not all services support this scope. + + .PARAMETER Parameters + Extra parameters a request will require. + It expects a hashtable with the key being the parameter name, and the value being a description of that parameter. + The ServiceUrl must include a placeholder for each parameter to insert into it. + + Example: + Parameter: @{ VaultName = 'Name of the Key Vault to execute against' } + ServiceUrl: https://%VAULTNAME%.vault.azure.net + + .PARAMETER Query + Extra Query Parameters to automatically include on all requests. + + .PARAMETER RawOnly + Disable default API response handling. + By default, when executing a request via Invoke-EntraRequest, the response is processed as if it were a default Graph API standard response. + Many other MS APIs follow the same standard, but not all do so. + When enabling this setting on a service, all requests against that service will NOT have that processing applied and instead return raw responses. + + .PARAMETER Environment + What environment this service should connect to. + Defaults to: 'Global' + + .PARAMETER AuthenticationUrl + The url used for the authentication requests to retrieve tokens. + Usually determined by the "Environment" parameter, but may be overridden in case of need. + + .EXAMPLE + PS C:\> Register-EntraService -Name Endpoint -ServiceUrl 'https://api.securitycenter.microsoft.com/api' -Resource 'https://api.securitycenter.microsoft.com' + + Registers the defender for endpoint API as a service. + + .EXAMPLE + PS C:\> Register-EntraService -Name 'PowerBI' -ServiceUrl 'https://api.powerbi.com/v1.0/myorg' -Resource 'https://analysis.windows.net/powerbi/api' -DefaultScopes @('Dataset.Read.All', 'Report.Read.All') -Header @{ 'Accept' = 'application/json' } + + Registers Power BI REST API service with common read scopes and required headers. + + .EXAMPLE + PS C:\> Register-EntraService -Name 'SharePointOnline' -ServiceUrl 'https://%TENANT%.sharepoint.com/_api' -Resource 'https://%TENANT%.sharepoint.com' -Parameters @{ Tenant = 'SharePoint tenant name (e.g., contoso)' } -DefaultScopes @('Sites.Read.All') -Query @{ '$format' = 'json' } + + Registers SharePoint Online REST API with dynamic tenant URL, requiring a tenant parameter and automatically formatting responses as JSON. + + .EXAMPLE + PS C:\> Register-EntraService -Name 'CustomCRM' -ServiceUrl 'https://crm.contoso.com/api/v2' -Resource 'api://contoso-crm-app' -NoRefresh -RawOnly -Header @{ 'X-API-Version' = '2.0'; 'Accept' = 'application/json' } + + Registers a custom CRM API that doesn't support refresh tokens and requires raw response handling with custom API versioning headers. + + #> + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $Name, + + [Parameter(Mandatory = $true)] + [string] + $ServiceUrl, + + [Parameter(Mandatory = $true)] + [string] + $Resource, + + [AllowEmptyCollection()] + [string[]] + $DefaultScopes = @(), + + [hashtable] + $Header = @{}, + + [string] + $HelpUrl, + + [switch] + $NoRefresh, + + [hashtable] + $Parameters = @{}, + + [Hashtable] + $Query = @{}, + + [switch] + $RawOnly, + + [Environment] + $Environment = 'Global', + + [string] + $AuthenticationUrl + ) + process { + $command = Get-Command Invoke-EntraRequest + $badParameters = $Parameters.Keys | Where-Object { $_ -in $command.Parameters.Keys } + if ($badParameters) { + Invoke-TerminatingException -Cmdlet $PSCmdlet -Message "Cannot define parameters that collide with Invoke-EntraRequest: $($badParameters -join ', ')" + } + $authUrl = switch ("$Environment") { + 'China' { 'https://login.chinacloudapi.cn' } + 'USGov' { 'https://login.microsoftonline.us' } + 'USGovDOD' { 'https://login.microsoftonline.us' } + default { 'https://login.microsoftonline.com' } + } + if ($AuthenticationUrl) { $authUrl = $AuthenticationUrl.TrimEnd('/') } + + $script:_EntraEndpoints[$Name] = [PSCustomObject]@{ + PSTypeName = 'EntraAuth.Service' + Name = $Name + ServiceUrl = $ServiceUrl + Resource = $Resource + DefaultScopes = $DefaultScopes + Header = $Header + HelpUrl = $HelpUrl + NoRefresh = $NoRefresh.ToBool() + Parameters = $Parameters + Query = $Query + RawOnly = $RawOnly.ToBool() + AuthenticationUrl = $authUrl + } + } +} + +function Set-EntraService { + <# + .SYNOPSIS + Modify the settings on an existing Service configuration. + + .DESCRIPTION + Modify the settings on an existing Service configuration. + Service configurations are defined using Register-EntraService and define how connections and requests to a specific API service / endpoint are performed. + + .PARAMETER Name + The name of the already existing Service configuration. + + .PARAMETER ServiceUrl + The base Url requests will use. + + .PARAMETER Resource + The Resource ID. Used when connecting to identify which scopes of an App Registration to use. + + .PARAMETER DefaultScopes + Default scopes to request. + Used in interactive delegate flows to provide a good default user experience. + Default scopes should usually include common read scenarios. + + .PARAMETER Header + Header data to include in each request. + + .PARAMETER HelpUrl + Link for more information about this service. + Ideally to documentation that helps setting up the connection. + + .PARAMETER NoRefresh + Delegate authentication flows should not request refresh tokens. + By default, delegate authentication flows will automatically request offline_access to get a refresh token. + This refresh token allows requesting new tokens when the current one is expiring without requiring additional + interactive logon actions. + However, not all services support this scope. + + .EXAMPLE + PS C:\> Set-EntraService -Name Endpoint -ServiceUrl 'https://api-us.securitycenter.microsoft.com/api' + + Changes the service url for the "Endpoint" service to 'https://api-us.securitycenter.microsoft.com/api'. + Note: It is generally recommened to select the service url most suitable for your tenant, geographically: + https://learn.microsoft.com/en-us/microsoft-365/security/defender-endpoint/api/exposed-apis-list?view=o365-worldwide#versioning + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] + [ArgumentCompleter({ Get-ServiceCompletion $args })] + [ValidateScript({ Assert-ServiceName -Name $_ })] + [string] + $Name, + + [string] + $ServiceUrl, + + [string] + $Resource, + + [AllowEmptyCollection()] + [string[]] + $DefaultScopes, + + [Hashtable] + $Header, + + [string] + $HelpUrl, + + [switch] + $NoRefresh + ) + process { + $service = $script:_EntraEndpoints.$Name + if ($PSBoundParameters.Keys -contains 'ServiceUrl') { $service.ServiceUrl = $ServiceUrl } + if ($PSBoundParameters.Keys -contains 'Resource') { $service.Resource = $Resource } + if ($PSBoundParameters.Keys -contains 'DefaultScopes') { $service.DefaultScopes = $DefaultScopes } + if ($PSBoundParameters.Keys -contains 'Header') { $service.Header = $Header } + if ($PSBoundParameters.Keys -contains 'HelpUrl') { $service.HelpUrl = $HelpUrl } + if ($PSBoundParameters.Keys -contains 'NoRefresh') { $service.HelpUrl = $NoRefresh.ToBool() } + } +} + +function Invoke-EntraRequest { + <# + .SYNOPSIS + Executes a web request against an entra-based service + + .DESCRIPTION + Executes a web request against an entra-based service + Handles all the authentication details once connected using Connect-EntraService. + + .PARAMETER Path + The relative path of the endpoint to query. + For example, to retrieve Microsoft Graph users, it would be a plain "users". + To access details on a particular defender for endpoint machine instead it would look thus: "machines/1e5bc9d7e413ddd7902c2932e418702b84d0cc07" + + .PARAMETER Body + Any body content needed for the request. + + .PARAMETER Query + Any query content to include in the request. + In opposite to -Body this is attached to the request Url and usually used for filtering. + + .PARAMETER Method + The Rest Method to use. + Defaults to GET + + .PARAMETER RequiredScopes + Any authentication scopes needed. + Used for documentary purposes only. + + .PARAMETER Header + Any additional headers to include on top of authentication and content-type. + + .PARAMETER ContentType + Specify the content-type of this request. + Equivalent to specifying it as a header entry, but added as dedicated parameter for user convenience. + + .PARAMETER Service + Which service to execute against. + Determines the API endpoint called to. + Defaults to "Graph" + + .PARAMETER SerializationDepth + How deeply to serialize the request body when converting it to json. + Defaults to: 99 + + .PARAMETER Token + A Token as created and maintained by this module. + If specified, it will override the -Service parameter. + + .PARAMETER NoPaging + Do not automatically page through responses sets. + By default, Invoke-EntraRequest is going to keep retrieving result pages until all data has been retrieved. + + .PARAMETER Raw + Do not process the response object and instead return the raw result returned by the API. + + .PARAMETER DeltaSession + A hashtable including delta sessions. + Use together with the delta endpoints, e.g. for the Graph API's user delta endpoint: + https://learn.microsoft.com/en-us/graph/api/user-delta + Provide an empty hashtable on the first request, the delta token data will be inserted into it. + Provide the same token for subsequent delta requests. + + This allows retrieving changes over time, without having to reload the entire dataset. + + .PARAMETER MinimalDelta + When receiving delta data, only return the changed properties (plus a unique identifier), rather than the full object. + Only used together with DeltaSession + + .EXAMPLE + PS C:\> Invoke-EntraRequest -Path 'alerts' -RequiredScopes 'Alert.Read' + + Return a list of defender alerts. + + .EXAMPLE + PS C:\> Invoke-EntraRequest -Path 'users/delta' -DeltaSession $delta + + Retrieves all users on first request. + Subsequent calls will only return users that have been changed in the meantime. +#> + [CmdletBinding(DefaultParameterSetName = 'default')] + param ( + [Parameter(Mandatory = $true)] + [string] + $Path, + + $Body, + + [Hashtable] + $Query = @{ }, + + [string] + $Method = 'GET', + + [string[]] + $RequiredScopes, + + [hashtable] + $Header = @{}, + + [string] + $ContentType, + + [ArgumentCompleter({ Get-ServiceCompletion $args })] + [ValidateScript({ Assert-ServiceName -Name $_ -IncludeTokens })] + [string] + $Service = $script:_DefaultService, + + [ValidateRange(1, 666)] + [int] + $SerializationDepth = 99, + + [EntraToken] + $Token, + + [switch] + $NoPaging, + + [switch] + $Raw, + + [hashtable] + $DeltaSession, + + [switch] + $MinimalDelta + ) + + DynamicParam { + if ($Resource) { return } + + $actualService = $Service + if (-not $actualService) { $actualService = $script:_DefaultService } + $serviceObject = $script:_EntraEndpoints.$actualService + if (-not $serviceObject) { return } + if ($serviceObject.Parameters.Count -lt 1) { return } + + $results = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new() + foreach ($pair in $serviceObject.Parameters.GetEnumerator()) { + $parameterAttribute = [System.Management.Automation.ParameterAttribute]::new() + $parameterAttribute.ParameterSetName = '__AllParameterSets' + $parameterAttribute.Mandatory = $true + $parameterAttribute.HelpMessage = $pair.Value + $attributesCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new() + $attributesCollection.Add($parameterAttribute) + $RuntimeParam = [System.Management.Automation.RuntimeDefinedParameter]::new($pair.Key, [object], $attributesCollection) + + $results.Add($pair.Key, $RuntimeParam) + } + + $results + } + + begin { + if ($Token) { + $tokenObject = $Token + } + else { + Assert-EntraConnection -Service $Service -Cmdlet $PSCmdlet -RequiredScopes $RequiredScopes + $tokenObject = $script:_EntraTokens.$Service + } + + $serviceObject = $script:_EntraEndpoints.$($tokenObject.Service) + if ($ContentType) { $Header['Content-Type'] = $ContentType } + } + process { + $parameters = @{ + Method = $Method + Uri = Resolve-RequestUri -TokenObject $tokenObject -ServiceObject $serviceObject -BoundParameters $PSBoundParameters + } + $originalUri = $parameters.Uri + + if ($PSBoundParameters.Keys -contains 'Body') { + if ($Body -is [string]) { + $parameters.Body = $Body + } + else { + $parameters.Body = $Body | ConvertTo-Json -Compress -Depth $SerializationDepth + } + } + # In PS5.1, some methods cannot contain a body + $noBodyMethods = 'Default', 'Get', 'Head' + if ($PSVersionTable.PSVersion.Major -lt 6 -and $Method -in $noBodyMethods) { + $parameters.Remove('Body') + } + + $queryClone = $Query.Clone() + if ($DeltaSession -and $DeltaSession[$originalUri].Token) { + $queryClone['$deltaToken'] = $DeltaSession[$originalUri].Token + } + $parameters.Uri += ConvertTo-QueryString -QueryHash $queryClone -DefaultQuery $tokenObject.Query + + do { + $tempHeader = $tokenObject.GetHeader().Clone() # GetHeader() automatically refreshes expired tokens + foreach ($pair in $Header.GetEnumerator()) { $tempHeader[$pair.Key] = $pair.Value } + if ($MinimalDelta) { $tempHeader['Prefer'] = 'return=minimal' } + $parameters.Headers = $tempHeader + Write-Verbose "Executing Request: $($Method) -> $($parameters.Uri)" + try { $result = Invoke-RestMethod @parameters -ErrorAction Stop } + catch { + $letItBurn = $true + $failure = $_ + + if ($_.ErrorDetails.Message) { + try { $details = $_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction Stop } + catch { $details = $_.ErrorDetails.Message } + if ($details.Error.Code -eq 'TooManyRequests') { + Write-Verbose "Throttling: $($details.error.message)" + $delay = 1 + ($details.error.message -replace '^.+ (\d+) .+$', '$1' -as [int]) + if ($delay -gt 5) { Write-Warning "Request is being throttled for $delay seconds" } + Start-Sleep -Seconds $delay + try { + $result = Invoke-RestMethod @parameters -ErrorAction Stop + $letItBurn = $false + } + catch { + $failure = $_ + } + } + } + + if ($letItBurn) { + Write-Warning "Request failed: $($Method) -> $($parameters.Uri)" + $PSCmdlet.ThrowTerminatingError($failure) + } + } + if (-not $Raw -and -not $tokenObject.RawOnly -and $result.PSObject.Properties.Where{ $_.Name -eq 'value' }) { $result.Value } + else { $result } + $parameters.Uri = $result.'@odata.nextLink' + + if ($DeltaSession -and $result.'@odata.deltaLink') { + $deltaToken = (($result.'@odata.deltaLink' -split '\?')[1] -split '=')[-1] + if (-not $DeltaSession[$originalUri]) { + $DeltaSession[$originalUri] = @{} + } + $DeltaSession[$originalUri]['Token'] = $deltaToken + } + } + while ($parameters.Uri -and -not $NoPaging) + } +} + +function Get-EntraFederationProvider { + <# + .SYNOPSIS + Lists all registered Federation Providers. + + .DESCRIPTION + Lists all registered Federation Providers. + Federation Providers are an EntraAuth concept and used to automatically do what is needed to access and use a Federated Credential, based on its environment. + See the documentation on Register-EntraFederationProvider for more details. + + .PARAMETER Name + The name of the provider to filter by. + Defaults to: * + + .EXAMPLE + PS C:\> Get-EntraFederationProvider + + Lists all registered Federation Providers. + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "")] + [CmdletBinding()] + param ( + [ArgumentCompleter({ + param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) + foreach ($provider in Get-EntraFederationProvider) { + if ($provider.Name -notlike "$wordToComplete*") { continue } + $text = $provider.Name + if ($text -match '\s') { $text = "'$($provider.Name -replace "'", "''")'" } + + [System.Management.Automation.CompletionResult]::new($text, $text, 'ParameterValue', $provider.Description) + } + })] + [string] + $Name = '*' + ) + process { + ($script:_FederationProviders.Values) | Where-Object Name -Like $Name | Sort-Object Priority + } +} + +function Register-EntraFederationProvider { + <# + .SYNOPSIS + Register logic to automatically retrieve the assertion needed in a Federated Credential authentication flow. + + .DESCRIPTION + Register logic to automatically retrieve the assertion needed in a Federated Credential authentication flow. + Federated credentials allow granting access to a trusted entity without requiring a secret. + + For example, with that it becomes possible, to authorize a github action to authenticate to Entra. + However, in order for the Github Action to be able to do that, it first needs to authenticate to Github and get a special token. + + This provider defined here serves to implement that step - and to allow you to do the same for your own providers. + + More Resources on Federated Credentials: + https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust?pivots=identity-wif-apps-methods-azp + https://learn.microsoft.com/en-us/entra/identity-platform/v2-oauth2-client-creds-grant-flow?wt.mc_id=SEC-MVP-5004985#third-case-access-token-request-with-a-federated-credential + + .PARAMETER Name + The name of the Federation Provider. + Pick something that represents the context the user would expect (e.g. "GithubAction", "FunctionApp", ...). + It usually would be related to the environment from which you connect. + + .PARAMETER Description + A description of the provider. + Especially useful to explain non-intuitive setup steps that are required to get things started. + + .PARAMETER Priority + How high the priority of the provider is. + The lower the number, the earlier it is tested for. + This property is used when auto-detecting which Federation Provider should be used. + The first match will stop further processing. + + .PARAMETER Test + A piece of code used to test, whether the Federation Provider can be used in the current situation. + This is used when trying to automatically detect, which provider to use. + + .PARAMETER Code + Code that generates a JWT token used as an Assertion for the Entra authentication, essentially serving as its secret. + + .EXAMPLE + PS C:\> Register-EntraFederationProvider -Name GithubAction -Priority 10 -Description 'For use within a Github Action. Remember to configure your workflow to use the "id-token: write" permission' -Test $test -Code $authCode + + Configures the GithubAction Federation Provider. + Assuming the scriptblocks provided work, this will allow simply running something like this within a Github Action: + Connect-EntraService -ClientID $clientID -TenantID $tenantID -Federated + Hint: This provider is preconfigured in EntraAuth, so this should work as it is. Use Get-EntraFederationProvider to inspect the actual implementing code. + #> + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] + $Name, + + [string] + $Description, + + [int] + $Priority = 50, + + [Parameter(Mandatory = $true)] + [scriptblock] + $Test, + + [Parameter(Mandatory = $true)] + [scriptblock] + $Code + ) + process { + $script:_FederationProviders[$Name] = [FederationProvider]@{ + Name = $Name + Description = $Description + Priority = $Priority + Test = $Test + Code = $Code + Type = 'Registered' + } + } +} + +function Resolve-EntraFederationProvider { + <# + .SYNOPSIS + Resolves which Federation Provider to use to calculate the Federation Credentials to use. + + .DESCRIPTION + Resolves which Federation Provider to use to calculate the Federation Credentials to use. + This executes the test code for all registered providers (in the order of their priority) until one applies. + + Federation Providers are an EntraAuth concept and used to automatically do what is needed to access and use a Federated Credential, based on its environment. + See the documentation on Register-EntraFederationProvider for more details. + + .PARAMETER Exclude + The Federation Provider to skip. + + .EXAMPLE + PS C:\> Resolve-EntraFederationProvider + + Resolves which Federation Provider to use to calculate the Federation Credentials to use. + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSReviewUnusedParameter", "")] + [CmdletBinding()] + param ( + [ArgumentCompleter({ + param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) + foreach ($provider in Get-EntraFederationProvider) { + if ($provider.Name -notlike "$wordToComplete*") { continue } + $text = $provider.Name + if ($text -match '\s') { $text = "'$($provider.Name -replace "'", "''")'" } + + [System.Management.Automation.CompletionResult]::new($text, $text, 'ParameterValue', $provider.Description) + } + })] + [string[]] + $Exclude + ) + process { + foreach ($provider in Get-EntraFederationProvider | Sort-Object Priority) { + if ($provider.Name -in $Exclude) { continue } + + if (& $provider.Test) { return $provider } + } + } +} + +function New-EntraFilterBuilder { + <# + .SYNOPSIS + Creates a new OData-Filter construction helper. + + .DESCRIPTION + Creates a new OData-Filter construction helper. + This helper class was designed to simplify the creation of OData filters for APIs such as the Microsoft Graph API. + Call the ".Add(...)" method to specify filter conditions. + + There are three ways to do so: + A) .Add(property, operator, value) + A single property comparison, with a specific operator and value. + + B) .Add(customFilter) + A custom piece of OData filter text. + + C) .Add(filterbuilder) + The output of another filterbuilder becomes part of the conditions for this one. + This allows building complex, nested filter statements. + + Finally, call ".Get()" to retrieve the full OData filter string or ".GetHeader()" to retrieve the filter header hashtable. + + For more in-depth help with the type, call the '.GetHelp()' method on the object. + + Useful Resources: + List of valid filter conditions: + https://learn.microsoft.com/en-us/graph/filter-query-parameter?tabs=http#operators-and-functions-supported-in-filter-expressions + + .PARAMETER Logic + The logic by which individual filter conditions are merged. + Options: + - AND (default) + - OR + + .EXAMPLE + PS C:\> $filter = New-EntraFilterBuilder + PS C:\> $filter.Add('displayName', 'eq', 'John Doe') + PS C:\> $filter.Add('organization', 'in', @('Contoso', 'Fabrikam')) + PS C:\> $filter.Get() + + Will return: "displayName eq 'John Doe' and organization in ('Contoso', 'Fabrikam')" + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] + [OutputType([FilterBuilder])] + [CmdletBinding()] + param ( + [ValidateSet('AND','OR')] + [string] + $Logic = 'AND' + ) + + process { + [FilterBuilder]::new($Logic) + } +} + +function New-EntraServiceSelector { + <# + .SYNOPSIS + Creates a helper type designed to help make a module implementing EntraAuth more flexible about what EntraAUth service to use. + + .DESCRIPTION + Creates a helper type designed to help make a module implementing EntraAuth more flexible about what EntraAUth service to use. + + While a module can easily define what service to use when calling Invoke-EntraRequest, this has some concerns: + + If multiple modules require the same service, they may interfere with each other by trying to use separate applications or having different scope requirements. + + If each module defines their own service instance (e.g. "Graph.MyModule"), then a script using multiple modules needs to authenticate multiple times, even if they all could use the same connection/token. + + The Service Selector aims to be a simple solution to this problem. + It is intended for _Modules_ that implement EntraAuth, not individual scripts. + + To fully execute on this, you will need to implement this in three locations: + - During Module Import: Declare defaults & Selector. + - At the beginning of your functions: Select chosen services. + - When executing requests: Use service as chosen. + + #======================================================================================================= + # During Module Import + $script:_services = @{ Graph = 'Graph'; MDE = 'Endpoint' } + $script:_serviceSelector = New-EntraServiceSelector -DefaultServices $script:_services + + # During the Begin stage of each function using EntraAuth + begin { + $services = $script:_serviceSelector.GetServiceMap($ServiceMap) # $ServiceMap is a hashtable parameter offered by your function + Assert-EntraConnection -Cmdlet $PSCmdlet -Service $services.Graph + } + + # When executing the actual request, later in the function + Invoke-EntraService -Service $services.Graph -Path users + #======================================================================================================= + + With this, somebody could call your command - let's call it "Get-DepartmentUser" - like this: + Get-DepartmentUser -ServiceMap @{ Graph = 'GraphBeta' } + And your function would use the beta version of the Graph api, without affecting any other script or module calling your function. + + Example Implementations: + - During Module Import: + https://github.com/FriedrichWeinmann/EntraAuth.Graph.Application/blob/master/EntraAuth.Graph.Application/internal/scripts/variables.ps1 + - Used in Functions: + https://github.com/FriedrichWeinmann/EntraAuth.Graph.Application/blob/3c5e9f3de31fd7946e6fe9ebdb938986165ff5ca/EntraAuth.Graph.Application/functions/Get-EAGAppRegistration.ps1#L78 + + .PARAMETER DefaultServices + The Default services to use. + Provide a hashtable of Labels mapping to EntraAuth services. + Example: + @{ Graph = 'Graph'; MDE = 'Endpoint' } + The key is what you use in your code as a label, the Value is the actual service in EntraAuth. + + .EXAMPLE + PS C:\> $script:_serviceSelector = New-EntraServiceSelector -DefaultServices $script:_services + + Creates a new ServiceSelector object and stores it in $script:_serviceSelector + #> + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] + [OutputType([ServiceSelector])] + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [hashtable] + $DefaultServices + ) + process { + [ServiceSelector]::new($DefaultServices) + } +} + +# Available Tokens +$script:_EntraTokens = @{} + +# Endpoint Configuration for Requests +$script:_EntraEndpoints = @{} + +# Plugins for automatic processing of Federated Authentication in the correct context +$script:_FederationProviders = @{} + +# The default service to connect to +$script:_DefaultService = 'Graph' + +# Registers the default service configurations +$endpointCfg = @{ + Name = 'Endpoint' + ServiceUrl = 'https://api.securitycenter.microsoft.com/api' + Resource = 'https://api.securitycenter.microsoft.com' + DefaultScopes = @() + Header = @{ 'Content-Type' = 'application/json' } + HelpUrl = 'https://learn.microsoft.com/en-us/microsoft-365/security/defender-endpoint/api/apis-intro?view=o365-worldwide' +} +Register-EntraService @endpointCfg + +$securityCfg = @{ + Name = 'Security' + ServiceUrl = 'https://api.security.microsoft.com/api' + Resource = 'https://security.microsoft.com/mtp/' + DefaultScopes = @('AdvancedHunting.Read') + Header = @{ 'Content-Type' = 'application/json' } + HelpUrl = 'https://learn.microsoft.com/en-us/microsoft-365/security/defender/api-create-app-web?view=o365-worldwide' +} +Register-EntraService @securityCfg + +$graphCfg = @{ + Name = 'Graph' + ServiceUrl = 'https://graph.microsoft.com/v1.0' + Resource = 'https://graph.microsoft.com' + DefaultScopes = @() + HelpUrl = 'https://developer.microsoft.com/en-us/graph/quick-start' +} +Register-EntraService @graphCfg + +$graphBetaCfg = @{ + Name = 'GraphBeta' + ServiceUrl = 'https://graph.microsoft.com/beta' + Resource = 'https://graph.microsoft.com' + DefaultScopes = @() + HelpUrl = 'https://developer.microsoft.com/en-us/graph/quick-start' +} +Register-EntraService @graphBetaCfg + +$azureCfg = @{ + Name = 'Azure' + ServiceUrl = 'https://management.azure.com' + Resource = 'https://management.core.windows.net/' + DefaultScopes = @() + HelpUrl = 'https://learn.microsoft.com/en-us/rest/api/azure/?view=rest-resources-2022-12-01' +} +Register-EntraService @azureCfg + +$azureKeyVaultCfg = @{ + Name = 'AzureKeyVault' + ServiceUrl = 'https://%VAULTNAME%.vault.azure.net' + Resource = 'https://vault.azure.net' + DefaultScopes = @() + HelpUrl = 'https://learn.microsoft.com/en-us/rest/api/keyvault/?view=rest-keyvault-secrets-7.4' + Parameters = @{ + VaultName = 'Name of the Key Vault to execute against' + } + Query = @{ + 'api-version' = '7.4' + } +} +Register-EntraService @azureKeyVaultCfg + +$logAnalyticsCfg = @{ + Name = 'LogAnalytics' + ServiceUrl = 'https://api.loganalytics.azure.com' + Resource = 'https://api.loganalytics.io' + DefaultScopes = @() + HelpUrl = 'https://docs.microsoft.com/en-us/azure/azure-monitor/logs/api/overview' + Header = @{ + 'Content-Type' = 'application/json' + } +} +Register-EntraService @logAnalyticsCfg + +# Default Federation Providers, to enable easy automatic Federation Authentication + +#-> Github Actions +$param = @{ + Name = 'GithubAction' + Description = 'For within the runtime of a Github Action runner. The workflow must define the permission "id-token: write", in order for the authentication to be valid.' + Priority = 10 # Lower = Attempted earlier + Test = { + if ($env:ACTIONS_ID_TOKEN_REQUEST_URL -and $env:ACTIONS_ID_TOKEN_REQUEST_TOKEN) { return $true } + + # If running in an Action but no token, warn about the misconfiguration + if (-not $env:GITHUB_ACTION -or -not $env:GITHUB_REPOSITORY) { return } + + Write-Warning @' +Github Action Runner detected, but no token available. +This usually happens based on a misconfiguration, with the Workflow not being granted access to the id-token needed. +Permission needed: + id-token: write +For more information on Github Action permission configuration, see this documentation: +https://docs.github.com/en/actions/how-tos/writing-workflows/choosing-what-your-workflow-does/controlling-permissions-for-github_token +'@ + } + Code = { + $response = Invoke-RestMethod -Uri "$env:ACTIONS_ID_TOKEN_REQUEST_URL&audience=api://AzureADTokenExchange" -Headers @{ + Authorization = "Bearer $env:ACTIONS_ID_TOKEN_REQUEST_TOKEN" + } -ErrorAction Stop + $response.Value + } +} +Register-EntraFederationProvider @param + +$param = @{ + Name = 'EntraMSI' + Description = 'Authenticate as the Managed Identity in the current context.' + Priority = 20 + Test = { + try { + $null = Connect-EntraService -Identity -Resource 'api://AzureADTokenExchange' -ErrorAction Stop + $true + } + catch { $false } + } + code = { + (Connect-EntraService -Identity -Resource 'api://AzureADTokenExchange').AccessToken + } +} +Register-EntraFederationProvider @param \ No newline at end of file diff --git a/PSFramework/modules/EntraAuth/1.8.56/LICENSE b/PSFramework/modules/EntraAuth/1.8.56/LICENSE new file mode 100644 index 00000000..194d22bc --- /dev/null +++ b/PSFramework/modules/EntraAuth/1.8.56/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Friedrich Weinmann + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/PSFramework/modules/EntraAuth/1.8.56/changelog.md b/PSFramework/modules/EntraAuth/1.8.56/changelog.md new file mode 100644 index 00000000..a56baab5 --- /dev/null +++ b/PSFramework/modules/EntraAuth/1.8.56/changelog.md @@ -0,0 +1,133 @@ +# Changelog + +## 1.8.56 (2026-09-24) + ++ Fix: Invoke-EntraRequest - fails json conversion if on error the API does not return json error message details + +## 1.8.55 (2026-06-08) + ++ Fix: Service: Azure Log Analytics not registered correctly. + +## 1.8.54 (2026-06-06) + ++ New: Service for connecting to the Log Analytics Api ++ Upd: Invoke-EntraRequest - added integrated support for delta request + +## 1.8.52 (2026-02-20) + ++ Fix: Connect-EntraService - Federated Credentials fail to refresh the token correctly ++ Fix: Filter Builder - custom filter conditions might not be evaluated correctly, if they contain multiple clauses. + +## 1.8.50 (2025-07-21) + ++ Fix: Federation Provider EntraMSI - unable to resolve Federation Provider + +## 1.8.49 (2025-07-21) + ++ New: Federation Provider EntraMSI - added a default federation provider for Managed Identities in Entra. ++ Upd: Invoke-EntraRequest - added parameter `-ContentType` ++ Upd: Connect-EntraService - now supports custom RedirectUris for AuthorizationCode flow + +## 1.8.46 (2025-07-11) + ++ New: Register-EntraFederationProvider - Register logic to automatically retrieve the assertion needed in a Federated Credential authentication flow. ++ New: Get-EntraFederationProvider - Lists all registered Federation Providers. ++ New: Resolve-EntraFederationProvider - Resolves which Federation Provider to use to calculate the Federation Credentials to use. ++ Upd: Connect-EntraService - now supports Federated Credentials flow ++ Upd: Connect-EntraService - AuthorizationCode flows no longer redirects to github at the end ++ Upd: Documentation update to provide better examples to many commands (#42; Many thanks, @Mynster9361) ++ Fix: Connect-EntraService - DeviceCode flow did not require TenantID when it is actually necessary + +## 1.7.39 (2025-04-15) + ++ Upd: New-EntraFilterBuilder - Now supports both AND and OR logic. ++ Upd: New-EntraFilterBuilder - Now supports adding other filter builders as nested filter. ++ Upd: New-EntraFilterBuilder - Now allows specifying, whether values should be put in quotes. ++ Fix: New-EntraFilterBuilder - does not respect order of conditions for custom filters. + +## 1.7.35 (2025-03-25) + ++ New: New-EntraFilterBuilder - Creates a new OData-Filter construction helper. ++ New: New-EntraServiceSelector - Creates a helper type designed to help make a module implementing EntraAuth more flexible about what EntraAUth service to use. + +## 1.6.33 (2025-03-10) + ++ New: New-EntraCustomToken - Create a custom token compatible with EntraAuth. ++ Upd: Register-EntraService - add `RawOnly` parameter to have all requests to that service use raw processing by default. + +## 1.5.31 (2025-03-05) + ++ Upd: Invoke-EntraRequest - now allows overriding default header entries + +## 1.5.30 (2025-03-05) + ++ Upd: Connect-EntraService - now accepts "Graph" or "Azure" as ClientID, resolving the respective first party App IDs. ++ Fix: Connect-EntraService - fails to find a certificate by name, when the cert store contains only a single certificate + +## 1.5.28 (2025-02-14) + ++ New: Import-EntraToken - Imports a token into the local token store. ++ Upd: Connect-EntraService - added `-FallbackAzAccount` parameter to allow MSI authentication to fall back to the existing Az Session in case of trouble. ++ Upd: Connect-EntraService - enabled multiple secret names to be specified when logging in via Key Vault. ++ Upd: Token - default Query values are now copied onto the token from the service configuration. ++ Upd: Invoke-EntraRequest - uses default Query values from the token, rather than the service configuration + +## 1.4.23 (2025-01-14) + ++ Upd: Connect-EntraService - removed TenantID requirement for most delegate flows, defaulting the parameter to "organizations". TenantID on the managed token object is now read from the returned token. + +## 1.4.22 (2024-12-04) + ++ Upd: Connect-EntraService - added `-UseRefreshToken` parameter for delegate flows, showing the interactive prompts only if needed. + +## 1.4.21 (2024-11-26) + ++ Upd: Added support for authenticating using an existing refresh token ++ Fix: Invoke-EntraRequest - "body not supported with this method" error when using Get requests with a body (#23) + +## 1.3.19 (2024-10-13) + ++ Upd: Invoke-EntraRequest - `-Body` parameter now supports raw string or custom objects. + +## 1.3.18 (2024-10-08) + ++ Upd: Added support for authenticating using the current Az.Accounts session ++ Upd: Added support for Sovereign Clouds (USGov, USGovDOD, China) and custom authentication urls. ++ Fix: Certificate Logon fails on timezones after UTC + +## 1.2.15 (2024-07-31) + ++ Fix: Refresh token may fail to authenticate to correct application ++ Fix: Managed Identity authentication fails on Azure VMs + +## 1.2.13 (2024-05-22) + ++ New: Supporting Managed Identity (User-Assigned or System Managed) ++ Upd: Service Configuration - can specify default query parameters. + +## 1.1.11 (2024-05-21) + ++ New: Service configurations - Added configurations for Azure & AzureKeyVault. ++ Upd: Connect-EntraService - Added support for direct Key Vault integration. ++ Upd: Service configurations - Added capability to require additional parameters that modify the base Service Url. ++ Fix: Token Renewal - bad parameter ServiceUrl. ++ Fix: Asset-EntraConnection - bad error message when assertion fails. + +## 1.0.6 (2024-05-15) + ++ Upd: Invoke-EntraRequest - added -NoPaging parameter to support disabling paging. ++ Upd: Invoke-EntraRequest - added -Raw parameter to support returning unprocessed results. + +## 1.0.4 (2024-04-19) + ++ Fix: Connect-EntraService - fails to register new sessions (#10) + +## 1.0.3 (2024-03-24) + ++ Upd: Connect-EntraService - added -Resource parameter to allow creating tokens without requiring a service (#7) ++ Upd: Connect-EntraService - added -BrowserMode parameter to allow pasting the link to whatever browser you prefer (#3) ++ Fix: Connect Browser - unknown command when PSFramework is not installed + +## 1.0.0 (2024-03-20) + ++ Initial Release diff --git a/PSFramework/modules/readme.md b/PSFramework/modules/readme.md new file mode 100644 index 00000000..c712b01b --- /dev/null +++ b/PSFramework/modules/readme.md @@ -0,0 +1,21 @@ +# Modules + +This folder contains modules included within PSFramework. +If possible, avoid including modules, but when not otherwise possible, this is the place to put them in. + +Fundamental rules: + ++ MIT License Modules only ++ Only Modules publicly available through Github or similar ++ Modules must be build-able from source without build dependencies ++ No Breaking Change policy applies to these modules as well ++ Must not lead to any runspace-/process-wide conflicts: No DLLs, no Type Extension XML that conflicts on import ++ Only one version of a given module ++ For each module, create a %MODULENAME%.md document besides this readme, describing ... + + ... what it is needed/used for + + ... any adjustments made from its source + + ... where it is from + +> Remember + +Nested modules are evil and should be avoided! diff --git a/PSFramework/snippets/help_par_EnableException.snippet b/PSFramework/snippets/help_par_EnableException.snippet deleted file mode 100644 index ca529cef..00000000 --- a/PSFramework/snippets/help_par_EnableException.snippet +++ /dev/null @@ -1,20 +0,0 @@ - - -
- help_par_EnableException - - Help for the EnableException parameter - Infernal Associates Ltd. - - Expansion - -
- - - - - -
-
\ No newline at end of file diff --git a/PSFramework/xml/PSFramework.Format.ps1xml b/PSFramework/xml/PSFramework.Format.ps1xml index 78e473b1..458f97f8 100644 --- a/PSFramework/xml/PSFramework.Format.ps1xml +++ b/PSFramework/xml/PSFramework.Format.ps1xml @@ -355,11 +355,6 @@ - - - - - @@ -374,22 +369,7 @@ ProviderVersion - IncludeModules - - - ExcludeModules - - - IncludeTags - - - ExcludeTags - - - Initialized - - - InstallationOptional + Description diff --git a/library/PSFramework/Commands/ConvertToPSFHashtableCommand.cs b/library/PSFramework/Commands/ConvertToPSFHashtableCommand.cs index 6a3fa97d..260fc88d 100644 --- a/library/PSFramework/Commands/ConvertToPSFHashtableCommand.cs +++ b/library/PSFramework/Commands/ConvertToPSFHashtableCommand.cs @@ -41,6 +41,24 @@ public class ConvertToPSFHashtableCommand : PSFCmdlet [Parameter()] public SwitchParameter IncludeEmpty; + /// + /// Exclude keys whose value is null + /// + [Parameter()] + public SwitchParameter ExcludeNull; + + /// + /// Exclude keys whose value is an empty string + /// + [Parameter()] + public SwitchParameter ExcludeEmptyString; + + /// + /// Exclude keys whose value is an empty collection + /// + [Parameter()] + public SwitchParameter ExcludeEmptyCollection; + /// /// Specifically designed for use in a command when passing through parameters with default values. /// Enabling this switch has the command inherit values from variables in the caller scope if their name has been specified in the Include parameter. @@ -225,6 +243,27 @@ protected override void ProcessRecord() result[Remap[key]] = value; } } + if (ExcludeNull || ExcludeEmptyString || ExcludeEmptyCollection) + { + object[] keys = result.Keys.Cast().ToArray(); + foreach (object key in keys) { + if (ExcludeNull && result[key] == null) + { + result.Remove(key); + continue; + } + if (ExcludeEmptyString && result[key] != null && result[key] is string && String.IsNullOrEmpty(result[key].ToString())) + { + result.Remove(key); + continue; + } + if (ExcludeEmptyCollection && result[key] != null && result[key] is ICollection && ((ICollection)result[key]).Count == 0) + { + result.Remove(key); + continue; + } + } + } if (AsPsfHashtable.ToBool()) result = new Object.PsfHashtable(result); diff --git a/library/PSFramework/Logging/FileSystemWriter.cs b/library/PSFramework/Logging/FileSystemWriter.cs new file mode 100644 index 00000000..da4ef426 --- /dev/null +++ b/library/PSFramework/Logging/FileSystemWriter.cs @@ -0,0 +1,111 @@ +using PSFramework.Message; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Management.Automation; +using System.Text; +using System.Threading.Tasks; + +namespace PSFramework.Logging +{ + /// + /// Helper class used by the FileSystem logging provider to write data at max performance + /// + public class FileSystemWriter + { + // Converter Code that generates CSV without headers + private static string CodeNoHeader = "Microsoft.PowerShell.Utility\\ConvertTo-Csv -NoTypeInformation -NoHeader"; + // Converter Code that generates CSV WITH headers + private static string CodeHeader = "Microsoft.PowerShell.Utility\\ConvertTo-Csv -NoTypeInformation"; + + /// + /// The Path to where is written. Changing this recalculates converters and establishes a filestream + /// + public string Path + { + get => _Path; + set + { + if (_Path == value) + return; + + // Close out previous writer and converter + End(); + + if (!LogHost.FileSystemModernLog || System.IO.File.Exists(value)) + _Converter = ScriptBlock.Create(CodeNoHeader).GetSteppablePipeline(); + else + _Converter = ScriptBlock.Create(CodeHeader).GetSteppablePipeline(); + _Converter.Begin(true); + + _Writer = new StreamWriter(value, true, new UTF8Encoding(true)); + _Writer.AutoFlush = true; + + _Path = value; + _Info = new FileInfo(value); + } + } + private string _Path; + + /// + /// Size of the logfile. + /// Defaults to 0 if file not present. + /// Used to determine file-split based on size. + /// + public long Size + { + get + { + _Info.Refresh(); + if (!_Info.Exists) + return 0; + return _Info.Length; + } + } + + private SteppablePipeline _Converter; + + private StreamWriter _Writer; + + private FileInfo _Info; + + /// + /// Writes a line to the logfile + /// + /// The line of text to write + public void WriteLine(string Line) + { + _Writer.WriteLine(Line); + } + + /// + /// Writes an object to the logfile. + /// Will convert it to csv first. + /// + /// The item to write + public void WriteObject(PSObject Item) + { + foreach (object item in _Converter.Process(Item)) + _Writer.WriteLine(item.ToString()); + } + + /// + /// Clean up both converter and writer + /// + public void End() + { + if (null != _Converter) + { + _Converter.End(); + _Converter = null; + } + + if (null != _Writer) + { + _Writer.Dispose(); + _Writer = null; + } + } + } +} diff --git a/library/PSFramework/Logging/Provider.cs b/library/PSFramework/Logging/Provider.cs index e9da6540..a487656f 100644 --- a/library/PSFramework/Logging/Provider.cs +++ b/library/PSFramework/Logging/Provider.cs @@ -17,6 +17,11 @@ public class Provider /// public string Name; + /// + /// A description for the logging provider + /// + public string Description; + /// /// Whether the logging provider is enabled. Only when this is set to true will the logging script execute its events. /// diff --git a/library/PSFramework/PSFramework.csproj b/library/PSFramework/PSFramework.csproj index 3246df40..f2a51c11 100644 --- a/library/PSFramework/PSFramework.csproj +++ b/library/PSFramework/PSFramework.csproj @@ -132,6 +132,7 @@ + diff --git a/library/PSFramework/Runspace/RSQueue.cs b/library/PSFramework/Runspace/RSQueue.cs index 65ad6dd2..df3f99a5 100644 --- a/library/PSFramework/Runspace/RSQueue.cs +++ b/library/PSFramework/Runspace/RSQueue.cs @@ -5,6 +5,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using System.Xml.Schema; namespace PSFramework.Runspace { @@ -53,9 +54,12 @@ public class RSQueue : ConcurrentQueue if (Closed) return; - Interlocked.Increment(ref TotalItemCount); - base.Enqueue(Input); - LastUpdate = DateTime.Now; + lock (this) + { + Interlocked.Increment(ref TotalItemCount); + base.Enqueue(Input); + LastUpdate = DateTime.Now; + } } /// @@ -73,8 +77,12 @@ public void EnqueueBulk(ICollection Input) if (Closed) return; - Interlocked.Increment(ref TotalItemCount); - base.Enqueue(item); + lock (this) + { + Interlocked.Increment(ref TotalItemCount); + base.Enqueue(item); + LastUpdate = DateTime.Now; + } } } @@ -110,6 +118,26 @@ public void Clear() } } + /// + /// Get all contents as an Array. + /// Possibly also clearing it out afterwards. + /// + /// If true, clear after reading as one threadsafe operation. + /// To content of the queued items + public object[] ToArray(bool Clear) + { + if (!Clear) + return ToArray(); + + lock (this) + { + object[] content = ToArray(); + while (Count > 0) + Dequeue(); + return content; + } + } + /// /// Take a look without removing anything /// diff --git a/library/PSFramework/Utility/UtilityHost.cs b/library/PSFramework/Utility/UtilityHost.cs index 02456680..bbe139cd 100644 --- a/library/PSFramework/Utility/UtilityHost.cs +++ b/library/PSFramework/Utility/UtilityHost.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; @@ -701,6 +702,137 @@ public static Meta.CallerInfo GetCallerInfo(int Level = 1) } #endregion Callstack Metadata + #region Comparisons + /// + /// Compare two hashtables. + /// Value comparison uses C#-based comparison logic. + /// + /// First Hashtable to compare + /// Second Hashtable to compare + /// Whether the two tables are equal + public static bool Compare(Hashtable Table1, Hashtable Table2) + { + if (Table1 == null && Table2 == null) return true; + if (Table1 == null && Table2 != null) return false; + if (Table1 != null && Table2 == null) return false; + + if (Table1.Count != Table2.Count) return false; + + foreach (DictionaryEntry row in Table1) + { + if (!Table2.ContainsKey(row.Key)) return false; + if (Table2[row.Key] != row.Value) return false; + } + foreach (DictionaryEntry row in Table2) + { + if (!Table1.ContainsKey(row.Key)) return false; + if (Table1[row.Key] != row.Value) return false; + } + + return true; + } + + /// + /// Compare two hashtables. + /// Value comparison uses PowerShell-based comparison logic. + /// + /// First Hashtable to compare + /// Second Hashtable to compare + /// Whether the comparison is case sensitive + /// Whether to recursively compare nested hashtables + /// If enabled, all entries in Table1 must be present in Table2, but not necessarily all entries in Table2 in Table1 + /// Whether the two tables are equal + public static bool ComparePS(Hashtable Table1, Hashtable Table2, bool CaseSensitive, bool Recurse, bool OneDirectional) + { + if (Table1 == null && Table2 == null) return true; + if (Table1 == null && Table2 != null) return false; + if (Table1 != null && Table2 == null) return false; + + if (!OneDirectional && Table1.Count != Table2.Count) return false; + + foreach (DictionaryEntry row in Table1) + { + if (!Table2.ContainsKey(row.Key)) return false; + if (Recurse && !LanguagePrimitives.Equals(Table2[row.Key], row.Value, !CaseSensitive)) + { + if (Table2[row.Key] is Hashtable && row.Value is Hashtable) + { + if (!ComparePS((Hashtable)Table2[row.Key], (Hashtable)row.Value, CaseSensitive, Recurse, OneDirectional)) + return false; + } + else + return false; + } + else if (!LanguagePrimitives.Equals(Table2[row.Key], row.Value, !CaseSensitive)) return false; + } + + if (OneDirectional) + return true; + + foreach (DictionaryEntry row in Table2) + { + if (!Table1.ContainsKey(row.Key)) return false; + if (Recurse && !LanguagePrimitives.Equals(Table1[row.Key], row.Value, !CaseSensitive)) + { + if (Table1[row.Key] is Hashtable && row.Value is Hashtable) + { + if (!ComparePS((Hashtable)Table1[row.Key], (Hashtable)row.Value, CaseSensitive, Recurse, false)) + return false; + } + else + return false; + } + else if (!LanguagePrimitives.Equals(Table1[row.Key], row.Value, !CaseSensitive)) return false; + } + + return true; + } + #endregion Comparisons + + /// + /// Checks, whether the specified parameters would resolve to one of the selected parameter sets. + /// Will return false, if the provided parameters would lead to an ambiguous parameter set, even if the specified sets would be among the still valid sets. + /// + /// The command for the parameters of which the test should be performed. + /// The names of the parameters specified. + /// The sets checked for. The resultant parameter set must be one of those specified. + /// Whether the specified parameters would resolve to one of the selected parameter sets + public static bool TestParameterSetAny(CommandInfo Command, string[] Parameters, string[] Sets) + { + if (null == Command) return false; + if (null == Sets) return false; + if (null == Parameters) + Parameters = new string[0]; + + List matches = new List(); + foreach (CommandParameterSetInfo info in Command.ParameterSets) + { + if (Parameters.Where(p => !info.Parameters.Select(o => o.Name).ToArray().Contains(p, StringComparer.OrdinalIgnoreCase)).Count() > 0) + continue; + matches.Add(info); + } + + CommandParameterSetInfo defaultSet = Command.ParameterSets.Where(s => s.IsDefault).FirstOrDefault(); + string effectiveSet = defaultSet?.Name; + + if (matches.Count == 1) + effectiveSet = matches[0].Name; + else if (matches.Count > 1) + { + if (null == defaultSet) + return false; + if (!matches.Select(o => o.Name).ToArray().Contains(effectiveSet)) + return false; + } + else + return false; + + if (String.IsNullOrEmpty(effectiveSet)) + return false; + + return Sets.Contains(effectiveSet, StringComparer.OrdinalIgnoreCase); + } + /// /// Stored scriptblocks that can be retrieved on demand anywhere within the process /// From 227ed58cc97532c8deabbf7966206425fa674a3e Mon Sep 17 00:00:00 2001 From: Friedrich Weinmann Date: Fri, 23 Oct 2026 13:01:10 +0200 Subject: [PATCH 2/2] added exemption --- PSFramework/tests/general/FileIntegrity.Exceptions.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PSFramework/tests/general/FileIntegrity.Exceptions.ps1 b/PSFramework/tests/general/FileIntegrity.Exceptions.ps1 index c98da514..0ed2dda5 100644 --- a/PSFramework/tests/general/FileIntegrity.Exceptions.ps1 +++ b/PSFramework/tests/general/FileIntegrity.Exceptions.ps1 @@ -20,7 +20,7 @@ $global:MayContainCommand = @{ "Write-Host" = @('Write-PSFHostColor.ps1') "Write-Verbose" = @() "Write-Warning" = @('assembly.ps1') - "Write-Error" = @('Import-PSFJson.ps1', 'Import-PSFPowerShellDataFile.ps1', 'Invoke-PSFCommand.ps1', 'Set-PSFFileContent.ps1', 'Stop-PSFFunction.ps1') + "Write-Error" = @('Import-PSFJson.ps1', 'Import-PSFPowerShellDataFile.ps1', 'Invoke-PSFCommand.ps1', 'Set-PSFFileContent.ps1', 'Stop-PSFFunction.ps1', 'azureloganalytics2.provider.ps1') "Write-Output" = @('filesystem.provider.ps1', 'gelf.provider.ps1', 'Import-PSFPowerShellDataFile.ps1', 'logfile.provider.ps1', 'input.ps1', 'teppCoreCode.ps1') "Write-Information" = @() "Write-Debug" = @()