AdhocAdam / smletsexchangeconnector

SMLets PowerShell based Exchange Connector for controlling Microsoft System Center Service Manager 2016+
https://adhocadam.github.io/smletsexchangeconnector/
GNU General Public License v3.0
29 stars 19 forks source link

dynamics assignment issue #151

Closed kenmcmi closed 4 years ago

kenmcmi commented 5 years ago

Testing the Dynamic Assignment in 1.6

I've set the value to random in the script

The email is processed but does not assign an analyst based off the support. This can be done manually in the Cireson portal.

On 9.4.1 of the portal

Attached are the errors that are outputted in the powershell console when it processes an email error.txt

AdhocAdam commented 5 years ago

After looking at the attached error output...

Error 1 This is related to the multi-mailbox feature and appears to be identical to #141

PS C:\scripts\1.6> C:\scripts\1.6\smletsExchangeConnector.ps1
Index operation failed; the array index evaluated to null.
At C:\scripts\1.6\smletsExchangeConnector.ps1:2450 char:24
+                 return $Mailboxes[$ScsmEmail]
+                        ~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : NullArrayIndex

Error 2 This is related directly to Dynamic Analyst Assignment. A few things here, while Get-SCSMObject is the first "break" since it's missing a required parameter to identify the Support Group from the Template to the Cireson Support Group Mapping. It seems even if it were to work in this context, it would immediately fail since Get-AdDomain isn't identified as a valid command. In which case, this looks like your missing the Active Directory PowerShell module wherever the connector is running. The failure to leverage AD PowerShell then leads to the final issue wherein Get-Random doesn't have a valid input. But again - this all starts with the missing value. Assuming you are using Incidents as the default new work item and not using Azure Machine Learning. Let's breakpoint the following line and see what kind of values are getting produced and how they ultimately pass into Set-AssignedToPerSupportGroup function as this calls the Get-TierMembers function where we're seeing the error you've attached.

https://github.com/AdhocAdam/smletsexchangeconnector/blob/fb8c14198bc24741fedc2c91915ccdec2f0e0b71/smletsExchangeConnector.ps1#L832

Get-SCSMObject : Cannot bind argument to parameter 'Id' because it is null.
At C:\scripts\1.6\smletsExchangeConnector.ps1:1841 char:54
+     $grpInScsm = (Get-ScsmObject @scsmMGMTParams -Id $groupId)
+                                                      ~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Get-SCSMObject], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,SMLets.GetSMObjectCommand

Get-AdDomain : The term 'Get-AdDomain' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, 
verify that the path is correct and try again.
At C:\scripts\1.6\smletsExchangeConnector.ps1:1845 char:16
+     $AdRoot = (Get-AdDomain @adParams -Identity $grpInScsm.Domain).DNSRoot
+                ~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (Get-AdDomain:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Get-Random : Cannot validate argument on parameter 'InputObject'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At C:\scripts\1.6\smletsExchangeConnector.ps1:1886 char:52
+             $userToAssign = $supportGroupMembers | Get-Random
+                                                    ~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Get-Random], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.GetRandomCommand

Error 3 This could be coming from a couple places such as setting attempting to set Announcements on the Cireson Portal or retrieving KA/RO Suggestions from the Cireson portal as it's attempting to retrieve a user from the Cireson Portal.

Invoke-RestMethod : {"success":false,"message":"User is not authenticated.","exception":null}
At C:\scripts\1.6\smletsExchangeConnector.ps1:2093 char:36
+         $ciresonPortalUserObject = Invoke-RestMethod -Uri ($ciresonPortalServer+ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-RestMethod], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand

PS C:\scripts\1.6> 
kenmcmi commented 5 years ago

Error 1

The output error does match the #141 but not the symptoms. The email processes as expected, applies template as expected. The emails are not being forwarded over and multi mailbox redirection is set to $false

Error2

Installed the AD module

Here is the up PS C:\scripts> C:\scripts\smletsExchangeConnector.ps1

Index operation failed; the array index evaluated to null.

At C:\scripts\smletsExchangeConnector.ps1:2450 char:24

Get-SCSMObject : Cannot bind argument to parameter 'Id' because it is null.

At C:\scripts\smletsExchangeConnector.ps1:1841 char:54

Get-ADDomain : Cannot validate argument on parameter 'Identity'. The argument is null. Provide a valid value for the argument, and then try

running the command again.

At C:\scripts\smletsExchangeConnector.ps1:1845 char:49

Get-Random : Cannot validate argument on parameter 'InputObject'. The argument is null or empty. Provide an argument that is not null or

empty, and then try the command again.

At C:\scripts\smletsExchangeConnector.ps1:1886 char:52

Error 3 (I resolved this one by adjusting the portal variables)

AdhocAdam commented 4 years ago

I've been looking these functions up and down, I've tried them across different environments, and they are no less from the current v1.6. I've only made two modifications here -

  1. You have to set the Display Name of your Incident Template as you've configured in the connector
  2. I've removed splatting from the functions, so you'll need to run this wherever you're currently running the SMlets Exchange Connector.

The output of this should return 2 users from the Support Group as defined in an Incident Template, with an Enum to AD Group mapping as defined in the Cireson Portal Mappings setting. If these don't work, I'd ask you breakpoint in either ISE/Code to see the exact moment a null value is returned.

$irTemplate = Get-SCSMObjectTemplate -DisplayName "Default Email Incident Template Display Name Here"
$domainUserClass = Get-SCSMClass -name "System.Domain.User$"
$assignedToUserRelClass  = Get-SCSMRelationshipClass -name "System.WorkItemAssignedToUser$"

function Get-TierMembers ($TierEnumId)
{
    #define classes
    $mapCls = Get-ScsmClass  -Name "Cireson.SupportGroupMapping"

    #pull the group based on support tier mapping
    $mapping = $mapCls | Get-ScsmObject  | ? { $_.SupportGroupId.Guid -eq $TierEnumId }
    $groupId = $mapping.AdGroupId

    #get the AD group object name
    $grpInScsm = (Get-ScsmObject  -Id $groupId)
    $grpSamAccountName = $grpInScsm.UserName

    #determine which domain to query, in case of multiple domains and trusts
    $AdRoot = (Get-AdDomain  -Identity $grpInScsm.Domain).DNSRoot

    if ($grpSamAccountName)
    {
        # Get the group membership
        [array]$supportTierMembers = Get-ADGroupMember  -Server $AdRoot -Identity $grpSamAccountName -Recursive | foreach-object {Get-SCSMObject -Class $domainUserClass -filter "Username -eq '$($_.samaccountname)'"}
    }
    return $supportTierMembers
}

function Get-AssignedToWorkItemVolume ($SCSMUser)
{
    #initialize the counter, get the user's assigned Work Items that aren't in some form of "Done"
    $assignedCount = 0
    $assignedWorkItemRelationships = Get-SCSMRelationshipObject -TargetRelationship $assignedToUserRelClass -TargetObject $SCSMUser 
    $assignedWorkItemRelationships = $assignedWorkItemRelationships | select-object SourceObject -ExpandProperty SourceObject | select-object -ExpandProperty values | ?{($_.type.name -eq "Status") -and (($_.value -notlike "*Resolve*") -and ($_.value -notlike "*Close*") -and ($_.value -notlike "*Complete*") -and ($_.value -notlike "*Skip*") -and ($_.value -notlike "*Cancel*"))}
    $assignedWorkItemRelationships | foreach-object {$assignedCount++}

    #build Assigned To Volume object
    $assignedToVolume = New-Object System.Object
    $assignedToVolume | Add-Member -type NoteProperty -name SCSMUser -value $SCSMUser
    $assignedToVolume | Add-Member -type NoteProperty -name AssignedCount -value $assignedCount
    return $assignedToVolume
}

#support group members
$tier = $irTemplate | select-object -expandproperty propertycollection | where-object{($_.path -like "*TierQueue*")} | select-object -ExpandProperty mixedvalue
$supportGroupMembers = Get-TierMembers -TierEnumId $tier

#random analyst
$supportGroupMembers | Get-Random
#least assigned analyst
$supportGroupMembers | foreach-object {Get-AssignedToWorkItemVolume -SCSMUser $_} | Sort-Object AssignedCount -Descending | Select-Object SCSMUser -ExpandProperty SCSMUser -first 1
kenmcmi commented 4 years ago

Here are the errors

From: Adam notifications@github.com Sent: Monday, November 18, 2019 10:53 PM To: AdhocAdam/smletsexchangeconnector smletsexchangeconnector@noreply.github.com Cc: Kenneth McMichael kenmcmi@atlasworldgroup.com; Author author@noreply.github.com Subject: Re: [AdhocAdam/smletsexchangeconnector] dynamics assignment issue (#151)

I've been looking these functions up and down, I've tried them across different environments, and they are no less from the current v1.6. I've only made two modifications here -

  1. You have to set the Display Name of your Incident Template as you've configured in the connector
  2. I've removed splatting from the functions, so you'll need to run this wherever you're currently running the SMlets Exchange Connector.

The output of this should return 2 users from the Support Group as defined in an Incident Template, with an Enum to AD Group mapping as defined in the Cireson Portal Mappings setting. If these don't work, I'd ask you breakpoint in either ISE/Code to see the exact moment a null value is returned.

$irTemplate = Get-SCSMObjectTemplate -DisplayName "Default Email Incident Template Display Name Here"

$domainUserClass = Get-SCSMClass -name "System.Domain.User$"

$assignedToUserRelClass = Get-SCSMRelationshipClass -name "System.WorkItemAssignedToUser$"

function Get-TierMembers ($TierEnumId)

{

#define classes

$mapCls = Get-ScsmClass  -Name "Cireson.SupportGroupMapping"

#pull the group based on support tier mapping

$mapping = $mapCls | Get-ScsmObject  | ? { $_.SupportGroupId.Guid -eq $TierEnumId }

$groupId = $mapping.AdGroupId

#get the AD group object name

$grpInScsm = (Get-ScsmObject  -Id $groupId)

$grpSamAccountName = $grpInScsm.UserName

#determine which domain to query, in case of multiple domains and trusts

$AdRoot = (Get-AdDomain  -Identity $grpInScsm.Domain).DNSRoot

if ($grpSamAccountName)

{

    # Get the group membership

    [array]$supportTierMembers = Get-ADGroupMember  -Server $AdRoot -Identity $grpSamAccountName -Recursive | foreach-object {Get-SCSMObject -Class $domainUserClass -filter "Username -eq '$($_.samaccountname)'"}

}

return $supportTierMembers

}

function Get-AssignedToWorkItemVolume ($SCSMUser)

{

#initialize the counter, get the user's assigned Work Items that aren't in some form of "Done"

$assignedCount = 0

$assignedWorkItemRelationships = Get-SCSMRelationshipObject -TargetRelationship $assignedToUserRelClass -TargetObject $SCSMUser

$assignedWorkItemRelationships = $assignedWorkItemRelationships | select-object SourceObject -ExpandProperty SourceObject | select-object -ExpandProperty values | ?{($_.type.name -eq "Status") -and (($_.value -notlike "*Resolve*") -and ($_.value -notlike "*Close*") -and ($_.value -notlike "*Complete*") -and ($_.value -notlike "*Skip*") -and ($_.value -notlike "*Cancel*"))}

$assignedWorkItemRelationships | foreach-object {$assignedCount++}

#build Assigned To Volume object

$assignedToVolume = New-Object System.Object

$assignedToVolume | Add-Member -type NoteProperty -name SCSMUser -value $SCSMUser

$assignedToVolume | Add-Member -type NoteProperty -name AssignedCount -value $assignedCount

return $assignedToVolume

}

support group members

$tier = $irTemplate | select-object -expandproperty propertycollection | where-object{($_.path -like "TierQueue")} | select-object -ExpandProperty mixedvalue

$supportGroupMembers = Get-TierMembers -TierEnumId $tier

random analyst

$supportGroupMembers | Get-Random

least assigned analyst

$supportGroupMembers | foreach-object {Get-AssignedToWorkItemVolume -SCSMUser $_} | Sort-Object AssignedCount -Descending | Select-Object SCSMUser -ExpandProperty SCSMUser -first 1

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://nam03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2FAdhocAdam%2Fsmletsexchangeconnector%2Fissues%2F151%3Femail_source%3Dnotifications%26email_token%3DAKR7KWN64ZSEMTD574VOMOTQUNWMLA5CNFSM4I4C4H62YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEEM3HRQ%23issuecomment-555332550&data=02%7C01%7Ckenmcmi%40atlasworldgroup.com%7C929513cc083845be689208d76cac6a82%7C3ff05e6340a949219613897a134cb31f%7C0%7C0%7C637097360105367397&sdata=sLFPprPK3SSDS1RRMxVuUnle1xLaJ2XBpmr87AZizdA%3D&reserved=0, or unsubscribehttps://nam03.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAKR7KWJWEPKNBS5GWCMF3MLQUNWMLANCNFSM4I4C4H6Q&data=02%7C01%7Ckenmcmi%40atlasworldgroup.com%7C929513cc083845be689208d76cac6a82%7C3ff05e6340a949219613897a134cb31f%7C0%7C0%7C637097360105377393&sdata=DmGr%2B7OUTAUzl45rYwoQGZXKp1BHe9UqFqCs79CWz8g%3D&reserved=0.

PS C:\scripts\QA> C:\scripts\QA\DynamicsAssignment.ps1 Get-SCSMObject : Cannot bind argument to parameter 'Id' because it is null. At C:\scripts\QA\DynamicsAssignment.ps1:15 char:39

Get-ADDomain : Cannot validate argument on parameter 'Identity'. The argument is null or an element of the argument collection contains a null value. At C:\scripts\QA\DynamicsAssignment.ps1:19 char:40

Get-Random : Cannot validate argument on parameter 'InputObject'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again. At C:\scripts\QA\DynamicsAssignment.ps1:49 char:24

Get-SCSMRelationshipObject : Cannot bind argument to parameter 'TargetObject' because it is null. At C:\scripts\QA\DynamicsAssignment.ps1:33 char:123

kenmcmi commented 4 years ago

Breakpooints https://drive.google.com/open?id=1catGhspSAjuaUlfFT0yDGZpXnSGAnSWl

Line by line https://drive.google.com/open?id=1i3HfpMsCM3eC5GAk9SnsrEqOFJRgo3WV

ckizziar commented 4 years ago

Well @AdhocAdam not sure what the bounty board is but I was able to reproduce this in 2.1 and 2.2 so here goes nothing. It seems depending on which default template is used, expanding the properties either presented no TierQueue

PS C:\ManagementPacks\smletsexchangeconnector-2.1> $irTemplate | select-object -expandproperty propertycollection
Path                                                                        MixedValue                                                                  
----                                                                        ----------                                                                  
$Context/Property[Type='WorkItemIncident!System.WorkItem.Incident']/Source$ $MPElement[Name='WorkItemIncident!IncidentSourceEnum.Portal']$              
$Context/Property[Type='WorkItem!System.WorkItem.TroubleTicket']/Impact$    $MPElement[Name='WorkItem!System.WorkItem.TroubleTicket.ImpactEnum.Medium']$

or returned one of the OOB default enumerations, in this case 'Tier1' which had been renamed 'T1 - Helpdesk'

PS C:\ManagementPacks\smletsexchangeconnector-2.1> $irTemplate | select-object -expandproperty propertycollection
Path                                                                      MixedValue                                                                   
----                                                                      ----------                                                                   
$Target/Property[Type='WorkItem!System.WorkItem.TroubleTicket']/Impact$   $MPElement[Name='WorkItem!System.WorkItem.TroubleTicket.ImpactEnum.Medium']$ 
$Target/Property[Type='WorkItem!System.WorkItem.TroubleTicket']/Urgency$  $MPElement[Name='WorkItem!System.WorkItem.TroubleTicket.UrgencyEnum.Medium']$
$Target/Property[Type='CoreIncident!System.WorkItem.Incident']/TierQueue$ $MPElement[Name='IncidentTierQueuesEnum.Tier1']$

Using a custom template as the default IR template, with a default support group set to 'T1 - Helpdesk' resolved the issue, properly returning the group ID for the TierQueue$ property.

@kenmcmi - I was able to reproduce this issue with the SCSM default templates "Default Incident Template" and "Generic Incident Request" as well as custom templates that did not have anything populated in the support group field by default, but the Cireson Support Group Mapping was set up correctly. You can't change it on defaults, but when creating a custom template you can populate this field on the form and save it to maintain a default value for that group. Can you try these steps to see if that resolves the problem on your end as well?

First, either create a custom incident template or edit the one you're using if it's not part of the sealed defaults, on the properties page (if editing) make sure the box is checked to open the template form after clicking ok, and click aforementioned ok. image

Once the form loads, populate the support group field with your desired default group and click ok. image

AdhocAdam commented 4 years ago

Thank you for taking the time to confirm this functionality @ckizziar!

I hope it's something this simple in which case it's just a matter of updating the documentation to ensure those using the connector are using wholly custom templates.

AdhocAdam commented 4 years ago

Wanted to bring up the recently addressed #188 here as well. But it should be noted it was centered around an actual issue with the logic to pick the analyst rather than being wholly an issue with the feature itself. Adding/citing this as further evidence to @ckizziar's point above.

AdhocAdam commented 4 years ago

Per documentation posted by @ckizziar and issues/pull requests raised by @bennyguk - this issue is being closed.