This commit is contained in:
Zack Meier
2026-04-15 15:45:50 -05:00
commit 1d304511b8
613 changed files with 140998 additions and 0 deletions
@@ -0,0 +1,49 @@
trigger:
- main
name: 'ITD.Shared-ServiceNow'
variables:
major: 0
minor: 8
patch: $(Build.BuildID)
buildVer: $(major).$(minor).$(Build.BuildID)
pool: itdwinautop1
stages:
- stage: Build
jobs:
- job: Build
steps:
- task: PowerShell@2
inputs:
filePath: '$(System.DefaultWorkingDirectory)/Build/build.ps1'
- task: NuGetCommand@2
inputs:
command: 'pack'
packagesToPack: '$(System.DefaultWorkingDirectory)/ITD.Shared-ServiceNow.nuspec'
versioningScheme: byEnvVar
versionEnvVar: buildVer
buildProperties: 'VERSIONHERE=$(buildVer)'
- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
ArtifactName: 'NuGetPackage'
publishLocation: 'Container'
- stage: Deploy
jobs:
- job: Deploy
steps:
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
artifactName: 'NuGetPackage'
itemPattern: '**'
targetPath: '$(Pipeline.Workspace)'
- task: NuGetCommand@2
inputs:
command: 'push'
packagesToPush: '$(Pipeline.Workspace)/ITD.Shared-ServiceNow.$(major).$(minor).$(Build.BuildID).nupkg'
nuGetFeedType: external
publishFeedCredentials: 'ITD_PwshGallery'
@@ -0,0 +1,17 @@
$buildVersion = $env:BUILDVER
$moduleName = 'ITD.Shared-ServiceNow'
$manifestPath = Join-Path -Path $env:SYSTEM_DEFAULTWORKINGDIRECTORY -ChildPath "$moduleName.psd1"
$modulePath = Join-Path -Path $env:SYSTEM_DEFAULTWORKINGDIRECTORY -ChildPath "$moduleName.psm1"
## Update build version in manifest
$manifestContent = Get-Content -Path $manifestPath -Raw
$manifestContent = $manifestContent -replace '<ModuleVersion>', $buildVersion
## Update functions to export in manifest
Import-Module $modulePath
$funcStrings = (Get-Module ITD.Shared-ServiceNow).ExportedCommands.Values.Name
$funcStrings = "'$($funcStrings -join "','")'"
$manifestContent = $manifestContent -replace "<FunctionsToExport>", $funcStrings
$manifestContent | Set-Content -Path $manifestPath
@@ -0,0 +1,12 @@
<?xml version="1.0"?>
<package>
<metadata>
<id>ITD.Shared-ServiceNow</id>
<version>$VERSIONHERE$</version>
<authors>Zack Meier</authors>
<description>Functions for ServiceNow API interaction</description>
</metadata>
<files>
<file src="**" exclude="**\.git\**;**\Build\**" />
</files>
</package>
@@ -0,0 +1,132 @@
#
# Module manifest for module 'ITD.Shared-ServiceNow'
#
# Generated by: zmeier
#
# Generated on: 6/14/2022
#
@{
# Script module or binary module file associated with this manifest.
RootModule = 'ITD.Shared-ServiceNow.psm1'
# Version number of this module.
ModuleVersion = '<ModuleVersion>'
# Supported PSEditions
# CompatiblePSEditions = @()
# ID used to uniquely identify this module
GUID = 'fee42fee-0aef-4376-894d-4d7e460d8fa2'
# Author of this module
Author = 'zmeier'
# Company or vendor of this module
CompanyName = 'State of North Dakota'
# Copyright statement for this module
Copyright = '(c) zmeier. All rights reserved.'
# Description of the functionality provided by this module
Description = 'Functions for ServiceNow API interaction'
# 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 = @()
# 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 = @(<FunctionsToExport>)
# 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 = @()
# A URL to the license for this module.
# LicenseUri = ''
# A URL to the main website for this project.
# ProjectUri = ''
# 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 = ''
}
@@ -0,0 +1,25 @@
#Get public and private function definition files.
$Public = @( Get-ChildItem -Path $PSScriptRoot\Public\*.ps1 -ErrorAction SilentlyContinue )
$Private = @( Get-ChildItem -Path $PSScriptRoot\Private\*.ps1 -ErrorAction SilentlyContinue )
#Dot source the files
Foreach($import in @($Public + $Private))
{
Try
{
. $import.fullname
}
Catch
{
Write-Error -Message "Failed to import function $($import.fullname): $_"
}
}
# Here I might...
# Read in or create an initial config file and variable
$Script:ServiceNowSession = @{}
# Export Public functions ($Public.BaseName) for WIP modules
# Set variables visible to the module and its functions only
Export-ModuleMember -Function $Public.Basename
@@ -0,0 +1,18 @@
function Get-ITDServiceNowVariable {
[CmdletBinding()]
param (
)
begin {
}
process {
}
end {
}
}
@@ -0,0 +1,95 @@
<#
.SYNOPSIS
A short one-line action-based description, e.g. 'Tests if a function is valid'
.DESCRIPTION
A longer description of the function, its purpose, common use cases, etc.
.NOTES
state values
-5 New
-4 Access
-2 Scheduled
-1 Implement
0 Review
3 Close
Close code
Close notes
.LINK
Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
Test-MyTestFunction -Verbose
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
#>
function Complete-ITDServiceNowChangeRequest {
[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string]
$Number,
[string]
$CloseCode,
[string]
$CloseNotes
)
begin {
}
process {
try {
Write-Verbose -Message ($Number + " If state is Assess, do nothing")
$CHG = Get-ITDServiceNowRecord -ItemType 'Change Request' -Number $Number
If ($CHG.State.display_value -eq "Assess") {
Write-Error -Message ($Number + " is currently in Assess state. Unable to continue until the CHG is Approved.")
}
Else {
Write-Verbose -Message ($Number + " If state is New and Type is Standard, set to Schedule")
$CHG = Get-ITDServiceNowRecord -ItemType 'Change Request' -Number $Number
If ($CHG.State.display_value -eq "New" -and $CHG.type.display_value -eq 'Standard') {
Update-ITDServiceNowRecord -ItemType 'Change Request' -Number $Number -Values @{
state = 'Scheduled'
} | Out-Null
}
Write-Verbose -Message ($Number + " If state is Schedule, set to Implement")
$CHG = Get-ITDServiceNowRecord -ItemType 'Change Request' -Number $Number
If ($CHG.State.display_value -eq "Scheduled") {
Update-ITDServiceNowRecord -ItemType 'Change Request' -Number $Number -Values @{
state = 'Implement'
} | Out-Null
}
Write-Verbose -Message ($Number + " If state is Implement, set to Review")
$CHG = Get-ITDServiceNowRecord -ItemType 'Change Request' -Number $Number
If ($CHG.State.display_value -eq "Implement") {
Update-ITDServiceNowRecord -ItemType 'Change Request' -Number $Number -Values @{
state = 'Review';
} | Out-Null
}
Write-Verbose -Message ($Number + " If state is Review, set to Close")
$CHG = Get-ITDServiceNowRecord -ItemType 'Change Request' -Number $Number
If ($CHG.State.display_value -eq "Review") {
Update-ITDServiceNowRecord -ItemType 'Change Request' -Number $Number -Values @{
state = 'Closed';
close_code = $CloseCode;
close_notes = $CloseNotes;
} | Out-Null
}#>
}
}
catch {
Write-Error -Message $error[0]
}
}
end {
}
}
@@ -0,0 +1,49 @@
<#
.SYNOPSIS
A short one-line action-based description, e.g. 'Tests if a function is valid'
.DESCRIPTION
A longer description of the function, its purpose, common use cases, etc.
.NOTES
Information or caveats about the function e.g. 'This function is not supported in Linux'
.LINK
Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
Test-MyTestFunction -Verbose
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
#>
function Get-ITDServiceNowChangeTemplateStandard {
[CmdletBinding()]
param (
[string]
$Name
)
begin {
}
process {
If($PSBoundParameters.ContainsKey('Name')){
$InvokeRestMethodParams = @{
Method = 'Get';
Uri = ($Script:ServiceNowSession.Uri + "/api/sn_chg_rest/change/standard/template?sysparm_query=active=true^name=$Name");
Headers = $Script:ServiceNowSession.Headers;
ContentType = $Script:ServiceNowSession.ContentType;
}
} Else {
$InvokeRestMethodParams = @{
Method = 'Get';
Uri = ($Script:ServiceNowSession.Uri + "/api/sn_chg_rest/change/standard/template?sysparm_query=active=true");
Headers = $Script:ServiceNowSession.Headers;
ContentType = $Script:ServiceNowSession.ContentType;
}
}
$InvokeResult = (Invoke-RestMethod @InvokeRestMethodParams).result
}
end {
Write-Output $InvokeResult
}
}
@@ -0,0 +1,281 @@
<#
.SYNOPSIS
Retrieve ServiceNow records based on the provided parameters.
.DESCRIPTION
Retrieve ServiceNow records based on the provided parameters. Use the ItemType parameter for frequently used tables.
If the ItemType is not listed, then use the Table parameter to specify the ServiceNow table you wish to query.
.PARAMETER ItemType
The type of item to retrieve. Valid values are 'Incident', 'Change Request', 'Catalog Task', and 'Request Item'.
.PARAMETER Table
The name of the ServiceNow table to query if the ItemType is not listed.
.PARAMETER SysId
The SysId of the record to retrieve.
.PARAMETER Number
The number of the record to retrieve.
.PARAMETER Filter
A filter to apply to the query.
.PARAMETER Limit
The maximum number of records to retrieve. Must be a positive integer.
.PARAMETER Fields
An array of fields to include in the results.
.PARAMETER IncludeCustomVariable
A switch to include custom variables in the results.
.PARAMETER IncludeVariableSet
A switch to include variable sets in the results.
.EXAMPLE
Get-ITDServiceNowRecord -ItemType 'Incident' -Number 'INC0012345'
This example retrieves the incident record with the specified number.
.EXAMPLE
Get-ITDServiceNowRecord -Table 'cmdb_ci_win_server' -Filter 'active=true' -Limit 10
This example retrieves up to 10 active Windows server records from the specified table.
.LINK
https://developer.servicenow.com/
#>
function Get-ITDServiceNowRecord {
[CmdletBinding(SupportsPaging)]
param (
[Parameter(ParameterSetName = 'ItemType')]
[ValidateSet('Incident', 'Change Request', 'Catalog Task', 'Request Item')]
[string]
$ItemType,
[Parameter(ParameterSetName = 'Table')]
[string]
$Table,
[string]
$SysId,
[string]
$Number,
[string]
$Filter,
[ValidateRange(1, [int]::MaxValue)]
[int]
$Limit,
[string[]]
$Fields,
[switch]
$IncludeCustomVariable,
[switch]
$IncludeVariableSet
)
begin {
}
process {
switch ($PSCmdlet.ParameterSetName) {
'ItemType' {
$Table = Get-ITDServiceNowTable -ItemType $ItemType
}
'Table' {
# examples: 'cmdb_ci_win_server', 'cmdb_ci_ip_network', 'cmdb_ci_service_auto', 'sc_item_option_mtom'
# don't do anything
}
}
$Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/" + $Table )
$Body = @{}
$sysparm_query = @()
switch ($PSBoundParameters.Keys) {
SysId {
$sysparm_query += "sys_id=$SysId"
}
Number {
$sysparm_query += "number=$Number"
}
Filter {
$sysparm_query += $Filter
}
Fields {
$sysparm_fields = $Fields -join ','
}
}
If ($PSCmdlet.PagingParameters.IncludeTotalCount) {
}
Else {
If ($PSBoundParameters.ContainsKey('Limit')) {
$sysparm_limit = $Limit
}
Else {
Write-Verbose "Limited to 10 records returned unless specified with Limit parameter"
$sysparm_limit = 10;
}
}
Write-Verbose $uri
$Body = @{
sysparm_limit = $sysparm_limit;
sysparm_query = $sysparm_query -join '^';
sysparm_display_value = 'all';
sysparm_fields = $sysparm_fields;
}
$InvokeRestMethodParams = @{
Method = 'Get';
Uri = $Uri
Headers = $Script:ServiceNowSession.Headers;
ContentType = $Script:ServiceNowSession.ContentType;
Body = $Body;
}
Write-Verbose -Message ($Body.sysparm_query)
try {
$Result = (Invoke-RestMethod @InvokeRestMethodParams).Result
}
catch [System.UriFormatException] {
Write-Error "Invalid URI session. Did you run New-ITDServiceNowSession before execution?"
}
If ($IncludeCustomVariable) {
ForEach ($Record in $Result) {
$RecordSysId = $Record.sys_id
<#
$CustomFieldsParams = @{
Method = 'Get';
Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/sc_item_option_mtom?request_item=" + $Record.Sys_id)
Headers = $Script:ServiceNowSession.Headers;
ContentType = $Script:ServiceNowSession.ContentType;
}
$CustomFieldsLookup = (Invoke-RestMethod @CustomFieldsParams).result
$sc_item_options = ForEach ($CustomField in $CustomFieldsLookup) {
#$scitemsysid = $sc_item_option.sc_item_option.value
$params = @{
Method = 'Get';
Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/sc_item_option?sys_id=" + $CustomField.sc_item_option.value ); #+ "&sysparm_limit=100"
Headers = ($Script:ServiceNowSession.Headers);
ContentType = "application/json"
}
(Invoke-RestMethod @params).result
}
$MyArrayList = [System.Collections.ArrayList]@()
ForEach ($sc_item_option in $sc_item_options) {
$params = @{
Method = 'Get';
Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/item_option_new?sys_id=" + $sc_item_option.item_option_new.value);
Headers = ($Script:ServiceNowSession.Headers);
ContentType = "application/json"
}
$vars = (Invoke-RestMethod @params).result
$obj = [PSCustomObject]@{
#sc_item_option_sysid = $sc_item_option.sys_id
#item_option_new_sysid = $vars.sys_id
name = $vars.name
question_text = $vars.question_text
value = $sc_item_option.value
type = $vars.type
# YES_NO = 1; MULTI_LINE_TEXT = 2; MULTIPLE_CHOICE = 3; NUMERIC_SCALE = 4; SELECT_BOX = 5; SINGLE_LINE_TEXT = 6; CHECKBOX = 7; REFERENCE = 8; DATE = 9; DATE_TIME = 10; LABEL = 11; BREAK = 12; MACRO = 14; UI_PAGE = 15; WIDE_SINGLE_LINE_TEXT = 16; MACRO_WITH_LABEL = 17; LOOKUP_SELECT_BOX = 18; CONTAINER_START = 19; CONTAINER_END = 20; LIST_COLLECTOR = 21; LOOKUP_MULTIPLE_CHOICE = 22; HTML = 23; SPLIT = 24; MASKED = 25;
}
$null = $MyArrayList.Add($obj)
}
$Record | Add-Member @{'CustomFields' = $MyArrayList }
$Record
}#>
$Record | Add-Member @{
'CustomVariable' = [pscustomobject]@{}
}
$InvokeRestMethodParams = @{
Method = 'Get';
Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/sc_item_option_mtom");
ContentType = ($Script:ServiceNowSession.ContentType);
Headers = ($Script:ServiceNowSession.Headers);
Body = @{
request_item = $Record.sys_id.value;
sysparm_fields = (@('sc_item_option.item_option_new.name',
'sc_item_option.value',
'sc_item_option.item_option_new.type',
'sc_item_option.item_option_new.question_text',
'sc_item_option.item_option_new.reference') -join ',');
#sysparm_query = "sc_item_option.item_option_new.typeIN1,2,3,4,5,6,7,8,9,10,16,18,21,22,26"
# YES_NO = 1; MULTI_LINE_TEXT = 2; MULTIPLE_CHOICE = 3; NUMERIC_SCALE = 4; SELECT_BOX = 5; SINGLE_LINE_TEXT = 6; CHECKBOX = 7; REFERENCE = 8; DATE = 9; DATE_TIME = 10; LABEL = 11; BREAK = 12; MACRO = 14; UI_PAGE = 15; WIDE_SINGLE_LINE_TEXT = 16; MACRO_WITH_LABEL = 17; LOOKUP_SELECT_BOX = 18; CONTAINER_START = 19; CONTAINER_END = 20; LIST_COLLECTOR = 21; LOOKUP_MULTIPLE_CHOICE = 22; HTML = 23; SPLIT = 24; MASKED = 25;
};
}
$customVars = (Invoke-RestMethod @InvokeRestMethodParams).result #-ov c
ForEach ($var in $customVars) {
$newVar = [pscustomobject] @{
Value = $var.'sc_item_option.value'
DisplayName = $var.'sc_item_option.item_option_new.question_text'
Type = $var.'sc_item_option.item_option_new.type'
}
# show the underlying value if the option is a reference type
<#if ($newVar.Type -eq 'Reference' ) {
$newVar.Value = (Get-ServiceNowRecord -Table $var.'sc_item_option.item_option_new.reference' -ID $var.'sc_item_option.value' -Property name -AsValue -ServiceNowSession $ServiceNowSession)
#>
$Record.CustomVariable | Add-Member @{ $var.'sc_item_option.item_option_new.name' = $newVar }
}
}
}
else {
}
If ($IncludeVariableSet) {
ForEach ($Record in $Result) {
$InvokeRestMethodParams = @{
Method = 'Get';
Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/sc_multi_row_question_answer?parent_id=" + $Record.sys_id.value);
ContentType = ($Script:ServiceNowSession.ContentType);
Headers = ($Script:ServiceNowSession.Headers);
}
$AllRows = (Invoke-RestMethod @InvokeRestMethodParams).result
$Row_Indexes = ($AllRows | Select-Object -Unique row_index).row_index
$ArrayList = [System.Collections.ArrayList]@()
ForEach ($Row in $Row_Indexes) {
$obj = [PSCustomObject]@{}
$RowProperties = $AllRows | Where-Object row_index -EQ $Row
$RowProperties | ForEach-Object -ThrottleLimit 10 -Parallel {
Write-Verbose -Message ("Property start " + ($USING:Script:ServiceNowSession.Uri + "/api/now/table/item_option_new?sys_id=" + $_.item_option_new.value) )
$params = @{
Method = 'Get';
Uri = ($USING:Script:ServiceNowSession.Uri + "/api/now/table/item_option_new?sys_id=" + $_.item_option_new.value);
ContentType = ($USING:Script:ServiceNowSession.ContentType);
Headers = ($USING:Script:ServiceNowSession.Headers);
MaximumRetryCount = 10;
RetryIntervalSec = 5;
}
$vars = (Invoke-RestMethod @params).result
$USING:obj | Add-Member -MemberType NoteProperty -Name $vars.name -Value $_.value
}
$null = $ArrayList.Add($obj)
}
$Record | Add-Member @{
'VariableSet' = $ArrayList
}
}
}
Write-Output $Result
}
end {
}
}
@@ -0,0 +1,32 @@
<#
.SYNOPSIS
A short one-line action-based description, e.g. 'Tests if a function is valid'
.DESCRIPTION
A longer description of the function, its purpose, common use cases, etc.
.NOTES
Information or caveats about the function e.g. 'This function is not supported in Linux'
.LINK
Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
Test-MyTestFunction -Verbose
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
#>
function Get-ITDServiceNowSession {
[CmdletBinding()]
param (
)
begin {
}
process {
}
end {
Write-Output $Script:ServiceNowSession
}
}
@@ -0,0 +1,56 @@
<#
.SYNOPSIS
A short one-line action-based description, e.g. 'Tests if a function is valid'
.DESCRIPTION
A longer description of the function, its purpose, common use cases, etc.
.NOTES
Information or caveats about the function e.g. 'This function is not supported in Linux'
.LINK
Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
Test-MyTestFunction -Verbose
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
#>
function Get-ITDServiceNowTable {
[CmdletBinding()]
param (
[string]
$ItemType
)
begin {
}
process {
switch ($ItemType) {
'Incident' {
$Table = 'incident'
}
'Change Request' {
$Table = 'change_request'
}
'Request' {
$Table = 'sc_request'
}
'Request Item' {
$Table = 'sc_req_item'
}
'Catalog Task' {
$Table = 'sc_task'
}
'cmdb_ci_server_list' {
$Table = 'cmdb_ci_server_list'
}
'cmdb_ci_win_server' {
$Table = 'cmdb_ci_win_server'
}
}
}
end {
Write-Verbose $Table
Write-Output $Table
}
}
@@ -0,0 +1,56 @@
<#
.SYNOPSIS
A short one-line action-based description, e.g. 'Tests if a function is valid'
.DESCRIPTION
A longer description of the function, its purpose, common use cases, etc.
.NOTES
Information or caveats about the function e.g. 'This function is not supported in Linux'
.LINK
Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
Test-MyTestFunction -Verbose
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
#>
function Get-ITDServiceNowUser {
[CmdletBinding()]
param (
[Parameter(ParameterSetName = 'Email')]
[string]
$Email,
[Parameter(ParameterSetName = 'Username')]
[string]
$Username,
[Parameter(ParameterSetName = 'SysId')]
[string]
$SysId
)
begin {
}
process {
$Query = "?sysparm_query="
If ($Email) { $Query += "email=$Email" }
If ($UserName) { $Query += "user_name=$Username" }
If ($SysId) { $Query += "sys_id=$SysId" }
$InvokeRestMethodParams = @{
Method = 'Get';
Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/sys_user" + $Query + "&sysparm_limit=10");
Headers = $Script:ServiceNowSession.Headers;
ContentType = $Script:ServiceNowSession.ContentType;
}
Write-Verbose $InvokeRestMethodParams.Uri
$Result = Invoke-RestMethod @InvokeRestMethodParams
}
end {
Write-Output $Result.result
}
}
@@ -0,0 +1,48 @@
<#
.SYNOPSIS
A short one-line action-based description, e.g. 'Tests if a function is valid'
.DESCRIPTION
A longer description of the function, its purpose, common use cases, etc.
.NOTES
Information or caveats about the function e.g. 'This function is not supported in Linux'
.LINK
Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
Test-MyTestFunction -Verbose
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
#>
function Get-ITDServiceNowUserGroup {
[CmdletBinding()]
param (
[string]
$Name
)
begin {
}
process {
# Invoke-RestMethod -Method GET -Uri ($Url + "api/now/table/sys_user_group?name=NDIT-Computer Systems&sysparm_limit=1") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type -ov x
$Query = "?sysparm_query="
If ($Name) { $Query += "name=$Name" }
$InvokeRestMethodParams = @{
Method = 'Get';
Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/sys_user_group" + $Query + "&sysparm_limit=10");
Headers = $Script:ServiceNowSession.Headers;
ContentType = $Script:ServiceNowSession.ContentType;
}
Write-Verbose $InvokeRestMethodParams.Uri
$Result = Invoke-RestMethod @InvokeRestMethodParams
}
end {
Write-Output $Result.result
}
}
@@ -0,0 +1,246 @@
<#
.SYNOPSIS
A short one-line action-based description, e.g. 'Tests if a function is valid'
.DESCRIPTION
A longer description of the function, its purpose, common use cases, etc.
.NOTES
$StartTime & $EndTime
Send local time in parameter as [datetime] object
Function will convert the date object to UTC, and convert that result to a string via .ToString()
API properties of start_date and end_date require datetime formatted as string
(Get-Date -AsUTC).ToString('yyyy-MM-dd HH:mm:ss')
.LINK
Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
$NewITDServiceNowChangeRequestParams = @{
TemplateName = 'NDIT-SPS-Server Add/Chg/Del'
RequestedByUsername = 'zmeier';
Category = 'Systems Platforms - Systems';
Subcategory = 'Windows';
Impact = 3;
ShortDescription = "things and stuff 5";
Description = "things and stuff description";
Justification = "things are being done to stuff";
Implementation = "do things to stuff";
RiskImpactAnalysis = "things will have stuff done to them";
BackoutPlan = "can't remove things from stuff"
TestPlan = "test stuff first"
WhoIsImpacted = "all the things";
StartTime = (Get-Date)
EndTime = (Get-Date).AddHours(1);
AssignmentGroup = 'NDIT-Computer Systems Windows';
ChangeManagerUsername = 'khellman';
ChangeCoordinatorUsername = 'gpgolberg';
AssignedToUsername = 'zmeier';
CabRequred = $false;
}
$CHG = New-ITDServiceNowChangeRequest @NewITDServiceNowChangeRequestParams
#>
function New-ITDServiceNowChangeRequest {
[CmdletBinding()]
param (
[Parameter(ParameterSetName = 'Standard')]
[string]
$TemplateName,
[string]
$RequestedByUsername,
[Parameter(Mandatory = $true)]
[string]
$Category,
[string]
$ConfigurationItemSysId,
[string]
$Subcategory,
[Parameter(Mandatory = $true)]
[string]
$ShortDescription,
[Parameter(Mandatory = $true)]
[string]
$Description,
[ValidateRange(1, 3)]
[int]
$Priority,
[ValidateRange(1, 3)]
[int]
$Impact,
[Parameter(Mandatory = $true)]
[string]
$Justification,
[Parameter(Mandatory = $true)]
[string]
$Implementation,
[Parameter(Mandatory = $true)]
[string]
$RiskImpactAnalysis,
[Parameter(Mandatory = $true)]
[string]
$BackoutPlan,
[Parameter(Mandatory = $true)]
[string]
$TestPlan,
[string]
$WhoIsImpacted,
[Parameter(Mandatory = $true)]
[string]
$ChangeManagerUsername,
[string]
$ChangeCoordinatorUsername,
[Parameter(Mandatory = $true)]
[string]
$AssignmentGroup,
[string]
$AssignedToUsername,
[Parameter(Mandatory = $true)]
[datetime]
$StartTime,
[Parameter(Mandatory = $true)]
[datetime]
$EndTime
<#
[ValidateSet($true,$false)]
[string]
$CabRequired = $true
#>
)
begin {
switch ($PSCmdlet.ParameterSetName) {
'Standard' {
Write-Verbose -Message "Standard Change Template parameter: $TemplateName" # Server Add/Chg/Del
# get standard template
$ChgTemplateStd = Get-ITDServiceNowChangeTemplateStandard -Name $TemplateName
$ChgTemplateStdSysId = $ChgTemplateStd.sys_id.value
}
Default {
}
}
}
process {
[PSCustomObject]$NewRecord = @{
category = $Category;
u_subcategory = $Subcategory
impact = $Impact;
urgency = $Urgency;
short_description = $ShortDescription;
description = $Description;
justification = $Justification;
implementation_plan = $Implementation;
risk_impact_analysis = $RiskImpactAnalysis;
backout_plan = $BackoutPlan;
test_plan = $TestPlan
u_who_is_impacted = $WhoIsImpacted;
start_date = (Get-Date -Date $StartTime -AsUTC).ToString('yyyy-MM-dd HH:mm:ss')
end_date = (Get-Date -Date $EndTime -AsUTC).ToString('yyyy-MM-dd HH:mm:ss')
}
If($ConfigurationItemSysId) {
$NewRecord += @{cmdb_ci = $ConfigurationItemSysId}
}
If ($CabRequired){
$NewRecord += @{cab_required = $true}
} Else {
$NewRecord += @{cab_required = $false}
}
If ($RequestedByUsername) {
$ReqBy = Get-ITDServiceNowUser -Username $RequestedByUsername
If (@($ReqBy).count -gt 1) {
Write-Error "Multiple requested users found, creation failed." -ErrorAction Stop
}
Else {
$NewRecord += @{requested_by = $ReqBy.sys_id }
}
}
If ($AssignmentGroup) {
$AssGroup = Get-ITDServiceNowUserGroup -Name $AssignmentGroup
If (@($AssGroup).count -gt 1) {
Write-Error "Multiple assignment groups found, creation failed." -ErrorAction Stop
}
Else {
$NewRecord += @{assignment_group = $AssGroup.sys_id }
}
}
$ChgManagerUsername = Get-ITDServiceNowUser -Username $ChangeManagerUsername
If (@($ChgManagerUsername).count -gt 1) {
Write-Error "Multiple users found for ChangeManagerUsername, creation failed." -ErrorAction Stop
}
Else {
$NewRecord += @{u_change_manager = $ChgManagerUsername.sys_id }
}
$ChgCoordUsername = Get-ITDServiceNowUser -Username $ChangeCoordinatorUsername
If (@($ChgCoordUsername).count -gt 1) {
Write-Error "Multiple users found for ChangeCoordinator, creation failed." -ErrorAction Stop
}
Else {
$NewRecord += @{u_change_coordinator = $ChgCoordUsername.sys_id }
}
If ($AssignedToUsername) {
$AssTo = Get-ITDServiceNowUser -Username $AssignedToUsername
If (@($AssTo).count -gt 1) {
Write-Error "Multiple assignment users found, incident creation failed." -ErrorAction Step
}
Else {
$NewRecord += @{assigned_to = $AssTo.sys_id }
}
}
Write-Verbose ($NewRecord | ConvertTo-Json)
switch ($PSCmdlet.ParameterSetName) {
'Standard' {
$Uri = ($Script:ServiceNowSession.Uri + "/api/sn_chg_rest/change/standard/$ChgTemplateStdSysId" );
}
Default {
Write-Verbose -Message ("Uri = " + $Uri)
$Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/change_request");
}
}
Write-Verbose -Message "Standard CHG Template SysId = $Uri"
$InvokeRestMethodParams = @{
Method = 'Post';
Uri = $Uri;
Body = $NewRecord | ConvertTo-Json;
Headers = $Script:ServiceNowSession.Headers;
ContentType = "application/json"
}
#Write-Output $InvokeRestMethodParams
$result = (Invoke-RestMethod @InvokeRestMethodParams).result
}
end {
Write-Output $result
}
}
@@ -0,0 +1,202 @@
<#
.SYNOPSIS
A short one-line action-based description, e.g. 'Tests if a function is valid'
.DESCRIPTION
A longer description of the function, its purpose, common use cases, etc.
.NOTES
$StartTime & $EndTime
Send local time in parameter as [datetime] object
Function will convert the date object to UTC, and convert that result to a string via .ToString()
API properties of start_date and end_date require datetime formatted as string
.LINK
Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
Test-MyTestFunction -Verbose
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
#>
function New-ITDServiceNowChangeRequestOG {
[CmdletBinding()]
param (
[string]
$RequestedByUsername,
[Parameter(Mandatory = $true)]
[string]
$Category,
[string]
$Subcategory,
[Parameter(Mandatory = $true)]
[string]
$ShortDescription,
[Parameter(Mandatory = $true)]
[string]
$Description,
[ValidateRange(1, 3)]
[int]
$Priority,
[ValidateRange(1, 3)]
[int]
$Impact,
[Parameter(Mandatory = $true)]
[string]
$Justification,
[Parameter(Mandatory = $true)]
[string]
$Implementation,
[Parameter(Mandatory = $true)]
[string]
$RiskImpactAnalysis,
[Parameter(Mandatory = $true)]
[string]
$BackoutPlan,
[Parameter(Mandatory = $true)]
[string]
$TestPlan,
[Parameter(Mandatory = $true)]
[string]
$WhoIsImpacted,
[Parameter(Mandatory = $true)]
[string]
$ChangeManagerUsername,
[string]
$ChangeCoordinatorUsername,
[Parameter(Mandatory = $true)]
[string]
$AssignmentGroup,
[string]
$AssignedToUsername,
[Parameter(Mandatory = $true)]
[datetime]
$StartTime,
[Parameter(Mandatory = $true)]
[datetime]
$EndTime
)
begin {
}
process {
<#payload = {
"category": category,
"u_subcategory": subCategory,
"u_change_manager": chngMngrID,
"assigned_to": userID,
"u_change_coordinator": chngCoordID,
"assignment_group": grpID,
"short_description": shortDesc,
"description": desc,
"justification": justDesc,
"implementation_plan": implmntPlan,
"risk_impact_analysis": riskImpact,
"backout_plan": backoutPlan,
"test_plan": testPlan,
"start_date": sTime,
"end_date": eTime,
"cab_required": False,
}#>
[PSCustomObject]$NewRecord = @{
category = $Category;
u_subcategory = $Subcategory
impact = $Impact;
urgency = $Urgency;
short_description = $ShortDescription;
description = $Description;
justification = $Justification;
implementation_plan = $Implementation;
risk_impact_analysis = $RiskImpactAnalysis;
backout_plan = $BackoutPlan;
test_plan = $TestPlan
u_who_is_impacted = $WhoIsImpacted;
start_date = $StartTime.ToUniversalTime().ToString(); # see help/notes
end_date = $EndTime.ToUniversalTime().ToString(); # see help/notes
}
If ($RequestedBy) {
$ReqBy = Get-ITDServiceNowUser -Username $RequestedBy
If (@($ReqBy).count -gt 1) {
Write-Error "Multiple requested users found, incident creation failed." -ErrorAction Stop
}
Else {
$NewRecord += @{requested_by = $ReqBy.sys_id }
}
}
If ($AssignmentGroup) {
$AssGroup = Get-ITDServiceNowUserGroup -Name $AssignmentGroup
If (@($AssGroup).count -gt 1) {
Write-Error "Multiple assignment groups found, incident creation failed." -ErrorAction Stop
}
Else {
$NewRecord += @{assignment_group = $AssGroup.sys_id }
}
}
$ChgManagerUsername = Get-ITDServiceNowUser -Username $ChangeManagerUsername
If (@($ChgManagerUsername).count -gt 1) {
Write-Error "Multiple users found for ChangeManagerUsername, incident creation failed." -ErrorAction Stop
}
Else {
$NewRecord += @{u_change_manager = $ChgManagerUsername.sys_id }
}
$ChgCoordUsername = Get-ITDServiceNowUser -Username $ChangeCoordinatorUsername
If (@($ChgCoordUsername).count -gt 1) {
Write-Error "Multiple users found for ChangeManagerUsername, incident creation failed." -ErrorAction Stop
}
Else {
$NewRecord += @{u_change_coordinator = $ChgCoordUsername.sys_id }
}
If ($AssignedToUsername) {
$AssTo = Get-ITDServiceNowUser -UserName $AssignedToUsername
If (@($AssTo).count -gt 1) {
Write-Error "Multiple assignment users found, incident creation failed." -ErrorAction Step
}
Else {
$NewRecord += @{assigned_to = $AssTo.sys_id }
}
}
Write-Verbose ($NewRecord | ConvertTo-Json)
$InvokeRestMethodParams = @{
Method = 'Post';
Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/change_request");
Body = $NewRecord | ConvertTo-Json;
Headers = $Script:ServiceNowSession.Headers;
ContentType = "application/json"
}
#Write-Output $InvokeRestMethodParams
$result = Invoke-RestMethod @InvokeRestMethodParams
}
end {
Write-Output $result
}
}
@@ -0,0 +1,120 @@
<#
.SYNOPSIS
Creates a new incident in ServiceNow.
.DESCRIPTION
This function creates a new incident in ServiceNow using the provided parameters. It requires either the caller's username or email, along with a short description and a detailed description of the incident.
.PARAMETER CallerUsername
The username of the caller reporting the incident. This parameter is mandatory if CallerEmail is not provided.
.PARAMETER CallerEmail
The email address of the caller reporting the incident. This parameter is mandatory if CallerUsername is not provided.
.PARAMETER ShortDescription
A brief summary of the incident.
.PARAMETER Description
A detailed description of the incident.
.PARAMETER Impact
The impact level of the incident. Valid values are 1 (High), 2 (Medium), and 3 (Low). Default is 3.
.PARAMETER Urgency
The urgency level of the incident. Valid values are 1 (High), 2 (Medium), and 3 (Low). Default is 3.
.PARAMETER Category
The category of the incident.
.EXAMPLE
New-ITDServiceNowIncident -CallerUsername 'jdoe' -ShortDescription 'System outage' -Description 'The system is down and not responding.' -Impact 1 -Urgency 1 -Category 'Network'
This example creates a new high-impact, high-urgency incident for a system outage reported by the user 'jdoe'.
#>
function New-ITDServiceNowIncident {
[CmdletBinding()]
param (
[Parameter(ParameterSetName = 'CallerUsername', Mandatory = $true)]
[string]
$CallerUsername,
[Parameter(ParameterSetName = 'CallerEmail', Mandatory = $true)]
[string]
$CallerEmail,
[Parameter(Mandatory = $true)]
[string]
$ShortDescription,
[Parameter(Mandatory = $true)]
[string]
$Description,
[ValidateRange(1, 3)]
[int]
$Impact = 3,
[ValidateRange(1, 3)]
[int]
$Urgency = 3,
[string]
$Category,
[string]
$Subcategory,
[string]
$AssignmentGroup,
[string]
$AssignedTo
)
begin {
}
process {
# determine caller id
switch ($PSCmdlet.ParameterSetName) {
'CallerUsername' {
$Caller = Get-ITDServiceNowUser -Username $CallerUsername
}
'CallerEmail' {
$Caller = Get-ITDServiceNowUser -Email $CallerEmail
}
}
If (@($Caller).count -gt 1) {
Write-Error "Multiple users found, incident creation failed." -ErrorAction Stop
}
[PSCustomObject]$NewRecord = @{
caller_id = $Caller.sys_id
short_description = $ShortDescription;
description = $Description;
impact = $Impact;
urgency = $Urgency;
category = $Category;
subcategory = $Subcategory
}
If ($AssignmentGroup) {
$AssGroup = Get-ITDServiceNowUserGroup -Name $AssignmentGroup
If (@($AssGroup).count -gt 1) {
Write-Error "Multiple assignment groups found, incident creation failed." -ErrorAction Step
}
Else {
$NewRecord += @{assignment_group = $AssGroup.sys_id }
}
}
$InvokeRestMethodParams = @{
Method = 'Post';
Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/incident");
Body = $NewRecord | ConvertTo-Json;
Headers = $Script:ServiceNowSession.Headers;
ContentType = "application/json"
}
#Write-Output $InvokeRestMethodParams
$result = Invoke-RestMethod @InvokeRestMethodParams
}
end {
$result #| select number, impact, urgency, assignment_group, short_description
}
}
@@ -0,0 +1,41 @@
<#
.SYNOPSIS
Creates a new record in a specified ServiceNow table.
.DESCRIPTION
This function creates a new record in the specified ServiceNow table using the provided values.
.PARAMETER Table
The name of the ServiceNow table where the new record will be created.
.PARAMETER Values
A hashtable containing the field names and values for the new record.
.EXAMPLE
$values = @{
short_description = 'New incident';
description = 'Detailed description of the incident';
impact = 3;
urgency = 3;
}
New-ITDServiceNowRecord -Table 'incident' -Values $values
This example creates a new incident record in the ServiceNow 'incident' table with the specified values.
.NOTES
Ensure that the ServiceNow session is correctly initialized before calling this function.
#>
function New-ITDServiceNowRecord {
param(
[string]
$Table,
[hashtable]
$Values
)
$InvokeRestMethodParams = @{
Method = 'Post';
Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/$Table");
Body = $Values | ConvertTo-Json;
Headers = $Script:ServiceNowSession.Headers;
ContentType = "application/json"
}
#Write-Output $InvokeRestMethodParams
$result = Invoke-RestMethod @InvokeRestMethodParams
}
@@ -0,0 +1,116 @@
<#
.SYNOPSIS
A short one-line action-based description, e.g. 'Tests if a function is valid'
.DESCRIPTION
A longer description of the function, its purpose, common use cases, etc.
.NOTES
Information or caveats about the function e.g. 'This function is not supported in Linux'
.LINK
Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
Test-MyTestFunction -Verbose
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
#>
function New-ITDServiceNowServiceCatalogRequest {
[CmdletBinding()]
param (
[string]
$CategoryItemName,
[string]
$RequestedForEmail,
[hashtable]
$Values
)
begin {
}
process {
Write-Verbose -Message "Retrieve Category Item information"
$InvokeRestMethodParams = @{
Method = 'Get';
Uri = ($Script:ServiceNowSession.Uri + "/api/sn_sc/servicecatalog/items?sysparm_limit=5000");
Headers = $Script:ServiceNowSession.Headers;
ContentType = $Script:ServiceNowSession.ContentType;
}
$CategoryAllItems = (Invoke-RestMethod @InvokeRestMethodParams).result
$CategoryItem = $CategoryAllItems | Where-Object Name -EQ $CategoryItemName
$CategoryItemSysId = $CategoryItem.sys_id
Write-Verbose -Message "Retrieve RequestedBy and manager information"
$RequestedForSNUser = Get-ITDServiceNowUser -Email $RequestedForEmail
$RequiredVariables = @{
# Requester Information
v_requested_for = $RequestedForSNUser.sys_id;
v_requested_by = $RequestedForSNUser.sys_id;
v_user_email = $RequestedForSNUser.email;
v_user_phone = $RequestedForSNUser.phone;
v_alt_contact = "";
# Approval Information
v_approval_department = "f3c65cef1bfed050bba0113fad4bcb1d"; # Information Technology Dept
v_approval_department_code = "112.0";
v_approval_division = "f40758231b321450bba0113fad4bcb2d"; # Computer Systems
###v_approval_division_code = "32";
###v_approval_charge_code = "";
v_manager = $RequestedForSNUser.manager.value;
v_user_in_servicenow = "Yes";
# unknown
###requester_information = "true";
###v_container_requested_for = "true";
###v_user_in_servicenow = "Yes";
###v_container_requested_by = "true";
###approval_information = "true";
###request_commnets = "true";
###request_information = "true";
}
$AllVariables = $RequiredVariables
$Values.Keys | ForEach-Object {
$AllVariables += @{$_ = $values[$_] }
}
$BodyObj = [PSCustomObject]@{
sysparm_quantity = "1";
variables = $AllVariables
}
$BodyJson = $BodyObj | ConvertTo-Json
$InvokeRestMethodParams = @{
Method = 'Post';
Uri = ($Script:ServiceNowSession.Uri + "/api/sn_sc/servicecatalog/items/$CategoryItemSysId/order_now");
Headers = $Script:ServiceNowSession.Headers;
ContentType = $Script:ServiceNowSession.ContentType;
Body = $BodyJson;
}
$InvokeResult = (Invoke-RestMethod @InvokeRestMethodParams).result #create the cart
#$InvokeResult = (Invoke-RestMethod @InvokeRestMethodParams).result
# Submit the cart to create the request
if ($InvokeResult.cart_id) {
$SubmitOrderParams = @{
Method = 'Post'
Uri = ($Script:ServiceNowSession.Uri + "/api/sn_sc/servicecatalog/cart/submit_order")
Headers = $Script:ServiceNowSession.Headers
ContentType = $Script:ServiceNowSession.ContentType
Body = (@{ cart_id = $InvokeResult.cart_id } | ConvertTo-Json)
}
$SubmitResult = (Invoke-RestMethod @SubmitOrderParams).result
} else {
$SubmitResult = $InvokeResult
}
}
end {
Write-Output $SubmitResult
}
}
@@ -0,0 +1,72 @@
<#
.SYNOPSIS
A short one-line action-based description, e.g. 'Tests if a function is valid'
.DESCRIPTION
A longer description of the function, its purpose, common use cases, etc.
.NOTES
Information or caveats about the function e.g. 'This function is not supported in Linux'
.LINK
Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
Test-MyTestFunction -Verbose
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
#>
function New-ITDServiceNowSession {
[CmdletBinding()]
param (
[Parameter(Mandatory=$true)]
[ValidateSet('Production', 'Test', 'Development')]
[string]
$Environment,
[Parameter(Mandatory=$true)]
[PSCredential]
$Credential
)
begin {
}
process {
switch ($Environment) {
'Production' {
$Url = 'https://northdakota.service-now.com'
}
'Test' {
$Url = 'https://northdakotatest.service-now.com'
}
'Development' {
$Url = 'https://northdakotadev.service-now.com'
}
}
$HeaderAuth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $Credential.UserName, $Credential.GetNetworkCredential().Password)))
$SNOWSessionHeader = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$SNOWSessionHeader.Add('Authorization', ('Basic {0}' -f $HeaderAuth))
$SNOWSessionHeader.Add('Accept', 'application/json')
$ContentType = "application/json"
$NewSession = @{
Uri = $Url;
Headers = $SNOWSessionHeader;
ContentType = $ContentType;
}
$Script:ServiceNowSession = $newSession
}
end {
}
}
<#
$HeaderAuth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $SNowVMCred.UserName, $SNowVMCred.GetNetworkCredential().Password)))
$SNOWSessionHeader = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$SNOWSessionHeader.Add('Authorization', ('Basic {0}' -f $HeaderAuth))
$SNOWSessionHeader.Add('Accept', 'application/json')
$ContentType = "application/json"
#>
@@ -0,0 +1,118 @@
<#
.SYNOPSIS
A short one-line action-based description, e.g. 'Tests if a function is valid'
.DESCRIPTION
A longer description of the function, its purpose, common use cases, etc.
.NOTES
Information or caveats about the function e.g. 'This function is not supported in Linux'
.LINK
Specify a URI to a help page, this will show when Get-Help -Online is used.
.EXAMPLE
Test-MyTestFunction -Verbose
Explanation of the function or its result. You can include multiple examples with additional .EXAMPLE lines
#>
function Update-ITDServiceNowRecord {
[CmdletBinding()]
param (
[Parameter(ParameterSetName = 'ItemType')]
[ValidateSet('Incident', 'Change Request', 'User', 'Catalog Task', 'Request Item')]
[string]
$ItemType,
[Parameter(ParameterSetName = 'Table')]
[string]
$Table,
[string]
$SysId,
[string]
$Number,
[hashtable]
$Values
)
begin {
}
process {
switch ($PSCmdlet.ParameterSetName) {
'ItemType' {
$Table = Get-ITDServiceNowTable -ItemType $ItemType
}
'Table' {
# examples: 'cmdb_ci_win_server', 'cmdb_ci_ip_network', 'cmdb_ci_service_auto', 'sc_item_option_mtom'
# don't do anything
}
}
$Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/" + $Table + "?")
#$Uri = ('https://northdakotatest.service-now.com' + "/api/now/table/" + $Table + "?")
switch ($PSBoundParameters.Keys) {
SysId {
Write-Verbose -Message ("sysid passed " + $PSBoundParameters.Item('sysid'))
$Uri += "sys_id=$SysId"
}
Number {
Write-Verbose -Message ("number passed " + $PSBoundParameters.Item('number'))
$Uri += "sysparm_query=number=$Number"
}
}
Write-Verbose $uri
$InvokeRestMethodParams = @{
Method = 'Get';
Uri = $Uri
#Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/" + $Table + "?sysparm_query=number=" + $Number + "&sysparm_limit=1");
Headers = $Script:ServiceNowSession.Headers;
ContentType = $Script:ServiceNowSession.ContentType;
}
try {
$RecordSearch = (Invoke-RestMethod @InvokeRestMethodParams).Result
$Uri = $null
}
catch [System.UriFormatException] {
Write-Error "Invalid URI session. Did you run New-ITDServiceNowSession before execution?"
}
switch (@($RecordSearch).count) { # @($Result).count
{ $_ -lt 1 } {
Write-Error -Message "Record not found"
}
{ $_ -gt 1 } {
Write-Error -Message "More than one record found"
}
{ $_ -eq 1 } {
Write-Verbose -Message 'Exactly one record found'
$SysId = $RecordSearch.sys_id
$Uri = ($Script:ServiceNowSession.Uri + "/api/now/table/" + $Table + "/" + $SysId)
Write-Verbose $Uri
$InvokeRestMethodParams = @{
Method = 'Patch';
Uri = $Uri
Body = $Values | ConvertTo-Json;
Headers = $Script:ServiceNowSession.Headers;
ContentType = $Script:ServiceNowSession.ContentType;
}
try {
$UpdateResult = (Invoke-RestMethod @InvokeRestMethodParams).Result
}
catch [System.UriFormatException] {
Write-Error "Invalid URI session. Did you run New-ITDServiceNowSession before execution?"
}
}
}
}
end {
Write-Output $UpdateResult
}
}
@@ -0,0 +1,492 @@
# required for basic auth
$Url = "https://northdakota.service-now.com"
$HeaderAuth = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes(("{0}:{1}" -f $SNowVMCred.UserName, $SnowVMCred.GetNetworkCredential().Password)))
$SNOWSessionHeader = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$SNOWSessionHeader.Add('Authorization', ('Basic {0}' -f $HeaderAuth))
$SNOWSessionHeader.Add('Accept', 'application/json')
$Type = "application/json"
# open incident in webgui, sysid is in the url
# example: https://northdakotatest.service-now.com/nav_to.do?uri=%2Fincident.do%3Fsys_id%3Db6e3f5d91b9a29d0128ec806604bcb9a%26sysparm_record_target%3Dtask%26sysparm_record_row%3D7%26sysparm_record_rows%3D10%26sysparm_record_list%3Dactive%3Dtrue%5Eassigned_to%3Djavascript:gs.user_id()%5EORDERBYDESCnumber
# sys_id=guid
Invoke-RestMethod -Method GET -Uri ($Url + "/api/now/table/incident/b6e3f5d91b9a29d0128ec806604bcb9a") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type -ov x
# 10000 results
#Invoke-RestMethod -Method GET -Uri ($Url + "api/now/table/incident") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type -ov y
#### better formatting
$InvokeRestMethodParams = @{
Method = 'Get';
Uri = ($Url + "/api/now/table/sc_req_item");
ContentType = $Type;
Headers = $SNOWSessionHeader;
Body = @{
sysparm_query = 'number=RITM0282695';
sysparm_limit = 1;
sysparm_display_value = 'true'; #### show human readable values, not just sysids
sysparm_fields = 'request,cat_item';
}
}
(Invoke-RestMethod @InvokeRestMethodParams -ov c).result
# known tables below
# incident INC########
Invoke-RestMethod -Method GET -Uri ($Url + "/api/now/table/incident?sysparm_query=number=INC0437213&sysparm_limit=1") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type -ov x
Invoke-RestMethod -Method GET -Uri ($Url + "/api/now/table/incident?sysparm_query=number=INC0437213&sysparm_limit=1&sysparm_display_value=true") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type -ov y
# change_request CHG########
Invoke-RestMethod -Method GET -Uri ($Url + "api/now/table/change_request?sysparm_query=number=CHG0089327&sysparm_limit=1") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type
#sc_request REQ########
Invoke-RestMethod -Method GET -Uri ($Url + "api/now/table/sc_request?sysparm_query=number=REQ0129027&sysparm_limit=1") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type
#sc_req_item RITM########
Invoke-RestMethod -Method GET -Uri ($Url + "api/now/table/sc_req_item?sysparm_query=number=RITM0134884&sysparm_limit=1") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type
#sc_task SCTASK#######
#sys_user
Invoke-RestMethod -Method GET -Uri ($Url + "api/now/table/sys_user?sysparm_query=email=zmeier@nd.gov&sysparm_limit=1") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type -ov x
#sys_user_group
Invoke-RestMethod -Method GET -Uri ($Url + "api/now/table/sys_user_group?name=NDIT-Computer Systems&sysparm_limit=1") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type -ov x
# cmdb_ci_ip_network
Invoke-RestMethod -Method GET -Uri ($Url + "api/now/table/cmdb_ci_ip_network") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type -ov x
# appname / cmdb_ci_service_auto_list
Invoke-RestMethod -Method GET -Uri ($Url + "api/now/table/cmdb_ci_service_auto") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type -ov x
https://northdakota.service-now.com/cmdb_ci_service_auto_list.do?sysparm_target=ni.VEacf3763e475c7514baa37834846d433c&sysparm_target_value=&sysparm_reference_value=&sysparm_nameofstack=reflist&sysparm_clear_stack=true&sysparm_element=not&sysparm_reference=cmdb_ci_service_auto&sysparm_view=sys_ref_list&sysparm_form_view=default&sysparm_additional_qual=&sysparm_parent_id=a3feaecb47d0b914baa37834846d4381&sysparm_domain_restore=false
# all tables
$a = Invoke-RestMethod -Method GET -Uri ($Url + "api/now/table/sys_db_object") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type
Invoke-RestMethod -Method GET -Uri ($Url + "api/now/table/sc_ic_category_request?&sysparm_limit=100") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type -ov c
# searching incidents
?sysparm_query=number=INC0437213
sysparm_query%3Dshort_descriptionLIKEhardware
Invoke-RestMethod -Method GET -Uri ($Url + "api/now/table/incident&sysparm_limit=3?sysparm_query=short_descriptionLIKEhardware") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type -ov x
# cmdb_ci_vmware_instance
Invoke-RestMethod -Method GET -Uri ($Url + "api/now/table/cmdb_ci_vmware_instance") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type -ov x
# create records
# incident
[PSCustomObject]$NewRecord = @{
short_description = "failed machine";
caller_id = "Zachary L Meier";
# and others, get record to view
}
$InvokeRestMethodParams = @{
Method = 'Post';
Uri = ($Url + "api/now/table/incident");
Body = $NewRecord | ConvertTo-Json;
Headers = $SnowSessionHeader;
ContentType = "application/json"
}
Invoke-RestMethod @InvokeRestMethodParams
# update records
# incident, sys_id required
# incident state 1 = new, 2 = in progress, 3 = on hold
[PSCustomObject]$SetRecord = @{
short_description = "lots of failed hardware";
description = "omg send help"
caller_id = "Zachary L Meier";
state = 3 # on hold
# and others, get record to view remaining options
}
$InvokeRestMethodParams = @{
Method = 'Put';
Uri = ($Url + "api/now/table/incident/fec7a7a91ba761504e2afeee034bcba8");
Body = $SetRecord | ConvertTo-Json;
Headers = $SnowSessionHeader;
ContentType = "application/json"
}
Invoke-RestMethod @InvokeRestMethodParams
# custom fields lookup
$RitmNum = 'RITM0157839'
$RitmNum = 'RITM0260967'
$Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $RitmNum
$params = @{
Method = 'Get';
Uri = ('https://northdakota.service-now.com/api/now/table/sc_item_option_mtom?request_item=' + $Ritm.Sys_id.value + '&sysparm_limit=1000');
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
$CustomFieldsLookup = (Invoke-RestMethod @params).result
# get each custom field individually
$sc_item_options = ForEach ($CustomField in $CustomFieldsLookup) {
#$scitemsysid = $sc_item_option.sc_item_option.value
$params = @{
Method = 'Get';
Uri = ("https://northdakota.service-now.com/api/now/table/sc_item_option?sys_id=" + $CustomField.sc_item_option.value ); #+ "&sysparm_limit=100"
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
(Invoke-RestMethod @params).result
}
$MyArrayList = [System.Collections.ArrayList]@()
ForEach ($sc_item_option in $sc_item_options) {
$params = @{
Method = 'Get';
Uri = ("https://northdakota.service-now.com/api/now/table/item_option_new?sys_id=" + $sc_item_option.item_option_new.value);
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
$vars = (Invoke-RestMethod @params).result
$obj = [PSCustomObject]@{
#sc_item_option_sysid = $sc_item_option.sys_id
#item_option_new_sysid = $vars.sys_id
name = $vars.name
question_text = $vars.question_text
value = $sc_item_option.value
type = $vars.type
# YES_NO = 1; MULTI_LINE_TEXT = 2; MULTIPLE_CHOICE = 3; NUMERIC_SCALE = 4; SELECT_BOX = 5; SINGLE_LINE_TEXT = 6; CHECKBOX = 7; REFERENCE = 8; DATE = 9; DATE_TIME = 10; LABEL = 11; BREAK = 12; MACRO = 14; UI_PAGE = 15; WIDE_SINGLE_LINE_TEXT = 16; MACRO_WITH_LABEL = 17; LOOKUP_SELECT_BOX = 18; CONTAINER_START = 19; CONTAINER_END = 20; LIST_COLLECTOR = 21; LOOKUP_MULTIPLE_CHOICE = 22; HTML = 23; SPLIT = 24; MASKED = 25;
}
$null = $MyArrayList.Add($obj)
}
#$Ritm | Add-Member -MemberType NoteProperty -Name CustomFields -Value $MyArrayList
#######################################
$Ritm | Add-Member @{
'CustomVariable' = [pscustomobject]@{}
}
$InvokeRestMethodParams = @{
Method = 'Get';
Uri = ($Url + "/api/now/table/sc_item_option_mtom");
Body = @{
request_item = $Ritm.sys_id;
sysparm_fields = (@('sc_item_option.item_option_new.name',
'sc_item_option.value',
'sc_item_option.item_option_new.type',
'sc_item_option.item_option_new.question_text',
'sc_item_option.item_option_new.reference') -join ',');
sysparm_query = "request_item=dd02ed854744bd18baa37834846d43fb^sc_item_option.item_option_new.typeIN1,2,3,4,5,6,7,8,9,10,16,18,21,22,26"
};
ContentType = 'application/json';
Headers = $SNOWSessionHeader;
}
$customVars = (Invoke-RestMethod @InvokeRestMethodParams).result #-ov c
ForEach ($var in $customVars) {
$newVar = [pscustomobject] @{
Value = $var.'sc_item_option.value'
DisplayName = $var.'sc_item_option.item_option_new.question_text'
Type = $var.'sc_item_option.item_option_new.type'
}
# show the underlying value if the option is a reference type
<#if ($newVar.Type -eq 'Reference' ) {
$newVar.Value = (Get-ServiceNowRecord -Table $var.'sc_item_option.item_option_new.reference' -ID $var.'sc_item_option.value' -Property name -AsValue -ServiceNowSession $ServiceNowSession)
}#>
$RITM.CustomVariable | Add-Member @{ $var.'sc_item_option.item_option_new.name' = $newVar }
}
request_item=dd02ed854744bd18baa37834846d43fb^sc_item_option.item_option_new.typeIN1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 16, 18, 21, 22, 26
#################################################################
41e3290a1b1aed14128ec806604bcb50
$params = @{
Method = 'Get';
Uri = ("https://northdakotatest.service-now.com/api/now/table/sc_item_option?sys_id=" + '41e3290a1b1aed14128ec806604bcb50' ); #+ "&sysparm_limit=100"
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
(Invoke-RestMethod @params).result
#get standard change template
$AllChangeTemplateStandard = Invoke-RestMethod -Method Get -Uri ($Url + "api/sn_chg_rest/change/standard/template?sysparm_query=active=true") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type
$AllChangeTemplateStandard = Invoke-RestMethod -Method Get -Uri ($Url + "api/sn_chg_rest/change/standard/template?sysparm_query=active=true^name=$Name") -Headers $SnowSessionHeader -ContentType $Type
$SearchResult = $AllChangeTemplateStandard.result | Where-Object { $_.Name.display_value -eq $StdChangeTemplateName }
# update record
$Number = 'CHG0098990'
Invoke-RestMethod -Method GET -Uri ($Url + "api/now/table/change_request/41b66f1e1b5af5104e2afeee034bcb97") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type -ov x
$Values = @{
short_description = 'this is a new description'
}
$Body = $Values | ConvertTo-Json
Invoke-RestMethod -Method Patch -Uri ($Url + "api/now/table/change_request/41b66f1e1b5af5104e2afeee034bcb97") -Credential $SNowVMCred -Headers $SnowSessionHeader -ContentType $Type -ov x -Body $body
# date/time current time
[DateTime]::UtcNow.ToString('yyyy-MM-dd HH:mm:ss');
(Get-Date -AsUTC).ToString('yyyy-MM-dd HH:mm:ss')
# submit service catalog request
$SysId = 'a490f76adbc0e8901b47105f68961941' #generic service request test
$CommentsFieldExample = @"
Create nd.gov Active Directory service account for use by ITD System Administrators:
{
"PasswordstateTitle": "itdzmtest99.nd.gov",
"PasswordstateList": "CSRC",
"SamAccountName": "svczmtest99",
"Description": "description for things"
}
"@
# submit catalog request, the powershell way
$BodyJson | ConvertFrom-Json
$BodyObj = [PSCustomObject]@{
sysparm_quantity = "1";
variables = [PSCustomObject]@{
v_user_phone = "(701) 328-4171";
v_requested_by = "206d9e091b8898102653997fbd4bcbd4";
v_approval_department_code = "112.0";
requester_information = "true";
v_container_requested_for = "true";
v_manager = "1c1d16451b8898102653997fbd4bcb3b";
v_requested_for = "206d9e091b8898102653997fbd4bcbd4";
v_type = "Server Systems/Hosting";
additional_comments = "comments";
v_user_in_servicenow = "Yes";
v_approval_division = "f40758231b321450bba0113fad4bcb2d";
v_container_requested_by = "true";
approval_information = "true";
v_approval_division_code = "32";
request_commnets = "true";
v_user_email = "zmeier@nd.gov";
request_information = "true";
v_alt_contact = "";
v_approval_department = "f3c65cef1bfed050bba0113fad4bcb1d";
v_approval_charge_code = "";
}
}
$NewJson = $BodyObj | ConvertTo-Json
$InvokeRestMethodParams = @{
Method = 'Post';
Uri = "https://northdakotatest.service-now.com/api/sn_sc/servicecatalog/items/a490f76adbc0e8901b47105f68961941/order_now";
Credential = $SNowVMCred;
Headers = $SNOWSessionHeader;
ContentType = $Type;
Body = $NewJson #'{"sysparm_quantity":"1","variables":{"v_user_phone":"(701) 328-4171","v_requested_by":"206d9e091b8898102653997fbd4bcbd4","v_approval_department_code":"112.0","requester_information":"true","v_container_requested_for":"true","v_manager":"1c1d16451b8898102653997fbd4bcb3b","v_requested_for":"206d9e091b8898102653997fbd4bcbd4","v_type":"Server Systems/Hosting","additional_comments":"moar comments!!2!","v_user_in_servicenow":"Yes","v_approval_division":"f40758231b321450bba0113fad4bcb2d","v_container_requested_by":"true","approval_information":"true","v_approval_division_code":"32","request_commnets":"true","v_user_email":"zmeier@nd.gov","request_information":"true","v_alt_contact":"","v_approval_department":"f3c65cef1bfed050bba0113fad4bcb1d","v_approval_charge_code":""},"sysparm_item_guid":"05adfdcf1b96bd104e2afeee034bcb1d","get_portal_messages":"true","sysparm_no_validation":"true","engagement_channel":"sp","referrer":null}'
}
Invoke-RestMethod @InvokeRestMethodParams -OutVariable e
# new vm form and custom variables
$RitmNum = 'RITM0233555'
$Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $RitmNum
$params = @{
Method = 'Get';
Uri = ('https://northdakotadev.service-now.com/api/now/table/sc_item_option_mtom?request_item=' + $Ritm.Sys_id + '&sysparm_limit=1000');
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
$CustomFieldsLookup = (Invoke-RestMethod @params).result
# get each custom field individually
$sc_item_options = ForEach ($CustomField in $CustomFieldsLookup) {
#$scitemsysid = $sc_item_option.sc_item_option.value
$params = @{
Method = 'Get';
Uri = ("https://northdakotadev.service-now.com/api/now/table/sc_item_option?sys_id=" + $CustomField.sc_item_option.value ); #+ "&sysparm_limit=100"
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
(Invoke-RestMethod @params).result
}
$MyArrayList = [System.Collections.ArrayList]@()
ForEach ($sc_item_option in $sc_item_options) {
$params = @{
Method = 'Get';
Uri = ("https://northdakotadev.service-now.com/api/now/table/item_option_new?sys_id=" + $sc_item_option.item_option_new.value);
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
$vars = (Invoke-RestMethod @params).result
$obj = [PSCustomObject]@{
#sc_item_option_sysid = $sc_item_option.sys_id
#item_option_new_sysid = $vars.sys_id
name = $vars.name
question_text = $vars.question_text
value = $sc_item_option.value
type = $vars.type
# YES_NO = 1; MULTI_LINE_TEXT = 2; MULTIPLE_CHOICE = 3; NUMERIC_SCALE = 4; SELECT_BOX = 5; SINGLE_LINE_TEXT = 6; CHECKBOX = 7; REFERENCE = 8; DATE = 9; DATE_TIME = 10; LABEL = 11; BREAK = 12; MACRO = 14; UI_PAGE = 15; WIDE_SINGLE_LINE_TEXT = 16; MACRO_WITH_LABEL = 17; LOOKUP_SELECT_BOX = 18; CONTAINER_START = 19; CONTAINER_END = 20; LIST_COLLECTOR = 21; LOOKUP_MULTIPLE_CHOICE = 22; HTML = 23; SPLIT = 24; MASKED = 25;
}
$null = $MyArrayList.Add($obj)
}
$params = @{
Method = 'Get';
Uri = ($Url + '/api/now/table/sc_item_option?sys_id=624e6fef47244610b7853238436d43a9');
Headers = $SNOWSessionHeader;
ContentType = 'application/json'
}
$x = Invoke-RestMethod @params
$params = @{
Method = 'Get';
Uri = ($Url + '/api/now/table/item_option_new_set?sys_id=5939ba3b47b04a90b7853238436d4372');
Headers = $SNOWSessionHeader;
ContentType = 'application/json'
}
$x = Invoke-RestMethod @params
#variable set lookup scratch
$params = @{
Method = 'Get';
Uri = ('https://northdakotadev.service-now.com/api/now/table/sc_req_item?sys_id=' + '3b94e3f1874e0a14a5aacbb6dabb35ac' + '&sysparm_limit=1000');
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
$x = (Invoke-RestMethod @params)
$params = @{
Method = 'Get';
Uri = ('https://northdakotadev.service-now.com/api/now/table/item_option_new_set?sys_id=' + '5939ba3b47b04a90b7853238436d4372' + '&sysparm_limit=1000');
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
$a = (Invoke-RestMethod @params).result
$params = @{
Method = 'Get';
Uri = ('https://northdakotadev.service-now.com/api/now/table/sc_cat_item');
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
$b = (Invoke-RestMethod @params).result
$c = $b | Where-Object sys_id -EQ 'c64e27af47244610b7853238436d435d'
$params = @{
Method = 'Get';
Uri = ('https://northdakotadev.service-now.com/api/now/table/item_option_new_set_list');
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
$d = (Invoke-RestMethod @params).result
$params = @{
Method = 'Get';
Uri = ('https://northdakotadev.service-now.com/api/now/table/sc_multi_row_question_answer');
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
$e = (Invoke-RestMethod @params).result
<#
sc_req_item --> sc_multi_row_question_answer.parent_id
#>
$RitmNum = 'RITM0233555'
$RitmNum = 'RITM0231641'
$Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number $RitmNum
$params = @{
Method = 'Get';
Uri = ('https://northdakotadev.service-now.com/api/now/table/sc_multi_row_question_answer?parent_id=' + $Ritm.sys_id);
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
$AllRows = (Invoke-RestMethod @params).result
#$AllRows | Group-Object row_index ####### USE THIS TO SEPARATE EACH ROW ENTRY
#item_option gets value
#vars gets name, type, question_text
$Row_Indexes = ($AllRows | Select-Object -Unique row_index).row_index
$ArrayList = [System.Collections.ArrayList]@()
ForEach ($Row in $Row_Indexes) {
$RowProperties = $AllRows | Where-Object row_index -EQ $Row
$obj = [PSCustomObject]@{
}
ForEach ($Property in $RowProperties) {
$params = @{
Method = 'Get';
Uri = ("https://northdakotadev.service-now.com/api/now/table/item_option_new?sys_id=" + $Property.item_option_new.value);
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
$vars = (Invoke-RestMethod @params).result
$obj | Add-Member -MemberType NoteProperty -Name $vars.name -Value $Property.value
}
$null = $ArrayList.Add($obj)
}
$params = @{
Method = 'Get';
Uri = ();
Headers = $SNOWSessionHeader;
ContentType = "application/json"
}
$CmdbCi = Get-ITDServiceNowRecord -Table cmdb_ci -SysId '4ac36cd11b0154509d7ada01dd4bcbdb'
$params = @{
Method = 'Get';
Uri = "https://northdakota.service-now.com/api/now/table/sys_history_set?sys_id=" + 'ebb4a8cddbbf0254c4582fcb139619b9';
Headers = $SNOWSessionHeader;
ContentType = 'application/json'
}
Invoke-RestMethod @params -ov z
#### cmdb key values POC
Get-ITDServiceNowRecord -Table 'cmdb_ci_win_server' -Filter @{name = 'itddotrtp2' }
$z = Get-ITDServiceNowRecord -Table 'cmdb_key_value' -Filter @{name = 'itddotrtp2' }
$ComputerName = 'itddotrtp2'
$CmdbCi = Get-ITDServiceNowRecord -Table 'cmdb_ci_server' -Filter ("name=$ComputerName")
$KeyValues = Get-ITDServiceNowRecord -Table 'cmdb_key_value' -Filter ('configuration_item=' + $CmdbCi.sys_id.value)
$KeyValues | Select-Object {$_.configuration_item.display_value},{$_.key.display_value},{$_.value.display_value}
# https://northdakotadev.service-now.com/now/nav/ui/classic/params/target/cmdb_key_value.do%3Fsys_id%3D31f4620bc38496505bc7d685e00131ac%26sysparm_record_target%3Dcmdb_key_value%26sysparm_record_row%3D2%26sysparm_record_rows%3D5%26sysparm_record_list%3Dconfiguration_item%253D67ba954bc30c121046637badc001311c
# https://northdakotadev.service-now.com/now/nav/ui/classic/params/target/cmdb_key_value.do%3Fsys_id%3D31f4620bc38496505bc7d685e00131ab%26sysparm_record_target%3Dcmdb_key_value%26sysparm_record_row%3D1%26sysparm_record_rows%3D5%26sysparm_record_list%3Dconfiguration_item%253D67ba954bc30c121046637badc001311c
@@ -0,0 +1,44 @@
$Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number 'RITM0252601' -IncludeVariableSet
ForEach ($row in $Ritm.VariableSet) {
$Ci = Get-ITDServiceNowRecord -Table 'cmdb_ci' -Filter ("name=" + $row.host_name.split('.')[0])
$NewApplicationSvc = Get-ITDServiceNowRecord -Table cmdb_ci_service_auto -SysId $row.application_info
$CustomObj = $row | select licensing_restrictions,support_hours,dr_protection
<#Update-ITDServiceNowRecord -Table 'cmdb_ci' -SysId $Ci.sys_id.value -Values @{
u_nd_application_svc = $NewApplicationSvc.name.display_value
short_description = ($CustomObj | ConvertTo-Json)
}#>
}
# key values
Get-ITDServiceNowRecord -Table 'cmdb_key_value' -Filter ('configuration_item=' + $Ci.sys_id.value)
New-ITDServiceNowRecord -Table 'cmdb_key_value' -Values @{
configuration_item = $ci.sys_id.value
key = 'AppName';
value = $NewApplicationSvc.name.display_value
}
$Ritm = Get-ITDServiceNowRecord -ItemType 'Request Item' -Number 'RITM0252601' -IncludeVariableSet
ForEach ($row in $Ritm.VariableSet) {
$Ci = Get-ITDServiceNowRecord -Table 'cmdb_ci' -Filter ("name=itdzmtest666")
$NewApplicationSvc = Get-ITDServiceNowRecord -Table cmdb_ci_service_auto -SysId $row.application_info
$CustomObj = $row | select licensing_restrictions,support_hours,dr_protection
Update-ITDServiceNowRecord -Table 'cmdb_ci' -SysId $Ci.sys_id.value -Values @{
u_nd_application_svc = $NewApplicationSvc.name.display_value
short_description = ($CustomObj | ConvertTo-Json)
}
}
# key values
Get-ITDServiceNowRecord -Table 'cmdb_key_value' -Filter ('configuration_item=' + $Ci.sys_id.value)
New-ITDServiceNowRecord -Table 'cmdb_key_value' -Values @{
configuration_item = $ci.sys_id.value
key = 'AppName';
value = $NewApplicationSvc.name.display_value
}
@@ -0,0 +1,170 @@
# property expressions for only custom attributes
$PropertyList = @(
@{
name = "name";
expression = { $_.name.display_value };
},
@{
name = "dns_domain";
expression = { $_.dns_domain.display_value } ;
},
@{
name = "environment";
expression = { $_.environment.display_value } ;
},
@{
name = 'operational_status';
expression = { $_.operational_status.display_value };
}
@{
name = 'sys_id';
expression = { $_.sys_id.value };
}
@{
name = 'sys_class_name';
expression = { $_.sys_class_name.value }
},
@{
name = "u_nd_type";
expression = { $_.u_nd_type.display_value }
},
@{
name = "u_nd_dr_protection";
expression = { $_.u_nd_dr_protection.display_value };
},
@{
name = "u_nd_licensing_restrictions";
expression = { $_.u_nd_licensing_restrictions.display_value }
},
@{
name = "u_nd_application_svc";
expression = { $_.u_nd_application_svc.display_value }
},
@{
name = "u_support_hours";
expression = { $_.u_support_hours.display_value }
},
@{
name = "u_srm_recovery_type";
expression = { $_.u_srm_recovery_type.display_value }
}
)
# Get all Ci properties and sort them alphabetically
# $Ci | Select-Object ([string[]]($Ci | Get-Member -MemberType NoteProperty | ForEach-Object{$_.Name} | Sort-Object))
$SharePointList = Get-ITDVMwareSharePointVMGuestList | Where-Object { $_.Status -ne 'Delete' -and $_.Status -ne 'Deleted' } | Sort-Object Title
# sync sharepoint to servicenow cmdb
ForEach ($SPItem in $SharePointList) {
try {
Write-Verbose -Message ("Start " + $SPItem.Title) -Verbose
$HostName = $SPItem.Title.split('.')[0]
$Ci = Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter "name=$HostName" | Select-Object -Property $PropertyList
#If ($null -eq $Ci.u_nd_dr_protection) {
switch ($SPItem.DR_Protection) {
'None' { $DRProtection = 'No DR' }
'VMware: ABR' { $DRProtection = 'VMWare: ABR' }
'VMware: RPO 0:15' { $DRProtection = 'VMWARE RPO: 0:15' }
'VMware: RPO 0:30' { $DRProtection = 'VMWARE RPO: 0:30' }
'VMware: RPO 1:00' { $DRProtection = 'VMWARE RPO: 1:00' }
'VMware: RPO 2:00' { $DRProtection = 'VMWARE RPO: 2:00' }
'VMware: RPO 4:00' { $DRProtection = 'VMWARE RPO: 4:00' }
'VMware: RPO 8:00' { $DRProtection = 'VMWARE RPO: 8:00' }
}
If ($Ci.u_nd_dr_protection -ne $DRProtection) {
Write-Verbose -Message ($Ci.Name + " dr_protection") -Verbose
Update-ITDServiceNowRecord -Table cmdb_ci_server -SysId $Ci.sys_id -Values @{
u_nd_dr_protection = $DRProtection;
} | Out-Null
}
#
If ($null -eq $Ci.u_nd_licensing_restrictions) {
Write-Verbose -Message ($Ci.Name + " licensing restrictions") -Verbose
Update-ITDServiceNowRecord -Table cmdb_ci_server -SysId $Ci.sys_id -Values @{
u_nd_licensing_restrictions = $SPItem.LicensingRestrictions;
}
}
If ($null -eq $SPItem.SRM_RecoveryVMtype) {
# do nothing
}
Else {
switch ($SPItem.SRM_RecoveryVMtype) {
'Reserved' { $SRMRecoveryType = 'Reserved' }
'Repurposed' { $SRMRecoveryType = 'Repurposed' }
}
If ($Ci.u_srm_recovery_type -ne $SRMRecoveryType) {
Write-Verbose -Message ($Ci.Name + " srm recovery type") -Verbose
Update-ITDServiceNowRecord -Table cmdb_ci_server -SysId $Ci.sys_id -Values @{
u_srm_recovery_type = $SRMRecoveryType;
}
}
$SRMRecoveryType = $null
}
If ($null -eq $Ci.u_support_hours) {
Write-Verbose -Message ($Ci.Name + " support hours") -Verbose
switch ($SPitem.Support_x0020_HoursId) {
1 {
$SupportHours = "All Day Every Day" ;
}
4 {
$SupportHours = "All Week 500 to 2300";
}
11 {
$SupportHours = "Weekdays 700 to 1800";
}
}
Write-Verbose -Message ($Ci.name + $SupportHours)
Update-ITDServiceNowRecord -Table cmdb_ci_server -SysId $Ci.sys_id -Values @{
u_support_hours = $SupportHours
} | Out-Null
$SupportHours = $null
}
}
catch {
$Hostname | Add-Content "C:\temp\syncerrors.txt"
}
Write-Verbose -Message ("End " + $SPItem.Title) -Verbose
}
Get-ITDServiceNowRecord -Table cmdb_ci_server | Select-Object Name, dns_domain
Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter "name=itdnet35p1" | Select-Object $PropertyList
$Filter = '&$select=ID,Title,Status,Network/Vlan_Id,Network/CIDR,AppName/Title,Cluster/Name,Support_x0020_Hours/Hours&$expand=Network/Id,AppName/Id,Cluster/Id,Support_x0020_Hours/Id'
$URLVMItems = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Guests')/items?" + '$top=10000' + $Filter
$Filter = '&$select=ID,Title,Support_x0020_Hours/Hours&$expand=Support_x0020_Hours/Id'
$URLVMItems = "https://share.nd.gov/itd/computer-systems/distributed-systems/vmware/_api/lists/getbytitle('VM Guests')/items?" + '$top=10000'
$InvokeWebRequestParams = @{
Uri = $URLVMItems;
Method = "Get";
headers = @{ "Accept" = "application/json;odata=verbose" };
UseBasicParsing = $true;
}
If ($Credential) { $InvokeWebRequestParams += @{Credential = $Credential } }
Else { $InvokeWebRequestParams += @{UseDefaultCredentials = $true } }
#$z = (Invoke-WebRequest -Uri $URL -Method Get -UseDefaultCredentials -headers @{ "Accept" = "application/json;odata=verbose" }) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
$z = (Invoke-WebRequest @InvokeWebRequestParams) -creplace '"Id":', '"Idx":' | ConvertFrom-Json
@@ -0,0 +1,116 @@
#### report on the differences between the SharePoint list and the CMDB
function Compare-ITDVMSharePointToCmdb {
[CmdletBinding()]
param (
)
begin {
$SPList = Get-ITDVMwareSharePointVMGuestList | Where-Object { $_.Status -ne "Delete" -and $_.Status -ne "Deleted" -and $_.Status -ne "Declined"}
$ArrayList = [System.Collections.ArrayList]@()
ForEach ($SPItem in $SPList) {
Write-Verbose -message ($SPItem.Title) -Verbose
$Cmdb = $null
$Hostname = $null
$obj = $null
$Hostname = $SPItem.Title.split('.')[0]
$Cmdb = Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter "name=$HostName"
$obj = [PSCustomObject]@{
SPTitle = $SPItem.Title;
CmdbHostName = $Cmdb.name.display_value;
Environment = $null;
AppName = $null;
LicensingRestrictions = $null;
DR_Protection = $null;
SRMRecoveryType = $null;
}
If ($SPItem.Environment -eq $Cmdb.Environment.display_value) {
$obj.Environment = $true
} Else {
$obj.Environment = $false
}
If ($SPItem.AppName -eq $Cmdb.u_nd_application_svc.display_value) {
$obj.AppName = $true
} Else {
$obj.AppName = $false
}
If ($SPItem.LicensingRestrictions -eq $Cmdb.u_nd_licensing_restrictions.display_value) {
$obj.LicensingRestrictions = $true
} Else {
$obj.LicensingRestrictions = $false
}
switch ($SPItem.DR_Protection) {
'None' {
If ($Cmdb.u_nd_dr_protection.display_value -eq 'No DR') {
$obj.DR_Protection = $true
}
Else {
$obj.DR_Protection = $false
}
}
'VMware: ABR' {
If ($Cmdb.u_nd_dr_protection.display_value -eq 'VMware: ABR') {
$obj.DR_Protection = $true
}
Else {
$obj.DR_Protection = $false
}
}
Default {
If ($Cmdb.u_nd_dr_protection.display_value -eq $SPItem.DR_Protection) {
$obj.DR_Protection = $true
}
Else {
$obj.DR_Protection = $false
}
}
}
switch ($SPItem.SRM_RecoveryVMtype) {
$null {
If ($null -eq $Cmdb.u_nd_srm_recovery_vm_type.display_value) {
$obj.SRMRecoveryType = $true
}
Else {
$obj.SRMRecoveryType = $false
}
}
'Reserved' {
If ($Cmdb.u_srm_recovery_type.display_value -eq 'Reserved') {
$obj.SRMRecoveryType = $true
}
Else {
$obj.SRMRecoveryType = $false
}
}
'Repurposed' {
If ($Cmdb.u_srm_recovery_type.display_value -eq 'Repurposed') {
$obj.SRMRecoveryType = $true
}
Else {
$obj.SRMRecoveryType = $false
}
}
}
$ArrayList.Add($obj) | Out-Null
}
}
process {
}
end {
Write-Output $ArrayList
}
}
@@ -0,0 +1,21 @@
$INCs=@"
INC0517190
INC0517191
INC0517192
INC0517193
"@
$INCs = ConvertTo-Array -MultiLineString $INCs
ForEach($IncNum in $INCs){
Update-ITDServiceNowRecord -ItemType Incident -Number $IncNum -Values @{
work_notes = 'new VMs deployed via OVA... added missing tags';
close_notes = 'new VMs deployed via OVA... added missing tags';
close_code = 'Solved (Permanently)';
u_underlying_cause = 'Configuration'
category = 'sp_systems';
subcategory = 'sp_backup';
assigned_to = "Zachary L Meier";
state = 'Closed';
}
}
@@ -0,0 +1,111 @@
$VMHostNames=@('itdvmnrmsec01.nd.gov')
# New-ITDServiceNowChangeRequest
$VMHostNames | ForEach-Object {
$NewITDServiceNowChangeRequestParams = @{
#TemplateName = 'NDIT-SPS-Server Add/Chg/Del'
RequestedByUsername = 'zmeier';
Category = 'Systems Platforms - Systems';
Subcategory = 'VMware';
Impact = 3;
ShortDescription = "Firmware and software updates for $_";
Description = "Following HPE VMware firmware/software recipe for 2024.04.01: HPE ProLiant Firmware Update and VMware upgrade to v7.0 U3p. The entire process will take 6-8 hours per server. http://vibsdepot.hpe.com/customimages/Valid-vLCM-Combos.pdf";
Justification = "Required for continued support";
Implementation = "install";
RiskImpactAnalysis = "Low - VMware hosts running on the HPE ProLiant platforms will be shutdown. All active virtual machine workloads will be migrated to other hosts in their respective clusters during the maintenance. No outage expected.";
BackoutPlan = "n/a"
TestPlan = "n/a"
WhoIsImpacted = "n/a";
StartTime = (Get-Date)
EndTime = (Get-Date).AddHours(8);
AssignmentGroup = 'NDIT-Computer Systems Windows';
ChangeManagerUsername = 'khellman';
ChangeCoordinatorUsername = 'gpgolberg';
AssignedToUsername = 'zmeier';
}
$CHG = New-ITDServiceNowChangeRequest @NewITDServiceNowChangeRequestParams
}
# To-do list
# Confirm-ITDServiceNowChangeRequest
$CHGNums = @"
CHG0143889
CHG0143888
CHG0143887
CHG0143886
CHG0143885
CHG0143884
CHG0143883
"@
$CHGNums = ConvertTo-Array -MultiLineString $CHGNums
$CHGNums | ForEach-Object {
Complete-ITDServiceNowChangeRequest -Number $_ -CloseCode "Successful" -CloseNotes "Firmware and software installed." #$CHG.Number.value
}
# use standard CHG template NDIT-SPS-Server Add/Chg/Del
<# ps lifecycle verbs
submit --- new
approve / deny --- skip if std chg
schedule --- ???
implement --- ???
confirm --- implement and review
complete --- close
#>
# date/time testing
Update-ITDServiceNowRecord -ItemType 'Change Request' -Number CHG0098995 -Values @{
start_date = (Get-Date -Year 2023 -Month 1 -Day 1 -Hour 0 -Minute 0 -Second 0 -AsUTC).ToString('yyyy-MM-dd HH:mm:ss');
end_date = (Get-Date -AsUTC).AddMinutes(1).ToString('yyyy-MM-dd HH:mm:ss')
}
# New-ITDServiceNowServiceCatalogRequest
$NewITDServiceNowServiceCatalogRequest = @{
CategoryItemName = "Application Server";
RequestedForEmail = 'zmeier@nd.gov';
Values = @{
request_type = "";
application_name = "";
environment = "";
require_hosting_quote = 'No';
server_name = '';
add_change_disaster_recovery = 'No';
additional_comments = "";
};
}
New-ITDServiceNowServiceCatalogRequest @NewITDServiceNowServiceCatalogRequest
# New Server Build Request x1
# server name
$ServerName = 'itdzmtest559.nd.gov'
# Subnet lookup
$Subnet = '10.11.12.0/23' ### review these lookup fields\
$cidr_block = Get-ITDServiceNowRecord -Table 'cmdb_ci_ip_network' -Filter "name=$Subnet"
# Agency lookup
$AgencyPrefix = "ITD"
switch ($AgencyPrefix) {
'ITD' { $AgencyNum = '112.0' }
}
$Agency = Get-ITDServiceNowRecord -Table 'cmn_department' -Filter "id=$AgencyNum"
# team lead lookup
$team_lead = Get-ITDServiceNowUser -Email 'gpgolberg@nd.gov'
# AppName lookup
$AppName = "Infra-VMware"
$application_info = Get-ITDServiceNowRecord -Table cmdb_ci_service -Filter ("name=$AppName")
@@ -0,0 +1,41 @@
function Get-ITDVMSharePointCmdbDiff {
[CmdletBinding()]
param (
[string]
$FQDN
)
begin {
}
process {
$SPItem = Get-ITDVMwareSharePointVMGuestList | Where-Object { $_.Status -ne "Delete" -and $_.Status -ne "Deleted" } | Where-Object { $_.Title -eq $FQDN }
$Cmdb = $null
$Hostname = $null
$obj = $null
$Hostname = $SPItem.Title.split('.')[0]
$Cmdb = Get-ITDServiceNowRecord -Table cmdb_ci_server -Filter "name=$HostName"
$obj = [PSCustomObject]@{
SpPTitle = $SPItem.Title;
CmdbHostName = $Cmdb.name.display_value;
SpEnvironment = $SPItem.Environment;
CmdbEnvironment = $Cmdb.environment.display_value;
SpAppName = $SPItem.AppName;
CmdbAppName = $Cmdb.u_nd_application_svc.display_value;
SpLicensingRestrictions = $SPItem.LicensingRestrictions;
CmdbLicensingRestrictions = $Cmdb.u_nd_licensing_restrictions.display_value;
SpDR_Protection = $SPItem.DR_Protection;;
CmdbDR_Protection = $Cmdb.u_nd_dr_protection.display_value;
SpSRMRecoveryType = $SPItem.SRM_RecoveryVMtype;
CmdbSRMRecoveryType = $Cmdb.u_srm_recovery_type.display_value;
}
}
end {
Write-Output $obj
}
}