PSCertUtils.Helpers.psm1


Function Get-X509CommonNameFromSubject {
  [CmdletBinding()]
  Param(
    [Parameter(Mandatory = $False, Position = 0)]
    [Alias('Subject', 'CertificateSubject')]
    [String] $X509Subject
  )

  If ([String]::IsNullOrWhiteSpace($X509Subject))
  {
    return ""
  }

  $SubjectParts = $($X509Subject -split ",").Trim()

  Foreach ($SubjectPart in $SubjectParts)
  {
    $SubPart = $($SubjectPart -split "=").Trim()
    if (($SubPart.Count -eq 2) -and ($SubPart[0] -eq "CN"))
    {
      return $SubPart[1]
    }
  }

  return ""

}


# Removes invalid characters from alias - maybe more than required
Function Get-SafeCertificateAlias {
  Param(
    [Parameter(Mandatory = $True, Position = 0)]
    [ValidateNotNullOrEmpty()]
    [Alias("FriendlyName", "Name", "CertAlias", "CertificateAlias")]
    [String] $Alias
  )

  $pattern = '[^a-zA-Z0-9-_()\W]'

  return $Alias -replace $pattern, ''

}


Function New-PSCertUtilsStandaloneScript {
  <#
  .SYNOPSIS
    Generate a standalone powershell script based off PSCertUtils module.
 
  .DESCRIPTION
    This function generates a powershell script with functions from this module and custom code,
    that can be used without having to install this module.
 
    Empty lines and comments from module functions are removed in this process, for a lighter script.
    A region is beeing added to allow simple collapsing of module functions.
 
    This function either requires a custom script file or a script block to be used for custom code that
    is added before the module functions and that should make use of these.
 
  .PARAMETER InstallScript
    Name or Path of the script file that will be created.
 
    Default: install.ps1
  .PARAMETER CustomScript
    Name or Path of the custom script file that is used to generate the script file.
 
    Cannot be used with CustomCode parameter.
 
    Default: user.install.ps1
  .PARAMETER CustomCode
    ScriptBlock with custom code that is used to generate the script file.
 
    Cannot be used with CustomScript parameter.
  .PARAMETER ExcludedFunctions
    List of functions that should not be exported to the script file.
 
    Default: @("New-PSCertUtilsStandaloneScript")
  .PARAMETER Force
    Switch to force the creation of the script file even if it exists.
 
  .EXAMPLE
    New-PSCertUtilsStandaloneScript
 
    Generate install.ps1 based of user.install.ps1 and default module functions
  .EXAMPLE
    New-PSCertUtilsStandaloneScript -CustomCode {}
 
    Generate install.ps1 based of default module functions and blank custom code
  .EXAMPLE
    New-PSCertUtilsStandaloneScript -CustomCode {} -ExcludedFunctions @() -Force
 
    Generate install.ps1 based of default module functions, blank custom code
    and all exported functions, existing install.ps1 will be overwritten.
 
  #>

  [CmdletBinding()]
  Param(
    [Parameter(Mandatory = $False, Position = 0)]
    [ValidateNotNullOrEmpty()]
    [Alias("Script", "FileName", "ScriptName")]
    [String] $InstallScript = "install.ps1",
    [Parameter(Mandatory = $False, ParameterSetName="ScriptFile", Position = 1)]
    [ValidateNotNullOrEmpty()]
    [Alias("Custom", "CustomFileName", "CustomScriptName")]
    [String] $CustomScript = "user.install.ps1",
    [Parameter(Mandatory = $True, ParameterSetName="ScriptBlock", Position = 1)]
    [ValidateNotNullOrEmpty()]
    [Alias("CustomScriptBlock", "ScriptBlock", "Code")]
    [ScriptBlock] $CustomCode,
    [Parameter(Mandatory = $False, Position = 2)]
    [ValidateNotNull()]
    [String[]] $ExcludedFunctions = @("New-PSCertUtilsStandaloneScript"),
    [Parameter(Mandatory = $False, Position = 3)]
    [Alias("Override", "OverrideExisting")]
    [Switch] $Force
  )

  # Variables for this script
  $PSModuleName = "PSCertUtils"
  $ModuleHeader = "#$PSModuleName install.ps1 script generated by $(whoami) on $(hostname) at: $(Get-Date)"
  $NewLine = [System.Environment]::NewLine

  # Test for existence of script and user part if parameters indicate script usage
  If (($PsCmdlet.ParameterSetName -eq "ScriptFile") -and (!(Test-Path $CustomScript))) {
    Write-Error "Could not find custom script at: $CustomScript - create custom script file at this location or use -CustomCode parameter." -ErrorAction Stop
  }

  # Test for existence of previous install script before possibly overriding it
  If ((Test-Path $InstallScript) -and (!$Force)) {
    Write-Error "Install script already existing with name: $InstallScript - delete manually or specify -Force before proceeding." -ErrorAction Stop
  }

  # Load module first to avoid cleanup if the module cannot be found
  $Module = Get-Module $PSModuleName

  # Create file with header
  $ModuleHeader |
    Set-Content -Path $InstallScript -Encoding UTF8

  # Get custom code from custom script if specified
  If ($PsCmdlet.ParameterSetName -eq "ScriptFile") {
    $CustomCode = Get-Content -Path $CustomScript
  }

  # Add the user part to the install script
  $CustomCode | Add-Content -Path $InstallScript

  # Get all exported functions from the module except excluded
  $ModuleFunctions = $Module.ExportedCommands.Values |
    Where-Object { $_.CommandType -eq "Function" } |
    Where-Object { $_.Name -notin $ExcludedFunctions }


  # Start region for module functions
  "#region $PSModuleName functions" | Add-Content -Path $InstallScript

  # Iterate functions to add them to the install file
  $ModuleFunctions | Foreach-Object {

    # Remove empty lines and comments from function code
    $FunctionLines = $_.Definition -split "`r`n" -split "`n" | Where-Object { $_ -notmatch '^\s*$' } | Where-Object { $_ -notmatch '^\s*#+' }
    $FunctionCode = $FunctionLines -join $NewLine

    # Add functions to file
    ("Function {0} {{{2}{1}{2}}}" -f $_.Name, $FunctionCode, $NewLine) | Add-Content -Path $InstallScript
  }

  # Close region for module functions
  "#endregion $PSModuleName functions" | Add-Content -Path $InstallScript

}