Foreword
Contributors
- Alain Tanguy
- Allen Chin
- Amy Zanatta
- Bill Kindle
- C.J. Zuk
- Chad Miars
- Christian Coventry
- Felipe Binotto
- Greg Onstot
- James Petty
- Joe Houghes
- John Hermes
- Jordan Borean
- Kevin Laux
- Kieran Jacobsen
- Kirill Nikolaev
- Martha Clancy
- Matt Corr
- Michael B. Smith
- Michael Lotter
- Michael Zanatta
- Nicholas Bissell
- Rob Derickson
- Steven Judd
- Wes Stahler
Acknowledgements
Disclaimer
Introduction
- About OnRamp
- Prerequisites
- A Note on Code Listings
- Feedback
- ICollaboration
1.Introduction to Git
- 1.1Understanding Terminology
- 1.2Creating a Local Repository
- 1.3Cloning an Existing Repository
- 1.4Understanding the Flow of Working in Git
- 1.5Your First Commit
- 1.6Creating a Branch
- 1.7Merging Branches
- 1.7.1Merge Commits
- 1.7.2Merge Conflicts
- 1.8Stashing Changes
- 1.9Rolling Back When Things Go Wrong
- 1.9.1Hard Reset in Action
- 1.10Connecting to a Remote Repository
- 1.11Starting Over When Things Really Go Wrong
- 1.11.1Starting From Scratch
- 1.12Conclusion
- 1.13Modern IT Automation With PowerShell Extras
- 1.14Further Reading
2.Code Reviews
- 2.1Purpose of Code Reviews
- 2.2How to Start with Code Reviews
- 2.2.1Define Code Conventions for Your Team or Project
- 2.2.2Define the Code Review Process for Your Team or Project
- 2.3Things to Consider When Performing a Code Review
- 2.4Code Review Best Practices
- 2.4.1Keep Your Changes Small
- 2.4.2Provide Constructive Feedback
- 2.4.3Balance Nit-Picks with Major Comments
- 2.4.4Create Pull Request Templates
- 2.4.5When to Approve
- 2.4.6Talk to Each Other
- 2.4.7Use Automation
- 2.5Tools to Help with Code Reviews
- 2.5.1PSScriptAnalyzer
- 2.5.2PowerShell Extension for Visual Studio Code
- 2.6Further Reading
- IIPowerShell Testing
3.The AAA Approach
- 3.1Arrange, Act, and Assert
- 3.1.1Arrange
- 3.1.2Act
- 3.1.3Assert
- 3.1.4Benefits of the AAA Approach
- 3.2Pester 5.0
- 3.2.1Pester Installation
- 3.3The Star Wars API Example
- 3.3.1So How Does It Work?
- 3.3.2Example Code
- 3.3.3Example Code Output
- 3.4Pester Tests
- 3.4.1Simple Tests
- 3.4.2Pester Verbosity
- 3.4.3Simple Test Output
- 3.4.4Mocked Tests
- 3.4.5Mocked Test Output
- 3.4.6Complex Tests
- 3.4.7Complex Test Output
- 3.5Conclusion
- 3.6Further Reading
4.Mocking
- 4.1Mocking and Mock Testing
- 4.1.1Stubs, Fakes, and Mocks
- 4.2Mocking in Pester with
Mock - 4.3Mock Testing and Verifiable Mocks
- 4.3.1Should -Invoke
- 4.3.2Should -InvokeVerifiable
- 4.3.3Running the Mock Assertion Tests
- Assert-MockCalled and Assert-VerifiableMock
- 4.4Mock Scoping
- PesterBoundParameters
- 4.5Mocking in the Module Scope with -ModuleName
- 4.5.1Mock Testing in the Module Scope
- 4.5.2Running the Module Scope Tests
- 4.6Dynamic Mock Behavior with -ParameterFilter
- 4.6.1Filtered Mock Assertions
- 4.6.2Running the Filtered Mock Tests
- 4.6.3Restricting Mock Calls Further with -ExclusiveFilter
- 4.7Calling Real Dependencies While They’re Mocked
- 4.8Removing Parameter Typecasting and Validation
- 4.9Mocking Native Applications
- 4.10Mocking .NET Objects with New-MockObject
- 4.11Next Steps
- 4.12Further Reading
5.Unit Testing
- 5.1Why Unit Testing?
- 5.2What Is Unit Testing?
- 5.3Testing Frameworks
- 5.3.1Black Box vs. White Box Testing
- 5.3.2The AAA Approach
- 5.4Pester
- 5.4.1Getting Started
- 5.4.2Defining Pester Test Files
- 5.4.3Pester Demo Code
- 5.4.4Pester Test Structure
- 5.4.5Mocking
- 5.4.6Running Pester Tests
- 5.4.7Pester Configuration
- 5.4.8Pester Automation
- 5.5Conclusion
- 5.6Further Reading
6.Parameterized Testing
- 6.1Pester Versions and Parameterized Tests
- 6.2Your First Test
- 6.2.1-ForEach
- 6.2.2Templates ‘<>’
- 6.2.3BeforeDiscovery
- 6.2.4Param
- 6.2.5Pester Container
- 6.2.6PesterConfiguration
- 6.3Pester v4
- 6.4Outputs
- 6.5One Last Example
- 6.6Conclusions
- 6.7Further Reading
- IIIPowerShell in Depth
7.Refactoring PowerShell
- 7.1Expanding on the Pipeline
- 7.2Expanded Splatting
- 7.3Interpolation
- 7.3.1Variable Substitution
- 7.3.2Using the Format (
-f) Operator - 7.4Refactoring Functions
- 7.4.1Simplify Functions to Perform a Singular Task
- 7.4.2Use Typecasting on Parameters
- 7.4.3Use Advanced Function Parameters
- 7.4.4Use Approved Verbs
- 7.4.5Use a Singular Output Object Type
- 7.5Writing Better Code
- 7.5.1Simplify Nested Statements
- 7.5.2Grouping Similar Code
- 7.5.3Refactoring Comments and Documentation
- 7.5.4Using Code Regions
- 7.5.5Refactoring Logic Flow to be Implicitly
$Trueor$False - 7.6Data Management
- 7.6.1JSON
- 7.6.2YAML
- 7.6.3XML
- 7.6.4CSV
- 7.6.5CLIXML
- 7.6.6Best Practices for Data Management
- 7.7Further Reading
8.Advanced Conditions
- 8.1Case Sensitive Operators
- 8.2Using the Switch Statement
- 8.2.1Using
-Regex - 8.2.2Using
-Wildcard - 8.2.3Using
-Exact - 8.2.4Using
-CaseSensitive - 8.2.5Using PowerShell Expressions for Matching
- 8.2.6
Default - 8.2.7Parsing Lists and Arrays
- 8.3Type Comparison and Conversion Operators:
-is,-isnotand-as - 8.3.1Using
-isand-isnot - 8.4Using
-asto Typecast Safely - 8.5Bitwise Operators (
-band,-bor,-bxor,-bnot,-shland-shr) - 8.5.1What is an
Enum? - Enum Reference
- 8.5.2Base-2 vs. Base-10 (Binary vs. Decimal)
- 8.5.3The AND Logic Gate
- 8.5.4The OR Logic Gate
- 8.5.5The NOT Logic Gate
- 8.5.6The XOR Logic Gate
- 8.5.7
-bandBitwise AND - 8.5.8
-borBitwise OR - 8.5.9
-bxorBitwise XOR - 8.5.10
-bnotBitwise NOT - 8.5.11
-shlShift Bits Left - 8.5.12
-shrShift Bits Right - 8.5.13Practical Applications
- 8.6
-likeand-notlike - 8.7
-matchand-notmatch - 8.8
-in,-contains,-notinand-notcontains - 8.9
-replace - 8.10Ternary Operator
(condition) ? <true> : <false> - 8.11Null-Coalescing Operator
?? - 8.12Null-Coalescing Assignment Operator
??= - 8.13Null-Conditional Operator
?.and?[] - 8.13.1Examples of
?. - 8.13.2Examples of
?[] - 8.14
:parentLoop Labels - 8.15PowerShell Operator Precedence
- 8.15.1Example - Operator Precedence (
,,[]) - 8.15.2Example - Parentheses
() - 8.15.3Example - Negation Operator
-not - 8.15.4Example - Equal Precedence
- 8.15.5Example - A Complex Expression
- 8.16Further Reading
9.Logging
- 9.1Why Log?
- 9.2What Makes for Good Logging
- 9.3What Should Never Be Logged
- 9.4Logging Basics
- 9.5Enable System-Level Logging
- 9.5.1Windows
- 9.5.2Event Log Locations
- 9.6Linux, macOS, WSL
- 9.7Logging for Troubleshooting
- 9.7.1Writing Console Output
- 9.8Persistent Logging Options
- 9.8.1PowerShell Transcription
- 9.8.2Logging to Files
- 9.8.3Using Tee-Object
- 9.9History
- 9.9.1Built-in History
- 9.9.2PSReadline History
- 9.9.3Writing to Windows Event Logs
- 9.9.4Cloud Shell
- 9.9.5Using Third Party modules for logging
- 9.10Summary
- 9.11Further Reading
10.Infrastructure as Code (IaC)
- 10.1Overview
- 10.2IaC Key Concepts
- 10.3IaC Benefits
- 10.4IaC Principles
- 10.4.1Source Control as the Single Source of Truth
- 10.4.2Modular
- 10.4.3Versioning
- 10.4.4Repeatable
- 10.4.5Disposable
- 10.4.6Self-Documented
- 10.4.7Testing and Monitoring
- 10.5IaC in Action
- 10.5.1Azure-SQL-Server.psm1
- 10.5.2Azure-Storage-Account.psm1
- 10.5.3Azure-Load-Balancer.psm1
- 10.5.4Azure-Virtual-Machine.psm1
- 10.6Configuration as Code (CaC)
- 10.6.1PowerShell Desired State Configuration (DSC)
- 10.6.2CaC in Action
- 10.7IaC and CaC: Better Together
- 10.8Conclusion
- 10.9Further Reading
- IVUsing Regexes
11.Regex 101
- Did you know?
- 11.1First Principles and Limitations
- 11.1.1Wildcard Patterns vs. Regexes
- 11.1.2Differences Between PowerShell Regexes and Others
- 11.2Getting Started
- 11.3Character Classes
- 11.4Custom Character Classes
- Character Classes Reference
- 11.5Quantifiers
- Quantifiers Reference
- 11.6Character Escape Sequences
- Character Escape Sequences Reference
- 11.7Anchors (Zero-Width Assertions)
- Anchors Reference
- 11.8Captures
- 11.9Visualizing Captures
- Grouping Constructs Reference
12.Accessing Regexes
- 12.1Using PowerShell Syntax
- 12.1.1-match Operator with Strings
- 12.1.2-match Operator with String Arrays
- 12.1.3-cmatch and -imatch Operators and Inverses
- 12.1.4-replace Operator with Strings
- 12.1.5-replace Operator with String Arrays
- 12.1.6-creplace and -ireplace Operators
- Comparison Operators Reference
- 12.1.7-split Operator with Strings
- 12.1.8-split Operator with String Arrays
- 12.1.9Splitting Strings with -split and a Script Block
- 12.1.10-csplit and -isplit Operators
- Split Reference
- 12.1.11Select-String Cmdlet
- Select-String Reference
- 12.1.12Where-Object Cmdlet with the -Match Parameter
- Where-Object Reference
- 12.1.13switch -Regex Statement
- Switch Reference
- 12.1.14ValidatePattern() Parameter Attribute
- ValidatePattern Reference
- 12.1.15Pester Should -Match and -MatchExactly Assertions
- Pester Assertions Reference
- 12.2Using the .NET Methods
- 12.2.1Constructors
- 12.2.2IsMatch()
- 12.2.3Match()
- Match Class in .NET
- 12.2.4Match.NextMatch() Instance Method
- 12.2.5Matches()
- 12.2.6Replace()
- 12.2.7Split()
- 12.2.8Escape() and Unescape()
- 12.2.9GetGroupNumbers() and GetGroupNames()
- 12.2.10GroupNameFromNumber() and GroupNumberFromName()
- .NET Regex Reference
- 12.3Regex Options
- 12.3.1RegexOptions.None (0)
- 12.3.2RegexOptions.IgnoreCase (1)
- 12.3.3RegexOptions.Multiline (2)
- 12.3.4RegexOptions.ExplicitCapture (4)
- 12.3.5RegexOptions.Compiled (8)
- 12.3.6RegexOptions.Singleline (16)
- 12.3.7RegexOptions.IgnorePatternWhitespace (32)
- 12.3.8RegexOptions.RightToLeft (64)
- 12.3.9RegexOptions.ECMAScript (256)
- 12.3.10RegexOptions.CultureInvariant (512)
- 12.3.11Combining Regex Options
- 12.3.12Inline Options
- Regex Options Reference
13.Regex Deep Dive
- 13.1Debugging Your Regex Patterns
- 13.1.1Regex Through the Eyes of an NFA Engine
- 13.1.2Backtracking and Branching
- 13.1.3Catastrophic Backtracking
- 13.1.4Atomic Groups
- 13.2Functionality to Consider
- 13.2.1No Subroutines
- 13.2.2No Recursion
- 13.2.3Possessive Quantifiers vs. Atomic Groups
- 13.2.4Variable-Length Lookbehinds
- 13.3Deconstructing a Pattern
- 13.4Advanced Syntax
- 13.4.1Unicode Categories and Blocks
- Unicode Categories and Blocks Reference
- .NET Character Encoding Reference
- 13.4.2Character Class Subtraction
- Character Class Subtraction Reference
- 13.4.3Using Inline Options
- 13.4.4Using Option Spans
- Inline Options Reference
- 13.4.5Comments in Regex
- 13.5Advanced Replacement Patterns
- 13.5.1Named and Numeric Captures
- 13.5.2Entire Match
- 13.5.3Match Span Prefixes and Postfixes
- 13.5.4Entire Input
- 13.5.5Last Capture
- 13.6Advanced Subexpressions and Backreferences
- 13.6.1Backreferences in Depth
- Backreference Constructs Reference
- 13.6.2Lookarounds in Depth
- Example 23: Thoughts
- Lookarounds Reference
- 13.6.3Conditional Logic
- Example 25: Thoughts
- Conditionals Reference
- 13.6.4Balancing Groups
- Balancing Groups Reference
14.Regex Best Practices
- 14.1Constrained and Unconstrained Input
- 14.2Backtracking and Exponential Operations
- 14.3Preventing ReDoS with Regex Time-Outs
- 14.4Capturing Just Enough
- 14.5Static vs. Instance Methods and Caching
- 14.6No More CompileToAssembly()
- 14.7Getting the Scope Right
- 14.8Iterative Development
- 14.9Edge Cases and Near Matches
- Best Practices Reference
- 14.10Thread Safety
- Regex Thread Safety Reference
- 14.11Next Steps
- 14.12Further Reading
- 14.12.1Official Reference Materials
- 14.12.2Other Materials
- VPowerShell Security
15.Script Signing
- 15.1What Is Script Signing and How It Protects You
- 15.1.1How Digital Signing Works
- 15.1.2How Code Signing Works in Modern Windows Systems
- 15.2The Anatomy of a Signed Script
- 15.3How to Sign a Script
- 15.3.1Acquiring a Code Signing Certificate
- 15.3.2How to Install Code Signing Certificates Properly
- 15.3.3Signing Process
- 15.3.4How to Prevent Your Signatures from Expiring
- 15.3.5What Else Can You Sign
- 15.4How to Verify a Signature
- 15.4.1Get-AuthenticodeSignature
- 15.4.2Sigcheck
- 15.4.3Signtool
- 15.4.4Execution Errors
- 15.5Scaling Out
- 15.5.1Use Your Own PKI
- 15.5.2Deploy Code Signing Certificates in a Corporate Environment
- 15.6Summary
- 15.7Further Reading
16.Script Execution Policies
- 16.1Types of Execution Policies
- 16.1.1AllSigned
- 16.1.2RemoteSigned
- 16.1.3Restricted
- 16.1.4Unrestricted
- 16.1.5Bypass
- 16.1.6Default
- 16.1.7Undefined
- 16.2Execution Policy Scope
- 16.2.1Scope Precedence
- 16.3Security Considerations
- 16.4Setting the Execution Policy
- 16.4.1Set-ExecutionPolicy
- 16.4.2Group Policy
- 16.4.3AppLocker
- 16.4.4Windows Defender Application Control
- 16.5Further Reading
17.Constrained Language Mode
- 17.1In Depth
- 17.1.1Language Modes
- 17.1.2Constrained Language Mode Features
- 17.2Limitations of Constrained Language Mode
- 17.2.1PowerShell Protect
- 17.3Deep Diving into Windows Lockdown Policy
- 17.3.1
GetLockdownPolicy() - 17.3.2
GetWldpPolicy() - 17.3.3
GetAppLockerPolicy() - 17.3.4
GetDebugLockdownPolicy() - 17.4Implementing Policies Using AppLocker Script Rules
- 17.4.1Introduction
- 17.4.2Getting Started
- 17.5Implementing Policies Using WDAC
- 17.5.1What Is WDAC?
- 17.6Deploying WDAC Using Microsoft Intune
- 17.6.1Prerequisites
- 17.6.2Creating a Device Policy
- 17.7Best Practices
- 17.8Further Reading
18.Just Enough Administration
- 18.1Introduction
- 18.1.1Requirements
- 18.2Background of JEA
- 18.2.1PowerShell Remoting 101
- 18.2.2An Overview of PowerShell Session Configuration
- 18.2.3PowerShell Remoting Authentication and Transport Encryption
- 18.3PowerShell Role Capabilities
- 18.3.1Implementing Windows PowerShell Role Capabilities in the Console
- 18.3.2Implementing PowerShell (Core) Role Capabilities in the Console
- 18.3.3Implementing PowerShell Role Capabilities Within DSC
- 18.4Getting Started With PowerShell Session Configuration
- 18.4.1Step 1: Enabling PowerShell Remoting
- 18.4.2Step 2: Creating/Registering the PowerShell Session Configuration
- 18.4.3Connecting to a PowerShell Session Configuration
- 18.4.4Role Definition Design Considerations
- 18.4.5Managing PowerShell Session Configurations
- 18.5An Overview of the Security Descriptor Definition Language (SDDL)
- 18.5.1Terms
- 18.5.2SDDL Overview
- 18.5.3SDDL Syntax
- 18.5.4Reading SDDLs
- 18.5.5Creating SDDLs from a Security Descriptor
- 18.6Auditing PowerShell Remoting Sessions
- 18.6.1Review Effective Rights
- 18.6.2PowerShell Event Logs
- 18.6.3Session Transcription Logs
- 18.6.4Removing Existing PowerShell Sessions
- 18.7Further Reading
Afterword
Index
- A, SYMBOLS
- B, C
- D, E
- F, G
- H, I
- J, K, L, M
- N
- O
- P
- R
- S
- T
- U, V, W
- Y

