Quantcast
Channel: Microsoft – JeffOps
Viewing all articles
Browse latest Browse all 120

What does a PowerShell function written by Microsoft look like?

$
0
0

This question lingered in my mind for a long, long time.
Becaues my mean method of learning to script is: read script, understand it, know it…
I see code, patterns in there, loops, methods, understand what happens and I’ve gained new knowledge.

So naturally I wanted to see how Microsoft does it. In my eyes they can write scripts a lot better than I can.
But… cmdlets are cmdlets, not functions. If you want to see inside the cmdlet you’ll need something like Vistual Studio or some other tool.
I wanted to look inside it right from inside the PowerShell console!

As it seems, you can do this with functions… so let me take you step by step in doing this.

First: Take a look at the PSDrives by executing Get-PSDrive:

PS D:\> get-psdrive

Name           Used (GB)     Free (GB) Provider      Root
----           ---------     --------- --------      ----
Alias                                  Alias
C                  58.33         41.66 FileSystem    C:\
cert                                   Certificate   \
D                  55.33        124.03 FileSystem    D:\
Env                                    Environment
Function                               Function
HKCU                                   Registry      HKEY_CURRENT_USER
HKLM                                   Registry      HKEY_LOCAL_MACHINE
Variable                               Variable
WSMan                                  WSMan

As you can see there is a PSDrive named ‘Function’. We’ll get back to that in a few lines…

Now let’s go to the second step: A function is part of a module. Import that module.

PS D:\> Import-Module operationsmanager

Now let’s get the content of that PSDrive named ‘Function’ by using the Get-ChildItem cmdlet:

PS D:\> Get-ChildItem Function:

CommandType     Name                                         Definition                                                                                              
-----------     ----                                         ----------                                                                                              
Function        A:                                           Set-Location A:                                                                                         
Function        Add-SCOMConnectorToTier                      ...                                                                                                     
Function        Add-SCOMRunAsAccount                         ...                                                                                                     
Function        Add-SCOMTieredManagementGroup                ...                                                                                                     
Function        B:                                           Set-Location B:                                                                                         
Function        C:                                           Set-Location C:

Now we get to the  cool part. A function is basically plain text. So you can get plain text by using… Get-Content :-)

PS D:\> Get-Content Function:\Add-SCOMRunAsAccount

So, here’s the code of the PowerShell function ‘Add-SCOMRunAsAccount’:

    [CmdletBinding(DefaultParameterSetName='Windows', SupportsShouldProcess=$true, ConfirmImpact='Medium')]
    param(

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'Windows')]
    [Switch]
    ${Windows},

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'CommunityString')]
    [Switch]
    ${CommunityString},

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'Basic')]
    [Switch]
    ${Basic},

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'Digest')]
    [Switch]
    ${Digest},

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'Simple')]
    [Switch]
    ${Simple},

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'ActionAccount')]
    [Switch]
    ${ActionAccount},

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'Binary')]
    [Switch]
    ${Binary},

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'SnmpV3')]
    [Switch]
    ${SnmpV3},

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'SCXMonitoring')]
    [Switch]
    ${SCXMonitoring},

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'SCXMaintenanceSSHKeyPriv')]
    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'SCXMaintenanceSSHKeyNoPrivSudo')]
    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'SCXMaintenanceSSHKeyNoPrivSu')]
    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'SCXMaintenanceUserPassPriv')]
    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'SCXMaintenanceUserPassNoPrivSudo')]
    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName = 'SCXMaintenanceUserPassNoPrivSu')]
    [Switch]
    ${SCXMaintenance},

    [Parameter(Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
    [Alias('DisplayName')]
    [ValidateNotNullOrEmpty()]
    [System.String]
    ${Name},

    [Parameter(ValueFromPipelineByPropertyName=$true)]
    [System.String]
    ${Description},

    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='Windows')]
    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='Basic')]
    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='Simple')]
    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='Digest')]
    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='ActionAccount')]
    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMonitoring')]
    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceUserPassPriv')]
    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceUserPassNoPrivSudo')]
    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceUserPassNoPrivSu')]
    [Alias('User')]
    [ValidateNotNullOrEmpty()]
    [System.Management.Automation.PSCredential]
    ${RunAsCredential},

    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='Binary')]
    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceSSHKeyPriv')]
    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceSSHKeyNoPrivSudo')]
    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceSSHKeyNoPrivSu')]
    [ValidateNotNullOrEmpty()]
    [ValidateScript({ $executionContext.SessionState.Path.GetResolvedPSPathFromPSPath($_) })]
    [System.String]
    ${Path},

    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='CommunityString')]
    [ValidateNotNullOrEmpty()]
    [System.Security.SecureString]
    ${String},

    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='SnmpV3')]
    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceSSHKeyPriv')]
    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceSSHKeyNoPrivSudo')]
    [Parameter(Mandatory=$true, Position=1, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceSSHKeyNoPrivSu')]
    [ValidateNotNullOrEmpty()]
    [System.String]
    ${UserName},

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName='SnmpV3')]
    [ValidateNotNullOrEmpty()]
    [System.Management.Automation.PSCredential]
    ${AuthProtocolAndKey},

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName='SnmpV3')]
    [ValidateNotNullOrEmpty()]
    [System.Management.Automation.PSCredential]
    ${PrivacyProtocolAndKey},

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName='SnmpV3')]
    [ValidateNotNullOrEmpty()]
    [System.String]
    ${Context},

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceSSHKeyPriv')]
    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceSSHKeyNoPrivSudo')]
    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceSSHKeyNoPrivSu')]
    [ValidateNotNullOrEmpty()]
    [System.Security.SecureString]
    ${Passphrase} = (new-object System.Security.SecureString),

    [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceSSHKeyPriv')]
    [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceUserPassPriv')]
    [Switch]
    ${Privileged},

    [Parameter(ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMonitoring')]
    [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceSSHKeyNoPrivSudo')]
    [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceUserPassNoPrivSudo')]
    [Switch]
    ${Sudo},

    [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceSSHKeyNoPrivSu')]
    [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceUserPassNoPrivSu')]
    [Switch]
    ${Su},

    [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceSSHKeyNoPrivSu')]
    [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName=$true, ParameterSetName='SCXMaintenanceUserPassNoPrivSu')]
    [ValidateNotNullOrEmpty()]
    [System.Security.SecureString]
    ${SuPassword},

    [ValidateNotNullOrEmpty()]
    [Microsoft.SystemCenter.Core.Connection.Connection[]]
    ${SCSession},

    [ValidateNotNullOrEmpty()]
    [System.String[]]
    ${ComputerName},

    [System.Management.Automation.PSCredential]
    ${Credential}
    )
begin {

        $MaintenanceFactory = [Microsoft.SystemCenter.CrossPlatform.ClientLibrary.CredentialManagement.MaintenanceRunAsAccount]::MaintenanceAuthenticationDataFactory
        $MonitoringFactory = [Microsoft.SystemCenter.CrossPlatform.ClientLibrary.CredentialManagement.MonitorRunAsAccount]::MonitorAuthenticationDataFactory

}
process {

        $managementGroupParameters = @{} + $psBoundParameters
        foreach ($k in @($managementGroupParameters.Keys))
        {
            if ('SCSession', 'ComputerName', 'Credential' -notcontains $k)
            {
                $null = $managementGroupParameters.Remove($k)
            }
        }

        $Group = Get-SCOMManagementGroup @managementGroupParameters
        $connection = [Microsoft.SystemCenter.OperationsManagerV10.Commands.OMV10Utility]::GetConnectionForManagementGroup($Group)

        if (-not $psCmdlet.ShouldProcess($Name))
        {
            return
        }

        if (-not $psBoundParameters.description)
        {
            $description = $name 
        }

        $accountProperties = @{
                Name = $name
                Description = $Description
            }

        $networkCredential = $null
        $typeName = $null

        if($psBoundParameters.ContainsKey("RunAsCredential"))
        {
            $networkCredential = $RunAsCredential.GetNetworkCredential()
            $accountProperties.UserName = $networkCredential.UserName
            $accountProperties.Data = $RunAsCredential.Password
        }

        $errorActionPreference = 'Stop'
        try
        {
            $accountData = $null

            # standard scom accounts
            if($psCmdlet.ParameterSetName -notlike 'SCX*')
            {
                switch ($psCmdlet.ParameterSetName)
                {
                    'Windows'
                    {
                       $typeName = 'WindowsCredentialSecureData'
                       if( $networkCredential.Domain)
                       {
                          $accountProperties.Domain = $networkCredential.Domain
                       }
                    }
                    'Basic' {$typeName = 'BasicCredentialSecureData'}
                    'Simple'{$typeName = 'SimpleCredentialSecureData'}
                    'Digest'{$typeName = 'DigestCredentialSecureData'}
                    'ActionAccount'
                    {
                       $typeName = 'ActionAccountSecureData'
                       if( $networkCredential.Domain)
                       {
                          $accountProperties.Domain = $networkCredential.Domain
                       }
                    }
                    'Binary'
                    {
                       $typeName = 'GenericSecureData'
                       $data = new-object System.Security.SecureString
                       $binPath = $psCmdlet.GetUnresolvedProviderPathFromPSPath($Path)
                       [byte[]]$bytes = [System.IO.File]::ReadAllBytes($binPath)
                       $encoded = [System.Convert]::ToBase64String($bytes)
                       $encoded.ToCharArray() |%{ $data.AppendChar($_) }
                       $accountProperties.Data = $data
                    }
                    'CommunityString'
                    {
                       $typeName = 'CommunityStringSecureData'
                       $accountProperties.Data = $String
                    }
                    'SnmpV3'
                    {
                       $typeName = 'SnmpV3SecureData'
                       $accountProperties.UserName = $UserName
                       $accountProperties.AuthenticationProtocol = 'None'
                       $accountProperties.AuthenticationKey = (new-object System.Security.SecureString)
                       $accountProperties.PrivacyProtocol = 'None'
                       $accountProperties.PrivacyKey = (new-object System.Security.SecureString)

                       if($psBoundParameters.ContainsKey("AuthProtocolAndKey"))
                       {
                          $accountProperties.AuthenticationProtocol = [Microsoft.EnterpriseManagement.Security.SnmpV3AuthenticationFunction] $AuthProtocolAndKey.GetNetworkCredential().UserName
                          $accountProperties.AuthenticationKey = $AuthProtocolAndKey.Password

                          if($psBoundParameters.ContainsKey("PrivacyProtocolAndKey"))
                          {
                             $accountProperties.PrivacyProtocol = [Microsoft.EnterpriseManagement.Security.SnmpV3EncryptionAlgorithm ]$PrivacyProtocolAndKey.GetNetworkCredential().UserName
                             $accountProperties.PrivacyKey = $PrivacyProtocolAndKey.Password
                          }
                       }

                       if($psBoundParameters.ContainsKey('Context'))
                       {
                           $accountProperties.ContextName = $Context 
                       }
                    }
                }

                $accountData = New-Object "Microsoft.EnterpriseManagement.Security.${typeName}" -Property $accountProperties
                Write-Debug 'Inserting Account Data'
                $Group.Security.insertSecureData($accountdata)
                $accountData = $Group.Security.GetSecureData($accountData.Id) | Add-Member -Name 'AccountType' -Value "SCOM${typeName}" -MemberType NoteProperty -PassThru

            }
            # x-plat accounts
            else
            {
                $accountData = $null
                if($psCmdlet.ParameterSetName -eq 'SCXMonitoring') {
                    $authenticationData = $MonitoringFactory.Invoke($RunAsCredential.Password, $Sudo.IsPresent)
                    $AccountData = 
                    [Microsoft.SystemCenter.CrossPlatform.ClientLibrary.CredentialManagement.CmdletSupport]::NewMonitorAccount($Connection, $Name, $Description, 
                        $networkCredential.Username, $authenticationData, [guid[]]@())
                }
                elseif ($psCmdlet.ParameterSetName -like 'SCXMaintenance*')
                {
                    Write-Debug 'Creating Maintenance Account Data'
                    $keyFile = $null
                    if($psCmdlet.ParameterSetName -like '*SSHKey*')
                    {
                       $keyFile = $psCmdlet.GetUnresolvedProviderPathFromPSPath($Path) | select -last 1
                    }

                    $authenticationData = 
                        switch($psCmdlet.ParameterSetName)
                        {
                           'SCXMaintenanceSSHKeyPriv'
                           {
                               $MaintenanceFactory.Invoke($keyFile, $PassPhrase, $false)
                           }
                           'SCXMaintenanceSSHKeyNoPrivSudo'
                           {
                               $MaintenanceFactory.Invoke($keyFile, $PassPhrase, $true)
                           }
                           'SCXMaintenanceSSHKeyNoPrivSu'
                           {
                               $MaintenanceFactory.Invoke($keyFile, $PassPhrase, $SuPassword)
                           }
                           'SCXMaintenanceUserPassPriv'
                           {
                               $MaintenanceFactory.Invoke($RunAsCredential.Password, $false)
                           }
                           'SCXMaintenanceUserPassNoPrivSudo'
                           {
                               $MaintenanceFactory.Invoke($RunAsCredential.Password, $true)
                           }
                           'SCXMaintenanceUserPassNoPrivSu'
                           {
                              $MaintenanceFactory.Invoke($RunAsCredential.Password, $SuPassword)
                           }
                        }

                    $AccountData = 
                       [Microsoft.SystemCenter.CrossPlatform.ClientLibrary.CredentialManagement.CmdletSupport]::NewMaintenanceAccount($Connection, $Name, $Description, 
                          $networkCredential.Username, $authenticationData, [guid[]]@())        
                }

            }

            $accountData
        }
        catch
        {
           Write-Error $_
        }       

}

Viewing all articles
Browse latest Browse all 120

Trending Articles